gfx/skia/trunk/src/core/SkDeque.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial