180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkJSON.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkString.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//    #define TRACE_SKJSON_LEAKS
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef TRACE_SKJSON_LEAKS
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static int gStringCount;
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static int gSlotCount;
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static int gObjectCount;
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static int gArrayCount;
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define LEAK_CODE(code) code
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define LEAK_CODE(code)
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic char* alloc_string(size_t len) {
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    LEAK_CODE(SkDebugf(" string[%d]\n", gStringCount++);)
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* str = (char*)sk_malloc_throw(len + 1);
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    str[len] = 0;
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return str;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic char* dup_string(const char src[]) {
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == src) {
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t len = strlen(src);
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char* dst = alloc_string(len);
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    memcpy(dst, src, len);
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return dst;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void free_string(char* str) {
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (str) {
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_free(str);
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        LEAK_CODE(SkASSERT(gStringCount > 0); SkDebugf("~string[%d]\n", --gStringCount);)
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct SkJSON::Object::Slot {
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Slot(const char name[], Type type) {
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        LEAK_CODE(SkDebugf(" slot[%d]\n", gSlotCount++);)
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(name);
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fNext = NULL;
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t len = strlen(name);
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // extra 1 for str[0] which stores the type
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char* str = alloc_string(1 + len);
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        str[0] = (char)type;
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // str[1] skips the type, len+1 includes the terminating 0 byte.
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        memcpy(&str[1], name, len + 1);
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fName = str;
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // fValue is uninitialized
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~Slot();
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Type type() const { return (Type)fName[0]; }
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const char* name() const { return &fName[1]; }
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Slot*   fNext;
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char*   fName;    // fName[0] is the type, &fName[1] is the "name"
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    union {
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Object* fObject;
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Array*  fArray;
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        char*   fString;
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int32_t fInt;
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        float   fFloat;
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        bool    fBool;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } fValue;
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Object::Slot::~Slot() {
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    free_string(fName);
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (this->type()) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kObject:
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            delete fValue.fObject;
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kArray:
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            delete fValue.fArray;
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kString:
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            free_string(fValue.fString);
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    LEAK_CODE(SkASSERT(gSlotCount > 0); SkDebugf("~slot[%d]\n", --gSlotCount);)
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Object::Iter::Iter(const Object& obj) : fSlot(obj.fHead) {}
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::Iter::done() const {
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL == fSlot;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::Iter::next() {
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSlot = fSlot->fNext;
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Type SkJSON::Object::Iter::type() const {
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->type();
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkJSON::Object::Iter::name() const {
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->name();
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Object* SkJSON::Object::Iter::objectValue() const {
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(kObject == fSlot->type());
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->fValue.fObject;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Array* SkJSON::Object::Iter::arrayValue() const {
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(kArray == fSlot->type());
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->fValue.fArray;
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst char* SkJSON::Object::Iter::stringValue() const {
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(kString == fSlot->type());
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->fValue.fString;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkJSON::Object::Iter::intValue() const {
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(kInt == fSlot->type());
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->fValue.fInt;
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querufloat SkJSON::Object::Iter::floatValue() const {
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(kFloat == fSlot->type());
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->fValue.fFloat;
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::Iter::boolValue() const {
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(fSlot);
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(kBool == fSlot->type());
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return fSlot->fValue.fBool;
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Object::Object() : fHead(NULL), fTail(NULL) {
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);)
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Object::Object(const Object& other) : fHead(NULL), fTail(NULL) {
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    LEAK_CODE(SkDebugf(" object[%d]\n", gObjectCount++);)
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Iter iter(other);
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!iter.done()) {
17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (iter.type()) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kObject:
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                this->addObject(iter.name(), new Object(*iter.objectValue()));
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kArray:
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                this->addArray(iter.name(), new Array(*iter.arrayValue()));
18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kString:
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                this->addString(iter.name(), dup_string(iter.stringValue()));
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kInt:
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                this->addInt(iter.name(), iter.intValue());
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kFloat:
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                this->addFloat(iter.name(), iter.floatValue());
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kBool:
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                this->addBool(iter.name(), iter.boolValue());
19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        iter.next();
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Object::~Object() {
20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Slot* slot = fHead;
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (slot) {
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Slot* next = slot->fNext;
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete slot;
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        slot = next;
20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    LEAK_CODE(SkASSERT(gObjectCount > 0); SkDebugf("~object[%d]\n", --gObjectCount);)
20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint SkJSON::Object::count() const {
21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int n = 0;
21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (const Slot* slot = fHead; slot; slot = slot->fNext) {
21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        n += 1;
21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return n;
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Object::Slot* SkJSON::Object::addSlot(Slot* slot) {
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL == slot->fNext);
21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == fHead) {
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL == fTail);
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fHead = fTail = slot;
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fTail);
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(NULL == fTail->fNext);
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTail->fNext = slot;
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fTail = slot;
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return slot;
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::addObject(const char name[], SkJSON::Object* value) {
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->addSlot(new Slot(name, kObject))->fValue.fObject = value;
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::addArray(const char name[], SkJSON::Array* value) {
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->addSlot(new Slot(name, kArray))->fValue.fArray = value;
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::addString(const char name[], const char value[]) {
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->addSlot(new Slot(name, kString))->fValue.fString = dup_string(value);
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::addInt(const char name[], int32_t value) {
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->addSlot(new Slot(name, kInt))->fValue.fInt = value;
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::addFloat(const char name[], float value) {
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->addSlot(new Slot(name, kFloat))->fValue.fFloat = value;
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::addBool(const char name[], bool value) {
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->addSlot(new Slot(name, kBool))->fValue.fBool = value;
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruconst SkJSON::Object::Slot* SkJSON::Object::findSlot(const char name[],
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                                     Type t) const {
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (const Slot* slot = fHead; slot; slot = slot->fNext) {
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (t == slot->type() && !strcmp(slot->name(), name)) {
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return slot;
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return NULL;
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::find(const char name[], Type t) const {
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->findSlot(name, t) != NULL;
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::findObject(const char name[], SkJSON::Object** value) const {
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Slot* slot = this->findSlot(name, kObject);
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (slot) {
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) {
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *value = slot->fValue.fObject;
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::findArray(const char name[], SkJSON::Array** value) const {
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Slot* slot = this->findSlot(name, kArray);
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (slot) {
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) {
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *value = slot->fValue.fArray;
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::findString(const char name[], SkString* value) const {
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Slot* slot = this->findSlot(name, kString);
29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (slot) {
29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) {
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            value->set(slot->fValue.fString);
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::findInt(const char name[], int32_t* value) const {
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Slot* slot = this->findSlot(name, kInt);
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (slot) {
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) {
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *value = slot->fValue.fInt;
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::findFloat(const char name[], float* value) const {
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Slot* slot = this->findSlot(name, kFloat);
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (slot) {
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) {
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *value = slot->fValue.fFloat;
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::findBool(const char name[], bool* value) const {
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const Slot* slot = this->findSlot(name, kBool);
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (slot) {
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (value) {
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *value = slot->fValue.fBool;
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkJSON::Object::remove(const char name[], Type t) {
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDEBUGCODE(int count = this->count();)
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Slot* prev = NULL;
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Slot* slot = fHead;
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (slot) {
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Slot* next = slot->fNext;
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (t == slot->type() && !strcmp(slot->name(), name)) {
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (prev) {
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(fHead != slot);
34680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                prev->fNext = next;
34780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } else {
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(fHead == slot);
34980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fHead = next;
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (fTail == slot) {
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fTail = prev;
35380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            delete slot;
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(count - 1 == this->count());
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prev = slot;
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        slot = next;
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(count == this->count());
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return false;
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void tabForLevel(int level) {
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < level; ++i) {
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("    ");
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::toDebugf() const {
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("{\n");
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->dumpLevel(0);
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDebugf("}\n");
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Object::dumpLevel(int level) const {
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (Slot* slot = fHead; slot; slot = slot->fNext) {
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Type t = slot->type();
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        tabForLevel(level + 1);
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("\"%s\" : ", slot->name());
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        switch (slot->type()) {
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kObject:
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (slot->fValue.fObject) {
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("{\n");
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    slot->fValue.fObject->dumpLevel(level + 1);
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    tabForLevel(level + 1);
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("}");
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("null");
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kArray:
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (slot->fValue.fArray) {
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("[");
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    slot->fValue.fArray->dumpLevel(level + 1);
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("]");
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("null");
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kString:
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("\"%s\"", slot->fValue.fString);
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kInt:
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("%d", slot->fValue.fInt);
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kFloat:
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("%g", slot->fValue.fFloat);
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            case kBool:
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("%s", slot->fValue.fBool ? "true" : "false");
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            default:
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkASSERT(!"how did I get here");
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (slot->fNext) {
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf(",");
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDebugf("\n");
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Array::dumpLevel(int level) const {
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == fCount) {
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int last = fCount - 1;
43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    switch (this->type()) {
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kObject: {
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("\n");
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i <= last; ++i) {
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                Object* obj = fArray.fObjects[i];
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tabForLevel(level + 1);
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (obj) {
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("{\n");
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    obj->dumpLevel(level + 1);
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    tabForLevel(level + 1);
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf(i < last ? "}," : "}");
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf(i < last ? "null," : "null");
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("\n");
44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kArray: {
45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf("\n");
45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i <= last; ++i) {
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                Array* array = fArray.fArrays[i];
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                tabForLevel(level + 1);
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                if (array) {
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf("[");
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    array->dumpLevel(level + 1);
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    tabForLevel(level + 1);
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf(i < last ? "]," : "]");
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                } else {
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SkDebugf(i < last ? "null," : "null");
46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf("\n");
46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kString: {
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i < last; ++i) {
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                const char* str = fArray.fStrings[i];
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf(str ? " \"%s\"," : " null,", str);
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            const char* str = fArray.fStrings[last];
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf(str ? " \"%s\" " : " null ", str);
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kInt: {
47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i < last; ++i) {
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf(" %d,", fArray.fInts[i]);
47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf(" %d ", fArray.fInts[last]);
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kFloat: {
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i < last; ++i) {
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf(" %g,", fArray.fFloats[i]);
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf(" %g ", fArray.fFloats[last]);
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        case kBool: {
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i < last; ++i) {
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SkDebugf(" %s,", fArray.fBools[i] ? "true" : "false");
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkDebugf(" %s ", fArray.fInts[last] ? "true" : "false");
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } break;
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        default:
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(!"unsupported array type");
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const uint8_t gBytesPerType[] = {
50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sizeof(SkJSON::Object*),
50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sizeof(SkJSON::Array*),
50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sizeof(char*),
50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sizeof(int32_t),
50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sizeof(float),
50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sizeof(bool)
50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef void* (*DupProc)(const void*);
51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void* dup_object(const void* src) {
51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkNEW_ARGS(SkJSON::Object, (*(SkJSON::Object*)src));
51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void* dup_array(const void* src) {
51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return SkNEW_ARGS(SkJSON::Array, (*(SkJSON::Array*)src));
51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const DupProc gDupProcs[] = {
52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dup_object,             // Object
52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    dup_array,              // Array
52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    (DupProc)dup_string,    // String
52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NULL,                   // int
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NULL,                   // float
52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NULL,                   // bool
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Array::init(Type type, int count, const void* src) {
52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    LEAK_CODE(SkDebugf(" array[%d]\n", gArrayCount++);)
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((unsigned)type < SK_ARRAY_COUNT(gBytesPerType));
53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (count < 0) {
53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        count = 0;
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t size = count * gBytesPerType[type];
53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCount = count;
53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fType = type;
54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fArray.fVoids = sk_malloc_throw(size);
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (src) {
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        DupProc proc = gDupProcs[fType];
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (!proc) {
54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            memcpy(fArray.fVoids, src, size);
54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            void** srcPtr = (void**)src;
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            void** dstPtr = (void**)fArray.fVoids;
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            for (int i = 0; i < fCount; ++i) {
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dstPtr[i] = proc(srcPtr[i]);
55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_bzero(fArray.fVoids, size);
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Array::Array(Type type, int count) {
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->init(type, count, NULL);
55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Array::Array(const int32_t values[], int count) {
56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->init(kInt, count, values);
56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Array::Array(const float values[], int count) {
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->init(kFloat, count, values);
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Array::Array(const bool values[], int count) {
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->init(kBool, count, values);
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Array::Array(const Array& other) {
57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->init(other.type(), other.count(), other.fArray.fVoids);
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef void (*FreeProc)(void*);
57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void free_object(void* obj) {
58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete (SkJSON::Object*)obj;
58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void free_array(void* array) {
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    delete (SkJSON::Array*)array;
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic const FreeProc gFreeProcs[] = {
58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    free_object,            // Object
58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    free_array,             // Array
59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    (FreeProc)free_string,  // String
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NULL,                   // int
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NULL,                   // float
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    NULL,                   // bool
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkJSON::Array::~Array() {
59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    FreeProc proc = gFreeProcs[fType];
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (proc) {
59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void** ptr = (void**)fArray.fVoids;
60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for (int i = 0; i < fCount; ++i) {
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            proc(ptr[i]);
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    sk_free(fArray.fVoids);
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    LEAK_CODE(SkASSERT(gArrayCount > 0); SkDebugf("~array[%d]\n", --gArrayCount);)
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Array::setObject(int index, Object* object) {
61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((unsigned)index < (unsigned)fCount);
61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Object*& prev = fArray.fObjects[index];
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (prev != object) {
61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete prev;
61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prev = object;
61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Array::setArray(int index, Array* array) {
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((unsigned)index < (unsigned)fCount);
62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Array*& prev = fArray.fArrays[index];
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (prev != array) {
62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        delete prev;
62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prev = array;
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkJSON::Array::setString(int index, const char str[]) {
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT((unsigned)index < (unsigned)fCount);
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    char*& prev = fArray.fStrings[index];
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (prev != str) {
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        free_string(prev);
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        prev = dup_string(str);
63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
635