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