1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkTDict_DEFINED 18 #define SkTDict_DEFINED 19 20 #include "SkChunkAlloc.h" 21 #include "SkTSearch.h" 22 #include "SkTDArray.h" 23 24 template <typename T> class SkTDict : SkNoncopyable { 25 public: SkTDict(size_t minStringAlloc)26 SkTDict(size_t minStringAlloc) : fStrings(minStringAlloc) {} 27 reset()28 void reset() 29 { 30 fArray.reset(); 31 fStrings.reset(); 32 } 33 count()34 int count() const { return fArray.count(); } 35 set(const char name[],const T & value)36 bool set(const char name[], const T& value) 37 { 38 return set(name, strlen(name), value); 39 } 40 set(const char name[],size_t len,const T & value)41 bool set(const char name[], size_t len, const T& value) 42 { 43 SkASSERT(name); 44 45 int index = this->find_index(name, len); 46 47 if (index >= 0) 48 { 49 fArray[index].fValue = value; 50 return false; 51 } 52 else 53 { 54 Pair* pair = fArray.insert(~index); 55 char* copy = (char*)fStrings.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType); 56 memcpy(copy, name, len); 57 copy[len] = '\0'; 58 pair->fName = copy; 59 pair->fValue = value; 60 return true; 61 } 62 } 63 find(const char name[])64 bool find(const char name[]) const 65 { 66 return this->find_index(name) >= 0; 67 } 68 find(const char name[],size_t len)69 bool find(const char name[], size_t len) const 70 { 71 return this->find_index(name, len) >= 0; 72 } 73 find(const char name[],T * value)74 bool find(const char name[], T* value) const 75 { 76 return find(name, strlen(name), value); 77 } 78 find(const char name[],size_t len,T * value)79 bool find(const char name[], size_t len, T* value) const 80 { 81 int index = this->find_index(name, len); 82 83 if (index >= 0) 84 { 85 if (value) 86 *value = fArray[index].fValue; 87 return true; 88 } 89 return false; 90 } 91 findKey(T & value,const char ** name)92 bool findKey(T& value, const char** name) const 93 { 94 Pair* end = fArray.end(); 95 for (Pair* pair = fArray.begin(); pair < end; pair++) { 96 if (pair->fValue != value) 97 continue; 98 *name = pair->fName; 99 return true; 100 } 101 return false; 102 } 103 104 public: 105 struct Pair { 106 const char* fName; 107 T fValue; 108 109 friend int operator<(const Pair& a, const Pair& b) 110 { 111 return strcmp(a.fName, b.fName); 112 } 113 friend int operator!=(const Pair& a, const Pair& b) 114 { 115 return strcmp(a.fName, b.fName); 116 } 117 }; 118 friend class Iter; 119 120 public: 121 class Iter { 122 public: Iter(const SkTDict<T> & dict)123 Iter(const SkTDict<T>& dict) 124 { 125 fIter = dict.fArray.begin(); 126 fStop = dict.fArray.end(); 127 } next(T * value)128 const char* next(T* value) 129 { 130 const char* name = NULL; 131 if (fIter < fStop) 132 { 133 name = fIter->fName; 134 if (value) 135 *value = fIter->fValue; 136 fIter += 1; 137 } 138 return name; 139 } 140 private: 141 Pair* fIter; 142 Pair* fStop; 143 }; 144 145 private: 146 SkTDArray<Pair> fArray; 147 SkChunkAlloc fStrings; 148 find_index(const char name[])149 int find_index(const char name[]) const 150 { 151 return find_index(name, strlen(name)); 152 } 153 find_index(const char name[],size_t len)154 int find_index(const char name[], size_t len) const 155 { 156 SkASSERT(name); 157 158 int count = fArray.count(); 159 int index = ~0; 160 161 if (count) 162 index = SkStrSearch(&fArray.begin()->fName, count, name, len, sizeof(Pair)); 163 return index; 164 } 165 friend class Iter; 166 }; 167 168 #endif 169 170