1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkTDict_DEFINED
9 #define SkTDict_DEFINED
10 
11 #include "SkChunkAlloc.h"
12 #include "SkTSearch.h"
13 #include "SkTDArray.h"
14 
15 template <typename T> class SkTDict : SkNoncopyable {
16 public:
SkTDict(size_t minStringAlloc)17     SkTDict(size_t minStringAlloc) : fStrings(minStringAlloc) {}
18 
reset()19     void reset() {
20         fArray.reset();
21         fStrings.reset();
22     }
23 
count()24     int count() const { return fArray.count(); }
25 
set(const char name[],const T & value)26     bool set(const char name[], const T& value) {
27         return set(name, strlen(name), value);
28     }
29 
set(const char name[],size_t len,const T & value)30     bool set(const char name[], size_t len, const T& value) {
31         SkASSERT(name);
32 
33         int index = this->find_index(name, len);
34 
35         if (index >= 0) {
36             fArray[index].fValue = value;
37             return false;
38         } else {
39             Pair*   pair = fArray.insert(~index);
40             char*   copy = (char*)fStrings.alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
41             memcpy(copy, name, len);
42             copy[len] = '\0';
43             pair->fName = copy;
44             pair->fValue = value;
45             return true;
46         }
47     }
48 
find(const char name[])49     bool find(const char name[]) const {
50         return this->find_index(name) >= 0;
51     }
52 
find(const char name[],size_t len)53     bool find(const char name[], size_t len) const {
54         return this->find_index(name, len) >= 0;
55     }
56 
find(const char name[],T * value)57     bool find(const char name[], T* value) const {
58         return find(name, strlen(name), value);
59     }
60 
find(const char name[],size_t len,T * value)61     bool find(const char name[], size_t len, T* value) const {
62         int index = this->find_index(name, len);
63 
64         if (index >= 0) {
65             if (value) {
66                 *value = fArray[index].fValue;
67             }
68             return true;
69         }
70         return false;
71     }
72 
findKey(T & value,const char ** name)73     bool findKey(T& value, const char** name) const {
74         const Pair* end = fArray.end();
75         for (const Pair* pair = fArray.begin(); pair < end; pair++) {
76             if (pair->fValue != value) {
77                 continue;
78             }
79             *name = pair->fName;
80             return true;
81         }
82         return false;
83     }
84 
85 public:
86     struct Pair {
87         const char* fName;
88         T           fValue;
89 
90         friend int operator<(const Pair& a, const Pair& b) {
91             return strcmp(a.fName, b.fName);
92         }
93 
94         friend int operator!=(const Pair& a, const Pair& b) {
95             return strcmp(a.fName, b.fName);
96         }
97     };
98     friend class Iter;
99 
100 public:
101     class Iter {
102     public:
Iter(const SkTDict<T> & dict)103         Iter(const SkTDict<T>& dict) {
104             fIter = dict.fArray.begin();
105             fStop = dict.fArray.end();
106         }
107 
next(T * value)108         const char* next(T* value) {
109             const char* name = NULL;
110             if (fIter < fStop) {
111                 name = fIter->fName;
112                 if (value) {
113                     *value = fIter->fValue;
114                 }
115                 fIter += 1;
116             }
117             return name;
118         }
119     private:
120         const Pair*   fIter;
121         const Pair*   fStop;
122     };
123 
124 private:
125     SkTDArray<Pair> fArray;
126     SkChunkAlloc    fStrings;
127 
find_index(const char name[])128     int find_index(const char name[]) const {
129         return find_index(name, strlen(name));
130     }
131 
find_index(const char name[],size_t len)132     int find_index(const char name[], size_t len) const {
133         SkASSERT(name);
134 
135         int count = fArray.count();
136         int index = ~0;
137 
138         if (count) {
139             index = SkStrSearch(&fArray.begin()->fName, count, name, len, sizeof(Pair));
140         }
141         return index;
142     }
143     friend class Iter;
144 };
145 
146 #endif
147