/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/
struct SkDeque::Block {
Block* fNext;
Block* fPrev; char* fBegin; // start of used section in this chunk char* fEnd; // end of used section in this chunk char* fStop; // end of the allocated chunk
if (nullptr == first->fBegin) {
INIT_CHUNK:
first->fEnd = first->fStop;
begin = first->fStop - fElemSize;
} else {
begin = first->fBegin - fElemSize; if (begin < first->start()) { // no more room in this chunk // should we alloc more as we accumulate more elements?
first = this->allocateBlock(fAllocCount);
first->fNext = fFrontBlock;
fFrontBlock->fPrev = first;
fFrontBlock = first; goto INIT_CHUNK;
}
}
if (nullptr == last->fBegin) {
INIT_CHUNK:
last->fBegin = last->start();
end = last->fBegin + fElemSize;
} else {
end = last->fEnd + fElemSize; if (end > last->fStop) { // no more room in this chunk // should we alloc more as we accumulate more elements?
last = this->allocateBlock(fAllocCount);
last->fPrev = fBackBlock;
fBackBlock->fNext = last;
fBackBlock = last; goto INIT_CHUNK;
}
}
if (first->fBegin == nullptr) { // we were marked empty from before
first = first->fNext;
SkASSERT(first != nullptr); // else we popped too far
first->fPrev = nullptr;
this->freeBlock(fFrontBlock);
fFrontBlock = first;
}
char* begin = first->fBegin + fElemSize;
SkASSERT(begin <= first->fEnd);
if (last->fEnd == nullptr) { // we were marked empty from before
last = last->fPrev;
SkASSERT(last != nullptr); // else we popped too far
last->fNext = nullptr;
this->freeBlock(fBackBlock);
fBackBlock = last;
}
char* end = last->fEnd - fElemSize;
SkASSERT(end >= last->fBegin);
// Due to how reset and next work, next actually returns the current element // pointed to by fPos and then updates fPos to point to the next one. void* SkDeque::Iter::next() { char* pos = fPos;
if (pos) { // if we were valid, try to move to the next setting char* next = pos + fElemSize;
SkASSERT(next <= fCurBlock->fEnd); if (next == fCurBlock->fEnd) { // exhausted this chunk, move to next do {
fCurBlock = fCurBlock->fNext;
} while (fCurBlock != nullptr && fCurBlock->fBegin == nullptr);
next = fCurBlock ? fCurBlock->fBegin : nullptr;
}
fPos = next;
} return pos;
}
// Like next, prev actually returns the current element pointed to by fPos and // then makes fPos point to the previous element. void* SkDeque::Iter::prev() { char* pos = fPos;
if (pos) { // if we were valid, try to move to the prior setting char* prev = pos - fElemSize;
SkASSERT(prev >= fCurBlock->fBegin - fElemSize); if (prev < fCurBlock->fBegin) { // exhausted this chunk, move to prior do {
fCurBlock = fCurBlock->fPrev;
} while (fCurBlock != nullptr && fCurBlock->fEnd == nullptr);
prev = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr;
}
fPos = prev;
} return pos;
}
// reset works by skipping through the spare blocks at the start (or end) // of the doubly linked list until a non-empty one is found. The fPos // member is then set to the first (or last) element in the block. If // there are no elements in the deque both fCurBlock and fPos will come // out of this routine nullptr. void SkDeque::Iter::reset(const SkDeque& d, IterStart startLoc) {
fElemSize = d.fElemSize;
if (kFront_IterStart == startLoc) { // initialize the iterator to start at the front
fCurBlock = d.fFrontBlock; while (fCurBlock && nullptr == fCurBlock->fBegin) {
fCurBlock = fCurBlock->fNext;
}
fPos = fCurBlock ? fCurBlock->fBegin : nullptr;
} else { // initialize the iterator to start at the back
fCurBlock = d.fBackBlock; while (fCurBlock && nullptr == fCurBlock->fEnd) {
fCurBlock = fCurBlock->fPrev;
}
fPos = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.