From 41f1c46ddc7d3ff622039bea8f67ea1efc8d5566 Mon Sep 17 00:00:00 2001 From: "mike@reedtribe.org" Date: Sat, 31 Dec 2011 01:58:40 +0000 Subject: add experimental class for json git-svn-id: http://skia.googlecode.com/svn/trunk@2939 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/utils/SkJSONObject.h | 60 ++++++++++ src/utils/SkJSONObject.cpp | 255 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 include/utils/SkJSONObject.h create mode 100644 src/utils/SkJSONObject.cpp diff --git a/include/utils/SkJSONObject.h b/include/utils/SkJSONObject.h new file mode 100644 index 0000000000..d83183472d --- /dev/null +++ b/include/utils/SkJSONObject.h @@ -0,0 +1,60 @@ +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkJSONObject_DEFINED +#define SkJSONObject_DEFINED + +#include "SkTypes.h" + +class SkString; + +class SkJSONObject { +public: + SkJSONObject() : fHead(NULL), fTail(NULL) {} + ~SkJSONObject(); + + enum Type { + kInvalid, + + kObject, + kString, + kInt, + kFloat, + kBool, + }; + + void addString(const char name[], const char value[]); + void addInt(const char name[], int32_t value); + void addFloat(const char name[], float value); + void addBool(const char name[], bool value); + /** + * Add the value object to this object, taking over + * ownership of the value object. + */ + void addObject(const char name[], SkJSONObject* value); + + Type find(const char name[], intptr_t* = NULL) const; + bool findString(const char name[], SkString* = NULL) const; + bool findInt(const char name[], int32_t* = NULL) const; + bool findFloat(const char name[], float* = NULL) const; + bool findBool(const char name[], bool* = NULL) const; + bool findObject(const char name[], SkJSONObject** = NULL) const; + + void dump() const; + +private: + struct Slot; + Slot* fHead; + Slot* fTail; + + const Slot* findSlot(const char name[]) const; + const Slot* findSlotAndType(const char name[], Type) const; + Slot* addSlot(Slot*); + void dumpLevel(int level) const; +}; + +#endif diff --git a/src/utils/SkJSONObject.cpp b/src/utils/SkJSONObject.cpp new file mode 100644 index 0000000000..acdb95f696 --- /dev/null +++ b/src/utils/SkJSONObject.cpp @@ -0,0 +1,255 @@ +/* + * 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 "SkJSONObject.h" +#include "SkString.h" + +struct SkJSONObject::Slot { + Slot(const char name[], SkJSONObject::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] : ""; + } + + SkJSONObject::Type type() const { + return fName ? (SkJSONObject::Type)fName[0] + : SkJSONObject::kInvalid; + } + + Slot* fNext; + char* fName; // fName[0] is the type + union { + SkJSONObject* fObject; + char* fString; + int32_t fInt; + float fFloat; + bool fBool; + intptr_t fIntPtr; // for generic getter + } fValue; +}; + +SkJSONObject::Slot::~Slot() { + switch (this->type()) { + case SkJSONObject::kObject: + delete fValue.fObject; + break; + case SkJSONObject::kString: + delete[] fValue.fString; + break; + default: + break; + } + delete[] fName; +} + +/////////////////////////////////////////////////////////////////////////////// + +SkJSONObject::~SkJSONObject() { + Slot* slot = fHead; + while (slot) { + Slot* next = slot->fNext; + delete slot; + slot = next; + } +} + +SkJSONObject::Slot* SkJSONObject::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 SkJSONObject::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 SkJSONObject::addInt(const char name[], int32_t value) { + Slot* slot = addSlot(new Slot(name, kInt)); + fTail->fValue.fInt = value; +} + +void SkJSONObject::addFloat(const char name[], float value) { + Slot* slot = addSlot(new Slot(name, kFloat)); + fTail->fValue.fFloat = value; +} + +void SkJSONObject::addBool(const char name[], bool value) { + Slot* slot = addSlot(new Slot(name, kBool)); + fTail->fValue.fBool = value; +} + +void SkJSONObject::addObject(const char name[], SkJSONObject* value) { + Slot* slot = addSlot(new Slot(name, kObject)); + fTail->fValue.fObject = value; +} + +/////////////////////////////////////////////////////////////////////////////// + +const SkJSONObject::Slot* SkJSONObject::findSlot(const char name[]) const { + for (const Slot* slot = fHead; slot; slot = slot->fNext) { + if (!strcmp(slot->name(), name)) { + return slot; + } + } + return NULL; +} + +const SkJSONObject::Slot* SkJSONObject::findSlotAndType(const char name[], + Type t) const { + const Slot* slot = this->findSlot(name); + if (slot && (slot->type() != t)) { + slot = NULL; + } + return slot; +} + +SkJSONObject::Type SkJSONObject::find(const char name[], intptr_t* value) const { + const Slot* slot = this->findSlot(name); + if (slot) { + if (value) { + *value = slot->fValue.fIntPtr; + } + return slot->type(); + } + return kInvalid; +} + +bool SkJSONObject::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 SkJSONObject::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 SkJSONObject::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 SkJSONObject::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 SkJSONObject::findObject(const char name[], SkJSONObject** 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 SkJSONObject::dump() const { + SkDebugf("{\n"); + this->dumpLevel(0); + SkDebugf("}\n"); +} + +void SkJSONObject::dumpLevel(int level) const { + for (Slot* slot = fHead; slot; slot = slot->fNext) { + Type t = slot->type(); + if (kInvalid == t) { + continue; + } + + 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 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"); + } +} + + -- cgit v1.2.3