• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/views/SkMetaData.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkMetaData.h"
19 
SkMetaData()20 SkMetaData::SkMetaData() : fRec(NULL)
21 {
22 }
23 
SkMetaData(const SkMetaData & src)24 SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL)
25 {
26     *this = src;
27 }
28 
~SkMetaData()29 SkMetaData::~SkMetaData()
30 {
31     this->reset();
32 }
33 
reset()34 void SkMetaData::reset()
35 {
36     Rec* rec = fRec;
37     while (rec)
38     {
39         Rec* next = rec->fNext;
40         Rec::Free(rec);
41         rec = next;
42     }
43     fRec = NULL;
44 }
45 
operator =(const SkMetaData & src)46 SkMetaData& SkMetaData::operator=(const SkMetaData& src)
47 {
48     this->reset();
49 
50     const Rec* rec = src.fRec;
51     while (rec)
52     {
53         this->set(rec->name(), rec->data(), rec->fDataLen, (Type)rec->fType, rec->fDataCount);
54         rec = rec->fNext;
55     }
56     return *this;
57 }
58 
setS32(const char name[],int32_t value)59 void SkMetaData::setS32(const char name[], int32_t value)
60 {
61     (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
62 }
63 
setScalar(const char name[],SkScalar value)64 void SkMetaData::setScalar(const char name[], SkScalar value)
65 {
66     (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
67 }
68 
setScalars(const char name[],int count,const SkScalar values[])69 SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[])
70 {
71     SkASSERT(count > 0);
72     if (count > 0)
73         return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count);
74     return NULL;
75 }
76 
setString(const char name[],const char value[])77 void SkMetaData::setString(const char name[], const char value[])
78 {
79     (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1);
80 }
81 
setPtr(const char name[],void * ptr)82 void SkMetaData::setPtr(const char name[], void* ptr)
83 {
84     (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1);
85 }
86 
setBool(const char name[],bool value)87 void SkMetaData::setBool(const char name[], bool value)
88 {
89     (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
90 }
91 
set(const char name[],const void * data,size_t dataSize,Type type,int count)92 void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
93 {
94     SkASSERT(name);
95     SkASSERT(dataSize);
96     SkASSERT(count > 0);
97 
98     (void)this->remove(name, type);
99 
100     size_t  len = strlen(name);
101     Rec*    rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1);
102 
103 #ifndef SK_DEBUG
104     rec->fType = SkToU8(type);
105 #else
106     rec->fType = type;
107 #endif
108     rec->fDataLen = SkToU8(dataSize);
109     rec->fDataCount = SkToU16(count);
110     if (data)
111         memcpy(rec->data(), data, dataSize * count);
112     memcpy(rec->name(), name, len + 1);
113 
114 #ifdef SK_DEBUG
115     rec->fName = rec->name();
116     switch (type) {
117     case kS32_Type:
118         rec->fData.fS32 = *(const int32_t*)rec->data();
119         break;
120     case kScalar_Type:
121         rec->fData.fScalar = *(const SkScalar*)rec->data();
122         break;
123     case kString_Type:
124         rec->fData.fString = (const char*)rec->data();
125         break;
126     case kPtr_Type:
127         rec->fData.fPtr = *(void**)rec->data();
128         break;
129     case kBool_Type:
130         rec->fData.fBool = *(const bool*)rec->data();
131         break;
132     default:
133         SkASSERT(!"bad type");
134         break;
135     }
136 #endif
137 
138     rec->fNext = fRec;
139     fRec = rec;
140     return rec->data();
141 }
142 
findS32(const char name[],int32_t * value) const143 bool SkMetaData::findS32(const char name[], int32_t* value) const
144 {
145     const Rec* rec = this->find(name, kS32_Type);
146     if (rec)
147     {
148         SkASSERT(rec->fDataCount == 1);
149         if (value)
150             *value = *(const int32_t*)rec->data();
151         return true;
152     }
153     return false;
154 }
155 
findScalar(const char name[],SkScalar * value) const156 bool SkMetaData::findScalar(const char name[], SkScalar* value) const
157 {
158     const Rec* rec = this->find(name, kScalar_Type);
159     if (rec)
160     {
161         SkASSERT(rec->fDataCount == 1);
162         if (value)
163             *value = *(const SkScalar*)rec->data();
164         return true;
165     }
166     return false;
167 }
168 
findScalars(const char name[],int * count,SkScalar values[]) const169 const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const
170 {
171     const Rec* rec = this->find(name, kScalar_Type);
172     if (rec)
173     {
174         if (count)
175             *count = rec->fDataCount;
176         if (values)
177             memcpy(values, rec->data(), rec->fDataCount * rec->fDataLen);
178         return (const SkScalar*)rec->data();
179     }
180     return NULL;
181 }
182 
findPtr(const char name[],void ** value) const183 bool SkMetaData::findPtr(const char name[], void** value) const
184 {
185     const Rec* rec = this->find(name, kPtr_Type);
186     if (rec)
187     {
188         SkASSERT(rec->fDataCount == 1);
189         if (value)
190             *value = *(void**)rec->data();
191         return true;
192     }
193     return false;
194 }
195 
findString(const char name[]) const196 const char* SkMetaData::findString(const char name[]) const
197 {
198     const Rec* rec = this->find(name, kString_Type);
199     SkASSERT(rec == NULL || rec->fDataLen == sizeof(char));
200     return rec ? (const char*)rec->data() : NULL;
201 }
202 
findBool(const char name[],bool * value) const203 bool SkMetaData::findBool(const char name[], bool* value) const
204 {
205     const Rec* rec = this->find(name, kBool_Type);
206     if (rec)
207     {
208         SkASSERT(rec->fDataCount == 1);
209         if (value)
210             *value = *(const bool*)rec->data();
211         return true;
212     }
213     return false;
214 }
215 
find(const char name[],Type type) const216 const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
217 {
218     const Rec* rec = fRec;
219     while (rec)
220     {
221         if (rec->fType == type && !strcmp(rec->name(), name))
222             return rec;
223         rec = rec->fNext;
224     }
225     return NULL;
226 }
227 
remove(const char name[],Type type)228 bool SkMetaData::remove(const char name[], Type type)
229 {
230     Rec* rec = fRec;
231     Rec* prev = NULL;
232     while (rec)
233     {
234         Rec* next = rec->fNext;
235         if (rec->fType == type && !strcmp(rec->name(), name))
236         {
237             if (prev)
238                 prev->fNext = next;
239             else
240                 fRec = next;
241             Rec::Free(rec);
242             return true;
243         }
244         prev = rec;
245         rec = next;
246     }
247     return false;
248 }
249 
removeS32(const char name[])250 bool SkMetaData::removeS32(const char name[])
251 {
252     return this->remove(name, kS32_Type);
253 }
254 
removeScalar(const char name[])255 bool SkMetaData::removeScalar(const char name[])
256 {
257     return this->remove(name, kScalar_Type);
258 }
259 
removeString(const char name[])260 bool SkMetaData::removeString(const char name[])
261 {
262     return this->remove(name, kString_Type);
263 }
264 
removePtr(const char name[])265 bool SkMetaData::removePtr(const char name[])
266 {
267     return this->remove(name, kPtr_Type);
268 }
269 
removeBool(const char name[])270 bool SkMetaData::removeBool(const char name[])
271 {
272     return this->remove(name, kBool_Type);
273 }
274 
275 ///////////////////////////////////////////////////////////////////////////////////
276 
Iter(const SkMetaData & metadata)277 SkMetaData::Iter::Iter(const SkMetaData& metadata)
278 {
279     fRec = metadata.fRec;
280 }
281 
reset(const SkMetaData & metadata)282 void SkMetaData::Iter::reset(const SkMetaData& metadata)
283 {
284     fRec = metadata.fRec;
285 }
286 
next(SkMetaData::Type * t,int * count)287 const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count)
288 {
289     const char* name = NULL;
290 
291     if (fRec)
292     {
293         if (t)
294             *t = (SkMetaData::Type)fRec->fType;
295         if (count)
296             *count = fRec->fDataCount;
297         name = fRec->name();
298 
299         fRec = fRec->fNext;
300     }
301     return name;
302 }
303 
304 ///////////////////////////////////////////////////////////////////////////////////
305 
Alloc(size_t size)306 SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size)
307 {
308     return (Rec*)sk_malloc_throw(size);
309 }
310 
Free(Rec * rec)311 void SkMetaData::Rec::Free(Rec* rec)
312 {
313     sk_free(rec);
314 }
315 
316 ///////////////////////////////////////////////////////////////////////////////////
317 ///////////////////////////////////////////////////////////////////////////////////
318 
319 #ifdef SK_DEBUG
320 
UnitTest()321 void SkMetaData::UnitTest()
322 {
323 #ifdef SK_SUPPORT_UNITTEST
324     SkMetaData  m1;
325 
326     SkASSERT(!m1.findS32("int"));
327     SkASSERT(!m1.findScalar("scalar"));
328     SkASSERT(!m1.findString("hello"));
329     SkASSERT(!m1.removeS32("int"));
330     SkASSERT(!m1.removeScalar("scalar"));
331     SkASSERT(!m1.removeString("hello"));
332     SkASSERT(!m1.removeString("true"));
333     SkASSERT(!m1.removeString("false"));
334 
335     m1.setS32("int", 12345);
336     m1.setScalar("scalar", SK_Scalar1 * 42);
337     m1.setString("hello", "world");
338     m1.setPtr("ptr", &m1);
339     m1.setBool("true", true);
340     m1.setBool("false", false);
341 
342     int32_t     n;
343     SkScalar    s;
344 
345     m1.setScalar("scalar", SK_Scalar1/2);
346 
347     SkASSERT(m1.findS32("int", &n) && n == 12345);
348     SkASSERT(m1.findScalar("scalar", &s) && s == SK_Scalar1/2);
349     SkASSERT(!strcmp(m1.findString("hello"), "world"));
350     SkASSERT(m1.hasBool("true", true));
351     SkASSERT(m1.hasBool("false", false));
352 
353     Iter    iter(m1);
354     const char* name;
355 
356     static const struct {
357         const char*         fName;
358         SkMetaData::Type    fType;
359         int                 fCount;
360     } gElems[] = {
361         { "int",    SkMetaData::kS32_Type,      1 },
362         { "scalar", SkMetaData::kScalar_Type,   1 },
363         { "ptr",    SkMetaData::kPtr_Type,      1 },
364         { "hello",  SkMetaData::kString_Type,   sizeof("world") },
365         { "true",   SkMetaData::kBool_Type,     1 },
366         { "false",  SkMetaData::kBool_Type,     1 }
367     };
368 
369     int                 loop = 0;
370     int count;
371     SkMetaData::Type    t;
372     while ((name = iter.next(&t, &count)) != NULL)
373     {
374         int match = 0;
375         for (unsigned i = 0; i < SK_ARRAY_COUNT(gElems); i++)
376         {
377             if (!strcmp(name, gElems[i].fName))
378             {
379                 match += 1;
380                 SkASSERT(gElems[i].fType == t);
381                 SkASSERT(gElems[i].fCount == count);
382             }
383         }
384         SkASSERT(match == 1);
385         loop += 1;
386     }
387     SkASSERT(loop == SK_ARRAY_COUNT(gElems));
388 
389     SkASSERT(m1.removeS32("int"));
390     SkASSERT(m1.removeScalar("scalar"));
391     SkASSERT(m1.removeString("hello"));
392     SkASSERT(m1.removeBool("true"));
393     SkASSERT(m1.removeBool("false"));
394 
395     SkASSERT(!m1.findS32("int"));
396     SkASSERT(!m1.findScalar("scalar"));
397     SkASSERT(!m1.findString("hello"));
398     SkASSERT(!m1.findBool("true"));
399     SkASSERT(!m1.findBool("false"));
400 #endif
401 }
402 
403 #endif
404 
405 
406