Home | History | Annotate | Download | only in utils
      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                 SkASSERT(!"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             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 
    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 }
    635