gfx/skia/trunk/src/pdf/SkTSet.h

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 * Copyright 2012 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #ifndef SkTSet_DEFINED
michael@0 9 #define SkTSet_DEFINED
michael@0 10
michael@0 11 #include "SkTSort.h"
michael@0 12 #include "SkTDArray.h"
michael@0 13 #include "SkTypes.h"
michael@0 14
michael@0 15 /** \class SkTSet<T>
michael@0 16
michael@0 17 The SkTSet template class defines a set. Elements are additionally
michael@0 18 guaranteed to be sorted by their insertion order.
michael@0 19 Main operations supported now are: add, merge, find and contains.
michael@0 20
michael@0 21 TSet<T> is mutable.
michael@0 22 */
michael@0 23
michael@0 24 // TODO: Add remove, intersect and difference operations.
michael@0 25 // TODO: Add bench tests.
michael@0 26 template <typename T> class SkTSet {
michael@0 27 public:
michael@0 28 SkTSet() {
michael@0 29 fSetArray = SkNEW(SkTDArray<T>);
michael@0 30 fOrderedArray = SkNEW(SkTDArray<T>);
michael@0 31 }
michael@0 32
michael@0 33 ~SkTSet() {
michael@0 34 SkASSERT(fSetArray);
michael@0 35 SkDELETE(fSetArray);
michael@0 36 SkASSERT(fOrderedArray);
michael@0 37 SkDELETE(fOrderedArray);
michael@0 38 }
michael@0 39
michael@0 40 SkTSet(const SkTSet<T>& src) {
michael@0 41 this->fSetArray = SkNEW_ARGS(SkTDArray<T>, (*src.fSetArray));
michael@0 42 this->fOrderedArray = SkNEW_ARGS(SkTDArray<T>, (*src.fOrderedArray));
michael@0 43 #ifdef SK_DEBUG
michael@0 44 validate();
michael@0 45 #endif
michael@0 46 }
michael@0 47
michael@0 48 SkTSet<T>& operator=(const SkTSet<T>& src) {
michael@0 49 *this->fSetArray = *src.fSetArray;
michael@0 50 *this->fOrderedArray = *src.fOrderedArray;
michael@0 51 #ifdef SK_DEBUG
michael@0 52 validate();
michael@0 53 #endif
michael@0 54 return *this;
michael@0 55 }
michael@0 56
michael@0 57 /** Merges src elements into this, and returns the number of duplicates
michael@0 58 * found. Elements from src will retain their ordering and will be ordered
michael@0 59 * after the elements currently in this set.
michael@0 60 *
michael@0 61 * Implementation note: this uses a 2-stage merge to obtain O(n log n) time.
michael@0 62 * The first stage goes through src.fOrderedArray, checking if
michael@0 63 * this->contains() is false before adding to this.fOrderedArray.
michael@0 64 * The second stage does a standard sorted list merge on the fSetArrays.
michael@0 65 */
michael@0 66 int mergeInto(const SkTSet<T>& src) {
michael@0 67 SkASSERT(fSetArray);
michael@0 68 SkASSERT(fOrderedArray);
michael@0 69
michael@0 70 // Do fOrderedArray merge.
michael@0 71 for (int i = 0; i < src.count(); ++i) {
michael@0 72 if (!contains((*src.fOrderedArray)[i])) {
michael@0 73 fOrderedArray->push((*src.fOrderedArray)[i]);
michael@0 74 }
michael@0 75 }
michael@0 76
michael@0 77 // Do fSetArray merge.
michael@0 78 int duplicates = 0;
michael@0 79
michael@0 80 SkTDArray<T>* fArrayNew = new SkTDArray<T>();
michael@0 81 fArrayNew->setReserve(fOrderedArray->count());
michael@0 82 int i = 0;
michael@0 83 int j = 0;
michael@0 84
michael@0 85 while (i < fSetArray->count() && j < src.count()) {
michael@0 86 if ((*fSetArray)[i] < (*src.fSetArray)[j]) {
michael@0 87 fArrayNew->push((*fSetArray)[i]);
michael@0 88 i++;
michael@0 89 } else if ((*fSetArray)[i] > (*src.fSetArray)[j]) {
michael@0 90 fArrayNew->push((*src.fSetArray)[j]);
michael@0 91 j++;
michael@0 92 } else {
michael@0 93 duplicates++;
michael@0 94 j++; // Skip one of the duplicates.
michael@0 95 }
michael@0 96 }
michael@0 97
michael@0 98 while (i < fSetArray->count()) {
michael@0 99 fArrayNew->push((*fSetArray)[i]);
michael@0 100 i++;
michael@0 101 }
michael@0 102
michael@0 103 while (j < src.count()) {
michael@0 104 fArrayNew->push((*src.fSetArray)[j]);
michael@0 105 j++;
michael@0 106 }
michael@0 107 SkDELETE(fSetArray);
michael@0 108 fSetArray = fArrayNew;
michael@0 109 fArrayNew = NULL;
michael@0 110
michael@0 111 #ifdef SK_DEBUG
michael@0 112 validate();
michael@0 113 #endif
michael@0 114 return duplicates;
michael@0 115 }
michael@0 116
michael@0 117 /** Adds a new element into set and returns false if the element is already
michael@0 118 * in this set.
michael@0 119 */
michael@0 120 bool add(const T& elem) {
michael@0 121 SkASSERT(fSetArray);
michael@0 122 SkASSERT(fOrderedArray);
michael@0 123
michael@0 124 int pos = 0;
michael@0 125 int i = find(elem, &pos);
michael@0 126 if (i >= 0) {
michael@0 127 return false;
michael@0 128 }
michael@0 129 *fSetArray->insert(pos) = elem;
michael@0 130 fOrderedArray->push(elem);
michael@0 131 #ifdef SK_DEBUG
michael@0 132 validate();
michael@0 133 #endif
michael@0 134 return true;
michael@0 135 }
michael@0 136
michael@0 137 /** Returns true if this set is empty.
michael@0 138 */
michael@0 139 bool isEmpty() const {
michael@0 140 SkASSERT(fOrderedArray);
michael@0 141 SkASSERT(fSetArray);
michael@0 142 SkASSERT(fSetArray->isEmpty() == fOrderedArray->isEmpty());
michael@0 143 return fOrderedArray->isEmpty();
michael@0 144 }
michael@0 145
michael@0 146 /** Return the number of elements in the set.
michael@0 147 */
michael@0 148 int count() const {
michael@0 149 SkASSERT(fOrderedArray);
michael@0 150 SkASSERT(fSetArray);
michael@0 151 SkASSERT(fSetArray->count() == fOrderedArray->count());
michael@0 152 return fOrderedArray->count();
michael@0 153 }
michael@0 154
michael@0 155 /** Return the number of bytes in the set: count * sizeof(T).
michael@0 156 */
michael@0 157 size_t bytes() const {
michael@0 158 SkASSERT(fOrderedArray);
michael@0 159 return fOrderedArray->bytes();
michael@0 160 }
michael@0 161
michael@0 162 /** Return the beginning of a set iterator.
michael@0 163 * Elements in the iterator will be sorted ascending.
michael@0 164 */
michael@0 165 const T* begin() const {
michael@0 166 SkASSERT(fOrderedArray);
michael@0 167 return fOrderedArray->begin();
michael@0 168 }
michael@0 169
michael@0 170 /** Return the end of a set iterator.
michael@0 171 */
michael@0 172 const T* end() const {
michael@0 173 SkASSERT(fOrderedArray);
michael@0 174 return fOrderedArray->end();
michael@0 175 }
michael@0 176
michael@0 177 const T& operator[](int index) const {
michael@0 178 SkASSERT(fOrderedArray);
michael@0 179 return (*fOrderedArray)[index];
michael@0 180 }
michael@0 181
michael@0 182 /** Resets the set (deletes memory and initiates an empty set).
michael@0 183 */
michael@0 184 void reset() {
michael@0 185 SkASSERT(fSetArray);
michael@0 186 SkASSERT(fOrderedArray);
michael@0 187 fSetArray->reset();
michael@0 188 fOrderedArray->reset();
michael@0 189 }
michael@0 190
michael@0 191 /** Rewinds the set (preserves memory and initiates an empty set).
michael@0 192 */
michael@0 193 void rewind() {
michael@0 194 SkASSERT(fSetArray);
michael@0 195 SkASSERT(fOrderedArray);
michael@0 196 fSetArray->rewind();
michael@0 197 fOrderedArray->rewind();
michael@0 198 }
michael@0 199
michael@0 200 /** Reserves memory for the set.
michael@0 201 */
michael@0 202 void setReserve(int reserve) {
michael@0 203 SkASSERT(fSetArray);
michael@0 204 SkASSERT(fOrderedArray);
michael@0 205 fSetArray->setReserve(reserve);
michael@0 206 fOrderedArray->setReserve(reserve);
michael@0 207 }
michael@0 208
michael@0 209 /** Returns true if the array contains this element.
michael@0 210 */
michael@0 211 bool contains(const T& elem) const {
michael@0 212 SkASSERT(fSetArray);
michael@0 213 return (this->find(elem) >= 0);
michael@0 214 }
michael@0 215
michael@0 216 /** Copies internal array to destination.
michael@0 217 */
michael@0 218 void copy(T* dst) const {
michael@0 219 SkASSERT(fOrderedArray);
michael@0 220 fOrderedArray->copyRange(dst, 0, fOrderedArray->count());
michael@0 221 }
michael@0 222
michael@0 223 /** Returns a const reference to the internal vector.
michael@0 224 */
michael@0 225 const SkTDArray<T>& toArray() {
michael@0 226 SkASSERT(fOrderedArray);
michael@0 227 return *fOrderedArray;
michael@0 228 }
michael@0 229
michael@0 230 /** Unref all elements in the set.
michael@0 231 */
michael@0 232 void unrefAll() {
michael@0 233 SkASSERT(fSetArray);
michael@0 234 SkASSERT(fOrderedArray);
michael@0 235 fOrderedArray->unrefAll();
michael@0 236 // Also reset the other array, as SkTDArray::unrefAll does an
michael@0 237 // implcit reset
michael@0 238 fSetArray->reset();
michael@0 239 }
michael@0 240
michael@0 241 /** safeUnref all elements in the set.
michael@0 242 */
michael@0 243 void safeUnrefAll() {
michael@0 244 SkASSERT(fSetArray);
michael@0 245 SkASSERT(fOrderedArray);
michael@0 246 fOrderedArray->safeUnrefAll();
michael@0 247 // Also reset the other array, as SkTDArray::safeUnrefAll does an
michael@0 248 // implcit reset
michael@0 249 fSetArray->reset();
michael@0 250 }
michael@0 251
michael@0 252 #ifdef SK_DEBUG
michael@0 253 void validate() const {
michael@0 254 SkASSERT(fSetArray);
michael@0 255 SkASSERT(fOrderedArray);
michael@0 256 fSetArray->validate();
michael@0 257 fOrderedArray->validate();
michael@0 258 SkASSERT(isSorted() && !hasDuplicates() && arraysConsistent());
michael@0 259 }
michael@0 260
michael@0 261 bool hasDuplicates() const {
michael@0 262 for (int i = 0; i < fSetArray->count() - 1; ++i) {
michael@0 263 if ((*fSetArray)[i] == (*fSetArray)[i + 1]) {
michael@0 264 return true;
michael@0 265 }
michael@0 266 }
michael@0 267 return false;
michael@0 268 }
michael@0 269
michael@0 270 bool isSorted() const {
michael@0 271 for (int i = 0; i < fSetArray->count() - 1; ++i) {
michael@0 272 // Use only < operator
michael@0 273 if (!((*fSetArray)[i] < (*fSetArray)[i + 1])) {
michael@0 274 return false;
michael@0 275 }
michael@0 276 }
michael@0 277 return true;
michael@0 278 }
michael@0 279
michael@0 280 /** Checks if fSetArray is consistent with fOrderedArray
michael@0 281 */
michael@0 282 bool arraysConsistent() const {
michael@0 283 if (fSetArray->count() != fOrderedArray->count()) {
michael@0 284 return false;
michael@0 285 }
michael@0 286 if (fOrderedArray->count() == 0) {
michael@0 287 return true;
michael@0 288 }
michael@0 289
michael@0 290 // Copy and sort fOrderedArray, then compare to fSetArray.
michael@0 291 // A O(n log n) algorithm is necessary as O(n^2) will choke some GMs.
michael@0 292 SkAutoMalloc sortedArray(fOrderedArray->bytes());
michael@0 293 T* sortedBase = reinterpret_cast<T*>(sortedArray.get());
michael@0 294 int count = fOrderedArray->count();
michael@0 295 fOrderedArray->copyRange(sortedBase, 0, count);
michael@0 296
michael@0 297 SkTQSort<T>(sortedBase, sortedBase + count - 1);
michael@0 298
michael@0 299 for (int i = 0; i < count; ++i) {
michael@0 300 if (sortedBase[i] != (*fSetArray)[i]) {
michael@0 301 return false;
michael@0 302 }
michael@0 303 }
michael@0 304
michael@0 305 return true;
michael@0 306 }
michael@0 307 #endif
michael@0 308
michael@0 309 private:
michael@0 310 SkTDArray<T>* fSetArray; // Sorted by pointer address for fast
michael@0 311 // lookup.
michael@0 312 SkTDArray<T>* fOrderedArray; // Sorted by insertion order for
michael@0 313 // deterministic output.
michael@0 314
michael@0 315 /** Returns the index in fSetArray where an element was found.
michael@0 316 * Returns -1 if the element was not found, and it fills *posToInsertSorted
michael@0 317 * with the index of the place where elem should be inserted to preserve the
michael@0 318 * internal array sorted.
michael@0 319 * If element was found, *posToInsertSorted is undefined.
michael@0 320 */
michael@0 321 int find(const T& elem, int* posToInsertSorted = NULL) const {
michael@0 322 SkASSERT(fSetArray);
michael@0 323
michael@0 324 if (fSetArray->count() == 0) {
michael@0 325 if (posToInsertSorted) {
michael@0 326 *posToInsertSorted = 0;
michael@0 327 }
michael@0 328 return -1;
michael@0 329 }
michael@0 330 int iMin = 0;
michael@0 331 int iMax = fSetArray->count();
michael@0 332
michael@0 333 while (iMin < iMax - 1) {
michael@0 334 int iMid = (iMin + iMax) / 2;
michael@0 335 if (elem < (*fSetArray)[iMid]) {
michael@0 336 iMax = iMid;
michael@0 337 } else {
michael@0 338 iMin = iMid;
michael@0 339 }
michael@0 340 }
michael@0 341 if (elem == (*fSetArray)[iMin]) {
michael@0 342 return iMin;
michael@0 343 }
michael@0 344 if (posToInsertSorted) {
michael@0 345 if (elem < (*fSetArray)[iMin]) {
michael@0 346 *posToInsertSorted = iMin;
michael@0 347 } else {
michael@0 348 *posToInsertSorted = iMin + 1;
michael@0 349 }
michael@0 350 }
michael@0 351
michael@0 352 return -1;
michael@0 353 }
michael@0 354 };
michael@0 355
michael@0 356 #endif

mercurial