OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkDeque.h" | 10 #include "SkDeque.h" |
11 | 11 |
12 struct SkDeque::Block { | 12 struct SkDeque::Block { |
13 Block* fNext; | 13 Block* fNext; |
14 Block* fPrev; | 14 Block* fPrev; |
15 char* fBegin; // start of used section in this chunk | 15 char* fBegin; // start of used section in this chunk |
16 char* fEnd; // end of used section in this chunk | 16 char* fEnd; // end of used section in this chunk |
17 char* fStop; // end of the allocated chunk | 17 char* fStop; // end of the allocated chunk |
18 | 18 |
19 char* start() { return (char*)(this + 1); } | 19 char* start() { return (char*)(this + 1); } |
20 const char* start() const { return (const char*)(this + 1); } | 20 const char* start() const { return (const char*)(this + 1); } |
21 | 21 |
22 void init(size_t size) { | 22 void init(size_t size) { |
23 fNext = fPrev = NULL; | 23 fNext = fPrev = nullptr; |
24 fBegin = fEnd = NULL; | 24 fBegin = fEnd = nullptr; |
25 fStop = (char*)this + size; | 25 fStop = (char*)this + size; |
26 } | 26 } |
27 }; | 27 }; |
28 | 28 |
29 SkDeque::SkDeque(size_t elemSize, int allocCount) | 29 SkDeque::SkDeque(size_t elemSize, int allocCount) |
30 : fElemSize(elemSize) | 30 : fElemSize(elemSize) |
31 , fInitialStorage(NULL) | 31 , fInitialStorage(nullptr) |
32 , fCount(0) | 32 , fCount(0) |
33 , fAllocCount(allocCount) { | 33 , fAllocCount(allocCount) { |
34 SkASSERT(allocCount >= 1); | 34 SkASSERT(allocCount >= 1); |
35 fFrontBlock = fBackBlock = NULL; | 35 fFrontBlock = fBackBlock = nullptr; |
36 fFront = fBack = NULL; | 36 fFront = fBack = nullptr; |
37 } | 37 } |
38 | 38 |
39 SkDeque::SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCo
unt) | 39 SkDeque::SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCo
unt) |
40 : fElemSize(elemSize) | 40 : fElemSize(elemSize) |
41 , fInitialStorage(storage) | 41 , fInitialStorage(storage) |
42 , fCount(0) | 42 , fCount(0) |
43 , fAllocCount(allocCount) { | 43 , fAllocCount(allocCount) { |
44 SkASSERT(storageSize == 0 || storage != NULL); | 44 SkASSERT(storageSize == 0 || storage != nullptr); |
45 SkASSERT(allocCount >= 1); | 45 SkASSERT(allocCount >= 1); |
46 | 46 |
47 if (storageSize >= sizeof(Block) + elemSize) { | 47 if (storageSize >= sizeof(Block) + elemSize) { |
48 fFrontBlock = (Block*)storage; | 48 fFrontBlock = (Block*)storage; |
49 fFrontBlock->init(storageSize); | 49 fFrontBlock->init(storageSize); |
50 } else { | 50 } else { |
51 fFrontBlock = NULL; | 51 fFrontBlock = nullptr; |
52 } | 52 } |
53 fBackBlock = fFrontBlock; | 53 fBackBlock = fFrontBlock; |
54 fFront = fBack = NULL; | 54 fFront = fBack = nullptr; |
55 } | 55 } |
56 | 56 |
57 SkDeque::~SkDeque() { | 57 SkDeque::~SkDeque() { |
58 Block* head = fFrontBlock; | 58 Block* head = fFrontBlock; |
59 Block* initialHead = (Block*)fInitialStorage; | 59 Block* initialHead = (Block*)fInitialStorage; |
60 | 60 |
61 while (head) { | 61 while (head) { |
62 Block* next = head->fNext; | 62 Block* next = head->fNext; |
63 if (head != initialHead) { | 63 if (head != initialHead) { |
64 this->freeBlock(head); | 64 this->freeBlock(head); |
65 } | 65 } |
66 head = next; | 66 head = next; |
67 } | 67 } |
68 } | 68 } |
69 | 69 |
70 void* SkDeque::push_front() { | 70 void* SkDeque::push_front() { |
71 fCount += 1; | 71 fCount += 1; |
72 | 72 |
73 if (NULL == fFrontBlock) { | 73 if (nullptr == fFrontBlock) { |
74 fFrontBlock = this->allocateBlock(fAllocCount); | 74 fFrontBlock = this->allocateBlock(fAllocCount); |
75 fBackBlock = fFrontBlock; // update our linklist | 75 fBackBlock = fFrontBlock; // update our linklist |
76 } | 76 } |
77 | 77 |
78 Block* first = fFrontBlock; | 78 Block* first = fFrontBlock; |
79 char* begin; | 79 char* begin; |
80 | 80 |
81 if (NULL == first->fBegin) { | 81 if (nullptr == first->fBegin) { |
82 INIT_CHUNK: | 82 INIT_CHUNK: |
83 first->fEnd = first->fStop; | 83 first->fEnd = first->fStop; |
84 begin = first->fStop - fElemSize; | 84 begin = first->fStop - fElemSize; |
85 } else { | 85 } else { |
86 begin = first->fBegin - fElemSize; | 86 begin = first->fBegin - fElemSize; |
87 if (begin < first->start()) { // no more room in this chunk | 87 if (begin < first->start()) { // no more room in this chunk |
88 // should we alloc more as we accumulate more elements? | 88 // should we alloc more as we accumulate more elements? |
89 first = this->allocateBlock(fAllocCount); | 89 first = this->allocateBlock(fAllocCount); |
90 first->fNext = fFrontBlock; | 90 first->fNext = fFrontBlock; |
91 fFrontBlock->fPrev = first; | 91 fFrontBlock->fPrev = first; |
92 fFrontBlock = first; | 92 fFrontBlock = first; |
93 goto INIT_CHUNK; | 93 goto INIT_CHUNK; |
94 } | 94 } |
95 } | 95 } |
96 | 96 |
97 first->fBegin = begin; | 97 first->fBegin = begin; |
98 | 98 |
99 if (NULL == fFront) { | 99 if (nullptr == fFront) { |
100 SkASSERT(NULL == fBack); | 100 SkASSERT(nullptr == fBack); |
101 fFront = fBack = begin; | 101 fFront = fBack = begin; |
102 } else { | 102 } else { |
103 SkASSERT(fBack); | 103 SkASSERT(fBack); |
104 fFront = begin; | 104 fFront = begin; |
105 } | 105 } |
106 | 106 |
107 return begin; | 107 return begin; |
108 } | 108 } |
109 | 109 |
110 void* SkDeque::push_back() { | 110 void* SkDeque::push_back() { |
111 fCount += 1; | 111 fCount += 1; |
112 | 112 |
113 if (NULL == fBackBlock) { | 113 if (nullptr == fBackBlock) { |
114 fBackBlock = this->allocateBlock(fAllocCount); | 114 fBackBlock = this->allocateBlock(fAllocCount); |
115 fFrontBlock = fBackBlock; // update our linklist | 115 fFrontBlock = fBackBlock; // update our linklist |
116 } | 116 } |
117 | 117 |
118 Block* last = fBackBlock; | 118 Block* last = fBackBlock; |
119 char* end; | 119 char* end; |
120 | 120 |
121 if (NULL == last->fBegin) { | 121 if (nullptr == last->fBegin) { |
122 INIT_CHUNK: | 122 INIT_CHUNK: |
123 last->fBegin = last->start(); | 123 last->fBegin = last->start(); |
124 end = last->fBegin + fElemSize; | 124 end = last->fBegin + fElemSize; |
125 } else { | 125 } else { |
126 end = last->fEnd + fElemSize; | 126 end = last->fEnd + fElemSize; |
127 if (end > last->fStop) { // no more room in this chunk | 127 if (end > last->fStop) { // no more room in this chunk |
128 // should we alloc more as we accumulate more elements? | 128 // should we alloc more as we accumulate more elements? |
129 last = this->allocateBlock(fAllocCount); | 129 last = this->allocateBlock(fAllocCount); |
130 last->fPrev = fBackBlock; | 130 last->fPrev = fBackBlock; |
131 fBackBlock->fNext = last; | 131 fBackBlock->fNext = last; |
132 fBackBlock = last; | 132 fBackBlock = last; |
133 goto INIT_CHUNK; | 133 goto INIT_CHUNK; |
134 } | 134 } |
135 } | 135 } |
136 | 136 |
137 last->fEnd = end; | 137 last->fEnd = end; |
138 end -= fElemSize; | 138 end -= fElemSize; |
139 | 139 |
140 if (NULL == fBack) { | 140 if (nullptr == fBack) { |
141 SkASSERT(NULL == fFront); | 141 SkASSERT(nullptr == fFront); |
142 fFront = fBack = end; | 142 fFront = fBack = end; |
143 } else { | 143 } else { |
144 SkASSERT(fFront); | 144 SkASSERT(fFront); |
145 fBack = end; | 145 fBack = end; |
146 } | 146 } |
147 | 147 |
148 return end; | 148 return end; |
149 } | 149 } |
150 | 150 |
151 void SkDeque::pop_front() { | 151 void SkDeque::pop_front() { |
152 SkASSERT(fCount > 0); | 152 SkASSERT(fCount > 0); |
153 fCount -= 1; | 153 fCount -= 1; |
154 | 154 |
155 Block* first = fFrontBlock; | 155 Block* first = fFrontBlock; |
156 | 156 |
157 SkASSERT(first != NULL); | 157 SkASSERT(first != nullptr); |
158 | 158 |
159 if (first->fBegin == NULL) { // we were marked empty from before | 159 if (first->fBegin == nullptr) { // we were marked empty from before |
160 first = first->fNext; | 160 first = first->fNext; |
161 first->fPrev = NULL; | 161 first->fPrev = nullptr; |
162 this->freeBlock(fFrontBlock); | 162 this->freeBlock(fFrontBlock); |
163 fFrontBlock = first; | 163 fFrontBlock = first; |
164 SkASSERT(first != NULL); // else we popped too far | 164 SkASSERT(first != nullptr); // else we popped too far |
165 } | 165 } |
166 | 166 |
167 char* begin = first->fBegin + fElemSize; | 167 char* begin = first->fBegin + fElemSize; |
168 SkASSERT(begin <= first->fEnd); | 168 SkASSERT(begin <= first->fEnd); |
169 | 169 |
170 if (begin < fFrontBlock->fEnd) { | 170 if (begin < fFrontBlock->fEnd) { |
171 first->fBegin = begin; | 171 first->fBegin = begin; |
172 SkASSERT(first->fBegin); | 172 SkASSERT(first->fBegin); |
173 fFront = first->fBegin; | 173 fFront = first->fBegin; |
174 } else { | 174 } else { |
175 first->fBegin = first->fEnd = NULL; // mark as empty | 175 first->fBegin = first->fEnd = nullptr; // mark as empty |
176 if (NULL == first->fNext) { | 176 if (nullptr == first->fNext) { |
177 fFront = fBack = NULL; | 177 fFront = fBack = nullptr; |
178 } else { | 178 } else { |
179 SkASSERT(first->fNext->fBegin); | 179 SkASSERT(first->fNext->fBegin); |
180 fFront = first->fNext->fBegin; | 180 fFront = first->fNext->fBegin; |
181 } | 181 } |
182 } | 182 } |
183 } | 183 } |
184 | 184 |
185 void SkDeque::pop_back() { | 185 void SkDeque::pop_back() { |
186 SkASSERT(fCount > 0); | 186 SkASSERT(fCount > 0); |
187 fCount -= 1; | 187 fCount -= 1; |
188 | 188 |
189 Block* last = fBackBlock; | 189 Block* last = fBackBlock; |
190 | 190 |
191 SkASSERT(last != NULL); | 191 SkASSERT(last != nullptr); |
192 | 192 |
193 if (last->fEnd == NULL) { // we were marked empty from before | 193 if (last->fEnd == nullptr) { // we were marked empty from before |
194 last = last->fPrev; | 194 last = last->fPrev; |
195 last->fNext = NULL; | 195 last->fNext = nullptr; |
196 this->freeBlock(fBackBlock); | 196 this->freeBlock(fBackBlock); |
197 fBackBlock = last; | 197 fBackBlock = last; |
198 SkASSERT(last != NULL); // else we popped too far | 198 SkASSERT(last != nullptr); // else we popped too far |
199 } | 199 } |
200 | 200 |
201 char* end = last->fEnd - fElemSize; | 201 char* end = last->fEnd - fElemSize; |
202 SkASSERT(end >= last->fBegin); | 202 SkASSERT(end >= last->fBegin); |
203 | 203 |
204 if (end > last->fBegin) { | 204 if (end > last->fBegin) { |
205 last->fEnd = end; | 205 last->fEnd = end; |
206 SkASSERT(last->fEnd); | 206 SkASSERT(last->fEnd); |
207 fBack = last->fEnd - fElemSize; | 207 fBack = last->fEnd - fElemSize; |
208 } else { | 208 } else { |
209 last->fBegin = last->fEnd = NULL; // mark as empty | 209 last->fBegin = last->fEnd = nullptr; // mark as empty |
210 if (NULL == last->fPrev) { | 210 if (nullptr == last->fPrev) { |
211 fFront = fBack = NULL; | 211 fFront = fBack = nullptr; |
212 } else { | 212 } else { |
213 SkASSERT(last->fPrev->fEnd); | 213 SkASSERT(last->fPrev->fEnd); |
214 fBack = last->fPrev->fEnd - fElemSize; | 214 fBack = last->fPrev->fEnd - fElemSize; |
215 } | 215 } |
216 } | 216 } |
217 } | 217 } |
218 | 218 |
219 int SkDeque::numBlocksAllocated() const { | 219 int SkDeque::numBlocksAllocated() const { |
220 int numBlocks = 0; | 220 int numBlocks = 0; |
221 | 221 |
222 for (const Block* temp = fFrontBlock; temp; temp = temp->fNext) { | 222 for (const Block* temp = fFrontBlock; temp; temp = temp->fNext) { |
223 ++numBlocks; | 223 ++numBlocks; |
224 } | 224 } |
225 | 225 |
226 return numBlocks; | 226 return numBlocks; |
227 } | 227 } |
228 | 228 |
229 SkDeque::Block* SkDeque::allocateBlock(int allocCount) { | 229 SkDeque::Block* SkDeque::allocateBlock(int allocCount) { |
230 Block* newBlock = (Block*)sk_malloc_throw(sizeof(Block) + allocCount * fElem
Size); | 230 Block* newBlock = (Block*)sk_malloc_throw(sizeof(Block) + allocCount * fElem
Size); |
231 newBlock->init(sizeof(Block) + allocCount * fElemSize); | 231 newBlock->init(sizeof(Block) + allocCount * fElemSize); |
232 return newBlock; | 232 return newBlock; |
233 } | 233 } |
234 | 234 |
235 void SkDeque::freeBlock(Block* block) { | 235 void SkDeque::freeBlock(Block* block) { |
236 sk_free(block); | 236 sk_free(block); |
237 } | 237 } |
238 | 238 |
239 /////////////////////////////////////////////////////////////////////////////// | 239 /////////////////////////////////////////////////////////////////////////////// |
240 | 240 |
241 SkDeque::Iter::Iter() : fCurBlock(NULL), fPos(NULL), fElemSize(0) {} | 241 SkDeque::Iter::Iter() : fCurBlock(nullptr), fPos(nullptr), fElemSize(0) {} |
242 | 242 |
243 SkDeque::Iter::Iter(const SkDeque& d, IterStart startLoc) { | 243 SkDeque::Iter::Iter(const SkDeque& d, IterStart startLoc) { |
244 this->reset(d, startLoc); | 244 this->reset(d, startLoc); |
245 } | 245 } |
246 | 246 |
247 // Due to how reset and next work, next actually returns the current element | 247 // Due to how reset and next work, next actually returns the current element |
248 // pointed to by fPos and then updates fPos to point to the next one. | 248 // pointed to by fPos and then updates fPos to point to the next one. |
249 void* SkDeque::Iter::next() { | 249 void* SkDeque::Iter::next() { |
250 char* pos = fPos; | 250 char* pos = fPos; |
251 | 251 |
252 if (pos) { // if we were valid, try to move to the next setting | 252 if (pos) { // if we were valid, try to move to the next setting |
253 char* next = pos + fElemSize; | 253 char* next = pos + fElemSize; |
254 SkASSERT(next <= fCurBlock->fEnd); | 254 SkASSERT(next <= fCurBlock->fEnd); |
255 if (next == fCurBlock->fEnd) { // exhausted this chunk, move to next | 255 if (next == fCurBlock->fEnd) { // exhausted this chunk, move to next |
256 do { | 256 do { |
257 fCurBlock = fCurBlock->fNext; | 257 fCurBlock = fCurBlock->fNext; |
258 } while (fCurBlock != NULL && fCurBlock->fBegin == NULL); | 258 } while (fCurBlock != nullptr && fCurBlock->fBegin == nullptr); |
259 next = fCurBlock ? fCurBlock->fBegin : NULL; | 259 next = fCurBlock ? fCurBlock->fBegin : nullptr; |
260 } | 260 } |
261 fPos = next; | 261 fPos = next; |
262 } | 262 } |
263 return pos; | 263 return pos; |
264 } | 264 } |
265 | 265 |
266 // Like next, prev actually returns the current element pointed to by fPos and | 266 // Like next, prev actually returns the current element pointed to by fPos and |
267 // then makes fPos point to the previous element. | 267 // then makes fPos point to the previous element. |
268 void* SkDeque::Iter::prev() { | 268 void* SkDeque::Iter::prev() { |
269 char* pos = fPos; | 269 char* pos = fPos; |
270 | 270 |
271 if (pos) { // if we were valid, try to move to the prior setting | 271 if (pos) { // if we were valid, try to move to the prior setting |
272 char* prev = pos - fElemSize; | 272 char* prev = pos - fElemSize; |
273 SkASSERT(prev >= fCurBlock->fBegin - fElemSize); | 273 SkASSERT(prev >= fCurBlock->fBegin - fElemSize); |
274 if (prev < fCurBlock->fBegin) { // exhausted this chunk, move to prior | 274 if (prev < fCurBlock->fBegin) { // exhausted this chunk, move to prior |
275 do { | 275 do { |
276 fCurBlock = fCurBlock->fPrev; | 276 fCurBlock = fCurBlock->fPrev; |
277 } while (fCurBlock != NULL && fCurBlock->fEnd == NULL); | 277 } while (fCurBlock != nullptr && fCurBlock->fEnd == nullptr); |
278 prev = fCurBlock ? fCurBlock->fEnd - fElemSize : NULL; | 278 prev = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr; |
279 } | 279 } |
280 fPos = prev; | 280 fPos = prev; |
281 } | 281 } |
282 return pos; | 282 return pos; |
283 } | 283 } |
284 | 284 |
285 // reset works by skipping through the spare blocks at the start (or end) | 285 // reset works by skipping through the spare blocks at the start (or end) |
286 // of the doubly linked list until a non-empty one is found. The fPos | 286 // of the doubly linked list until a non-empty one is found. The fPos |
287 // member is then set to the first (or last) element in the block. If | 287 // member is then set to the first (or last) element in the block. If |
288 // there are no elements in the deque both fCurBlock and fPos will come | 288 // there are no elements in the deque both fCurBlock and fPos will come |
289 // out of this routine NULL. | 289 // out of this routine nullptr. |
290 void SkDeque::Iter::reset(const SkDeque& d, IterStart startLoc) { | 290 void SkDeque::Iter::reset(const SkDeque& d, IterStart startLoc) { |
291 fElemSize = d.fElemSize; | 291 fElemSize = d.fElemSize; |
292 | 292 |
293 if (kFront_IterStart == startLoc) { | 293 if (kFront_IterStart == startLoc) { |
294 // initialize the iterator to start at the front | 294 // initialize the iterator to start at the front |
295 fCurBlock = d.fFrontBlock; | 295 fCurBlock = d.fFrontBlock; |
296 while (fCurBlock && NULL == fCurBlock->fBegin) { | 296 while (fCurBlock && nullptr == fCurBlock->fBegin) { |
297 fCurBlock = fCurBlock->fNext; | 297 fCurBlock = fCurBlock->fNext; |
298 } | 298 } |
299 fPos = fCurBlock ? fCurBlock->fBegin : NULL; | 299 fPos = fCurBlock ? fCurBlock->fBegin : nullptr; |
300 } else { | 300 } else { |
301 // initialize the iterator to start at the back | 301 // initialize the iterator to start at the back |
302 fCurBlock = d.fBackBlock; | 302 fCurBlock = d.fBackBlock; |
303 while (fCurBlock && NULL == fCurBlock->fEnd) { | 303 while (fCurBlock && nullptr == fCurBlock->fEnd) { |
304 fCurBlock = fCurBlock->fPrev; | 304 fCurBlock = fCurBlock->fPrev; |
305 } | 305 } |
306 fPos = fCurBlock ? fCurBlock->fEnd - fElemSize : NULL; | 306 fPos = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr; |
307 } | 307 } |
308 } | 308 } |
OLD | NEW |