OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2011 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SkJSON.h" | |
9 #include "SkString.h" | |
10 | |
11 #ifdef SK_DEBUG | |
12 // #define TRACE_SKJSON_LEAKS | |
13 #endif | |
14 | |
15 #ifdef TRACE_SKJSON_LEAKS | |
16 static int gStringCount; | |
17 static int gSlotCount; | |
18 static int gObjectCount; | |
19 static int gArrayCount; | |
20 #define LEAK_CODE(code) code | |
21 #else | |
22 #define LEAK_CODE(code) | |
23 #endif | |
24 | |
25 /////////////////////////////////////////////////////////////////////////////// | |
26 | |
27 static char* alloc_string(size_t len) { | |
28 LEAK_CODE(SkDebugf(" string[%d]\n", gStringCount++);) | |
29 char* str = (char*)sk_malloc_throw(len + 1); | |
30 str[len] = 0; | |
31 return str; | |
32 } | |
33 | |
34 static char* dup_string(const char src[]) { | |
35 if (NULL == src) { | |
36 return NULL; | |
37 } | |
38 size_t len = strlen(src); | |
39 char* dst = alloc_string(len); | |
40 memcpy(dst, src, len); | |
41 return dst; | |
42 } | |
43 | |
44 static void free_string(char* str) { | |
45 if (str) { | |
46 sk_free(str); | |
47 LEAK_CODE(SkASSERT(gStringCount > 0); SkDebugf("~string[%d]\n", --gStrin
gCount);) | |
48 } | |
49 } | |
50 | |
51 /////////////////////////////////////////////////////////////////////////////// | |
52 | |
53 struct SkJSON::Object::Slot { | |
54 Slot(const char name[], Type type) { | |
55 LEAK_CODE(SkDebugf(" slot[%d]\n", gSlotCount++);) | |
56 SkASSERT(name); | |
57 | |
58 fNext = NULL; | |
59 | |
60 size_t len = strlen(name); | |
61 // extra 1 for str[0] which stores the type | |
62 char* str = alloc_string(1 + len); | |
63 str[0] = (char)type; | |
64 // str[1] skips the type, len+1 includes the terminating 0 byte. | |
65 memcpy(&str[1], name, len + 1); | |
66 fName = str; | |
67 | |
68 // fValue is uninitialized | |
69 } | |
70 ~Slot(); | |
71 | |
72 Type type() const { return (Type)fName[0]; } | |
73 const char* name() const { return &fName[1]; } | |
74 | |
75 Slot* fNext; | |
76 char* fName; // fName[0] is the type, &fName[1] is the "name" | |
77 union { | |
78 Object* fObject; | |
79 Array* fArray; | |
80 char* fString; | |
81 int32_t fInt; | |
82 float fFloat; | |
83 bool fBool; | |
84 } fValue; | |
85 }; | |
86 | |
87 SkJSON::Object::Slot::~Slot() { | |
88 free_string(fName); | |
89 switch (this->type()) { | |
90 case kObject: | |
91 delete fValue.fObject; | |
92 break; | |
93 case kArray: | |
94 delete fValue.fArray; | |
95 break; | |
96 case kString: | |
97 free_string(fValue.fString); | |
98 break; | |
99 default: | |
100 break; | |
101 } | |
102 LEAK_CODE(SkASSERT(gSlotCount > 0); SkDebugf("~slot[%d]\n", --gSlotCount);) | |
103 } | |
104 | |
105 /////////////////////////////////////////////////////////////////////////////// | |
106 | |
107 SkJSON::Object::Iter::Iter(const Object& obj) : fSlot(obj.fHead) {} | |
108 | |
109 bool SkJSON::Object::Iter::done() const { | |
110 return NULL == fSlot; | |
111 } | |
112 | |
113 void SkJSON::Object::Iter::next() { | |
114 SkASSERT(fSlot); | |
115 fSlot = fSlot->fNext; | |
116 } | |
117 | |
118 SkJSON::Type SkJSON::Object::Iter::type() const { | |
119 SkASSERT(fSlot); | |
120 return fSlot->type(); | |
121 } | |
122 | |
123 const char* SkJSON::Object::Iter::name() const { | |
124 SkASSERT(fSlot); | |
125 return fSlot->name(); | |
126 } | |
127 | |
128 SkJSON::Object* SkJSON::Object::Iter::objectValue() const { | |
129 SkASSERT(fSlot); | |
130 SkASSERT(kObject == fSlot->type()); | |
131 return fSlot->fValue.fObject; | |
132 } | |
133 | |
134 SkJSON::Array* SkJSON::Object::Iter::arrayValue() const { | |
135 SkASSERT(fSlot); | |
136 SkASSERT(kArray == fSlot->type()); | |
137 return fSlot->fValue.fArray; | |
138 } | |
139 | |
140 const char* SkJSON::Object::Iter::stringValue() const { | |
141 SkASSERT(fSlot); | |
142 SkASSERT(kString == fSlot->type()); | |
143 return fSlot->fValue.fString; | |
144 } | |
145 | |
146 int32_t SkJSON::Object::Iter::intValue() const { | |
147 SkASSERT(fSlot); | |
148 SkASSERT(kInt == fSlot->type()); | |
149 return fSlot->fValue.fInt; | |
150 } | |
151 | |
152 float SkJSON::Object::Iter::floatValue() const { | |
153 SkASSERT(fSlot); | |
154 SkASSERT(kFloat == fSlot->type()); | |
155 return fSlot->fValue.fFloat; | |
156 } | |
157 | |
158 bool SkJSON::Object::Iter::boolValue() const { | |
159 SkASSERT(fSlot); | |
160 SkASSERT(kBool == fSlot->type()); | |
161 return fSlot->fValue.fBool; | |
162 } | |
163 | |
164 /////////////////////////////////////////////////////////////////////////////// | |
165 | |
166 SkJSON::Object::Object() : fHead(NULL), fTail(NULL) { | |
167 LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);) | |
168 } | |
169 | |
170 SkJSON::Object::Object(const Object& other) : fHead(NULL), fTail(NULL) { | |
171 LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);) | |
172 | |
173 Iter iter(other); | |
174 while (!iter.done()) { | |
175 switch (iter.type()) { | |
176 case kObject: | |
177 this->addObject(iter.name(), new Object(*iter.objectValue())); | |
178 break; | |
179 case kArray: | |
180 this->addArray(iter.name(), new Array(*iter.arrayValue())); | |
181 break; | |
182 case kString: | |
183 this->addString(iter.name(), dup_string(iter.stringValue())); | |
184 break; | |
185 case kInt: | |
186 this->addInt(iter.name(), iter.intValue()); | |
187 break; | |
188 case kFloat: | |
189 this->addFloat(iter.name(), iter.floatValue()); | |
190 break; | |
191 case kBool: | |
192 this->addBool(iter.name(), iter.boolValue()); | |
193 break; | |
194 } | |
195 iter.next(); | |
196 } | |
197 } | |
198 | |
199 SkJSON::Object::~Object() { | |
200 Slot* slot = fHead; | |
201 while (slot) { | |
202 Slot* next = slot->fNext; | |
203 delete slot; | |
204 slot = next; | |
205 } | |
206 LEAK_CODE(SkASSERT(gObjectCount > 0); SkDebugf("~object[%d]\n", --gObjectCou
nt);) | |
207 } | |
208 | |
209 int SkJSON::Object::count() const { | |
210 int n = 0; | |
211 for (const Slot* slot = fHead; slot; slot = slot->fNext) { | |
212 n += 1; | |
213 } | |
214 return n; | |
215 } | |
216 | |
217 SkJSON::Object::Slot* SkJSON::Object::addSlot(Slot* slot) { | |
218 SkASSERT(NULL == slot->fNext); | |
219 if (NULL == fHead) { | |
220 SkASSERT(NULL == fTail); | |
221 fHead = fTail = slot; | |
222 } else { | |
223 SkASSERT(fTail); | |
224 SkASSERT(NULL == fTail->fNext); | |
225 fTail->fNext = slot; | |
226 fTail = slot; | |
227 } | |
228 return slot; | |
229 } | |
230 | |
231 void SkJSON::Object::addObject(const char name[], SkJSON::Object* value) { | |
232 this->addSlot(new Slot(name, kObject))->fValue.fObject = value; | |
233 } | |
234 | |
235 void SkJSON::Object::addArray(const char name[], SkJSON::Array* value) { | |
236 this->addSlot(new Slot(name, kArray))->fValue.fArray = value; | |
237 } | |
238 | |
239 void SkJSON::Object::addString(const char name[], const char value[]) { | |
240 this->addSlot(new Slot(name, kString))->fValue.fString = dup_string(value); | |
241 } | |
242 | |
243 void SkJSON::Object::addInt(const char name[], int32_t value) { | |
244 this->addSlot(new Slot(name, kInt))->fValue.fInt = value; | |
245 } | |
246 | |
247 void SkJSON::Object::addFloat(const char name[], float value) { | |
248 this->addSlot(new Slot(name, kFloat))->fValue.fFloat = value; | |
249 } | |
250 | |
251 void SkJSON::Object::addBool(const char name[], bool value) { | |
252 this->addSlot(new Slot(name, kBool))->fValue.fBool = value; | |
253 } | |
254 | |
255 /////////////////////////////////////////////////////////////////////////////// | |
256 | |
257 const SkJSON::Object::Slot* SkJSON::Object::findSlot(const char name[], | |
258 Type t) const { | |
259 for (const Slot* slot = fHead; slot; slot = slot->fNext) { | |
260 if (t == slot->type() && !strcmp(slot->name(), name)) { | |
261 return slot; | |
262 } | |
263 } | |
264 return NULL; | |
265 } | |
266 | |
267 bool SkJSON::Object::find(const char name[], Type t) const { | |
268 return this->findSlot(name, t) != NULL; | |
269 } | |
270 | |
271 bool SkJSON::Object::findObject(const char name[], SkJSON::Object** value) const
{ | |
272 const Slot* slot = this->findSlot(name, kObject); | |
273 if (slot) { | |
274 if (value) { | |
275 *value = slot->fValue.fObject; | |
276 } | |
277 return true; | |
278 } | |
279 return false; | |
280 } | |
281 | |
282 bool SkJSON::Object::findArray(const char name[], SkJSON::Array** value) const { | |
283 const Slot* slot = this->findSlot(name, kArray); | |
284 if (slot) { | |
285 if (value) { | |
286 *value = slot->fValue.fArray; | |
287 } | |
288 return true; | |
289 } | |
290 return false; | |
291 } | |
292 | |
293 bool SkJSON::Object::findString(const char name[], SkString* value) const { | |
294 const Slot* slot = this->findSlot(name, kString); | |
295 if (slot) { | |
296 if (value) { | |
297 value->set(slot->fValue.fString); | |
298 } | |
299 return true; | |
300 } | |
301 return false; | |
302 } | |
303 | |
304 bool SkJSON::Object::findInt(const char name[], int32_t* value) const { | |
305 const Slot* slot = this->findSlot(name, kInt); | |
306 if (slot) { | |
307 if (value) { | |
308 *value = slot->fValue.fInt; | |
309 } | |
310 return true; | |
311 } | |
312 return false; | |
313 } | |
314 | |
315 bool SkJSON::Object::findFloat(const char name[], float* value) const { | |
316 const Slot* slot = this->findSlot(name, kFloat); | |
317 if (slot) { | |
318 if (value) { | |
319 *value = slot->fValue.fFloat; | |
320 } | |
321 return true; | |
322 } | |
323 return false; | |
324 } | |
325 | |
326 bool SkJSON::Object::findBool(const char name[], bool* value) const { | |
327 const Slot* slot = this->findSlot(name, kBool); | |
328 if (slot) { | |
329 if (value) { | |
330 *value = slot->fValue.fBool; | |
331 } | |
332 return true; | |
333 } | |
334 return false; | |
335 } | |
336 | |
337 bool SkJSON::Object::remove(const char name[], Type t) { | |
338 SkDEBUGCODE(int count = this->count();) | |
339 Slot* prev = NULL; | |
340 Slot* slot = fHead; | |
341 while (slot) { | |
342 Slot* next = slot->fNext; | |
343 if (t == slot->type() && !strcmp(slot->name(), name)) { | |
344 if (prev) { | |
345 SkASSERT(fHead != slot); | |
346 prev->fNext = next; | |
347 } else { | |
348 SkASSERT(fHead == slot); | |
349 fHead = next; | |
350 } | |
351 if (fTail == slot) { | |
352 fTail = prev; | |
353 } | |
354 delete slot; | |
355 SkASSERT(count - 1 == this->count()); | |
356 return true; | |
357 } | |
358 prev = slot; | |
359 slot = next; | |
360 } | |
361 SkASSERT(count == this->count()); | |
362 return false; | |
363 } | |
364 | |
365 /////////////////////////////////////////////////////////////////////////////// | |
366 | |
367 static void tabForLevel(int level) { | |
368 for (int i = 0; i < level; ++i) { | |
369 SkDebugf(" "); | |
370 } | |
371 } | |
372 | |
373 void SkJSON::Object::toDebugf() const { | |
374 SkDebugf("{\n"); | |
375 this->dumpLevel(0); | |
376 SkDebugf("}\n"); | |
377 } | |
378 | |
379 void SkJSON::Object::dumpLevel(int level) const { | |
380 for (Slot* slot = fHead; slot; slot = slot->fNext) { | |
381 Type t = slot->type(); | |
382 tabForLevel(level + 1); | |
383 SkDebugf("\"%s\" : ", slot->name()); | |
384 switch (slot->type()) { | |
385 case kObject: | |
386 if (slot->fValue.fObject) { | |
387 SkDebugf("{\n"); | |
388 slot->fValue.fObject->dumpLevel(level + 1); | |
389 tabForLevel(level + 1); | |
390 SkDebugf("}"); | |
391 } else { | |
392 SkDebugf("null"); | |
393 } | |
394 break; | |
395 case kArray: | |
396 if (slot->fValue.fArray) { | |
397 SkDebugf("["); | |
398 slot->fValue.fArray->dumpLevel(level + 1); | |
399 SkDebugf("]"); | |
400 } else { | |
401 SkDebugf("null"); | |
402 } | |
403 break; | |
404 case kString: | |
405 SkDebugf("\"%s\"", slot->fValue.fString); | |
406 break; | |
407 case kInt: | |
408 SkDebugf("%d", slot->fValue.fInt); | |
409 break; | |
410 case kFloat: | |
411 SkDebugf("%g", slot->fValue.fFloat); | |
412 break; | |
413 case kBool: | |
414 SkDebugf("%s", slot->fValue.fBool ? "true" : "false"); | |
415 break; | |
416 default: | |
417 SkDEBUGFAIL("how did I get here"); | |
418 break; | |
419 } | |
420 if (slot->fNext) { | |
421 SkDebugf(","); | |
422 } | |
423 SkDebugf("\n"); | |
424 } | |
425 } | |
426 | |
427 void SkJSON::Array::dumpLevel(int level) const { | |
428 if (0 == fCount) { | |
429 return; | |
430 } | |
431 int last = fCount - 1; | |
432 | |
433 switch (this->type()) { | |
434 case kObject: { | |
435 SkDebugf("\n"); | |
436 for (int i = 0; i <= last; ++i) { | |
437 Object* obj = fArray.fObjects[i]; | |
438 tabForLevel(level + 1); | |
439 if (obj) { | |
440 SkDebugf("{\n"); | |
441 obj->dumpLevel(level + 1); | |
442 tabForLevel(level + 1); | |
443 SkDebugf(i < last ? "}," : "}"); | |
444 } else { | |
445 SkDebugf(i < last ? "null," : "null"); | |
446 } | |
447 SkDebugf("\n"); | |
448 } | |
449 } break; | |
450 case kArray: { | |
451 SkDebugf("\n"); | |
452 for (int i = 0; i <= last; ++i) { | |
453 Array* array = fArray.fArrays[i]; | |
454 tabForLevel(level + 1); | |
455 if (array) { | |
456 SkDebugf("["); | |
457 array->dumpLevel(level + 1); | |
458 tabForLevel(level + 1); | |
459 SkDebugf(i < last ? "]," : "]"); | |
460 } else { | |
461 SkDebugf(i < last ? "null," : "null"); | |
462 } | |
463 SkDebugf("\n"); | |
464 } | |
465 } break; | |
466 case kString: { | |
467 for (int i = 0; i < last; ++i) { | |
468 const char* str = fArray.fStrings[i]; | |
469 SkDebugf(str ? " \"%s\"," : " null,", str); | |
470 } | |
471 const char* str = fArray.fStrings[last]; | |
472 SkDebugf(str ? " \"%s\" " : " null ", str); | |
473 } break; | |
474 case kInt: { | |
475 for (int i = 0; i < last; ++i) { | |
476 SkDebugf(" %d,", fArray.fInts[i]); | |
477 } | |
478 SkDebugf(" %d ", fArray.fInts[last]); | |
479 } break; | |
480 case kFloat: { | |
481 for (int i = 0; i < last; ++i) { | |
482 SkDebugf(" %g,", fArray.fFloats[i]); | |
483 } | |
484 SkDebugf(" %g ", fArray.fFloats[last]); | |
485 } break; | |
486 case kBool: { | |
487 for (int i = 0; i < last; ++i) { | |
488 SkDebugf(" %s,", fArray.fBools[i] ? "true" : "false"); | |
489 } | |
490 SkDebugf(" %s ", fArray.fInts[last] ? "true" : "false"); | |
491 } break; | |
492 default: | |
493 SkDEBUGFAIL("unsupported array type"); | |
494 break; | |
495 } | |
496 } | |
497 | |
498 /////////////////////////////////////////////////////////////////////////////// | |
499 | |
500 static const uint8_t gBytesPerType[] = { | |
501 sizeof(SkJSON::Object*), | |
502 sizeof(SkJSON::Array*), | |
503 sizeof(char*), | |
504 sizeof(int32_t), | |
505 sizeof(float), | |
506 sizeof(bool) | |
507 }; | |
508 | |
509 typedef void* (*DupProc)(const void*); | |
510 | |
511 static void* dup_object(const void* src) { | |
512 return SkNEW_ARGS(SkJSON::Object, (*(SkJSON::Object*)src)); | |
513 } | |
514 | |
515 static void* dup_array(const void* src) { | |
516 return SkNEW_ARGS(SkJSON::Array, (*(SkJSON::Array*)src)); | |
517 } | |
518 | |
519 static const DupProc gDupProcs[] = { | |
520 dup_object, // Object | |
521 dup_array, // Array | |
522 (DupProc)dup_string, // String | |
523 NULL, // int | |
524 NULL, // float | |
525 NULL, // bool | |
526 }; | |
527 | |
528 void SkJSON::Array::init(Type type, int count, const void* src) { | |
529 LEAK_CODE(SkDebugf(" array[%d]\n", gArrayCount++);) | |
530 | |
531 SkASSERT((unsigned)type < SK_ARRAY_COUNT(gBytesPerType)); | |
532 | |
533 if (count < 0) { | |
534 count = 0; | |
535 } | |
536 size_t size = count * gBytesPerType[type]; | |
537 | |
538 fCount = count; | |
539 fType = type; | |
540 fArray.fVoids = sk_malloc_throw(size); | |
541 if (src) { | |
542 DupProc proc = gDupProcs[fType]; | |
543 if (!proc) { | |
544 memcpy(fArray.fVoids, src, size); | |
545 } else { | |
546 void** srcPtr = (void**)src; | |
547 void** dstPtr = (void**)fArray.fVoids; | |
548 for (int i = 0; i < fCount; ++i) { | |
549 dstPtr[i] = proc(srcPtr[i]); | |
550 } | |
551 } | |
552 } else { | |
553 sk_bzero(fArray.fVoids, size); | |
554 } | |
555 } | |
556 | |
557 SkJSON::Array::Array(Type type, int count) { | |
558 this->init(type, count, NULL); | |
559 } | |
560 | |
561 SkJSON::Array::Array(const int32_t values[], int count) { | |
562 this->init(kInt, count, values); | |
563 } | |
564 | |
565 SkJSON::Array::Array(const float values[], int count) { | |
566 this->init(kFloat, count, values); | |
567 } | |
568 | |
569 SkJSON::Array::Array(const bool values[], int count) { | |
570 this->init(kBool, count, values); | |
571 } | |
572 | |
573 SkJSON::Array::Array(const Array& other) { | |
574 this->init(other.type(), other.count(), other.fArray.fVoids); | |
575 } | |
576 | |
577 typedef void (*FreeProc)(void*); | |
578 | |
579 static void free_object(void* obj) { | |
580 delete (SkJSON::Object*)obj; | |
581 } | |
582 | |
583 static void free_array(void* array) { | |
584 delete (SkJSON::Array*)array; | |
585 } | |
586 | |
587 static const FreeProc gFreeProcs[] = { | |
588 free_object, // Object | |
589 free_array, // Array | |
590 (FreeProc)free_string, // String | |
591 NULL, // int | |
592 NULL, // float | |
593 NULL, // bool | |
594 }; | |
595 | |
596 SkJSON::Array::~Array() { | |
597 FreeProc proc = gFreeProcs[fType]; | |
598 if (proc) { | |
599 void** ptr = (void**)fArray.fVoids; | |
600 for (int i = 0; i < fCount; ++i) { | |
601 proc(ptr[i]); | |
602 } | |
603 } | |
604 sk_free(fArray.fVoids); | |
605 | |
606 LEAK_CODE(SkASSERT(gArrayCount > 0); SkDebugf("~array[%d]\n", --gArrayCount)
;) | |
607 } | |
608 | |
609 void SkJSON::Array::setObject(int index, Object* object) { | |
610 SkASSERT((unsigned)index < (unsigned)fCount); | |
611 Object*& prev = fArray.fObjects[index]; | |
612 if (prev != object) { | |
613 delete prev; | |
614 prev = object; | |
615 } | |
616 } | |
617 | |
618 void SkJSON::Array::setArray(int index, Array* array) { | |
619 SkASSERT((unsigned)index < (unsigned)fCount); | |
620 Array*& prev = fArray.fArrays[index]; | |
621 if (prev != array) { | |
622 delete prev; | |
623 prev = array; | |
624 } | |
625 } | |
626 | |
627 void SkJSON::Array::setString(int index, const char str[]) { | |
628 SkASSERT((unsigned)index < (unsigned)fCount); | |
629 char*& prev = fArray.fStrings[index]; | |
630 if (prev != str) { | |
631 free_string(prev); | |
632 prev = dup_string(str); | |
633 } | |
634 } | |
OLD | NEW |