blob: c366bd3fee4abbbfe45bc506776d71e954f64d85 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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
20SkMetaData::SkMetaData() : fRec(NULL)
21{
22}
23
24SkMetaData::SkMetaData(const SkMetaData& src) : fRec(NULL)
25{
26 *this = src;
27}
28
29SkMetaData::~SkMetaData()
30{
31 this->reset();
32}
33
34void 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
46SkMetaData& 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
59void SkMetaData::setS32(const char name[], int32_t value)
60{
61 (void)this->set(name, &value, sizeof(int32_t), kS32_Type, 1);
62}
63
64void SkMetaData::setScalar(const char name[], SkScalar value)
65{
66 (void)this->set(name, &value, sizeof(SkScalar), kScalar_Type, 1);
67}
68
69SkScalar* 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
77void SkMetaData::setString(const char name[], const char value[])
78{
79 (void)this->set(name, value, sizeof(char), kString_Type, strlen(value) + 1);
80}
81
82void SkMetaData::setPtr(const char name[], void* ptr)
83{
84 (void)this->set(name, &ptr, sizeof(void*), kPtr_Type, 1);
85}
86
87void SkMetaData::setBool(const char name[], bool value)
88{
89 (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
90}
91
92void* 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
143bool 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
156bool 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
169const 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
183bool 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
196const 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
203bool 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
216const 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
228bool 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
250bool SkMetaData::removeS32(const char name[])
251{
252 return this->remove(name, kS32_Type);
253}
254
255bool SkMetaData::removeScalar(const char name[])
256{
257 return this->remove(name, kScalar_Type);
258}
259
260bool SkMetaData::removeString(const char name[])
261{
262 return this->remove(name, kString_Type);
263}
264
265bool SkMetaData::removePtr(const char name[])
266{
267 return this->remove(name, kPtr_Type);
268}
269
270bool SkMetaData::removeBool(const char name[])
271{
272 return this->remove(name, kBool_Type);
273}
274
275///////////////////////////////////////////////////////////////////////////////////
276
277SkMetaData::Iter::Iter(const SkMetaData& metadata)
278{
279 fRec = metadata.fRec;
280}
281
282void SkMetaData::Iter::reset(const SkMetaData& metadata)
283{
284 fRec = metadata.fRec;
285}
286
287const 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
306SkMetaData::Rec* SkMetaData::Rec::Alloc(size_t size)
307{
308 return (Rec*)sk_malloc_throw(size);
309}
310
311void SkMetaData::Rec::Free(Rec* rec)
312{
313 sk_free(rec);
314}
315
316///////////////////////////////////////////////////////////////////////////////////
317///////////////////////////////////////////////////////////////////////////////////
318
319#ifdef SK_DEBUG
320
321void 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