|
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", --gStringCount);) |
|
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", --gObjectCount);) |
|
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 } |