blob: 1d423a40ed53e5f4f1cb57c30050ec888cda9b07 [file] [log] [blame]
croachrose48ede9b2006-11-08 19:24:48 +00001/* libs/graphics/views/SkMetaData.cpp
2**
3** Copyright 2006, Google Inc.
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
croachrose0f87cd82006-09-20 15:47:42 +000018#include "SkMetaData.h"
19
20SkMetaData::SkMetaData() : fRec(NULL)
21{
22}
23
24SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL)
25{
croachrose48ede9b2006-11-08 19:24:48 +000026 *this = src;
croachrose0f87cd82006-09-20 15:47:42 +000027}
28
29SkMetaData::~SkMetaData()
30{
croachrose48ede9b2006-11-08 19:24:48 +000031 this->reset();
croachrose0f87cd82006-09-20 15:47:42 +000032}
33
34void SkMetaData::reset()
35{
croachrose48ede9b2006-11-08 19:24:48 +000036 Rec* rec = fRec;
37 while (rec)
38 {
39 Rec* next = rec->fNext;
40 Rec::Free(rec);
41 rec = next;
42 }
43 fRec = NULL;
croachrose0f87cd82006-09-20 15:47:42 +000044}
45
croachrose48ede9b2006-11-08 19:24:48 +000046SkMetaData& SkMetaData::operator=(const SkMetaData& src)
croachrose0f87cd82006-09-20 15:47:42 +000047{
croachrose48ede9b2006-11-08 19:24:48 +000048 this->reset();
croachrose0f87cd82006-09-20 15:47:42 +000049
croachrose48ede9b2006-11-08 19:24:48 +000050 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;
croachrose0f87cd82006-09-20 15:47:42 +000057}
58
59void SkMetaData::setS32(const char name[], int32_t value)
60{
croachrose48ede9b2006-11-08 19:24:48 +000061 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
croachrose0f87cd82006-09-20 15:47:42 +000062}
63
64void SkMetaData::setScalar(const char name[], SkScalar value)
65{
croachrose48ede9b2006-11-08 19:24:48 +000066 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
croachrose0f87cd82006-09-20 15:47:42 +000067}
68
69SkScalar* SkMetaData::setScalars(const char name[], int count, const SkScalar values[])
70{
croachrose48ede9b2006-11-08 19:24:48 +000071 SkASSERT(count > 0);
72 if (count > 0)
73 return (SkScalar*)this->set(name, values, sizeof(SkScalar), kScalar_Type, count);
74 return NULL;
croachrose0f87cd82006-09-20 15:47:42 +000075}
76
77void SkMetaData::setString(const char name[], const char value[])
78{
croachrose48ede9b2006-11-08 19:24:48 +000079 (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1);
croachrose0f87cd82006-09-20 15:47:42 +000080}
81
82void SkMetaData::setPtr(const char name[], void* ptr)
83{
croachrose48ede9b2006-11-08 19:24:48 +000084 (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1);
croachrose0f87cd82006-09-20 15:47:42 +000085}
86
87void SkMetaData::setBool(const char name[], bool value)
88{
croachrose48ede9b2006-11-08 19:24:48 +000089 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
croachrose0f87cd82006-09-20 15:47:42 +000090}
91
92void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
93{
croachrose48ede9b2006-11-08 19:24:48 +000094 SkASSERT(name);
95 SkASSERT(dataSize);
96 SkASSERT(count > 0);
croachrose0f87cd82006-09-20 15:47:42 +000097
croachrose48ede9b2006-11-08 19:24:48 +000098 (void)this->remove(name, type);
croachrose0f87cd82006-09-20 15:47:42 +000099
croachrose48ede9b2006-11-08 19:24:48 +0000100 size_t len = strlen(name);
101 Rec* rec = Rec::Alloc(sizeof(Rec) + dataSize * count + len + 1);
croachrose0f87cd82006-09-20 15:47:42 +0000102
103#ifndef SK_DEBUG
croachrose48ede9b2006-11-08 19:24:48 +0000104 rec->fType = SkToU8(type);
croachrose0f87cd82006-09-20 15:47:42 +0000105#else
croachrose48ede9b2006-11-08 19:24:48 +0000106 rec->fType = type;
croachrose0f87cd82006-09-20 15:47:42 +0000107#endif
croachrose48ede9b2006-11-08 19:24:48 +0000108 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);
croachrose0f87cd82006-09-20 15:47:42 +0000113
114#ifdef SK_DEBUG
croachrose48ede9b2006-11-08 19:24:48 +0000115 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 }
croachrose0f87cd82006-09-20 15:47:42 +0000136#endif
137
croachrose48ede9b2006-11-08 19:24:48 +0000138 rec->fNext = fRec;
139 fRec = rec;
140 return rec->data();
croachrose0f87cd82006-09-20 15:47:42 +0000141}
142
143bool SkMetaData::findS32(const char name[], int32_t* value) const
144{
croachrose48ede9b2006-11-08 19:24:48 +0000145 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;
croachrose0f87cd82006-09-20 15:47:42 +0000154}
155
156bool SkMetaData::findScalar(const char name[], SkScalar* value) const
157{
croachrose48ede9b2006-11-08 19:24:48 +0000158 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;
croachrose0f87cd82006-09-20 15:47:42 +0000167}
168
169const SkScalar* SkMetaData::findScalars(const char name[], int* count, SkScalar values[]) const
170{
croachrose48ede9b2006-11-08 19:24:48 +0000171 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;
croachrose0f87cd82006-09-20 15:47:42 +0000181}
182
183bool SkMetaData::findPtr(const char name[], void** value) const
184{
croachrose48ede9b2006-11-08 19:24:48 +0000185 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;
croachrose0f87cd82006-09-20 15:47:42 +0000194}
195
196const char* SkMetaData::findString(const char name[]) const
197{
croachrose48ede9b2006-11-08 19:24:48 +0000198 const Rec* rec = this->find(name, kString_Type);
199 SkASSERT(rec == NULL || rec->fDataLen == sizeof(char));
200 return rec ? (const char*)rec->data() : NULL;
croachrose0f87cd82006-09-20 15:47:42 +0000201}
202
203bool SkMetaData::findBool(const char name[], bool* value) const
204{
croachrose48ede9b2006-11-08 19:24:48 +0000205 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;
croachrose0f87cd82006-09-20 15:47:42 +0000214}
215
216const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
217{
croachrose48ede9b2006-11-08 19:24:48 +0000218 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;
croachrose0f87cd82006-09-20 15:47:42 +0000226}
227
228bool SkMetaData::remove(const char name[], Type type)
229{
croachrose48ede9b2006-11-08 19:24:48 +0000230 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;
croachrose0f87cd82006-09-20 15:47:42 +0000248}
249
250bool SkMetaData::removeS32(const char name[])
251{
croachrose48ede9b2006-11-08 19:24:48 +0000252 return this->remove(name, kS32_Type);
croachrose0f87cd82006-09-20 15:47:42 +0000253}
254
255bool SkMetaData::removeScalar(const char name[])
256{
croachrose48ede9b2006-11-08 19:24:48 +0000257 return this->remove(name, kScalar_Type);
croachrose0f87cd82006-09-20 15:47:42 +0000258}
259
260bool SkMetaData::removeString(const char name[])
261{
croachrose48ede9b2006-11-08 19:24:48 +0000262 return this->remove(name, kString_Type);
croachrose0f87cd82006-09-20 15:47:42 +0000263}
264
265bool SkMetaData::removePtr(const char name[])
266{
croachrose48ede9b2006-11-08 19:24:48 +0000267 return this->remove(name, kPtr_Type);
croachrose0f87cd82006-09-20 15:47:42 +0000268}
269
270bool SkMetaData::removeBool(const char name[])
271{
croachrose48ede9b2006-11-08 19:24:48 +0000272 return this->remove(name, kBool_Type);
croachrose0f87cd82006-09-20 15:47:42 +0000273}
274
275///////////////////////////////////////////////////////////////////////////////////
276
277SkMetaData::Iter::Iter(const SkMetaData& metadata)
278{
croachrose48ede9b2006-11-08 19:24:48 +0000279 fRec = metadata.fRec;
croachrose0f87cd82006-09-20 15:47:42 +0000280}
281
282void SkMetaData::Iter::reset(const SkMetaData& metadata)
283{
croachrose48ede9b2006-11-08 19:24:48 +0000284 fRec = metadata.fRec;
croachrose0f87cd82006-09-20 15:47:42 +0000285}
286
287const char* SkMetaData::Iter::next(SkMetaData::Type* t, int* count)
288{
croachrose48ede9b2006-11-08 19:24:48 +0000289 const char* name = NULL;
croachrose0f87cd82006-09-20 15:47:42 +0000290
croachrose48ede9b2006-11-08 19:24:48 +0000291 if (fRec)
292 {
293 if (t)
294 *t = (SkMetaData::Type)fRec->fType;
295 if (count)
296 *count = fRec->fDataCount;
297 name = fRec->name();
croachrose0f87cd82006-09-20 15:47:42 +0000298
croachrose48ede9b2006-11-08 19:24:48 +0000299 fRec = fRec->fNext;
300 }
301 return name;
croachrose0f87cd82006-09-20 15:47:42 +0000302}
303
304///////////////////////////////////////////////////////////////////////////////////
305
306SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size)
307{
croachrose48ede9b2006-11-08 19:24:48 +0000308 return (Rec*)sk_malloc_throw(size);
croachrose0f87cd82006-09-20 15:47:42 +0000309}
310
311void SkMetaData::Rec::Free(Rec* rec)
312{
croachrose48ede9b2006-11-08 19:24:48 +0000313 sk_free(rec);
croachrose0f87cd82006-09-20 15:47:42 +0000314}
315
316///////////////////////////////////////////////////////////////////////////////////
317///////////////////////////////////////////////////////////////////////////////////
318
319#ifdef SK_DEBUG
320
321void SkMetaData::UnitTest()
322{
323#ifdef SK_SUPPORT_UNITTEST
croachrose48ede9b2006-11-08 19:24:48 +0000324 SkMetaData m1;
croachrose0f87cd82006-09-20 15:47:42 +0000325
croachrose48ede9b2006-11-08 19:24:48 +0000326 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"));
croachrose0f87cd82006-09-20 15:47:42 +0000334
croachrose48ede9b2006-11-08 19:24:48 +0000335 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);
croachrose0f87cd82006-09-20 15:47:42 +0000341
croachrose48ede9b2006-11-08 19:24:48 +0000342 int32_t n;
343 SkScalar s;
croachrose0f87cd82006-09-20 15:47:42 +0000344
croachrose48ede9b2006-11-08 19:24:48 +0000345 m1.setScalar("scalar", SK_Scalar1/2);
croachrose0f87cd82006-09-20 15:47:42 +0000346
croachrose48ede9b2006-11-08 19:24:48 +0000347 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));
croachrose0f87cd82006-09-20 15:47:42 +0000352
croachrose48ede9b2006-11-08 19:24:48 +0000353 Iter iter(m1);
354 const char* name;
croachrose0f87cd82006-09-20 15:47:42 +0000355
croachrose48ede9b2006-11-08 19:24:48 +0000356 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 };
croachrose0f87cd82006-09-20 15:47:42 +0000368
croachrose48ede9b2006-11-08 19:24:48 +0000369 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));
croachrose0f87cd82006-09-20 15:47:42 +0000388
croachrose48ede9b2006-11-08 19:24:48 +0000389 SkASSERT(m1.removeS32("int"));
390 SkASSERT(m1.removeScalar("scalar"));
391 SkASSERT(m1.removeString("hello"));
392 SkASSERT(m1.removeBool("true"));
393 SkASSERT(m1.removeBool("false"));
croachrose0f87cd82006-09-20 15:47:42 +0000394
croachrose48ede9b2006-11-08 19:24:48 +0000395 SkASSERT(!m1.findS32("int"));
396 SkASSERT(!m1.findScalar("scalar"));
397 SkASSERT(!m1.findString("hello"));
398 SkASSERT(!m1.findBool("true"));
399 SkASSERT(!m1.findBool("false"));
croachrose0f87cd82006-09-20 15:47:42 +0000400#endif
401}
402
403#endif
404
405