• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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