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