• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
alloc_string(size_t len)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 
dup_string(const char src[])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 
free_string(char * str)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 {
SlotSkJSON::Object::Slot54     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 
typeSkJSON::Object::Slot72     Type type() const { return (Type)fName[0]; }
nameSkJSON::Object::Slot73     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 
~Slot()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 
Iter(const Object & obj)107 SkJSON::Object::Iter::Iter(const Object& obj) : fSlot(obj.fHead) {}
108 
done() const109 bool SkJSON::Object::Iter::done() const {
110     return NULL == fSlot;
111 }
112 
next()113 void SkJSON::Object::Iter::next() {
114     SkASSERT(fSlot);
115     fSlot = fSlot->fNext;
116 }
117 
type() const118 SkJSON::Type SkJSON::Object::Iter::type() const {
119     SkASSERT(fSlot);
120     return fSlot->type();
121 }
122 
name() const123 const char* SkJSON::Object::Iter::name() const {
124     SkASSERT(fSlot);
125     return fSlot->name();
126 }
127 
objectValue() const128 SkJSON::Object* SkJSON::Object::Iter::objectValue() const {
129     SkASSERT(fSlot);
130     SkASSERT(kObject == fSlot->type());
131     return fSlot->fValue.fObject;
132 }
133 
arrayValue() const134 SkJSON::Array* SkJSON::Object::Iter::arrayValue() const {
135     SkASSERT(fSlot);
136     SkASSERT(kArray == fSlot->type());
137     return fSlot->fValue.fArray;
138 }
139 
stringValue() const140 const char* SkJSON::Object::Iter::stringValue() const {
141     SkASSERT(fSlot);
142     SkASSERT(kString == fSlot->type());
143     return fSlot->fValue.fString;
144 }
145 
intValue() const146 int32_t SkJSON::Object::Iter::intValue() const {
147     SkASSERT(fSlot);
148     SkASSERT(kInt == fSlot->type());
149     return fSlot->fValue.fInt;
150 }
151 
floatValue() const152 float SkJSON::Object::Iter::floatValue() const {
153     SkASSERT(fSlot);
154     SkASSERT(kFloat == fSlot->type());
155     return fSlot->fValue.fFloat;
156 }
157 
boolValue() const158 bool SkJSON::Object::Iter::boolValue() const {
159     SkASSERT(fSlot);
160     SkASSERT(kBool == fSlot->type());
161     return fSlot->fValue.fBool;
162 }
163 
164 ///////////////////////////////////////////////////////////////////////////////
165 
Object()166 SkJSON::Object::Object() : fHead(NULL), fTail(NULL) {
167     LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);)
168 }
169 
Object(const Object & other)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 
~Object()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 
count() const209 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 
addSlot(Slot * slot)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 
addObject(const char name[],SkJSON::Object * value)231 void SkJSON::Object::addObject(const char name[], SkJSON::Object* value) {
232     this->addSlot(new Slot(name, kObject))->fValue.fObject = value;
233 }
234 
addArray(const char name[],SkJSON::Array * value)235 void SkJSON::Object::addArray(const char name[], SkJSON::Array* value) {
236     this->addSlot(new Slot(name, kArray))->fValue.fArray = value;
237 }
238 
addString(const char name[],const char value[])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 
addInt(const char name[],int32_t value)243 void SkJSON::Object::addInt(const char name[], int32_t value) {
244     this->addSlot(new Slot(name, kInt))->fValue.fInt = value;
245 }
246 
addFloat(const char name[],float value)247 void SkJSON::Object::addFloat(const char name[], float value) {
248     this->addSlot(new Slot(name, kFloat))->fValue.fFloat = value;
249 }
250 
addBool(const char name[],bool value)251 void SkJSON::Object::addBool(const char name[], bool value) {
252     this->addSlot(new Slot(name, kBool))->fValue.fBool = value;
253 }
254 
255 ///////////////////////////////////////////////////////////////////////////////
256 
findSlot(const char name[],Type t) const257 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 
find(const char name[],Type t) const267 bool SkJSON::Object::find(const char name[], Type t) const {
268     return this->findSlot(name, t) != NULL;
269 }
270 
findObject(const char name[],SkJSON::Object ** value) const271 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 
findArray(const char name[],SkJSON::Array ** value) const282 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 
findString(const char name[],SkString * value) const293 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 
findInt(const char name[],int32_t * value) const304 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 
findFloat(const char name[],float * value) const315 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 
findBool(const char name[],bool * value) const326 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 
remove(const char name[],Type t)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 
tabForLevel(int level)367 static void tabForLevel(int level) {
368     for (int i = 0; i < level; ++i) {
369         SkDebugf("    ");
370     }
371 }
372 
toDebugf() const373 void SkJSON::Object::toDebugf() const {
374     SkDebugf("{\n");
375     this->dumpLevel(0);
376     SkDebugf("}\n");
377 }
378 
dumpLevel(int level) const379 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                 SkASSERT(!"how did I get here");
418                 break;
419         }
420         if (slot->fNext) {
421             SkDebugf(",");
422         }
423         SkDebugf("\n");
424     }
425 }
426 
dumpLevel(int level) const427 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             SkASSERT(!"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 
dup_object(const void * src)511 static void* dup_object(const void* src) {
512     return SkNEW_ARGS(SkJSON::Object, (*(SkJSON::Object*)src));
513 }
514 
dup_array(const void * src)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 
init(Type type,int count,const void * src)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 
Array(Type type,int count)557 SkJSON::Array::Array(Type type, int count) {
558     this->init(type, count, NULL);
559 }
560 
Array(const int32_t values[],int count)561 SkJSON::Array::Array(const int32_t values[], int count) {
562     this->init(kInt, count, values);
563 }
564 
Array(const float values[],int count)565 SkJSON::Array::Array(const float values[], int count) {
566     this->init(kFloat, count, values);
567 }
568 
Array(const bool values[],int count)569 SkJSON::Array::Array(const bool values[], int count) {
570     this->init(kBool, count, values);
571 }
572 
Array(const Array & other)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 
free_object(void * obj)579 static void free_object(void* obj) {
580     delete (SkJSON::Object*)obj;
581 }
582 
free_array(void * array)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 
~Array()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 
setObject(int index,Object * object)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 
setArray(int index,Array * array)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 
setString(int index,const char str[])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 }
635 
636 
637 
638