michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkJSON_DEFINED michael@0: #define SkJSON_DEFINED michael@0: michael@0: #include "SkTypes.h" michael@0: michael@0: class SkStream; michael@0: class SkString; michael@0: michael@0: class SkJSON { michael@0: public: michael@0: enum Type { michael@0: kObject, michael@0: kArray, michael@0: kString, michael@0: kInt, michael@0: kFloat, michael@0: kBool, michael@0: }; michael@0: michael@0: class Array; michael@0: michael@0: class Object { michael@0: private: michael@0: struct Slot; michael@0: michael@0: public: michael@0: Object(); michael@0: Object(const Object&); michael@0: ~Object(); michael@0: michael@0: /** michael@0: * Create a new slot with the specified name and value. The name michael@0: * parameter is copied, but ownership of the Object parameter is michael@0: * transferred. The Object parameter may be null, but the name must michael@0: * not be null. michael@0: */ michael@0: void addObject(const char name[], Object* value); michael@0: michael@0: /** michael@0: * Create a new slot with the specified name and value. The name michael@0: * parameter is copied, but ownership of the Array parameter is michael@0: * transferred. The Array parameter may be null, but the name must michael@0: * not be null. michael@0: */ michael@0: void addArray(const char name[], Array* value); michael@0: michael@0: /** michael@0: * Create a new slot with the specified name and value. Both parameters michael@0: * are copied. The value parameter may be null, but the name must michael@0: * not be null. michael@0: */ michael@0: void addString(const char name[], const char value[]); michael@0: michael@0: /** michael@0: * Create a new slot with the specified name and value. The name michael@0: * parameter is copied, and must not be null. michael@0: */ michael@0: void addInt(const char name[], int32_t value); michael@0: michael@0: /** michael@0: * Create a new slot with the specified name and value. The name michael@0: * parameter is copied, and must not be null. michael@0: */ michael@0: void addFloat(const char name[], float value); michael@0: michael@0: /** michael@0: * Create a new slot with the specified name and value. The name michael@0: * parameter is copied, and must not be null. michael@0: */ michael@0: void addBool(const char name[], bool value); michael@0: michael@0: /** michael@0: * Return the number of slots/fields in this object. These can be michael@0: * iterated using Iter. michael@0: */ michael@0: int count() const; michael@0: michael@0: /** michael@0: * Returns true if a slot matching the name and Type is found. michael@0: */ michael@0: bool find(const char name[], Type) const; michael@0: bool findObject(const char name[], Object** = NULL) const; michael@0: bool findArray(const char name[], Array** = NULL) const; michael@0: bool findString(const char name[], SkString* = NULL) const; michael@0: bool findInt(const char name[], int32_t* = NULL) const; michael@0: bool findFloat(const char name[], float* = NULL) const; michael@0: bool findBool(const char name[], bool* = NULL) const; michael@0: michael@0: /** michael@0: * Finds the first slot matching the name and Type and removes it. michael@0: * Returns true if found, false if not. michael@0: */ michael@0: bool remove(const char name[], Type); michael@0: michael@0: void toDebugf() const; michael@0: michael@0: /** michael@0: * Iterator class which returns all of the fields/slots in an Object, michael@0: * in the order that they were added. michael@0: */ michael@0: class Iter { michael@0: public: michael@0: Iter(const Object&); michael@0: michael@0: /** michael@0: * Returns true when there are no more entries in the iterator. michael@0: * In this case, no other methods should be called. michael@0: */ michael@0: bool done() const; michael@0: michael@0: /** michael@0: * Moves the iterator to the next element. Should only be called michael@0: * if done() returns false. michael@0: */ michael@0: void next(); michael@0: michael@0: /** michael@0: * Returns the type of the current element. Should only be called michael@0: * if done() returns false. michael@0: */ michael@0: Type type() const; michael@0: michael@0: /** michael@0: * Returns the name of the current element. Should only be called michael@0: * if done() returns false. michael@0: */ michael@0: const char* name() const; michael@0: michael@0: /** michael@0: * Returns the type of the current element. Should only be called michael@0: * if done() returns false and type() returns kObject. michael@0: */ michael@0: Object* objectValue() const; michael@0: michael@0: /** michael@0: * Returns the type of the current element. Should only be called michael@0: * if done() returns false and type() returns kArray. michael@0: */ michael@0: Array* arrayValue() const; michael@0: michael@0: /** michael@0: * Returns the type of the current element. Should only be called michael@0: * if done() returns false and type() returns kString. michael@0: */ michael@0: const char* stringValue() const; michael@0: michael@0: /** michael@0: * Returns the type of the current element. Should only be called michael@0: * if done() returns false and type() returns kInt. michael@0: */ michael@0: int32_t intValue() const; michael@0: michael@0: /** michael@0: * Returns the type of the current element. Should only be called michael@0: * if done() returns false and type() returns kFloat. michael@0: */ michael@0: float floatValue() const; michael@0: michael@0: /** michael@0: * Returns the type of the current element. Should only be called michael@0: * if done() returns false and type() returns kBool. michael@0: */ michael@0: bool boolValue() const; michael@0: michael@0: private: michael@0: Slot* fSlot; michael@0: }; michael@0: michael@0: private: michael@0: Slot* fHead; michael@0: Slot* fTail; michael@0: michael@0: const Slot* findSlot(const char name[], Type) const; michael@0: Slot* addSlot(Slot*); michael@0: void dumpLevel(int level) const; michael@0: michael@0: friend class Array; michael@0: }; michael@0: michael@0: class Array { michael@0: public: michael@0: /** michael@0: * Creates an array with the specified Type and element count. All michael@0: * entries are initialized to NULL/0/false. michael@0: */ michael@0: Array(Type, int count); michael@0: michael@0: /** michael@0: * Creates an array of ints, initialized by copying the specified michael@0: * values. michael@0: */ michael@0: Array(const int32_t values[], int count); michael@0: michael@0: /** michael@0: * Creates an array of floats, initialized by copying the specified michael@0: * values. michael@0: */ michael@0: Array(const float values[], int count); michael@0: michael@0: /** michael@0: * Creates an array of bools, initialized by copying the specified michael@0: * values. michael@0: */ michael@0: Array(const bool values[], int count); michael@0: michael@0: Array(const Array&); michael@0: ~Array(); michael@0: michael@0: int count() const { return fCount; } michael@0: Type type() const { return fType; } michael@0: michael@0: /** michael@0: * Replace the element at the specified index with the specified michael@0: * Object (which may be null). Ownership of the Object is transferred. michael@0: * Should only be called if the Array's type is kObject. michael@0: */ michael@0: void setObject(int index, Object*); michael@0: michael@0: /** michael@0: * Replace the element at the specified index with the specified michael@0: * Array (which may be null). Ownership of the Array is transferred. michael@0: * Should only be called if the Array's type is kArray. michael@0: */ michael@0: void setArray(int index, Array*); michael@0: michael@0: /** michael@0: * Replace the element at the specified index with a copy of the michael@0: * specified string (which may be null). Should only be called if the michael@0: * Array's type is kString. michael@0: */ michael@0: void setString(int index, const char str[]); michael@0: michael@0: Object* const* objects() const { michael@0: SkASSERT(kObject == fType); michael@0: return fArray.fObjects; michael@0: } michael@0: Array* const* arrays() const { michael@0: SkASSERT(kObject == fType); michael@0: return fArray.fArrays; michael@0: } michael@0: const char* const* strings() const { michael@0: SkASSERT(kString == fType); michael@0: return fArray.fStrings; michael@0: } michael@0: int32_t* ints() const { michael@0: SkASSERT(kInt == fType); michael@0: return fArray.fInts; michael@0: } michael@0: float* floats() const { michael@0: SkASSERT(kFloat == fType); michael@0: return fArray.fFloats; michael@0: } michael@0: bool* bools() const { michael@0: SkASSERT(kBool == fType); michael@0: return fArray.fBools; michael@0: } michael@0: michael@0: private: michael@0: int fCount; michael@0: Type fType; michael@0: union { michael@0: void* fVoids; michael@0: Object** fObjects; michael@0: Array** fArrays; michael@0: char** fStrings; michael@0: int32_t* fInts; michael@0: float* fFloats; michael@0: bool* fBools; michael@0: } fArray; michael@0: michael@0: void init(Type, int count, const void* src); michael@0: void dumpLevel(int level) const; michael@0: michael@0: friend class Object; michael@0: }; michael@0: }; michael@0: michael@0: #endif