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