| 1 |  | 
|---|
| 2 | /* | 
|---|
| 3 | * Copyright 2006 The Android Open Source Project | 
|---|
| 4 | * | 
|---|
| 5 | * Use of this source code is governed by a BSD-style license that can be | 
|---|
| 6 | * found in the LICENSE file. | 
|---|
| 7 | */ | 
|---|
| 8 |  | 
|---|
| 9 |  | 
|---|
| 10 | #ifndef SkTSearch_DEFINED | 
|---|
| 11 | #define SkTSearch_DEFINED | 
|---|
| 12 |  | 
|---|
| 13 | #include "include/core/SkTypes.h" | 
|---|
| 14 |  | 
|---|
| 15 | /** | 
|---|
| 16 | *  All of the SkTSearch variants want to return the index (0...N-1) of the | 
|---|
| 17 | *  found element, or the bit-not of where to insert the element. | 
|---|
| 18 | * | 
|---|
| 19 | *  At a simple level, if the return value is negative, it was not found. | 
|---|
| 20 | * | 
|---|
| 21 | *  For clients that want to insert the new element if it was not found, use | 
|---|
| 22 | *  the following logic: | 
|---|
| 23 | * | 
|---|
| 24 | *  int index = SkTSearch(...); | 
|---|
| 25 | *  if (index >= 0) { | 
|---|
| 26 | *      // found at index | 
|---|
| 27 | *  } else { | 
|---|
| 28 | *      index = ~index; // now we are positive | 
|---|
| 29 | *      // insert at index | 
|---|
| 30 | *  } | 
|---|
| 31 | */ | 
|---|
| 32 |  | 
|---|
| 33 |  | 
|---|
| 34 | // The most general form of SkTSearch takes an array of T and a key of type K. A functor, less, is | 
|---|
| 35 | // used to perform comparisons. It has two function operators: | 
|---|
| 36 | //      bool operator() (const T& t, const K& k) | 
|---|
| 37 | //      bool operator() (const K& t, const T& k) | 
|---|
| 38 | template <typename T, typename K, typename LESS> | 
|---|
| 39 | int SkTSearch(const T base[], int count, const K& key, size_t elemSize, LESS& less) | 
|---|
| 40 | { | 
|---|
| 41 | SkASSERT(count >= 0); | 
|---|
| 42 | if (count <= 0) { | 
|---|
| 43 | return ~0; | 
|---|
| 44 | } | 
|---|
| 45 |  | 
|---|
| 46 | SkASSERT(base != nullptr); // base may be nullptr if count is zero | 
|---|
| 47 |  | 
|---|
| 48 | int lo = 0; | 
|---|
| 49 | int hi = count - 1; | 
|---|
| 50 |  | 
|---|
| 51 | while (lo < hi) { | 
|---|
| 52 | int mid = lo + ((hi - lo) >> 1); | 
|---|
| 53 | const T* elem = (const T*)((const char*)base + mid * elemSize); | 
|---|
| 54 |  | 
|---|
| 55 | if (less(*elem, key)) | 
|---|
| 56 | lo = mid + 1; | 
|---|
| 57 | else | 
|---|
| 58 | hi = mid; | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | const T* elem = (const T*)((const char*)base + hi * elemSize); | 
|---|
| 62 | if (less(*elem, key)) { | 
|---|
| 63 | hi += 1; | 
|---|
| 64 | hi = ~hi; | 
|---|
| 65 | } else if (less(key, *elem)) { | 
|---|
| 66 | hi = ~hi; | 
|---|
| 67 | } | 
|---|
| 68 | return hi; | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | // Adapts a less-than function to a functor. | 
|---|
| 72 | template <typename T, bool (LESS)(const T&, const T&)> struct SkTLessFunctionToFunctorAdaptor { | 
|---|
| 73 | bool operator()(const T& a, const T& b) { return LESS(a, b); } | 
|---|
| 74 | }; | 
|---|
| 75 |  | 
|---|
| 76 | // Specialization for case when T==K and the caller wants to use a function rather than functor. | 
|---|
| 77 | template <typename T, bool (LESS)(const T&, const T&)> | 
|---|
| 78 | int SkTSearch(const T base[], int count, const T& target, size_t elemSize) { | 
|---|
| 79 | static SkTLessFunctionToFunctorAdaptor<T, LESS> functor; | 
|---|
| 80 | return SkTSearch(base, count, target, elemSize, functor); | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | // Adapts operator < to a functor. | 
|---|
| 84 | template <typename T> struct SkTLessFunctor { | 
|---|
| 85 | bool operator()(const T& a, const T& b) { return a < b; } | 
|---|
| 86 | }; | 
|---|
| 87 |  | 
|---|
| 88 | // Specialization for T==K, compare using op <. | 
|---|
| 89 | template <typename T> | 
|---|
| 90 | int SkTSearch(const T base[], int count, const T& target, size_t elemSize) { | 
|---|
| 91 | static SkTLessFunctor<T> functor; | 
|---|
| 92 | return SkTSearch(base, count, target, elemSize, functor); | 
|---|
| 93 | } | 
|---|
| 94 |  | 
|---|
| 95 | // Similar to SkLessFunctionToFunctorAdaptor but makes the functor interface take T* rather than T. | 
|---|
| 96 | template <typename T, bool (LESS)(const T&, const T&)> struct SkTLessFunctionToPtrFunctorAdaptor { | 
|---|
| 97 | bool operator() (const T* t, const T* k) { return LESS(*t, *k); } | 
|---|
| 98 | }; | 
|---|
| 99 |  | 
|---|
| 100 | // Specialization for case where domain is an array of T* and the key value is a T*, and you want | 
|---|
| 101 | // to compare the T objects, not the pointers. | 
|---|
| 102 | template <typename T, bool (LESS)(const T&, const T&)> | 
|---|
| 103 | int SkTSearch(T* base[], int count, T* target, size_t elemSize) { | 
|---|
| 104 | static SkTLessFunctionToPtrFunctorAdaptor<T, LESS> functor; | 
|---|
| 105 | return SkTSearch(base, count, target, elemSize, functor); | 
|---|
| 106 | } | 
|---|
| 107 |  | 
|---|
| 108 | int SkStrSearch(const char*const* base, int count, const char target[], | 
|---|
| 109 | size_t target_len, size_t elemSize); | 
|---|
| 110 | int SkStrSearch(const char*const* base, int count, const char target[], | 
|---|
| 111 | size_t elemSize); | 
|---|
| 112 |  | 
|---|
| 113 | /** Like SkStrSearch, but treats target as if it were all lower-case. Assumes that | 
|---|
| 114 | base points to a table of lower-case strings. | 
|---|
| 115 | */ | 
|---|
| 116 | int SkStrLCSearch(const char*const* base, int count, const char target[], | 
|---|
| 117 | size_t target_len, size_t elemSize); | 
|---|
| 118 | int SkStrLCSearch(const char*const* base, int count, const char target[], | 
|---|
| 119 | size_t elemSize); | 
|---|
| 120 |  | 
|---|
| 121 | /** Helper class to convert a string to lower-case, but only modifying the ascii | 
|---|
| 122 | characters. This makes the routine very fast and never changes the string | 
|---|
| 123 | length, but it is not suitable for linguistic purposes. Normally this is | 
|---|
| 124 | used for buiding and searching string tables. | 
|---|
| 125 | */ | 
|---|
| 126 | class SkAutoAsciiToLC { | 
|---|
| 127 | public: | 
|---|
| 128 | SkAutoAsciiToLC(const char str[], size_t len = (size_t)-1); | 
|---|
| 129 | ~SkAutoAsciiToLC(); | 
|---|
| 130 |  | 
|---|
| 131 | const char* lc() const { return fLC; } | 
|---|
| 132 | size_t      length() const { return fLength; } | 
|---|
| 133 |  | 
|---|
| 134 | private: | 
|---|
| 135 | char*   fLC;    // points to either the heap or fStorage | 
|---|
| 136 | size_t  fLength; | 
|---|
| 137 | enum { | 
|---|
| 138 | STORAGE = 64 | 
|---|
| 139 | }; | 
|---|
| 140 | char    fStorage[STORAGE+1]; | 
|---|
| 141 | }; | 
|---|
| 142 |  | 
|---|
| 143 | // Helper when calling qsort with a compare proc that has typed its arguments | 
|---|
| 144 | #define SkCastForQSort(compare) reinterpret_cast<int (*)(const void*, const void*)>(compare) | 
|---|
| 145 |  | 
|---|
| 146 | #endif | 
|---|
| 147 |  | 
|---|