diff options
author | 2012-01-02 00:34:50 +0000 | |
---|---|---|
committer | 2012-01-02 00:34:50 +0000 | |
commit | 0f175a6dabf6cc02d1630c62dc8074dabe73c61c (patch) | |
tree | 2181a81ebf754cfebde305f6aba9e40d6b346b56 /src/utils | |
parent | 41f1c46ddc7d3ff622039bea8f67ea1efc8d5566 (diff) |
experiment #2 for JSON data
git-svn-id: http://skia.googlecode.com/svn/trunk@2940 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/SkJSON.cpp | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/src/utils/SkJSON.cpp b/src/utils/SkJSON.cpp new file mode 100644 index 0000000000..acdc9a71f0 --- /dev/null +++ b/src/utils/SkJSON.cpp @@ -0,0 +1,334 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkJSON.h" +#include "SkString.h" + +struct SkJSON::Object::Slot { + Slot(const char name[], Type type) { + fNext = NULL; + + size_t len = strlen(name); + char* str = new char[len + 2]; + str[0] = (char)type; + memcpy(str + 1, name, len + 1); + fName = str; + + // fValue is uninitialized + } + ~Slot(); + + const char* name() const { + return fName ? &fName[1] : ""; + } + + Type type() const { + return (Type)fName[0]; + } + + Slot* fNext; + char* fName; // fName[0] is the type + union { + SkJSON::Object* fObject; + SkJSON::Array* fArray; + char* fString; + int32_t fInt; + float fFloat; + bool fBool; + intptr_t fIntPtr; // for generic getter + } fValue; +}; + +SkJSON::Object::Slot::~Slot() { + switch (this->type()) { + case kObject: + delete fValue.fObject; + break; + case kArray: + case kString: + delete[] fValue.fString; + break; + default: + break; + } + delete[] fName; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkJSON::Object::~Object() { + Slot* slot = fHead; + while (slot) { + Slot* next = slot->fNext; + delete slot; + slot = next; + } +} + +SkJSON::Object::Slot* SkJSON::Object::addSlot(Slot* slot) { + SkASSERT(NULL == slot->fNext); + if (NULL == fHead) { + SkASSERT(NULL == fTail); + fHead = fTail = slot; + } else { + SkASSERT(fTail); + SkASSERT(NULL == fTail->fNext); + fTail->fNext = slot; + fTail = slot; + } +} + +void SkJSON::Object::addObject(const char name[], SkJSON::Object* value) { + Slot* slot = addSlot(new Slot(name, kObject)); + fTail->fValue.fObject = value; +} + +void SkJSON::Object::addArray(const char name[], SkJSON::Array* value) { + Slot* slot = addSlot(new Slot(name, kArray)); + fTail->fValue.fArray = value; +} + +void SkJSON::Object::addString(const char name[], const char value[]) { + Slot* slot = addSlot(new Slot(name, kString)); + size_t len = strlen(value); + char* str = new char[len + 1]; + memcpy(str, value, len + 1); + slot->fValue.fString = str; +} + +void SkJSON::Object::addInt(const char name[], int32_t value) { + Slot* slot = addSlot(new Slot(name, kInt)); + fTail->fValue.fInt = value; +} + +void SkJSON::Object::addFloat(const char name[], float value) { + Slot* slot = addSlot(new Slot(name, kFloat)); + fTail->fValue.fFloat = value; +} + +void SkJSON::Object::addBool(const char name[], bool value) { + Slot* slot = addSlot(new Slot(name, kBool)); + fTail->fValue.fBool = value; +} + +/////////////////////////////////////////////////////////////////////////////// + +const SkJSON::Object::Slot* SkJSON::Object::findSlot(const char name[]) const { + for (const Slot* slot = fHead; slot; slot = slot->fNext) { + if (!strcmp(slot->name(), name)) { + return slot; + } + } + return NULL; +} + +const SkJSON::Object::Slot* SkJSON::Object::findSlotAndType(const char name[], + Type t) const { + const Slot* slot = this->findSlot(name); + if (slot && (slot->type() != t)) { + slot = NULL; + } + return slot; +} + +bool SkJSON::Object::findString(const char name[], SkString* value) const { + const Slot* slot = this->findSlotAndType(name, kString); + if (slot) { + if (value) { + value->set(slot->fValue.fString); + } + return true; + } + return false; +} + +bool SkJSON::Object::findInt(const char name[], int32_t* value) const { + const Slot* slot = this->findSlotAndType(name, kInt); + if (slot) { + if (value) { + *value = slot->fValue.fInt; + } + return true; + } + return false; +} + +bool SkJSON::Object::findFloat(const char name[], float* value) const { + const Slot* slot = this->findSlotAndType(name, kFloat); + if (slot) { + if (value) { + *value = slot->fValue.fFloat; + } + return true; + } + return false; +} + +bool SkJSON::Object::findBool(const char name[], bool* value) const { + const Slot* slot = this->findSlotAndType(name, kBool); + if (slot) { + if (value) { + *value = slot->fValue.fBool; + } + return true; + } + return false; +} + +bool SkJSON::Object::findObject(const char name[], SkJSON::Object** value) const { + const Slot* slot = this->findSlotAndType(name, kObject); + if (slot) { + if (value) { + *value = slot->fValue.fObject; + } + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////////////// + +static void tabForLevel(int level) { + for (int i = 0; i < level; ++i) { + SkDebugf(" "); + } +} + +void SkJSON::Object::dump() const { + SkDebugf("{\n"); + this->dumpLevel(0); + SkDebugf("}\n"); +} + +void SkJSON::Object::dumpLevel(int level) const { + for (Slot* slot = fHead; slot; slot = slot->fNext) { + Type t = slot->type(); + tabForLevel(level + 1); + SkDebugf("\"%s\" : ", slot->name()); + switch (slot->type()) { + case kObject: + if (slot->fValue.fObject) { + SkDebugf("{\n"); + slot->fValue.fObject->dumpLevel(level + 1); + tabForLevel(level + 1); + SkDebugf("}"); + } else { + SkDebugf("null"); + } + break; + case kArray: + if (slot->fValue.fArray) { + SkDebugf("["); + slot->fValue.fArray->dumpLevel(level + 1); + SkDebugf("]"); + } else { + SkDebugf("null"); + } + break; + case kString: + SkDebugf("\"%s\"", slot->fValue.fString); + break; + case kInt: + SkDebugf("%d", slot->fValue.fInt); + break; + case kFloat: + SkDebugf("%g", slot->fValue.fFloat); + break; + case kBool: + SkDebugf("%s", slot->fValue.fBool ? "true" : "false"); + break; + default: + SkASSERT(!"how did I get here"); + break; + } + if (slot->fNext) { + SkDebugf(","); + } + SkDebugf("\n"); + } +} + +void SkJSON::Array::dumpLevel(int level) const { + if (0 == fCount) { + return; + } + int last = fCount - 1; + + switch (this->type()) { + case kInt: { + for (int i = 0; i < last; ++i) { + SkDebugf(" %d,", fArray.fInts[i]); + } + SkDebugf(" %d ", fArray.fInts[last]); + } break; + case kFloat: { + for (int i = 0; i < last; ++i) { + SkDebugf(" %g,", fArray.fFloats[i]); + } + SkDebugf(" %g ", fArray.fFloats[last]); + } break; + case kBool: { + for (int i = 0; i < last; ++i) { + SkDebugf(" %s,", fArray.fBools[i] ? "true" : "false"); + } + SkDebugf(" %s ", fArray.fInts[last] ? "true" : "false"); + } break; + default: + SkASSERT(!"unsupported array type"); + break; + } +} + +/////////////////////////////////////////////////////////////////////////////// + +static const uint8_t gBytesPerType[] = { + sizeof(SkJSON::Object*), + sizeof(SkJSON::Array*), + sizeof(char*), + sizeof(int32_t), + sizeof(float), + sizeof(bool) +}; + +void SkJSON::Array::init(Type type, int count, const void* src) { + if (count < 0) { + count = 0; + } + size_t size = count * gBytesPerType[type]; + + fCount = count; + fType = type; + fArray.fVoids = sk_malloc_throw(size); + if (src) { + memcpy(fArray.fVoids, src, size); + } +} + +SkJSON::Array::Array(Type type, int count) { + this->init(type, count, NULL); +} + +SkJSON::Array::Array(const int32_t values[], int count) { + this->init(kInt, count, values); +} + +SkJSON::Array::Array(const float values[], int count) { + this->init(kFloat, count, values); +} + +SkJSON::Array::Array(const bool values[], int count) { + this->init(kBool, count, values); +} + +SkJSON::Array::Array(const Array& src) { + this->init(src.type(), src.count(), src.fArray.fVoids); +} + +SkJSON::Array::~Array() { + sk_free(fArray.fVoids); +} + |