OLD | NEW |
---|---|
(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_ | |
OLD | NEW |