Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(400)

Side by Side Diff: base/gap_buffer.h

Issue 5158004: Generic Gap Buffer data structure (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Addressed reviewer's comments Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/base.gypi ('k') | base/gap_buffer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_GAP_BUFFER_H_
6 #define BASE_GAP_BUFFER_H_
7 #pragma once
8
9 #include <stdio.h>
tfarina 2010/11/18 12:03:23 Hum? Why do you need this here? If it is for memmo
varunjain 2010/11/18 17:53:44 removed
10 #include <vector>
11
12 #include "base/basictypes.h"
13 #include "base/logging.h"
tfarina 2010/11/18 12:03:23 Do you this include here?
varunjain 2010/11/18 17:53:44 I had NOTIMPLEMENTED() in one of the methods which
14 #include "base/scoped_ptr.h"
15
16 namespace base {
17
18 ////////////////////////////////////////////////////////////////////////////////
19 //
20 // This class implements a standard GapBuffer
rjkroege 2010/11/18 19:34:28 I don't understand the "why" of your API. I think
21 // (http://en.wikipedia.org/wiki/Gap_buffer)
22 //
sky 2010/11/18 18:26:07 You need some description of this class rather tha
23 ////////////////////////////////////////////////////////////////////////////////
24 template<class T>
sky 2010/11/18 18:26:07 We've trying to move all strings to string16. Coul
25 class GapBuffer {
26 public:
27 // Constructor. The initial size of the buffer can be specified in the
tfarina 2010/11/18 12:03:23 Please, can you move the implementation of all the
varunjain 2010/11/18 17:53:44 This is a template.. if I move the implementation
28 // argument (defaults to 10).
29 explicit GapBuffer(int size) {
sky 2010/11/18 18:26:07 Is anyone really going to want to specify the init
30 if (size < kMinResizeAmount) {
31 size = kMinResizeAmount;
32 }
33
34 buffer_.reset(new T[size]);
35 buffer_size_ = size;
36 gap_start_ = 0;
37 gap_end_ = buffer_size_;
38 }
39
40 // Constructor. Initializes the gap buffer with values from the input buffer.
41 GapBuffer(const T* buffer, int buffer_size) {
sky 2010/11/18 18:26:07 Use member initialize list for setting all fields.
42 buffer_size_ = buffer_size + kMinResizeAmount;
43 buffer_.reset(new T[buffer_size_]);
44 gap_start_ = buffer_size;
45 gap_end_ = buffer_size_;
46 memmove(buffer_.get(), buffer, sizeof(T) * buffer_size);
47 }
48
49 // Moves the Gap left by "count" positions (until it hits the start of the
sky 2010/11/18 18:26:07 Gap -> gap
rjkroege 2010/11/18 19:34:28 you can refactor move-left and move-right into 1
50 // buffer). The gap size remains constant. Contents from the start of the gap
51 // are moved to the end.
52 void MoveGapLeft(int count) {
sky 2010/11/18 18:26:07 Why do we have the move left/right. Can't it just
53 if (buffer_.get() && gap_start_ > 0) {
sky 2010/11/18 18:26:07 Why do you check buffer_.get() here?
54 int new_gap_start = (gap_start_ >= count)? gap_start_ - count : 0;
55 int num_elements = gap_start_ - new_gap_start;
56 memmove(buffer_.get() + gap_end_ - num_elements,
57 buffer_.get() + new_gap_start, sizeof(T) * num_elements);
58 gap_start_ = new_gap_start;
59 gap_end_ -= num_elements;
60 }
61 }
62
63 // Moves the Gap right by "count" positions (until it hits the end of the
64 // buffer). The gap size remains constant. Contents from the end of the gap
65 // are moved to the start.
66 void MoveGapRight(int count) {
67 if (gap_end_ < buffer_size_) {
68 int new_gap_end = (gap_end_ + count > buffer_size_)? buffer_size_
69 : gap_end_ + count;
70 int num_elements = new_gap_end - gap_end_;
71 memmove(buffer_.get() + gap_start_, buffer_.get() + gap_end_,
72 sizeof(T) * num_elements);
73 gap_start_ += num_elements;
74 gap_end_ = new_gap_end;
75 }
76 }
77
78 // Moves the Gap to the left until its just after the first occurrence of
79 // "object". If object is not found it moves the gap all the way to the
80 // beginning of the buffer.
81 void MoveGapLeftTo(T object) {
sky 2010/11/18 18:26:07 Why is this and MoveGapRightTo needed?
82 for (; gap_start_ > 0 && buffer_[gap_start_ - 1] != object;) {
83 MoveGapLeftByOne();
84 }
85 }
86
87 // Moves the Gap to the right until its just after the first occurrence of
88 // "object". If object is not found it moves the gap all the way to the end
89 // of the buffer.
90 void MoveGapRightTo(T object) {
91 for (; gap_end_ < buffer_size_ && buffer_[gap_end_] != object;) {
92 MoveGapRightByOne();
93 }
94 // Move one more space to get after the occurrence on "object".
95 MoveGapRight(1);
96 }
97
98 // Inserts one element in the gap at the beginning. Gap size decreases by one.
99 // If gap is full, it resizes the buffer_ to create gap and then inserts.
100 void InsertAtGapStart(T object) {
101 if (gap_start_ < gap_end_) {
102 buffer_[gap_start_] = object;
103 gap_start_++;
104 } else {
105 ResizeBuffer();
106 InsertAtGapStart(object);
107 }
108 }
109
110 // Removes an element from the beginning of the gap increasing the gap size
111 // by one (unless the gap is already at the beginning of the buffer). Returns
112 // a pointer to the element removed.
113 const T* RemoveFromGapStart() {
114 if (gap_start_ > 0) {
115 gap_start_--;
116 return buffer_.get() + gap_start_;
117 } else {
118 return NULL;
119 }
120 }
121
122 // Removes an element from the end of the gap increasing the gap size
123 // by one (unless the gap is already at the end of the buffer). Returns a
124 // pointer to the element removed.
125 const T* RemoveFromGapEnd() {
126 if (gap_end_ < buffer_size_) {
127 gap_end_++;
128 return buffer_.get() + gap_end_ - 1;
129 } else {
130 return NULL;
131 }
132 }
133
134 // Replaces the part of the buffer from "start" (inclusive) upto "end" with
135 // "replacement". Resizes the gap appropriately. <start-end> should not
136 // overlap with the gap.
137 // FIXME: implement this.
138 void Replace(int start, int end, T replacement) { }
139
140 // Gets the contents of the buffer (removing the gap) in vector "contents".
141 void GetContents(std::vector<T>* contents) {
rjkroege 2010/11/18 19:34:28 ultimately, we'll want strings right? not a vector
142 contents->clear();
143 int size = GetCurrentSize();
144 if (size) {
145 int i, j;
146 for (i = 0; i < gap_start_; i++) {
147 (*contents).push_back(buffer_[i]);
148 }
149 for (j = gap_end_; j < buffer_size_; j++, i++) {
150 (*contents).push_back(buffer_[j]);
151 }
152 }
153 }
154
155 // Gets the current number of elements in the buffer.
156 int GetCurrentSize() {
157 return buffer_size_ - (gap_end_ - gap_start_);
158 }
159
160 // Gets the size of the underlying buffer.
161 int GetBufferSize() {
162 return buffer_size_;
163 }
164
165 // Gets the gap_start_ index (essentially the current cursor position).
166 int GetGapStart() {
167 return gap_start_;
168 }
169
170 private:
171 // Increases the size of the buffer by 10% of current size. Unsafe.. assumes
172 // that the buffer is already allocated. Should not be invoked for
rjkroege 2010/11/18 19:34:28 you should assert that the buffer has been initial
173 // un-initialized buffer.
174 // FIXME: explore more efficient resizing.
rjkroege 2010/11/18 19:34:28 Given that this is a buffer that is backing the om
175 void ResizeBuffer() {
176 int size_increment = (buffer_size_ / 10.0 < kMinResizeAmount)?
177 kMinResizeAmount : buffer_size_ / 10.0;
178 int new_size = buffer_size_ + size_increment;
179 T* new_buffer = new T[new_size];
180 memmove(new_buffer, buffer_.get(), sizeof(T) * gap_start_);
181 memmove(new_buffer + gap_start_ + new_size, buffer_.get() + gap_end_,
182 sizeof(T) * (buffer_size_ - gap_end_));
183 gap_end_ = new_size - (buffer_size_ - gap_end_);
184 buffer_size_ = new_size;
185 buffer_.reset(new_buffer);
186 }
187
188 // Internal helper function. Should not be used on its own as it doesnot do
189 // any sanity checks. Use MoveGapLeft() or MoveGapLeftTo() instead.
190 void MoveGapLeftByOne() {
191 gap_start_--;
192 gap_end_--;
193 buffer_[gap_end_] = buffer_[gap_start_];
194 }
195
196 // Internal helper function. Should not be used on its own as it doesnot do
197 // any sanity checks. Use MoveGapRight() or MoveGapRightTo() instead.
198 void MoveGapRightByOne() {
199 buffer_[gap_start_] = buffer_[gap_end_];
200 gap_start_++;
201 gap_end_++;
202 }
203
204 scoped_array<T> buffer_;
205 int buffer_size_;
206 int gap_start_;
207 int gap_end_;
208
209 // In case of resizing the buffer, we will increase the length at least by
210 // kMinResizeAmount to avoid frequent resizing.
211 static const int kMinResizeAmount = 10;
212
213 DISALLOW_COPY_AND_ASSIGN(GapBuffer);
214 };
215
216 } // namespace
tfarina 2010/11/18 12:03:23 // namespace base
varunjain 2010/11/18 17:53:44 Done.
217
218 #endif // BASE_GAP_BUFFER_H_
OLDNEW
« no previous file with comments | « base/base.gypi ('k') | base/gap_buffer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698