JSONChildren.h | JSONChildren.h | |||
---|---|---|---|---|
#ifndef JSONCHILDREN_H | #ifndef JSONCHILDREN_H | |||
#define JSONCHILDREN_H | #define JSONCHILDREN_H | |||
#ifdef _LINUX_ | #include "JSONMemory.h" | |||
#include <cstdlib> //for malloc, realloc, and free | #include "JSONDebug.h" //for JSON_ASSERT macro | |||
#include <cstring> //for memmove | ||||
#endif | ||||
#include "Debug.h" //for libJSON_ASSERT macro | ||||
#ifdef DEBUG | #define json_foreach(children, iterator)\ | |||
extern ErrorCallback Error; //tell the user program that something | JSONNode ** iterator = children.begin();\ | |||
went wrong | for(JSONNode ** iterator##_end = children.end(); iterator != iterator## | |||
#endif | _end; ++iterator) | |||
/* | /* | |||
This class is essentially a vector that has been heavily optimized for | This class is essentially a vector that has been heavily optimized for the | |||
the specific purpose | specific purpose | |||
of holding JSONNode children. It acts the same way as a vector, it has | of holding JSONNode children. It acts the same way as a vector, it has a | |||
a automatically | automatically | |||
expanding array. On destruction, this container automatically destroys | expanding array. On destruction, this container automatically destroys ev | |||
everything contained | erything contained | |||
in it as well, so that you libJSON doesn't have to do that. | in it as well, so that you libJSON doesn't have to do that. | |||
T is JSONNode*, I can't define it that way directly because JSONNode us | T is JSONNode*, I can't define it that way directly because JSONNode uses | |||
es this container, and because | this container, and because | |||
the container deletes the children automatically, forward declaration c | the container deletes the children automatically, forward declaration can' | |||
an't be used | t be used | |||
*/ | */ | |||
class JSONNode; //forward declaration | class JSONNode; //forward declaration | |||
class jsonChildren { | class jsonChildren { | |||
public: | public: | |||
//starts completely empty and the array is not allocated | //starts completely empty and the array is not allocated | |||
jsonChildren(void){ | jsonChildren(void) : array(0), mysize(0), mycapacity(0) { } | |||
mysize = mycapacity = 0; | ||||
array = 0; | ||||
} | ||||
//deletes the array and everything that is contained within it (usi | ||||
ng delete) | ||||
~jsonChildren(void){ | ||||
if (array){ //the following function calls are safe, but take | ||||
more time than a check here | ||||
deleteAll(); | ||||
free(array); | ||||
} | ||||
} | ||||
//Adds something to the vector, doubling the array if necessary | //deletes the array and everything that is contained within it (using d | |||
void push_back(JSONNode * item){ | elete) | |||
if (mysize == mycapacity){ //it's full | ~jsonChildren(void){ | |||
if (!mycapacity){ //the array hasn't been created yet | if (array){ //the following function calls are safe, but take mo | |||
libJSON_ASSERT(!array, TEXT("Expanding a 0 capacity arr | re time than a check here | |||
ay, but not null")); | deleteAll(); | |||
array = (JSONNode **)malloc(8 * sizeof(JSONNode *)); / | libjson_free<JSONNode*>(array); | |||
/8 seems average for JSON, and it's only 64 bytes | } | |||
libJSON_ASSERT(array, TEXT("mallocing array failed")); | } | |||
mycapacity = 8; | ||||
} else { | ||||
mycapacity <<= 1; //double the size of the array | ||||
array = (JSONNode **)realloc(array, mycapacity * sizeof | ||||
(JSONNode *)); | ||||
libJSON_ASSERT(array, TEXT("reallocing array failed")); | ||||
} | ||||
} | ||||
array[mysize++] = item; | ||||
} | ||||
//gets an item out of the vector by it's position | //increase the size of the array | |||
inline JSONNode * operator[] (unsigned int position) const { | void inc(json_index_t amount); | |||
libJSON_ASSERT(position < mysize, TEXT("Using [] out of bounds" | void inc(void); | |||
)); | ||||
libJSON_ASSERT(position < mycapacity, TEXT("Using [] out of bou | ||||
nds")); | ||||
libJSON_ASSERT(array, TEXT("Array is null")); | ||||
return array[position]; | ||||
} | ||||
//returns the allocated capacity, but keep in mind that some might | //Adds something to the vector, doubling the array if necessary | |||
not be valid | void push_back(JSONNode * item){ | |||
inline unsigned int capacity() const { | inc(); | |||
return mycapacity; | array[mysize++] = item; | |||
} | } | |||
//returns the number of valid objects within the vector | //Adds something to the front of the vector, doubling the array if nece | |||
inline unsigned int size() const { | ssary | |||
return mysize; | void push_front(JSONNode * item){ | |||
} | inc(); | |||
memmove(array + 1, array, mysize++ * sizeof(JSONNode *)); | ||||
array[0] = item; | ||||
} | ||||
//tests whether or not the vector is empty | //gets an item out of the vector by it's position | |||
inline bool empty() const { | inline JSONNode * operator[] (json_index_t position) const { | |||
return mysize == 0; | JSON_ASSERT(position < mysize, JSON_TEXT("Using [] out of bounds" | |||
} | )); | |||
JSON_ASSERT(position < mycapacity, JSON_TEXT("Using [] out of bou | ||||
nds")); | ||||
JSON_ASSERT(array, JSON_TEXT("Array is null")); | ||||
return array[position]; | ||||
} | ||||
//tests whether or not the vector is empty | //returns the allocated capacity, but keep in mind that some might not | |||
inline bool not_empty() const { | be valid | |||
return mysize != 0; | inline json_index_t capacity() const { | |||
} | return mycapacity; | |||
} | ||||
//clears (and deletes) everything from the vector and sets it's siz | //returns the number of valid objects within the vector | |||
e to 0 | inline json_index_t size() const { | |||
inline void clear(){ | return mysize; | |||
if (array){ //don't bother clearing anything if there is nothi | } | |||
ng in it | ||||
libJSON_ASSERT(mycapacity == 0, TEXT("mycapacity is not zer | ||||
o, but array is null")); | ||||
deleteAll(); | ||||
mysize = 0; | ||||
} | ||||
libJSON_ASSERT(mysize == 0, TEXT("mysize is not zero after clea | ||||
r")); | ||||
} | ||||
//returns the beginning of the array | //tests whether or not the vector is empty | |||
inline JSONNode * * begin(void) const { | inline bool empty() const { | |||
return array; | return mysize == 0; | |||
} | } | |||
//returns the end of the array | //clears (and deletes) everything from the vector and sets it's size to | |||
inline JSONNode * * end(void) const { | 0 | |||
return array + mysize; | inline void clear(){ | |||
} | if (array){ //don't bother clearing anything if there is nothing | |||
in it | ||||
JSON_ASSERT(mycapacity != 0, JSON_TEXT("mycapacity is not | ||||
zero, but array is null")); | ||||
deleteAll(); | ||||
mysize = 0; | ||||
} | ||||
JSON_ASSERT(mysize == 0, JSON_TEXT("mysize is not zero after clea | ||||
r")); | ||||
} | ||||
//This function DOES NOT delete the item it points to | //returns the beginning of the array | |||
inline void erase(JSONNode * * position){ | inline JSONNode ** begin(void) const { | |||
libJSON_ASSERT(array, TEXT("erasing something from a null array | return array; | |||
")); | } | |||
libJSON_ASSERT(position >= array, TEXT("position is beneat the | ||||
start of the array")); | ||||
libJSON_ASSERT(position < array + mysize, TEXT("erasing out of | ||||
bounds")); | ||||
memmove(position, position + 1, (mysize-- - (position - array) | ||||
- 1) * sizeof(JSONNode *)); | ||||
} | ||||
inline void reserve(unsigned int amount){ | //returns the end of the array | |||
libJSON_ASSERT(!array, TEXT("reserve is not meant to expand a p | inline JSONNode ** end(void) const { | |||
reexisting array")); | return array + mysize; | |||
libJSON_ASSERT(!mycapacity, TEXT("reservec is not meant to expa | } | |||
nd a preexisting array")); | ||||
libJSON_ASSERT(!mysize, TEXT("reserves is not meant to expand a | ||||
preexisting array")); | ||||
array = (JSONNode **)malloc(amount * sizeof(JSONNode *)); //8 | ||||
seems average for JSON, and it's only 64 bytes | ||||
libJSON_ASSERT(array, TEXT("mallocing array failed")); | ||||
mycapacity = amount; | ||||
} | ||||
//shrinks the array to only as large as it needs to be to hold ever | //makes sure that even after shirnking and expanding, the iterator is i | |||
ything within it | n same relative position | |||
inline void shrink(){ | struct iteratorKeeper { | |||
#ifdef JSON_LESS_MEMORY //if memory doesn't matter to the user | public: | |||
, go for speed, leave it the way it is | #ifdef JSON_LIBRARY | |||
if (mysize == 0){ //size is zero, we should completely fre | iteratorKeeper(jsonChildren * pthis, JSONNode ** & positio | |||
e the array | n) : | |||
free(array); //free does checks for a null pointer, so | myRelativeOffset((json_index_t)(position - pthis -> | |||
don't bother checking | array)), | |||
array = 0; | #else | |||
} else { //need to shrink it, using realloc | iteratorKeeper(jsonChildren * pthis, JSONNode ** & positio | |||
libJSON_ASSERT(array, TEXT("shrinking a null array that | n, bool reverse = false) : | |||
is not size 0")); | myRelativeOffset(reverse ? (json_index_t)(pthis -> | |||
array = (JSONNode **)realloc(array, mysize); | array + (size_t)pthis -> mysize - position) : (json_index_t)(position - pth | |||
} | is -> array)), | |||
mycapacity = mysize; | myReverse(reverse), | |||
#endif | #endif | |||
} | myChildren(pthis), | |||
myPos(position){} | ||||
#ifdef DEBUG | ~iteratorKeeper(void){ | |||
//returns how much memory the container is currently using (min | #ifdef JSON_LIBRARY | |||
us the size of itself, which is already accounted for | myPos = myChildren -> array + myRelativeOffset; | |||
unsigned int GetMemoryUsage(void) const { | #else | |||
return mycapacity * sizeof(JSONNode *); | if (myReverse){ | |||
} | myPos = myChildren -> array + myChildren -> | |||
#endif | mysize - myRelativeOffset; | |||
} else { | ||||
myPos = myChildren -> array + myRelativeOffs | ||||
et; | ||||
} | ||||
#endif | ||||
} | ||||
private: | private: | |||
void deleteAll(void); //implemented in JSONNode.cpp | iteratorKeeper(const iteratorKeeper &); | |||
iteratorKeeper & operator = (const iteratorKeeper &); | ||||
JSONNode * * array; //the expandable array | jsonChildren * myChildren; | |||
#ifdef JSON_LESS_MEMORY | JSONNode ** & myPos; | |||
//maximum of 1 million children | json_index_t myRelativeOffset; | |||
unsigned int mysize : 20; //the number of valid items | #ifndef JSON_LIBRARY | |||
unsigned int mycapacity : 20; //the number of possible items | bool myReverse BITS(1); | |||
#else | #endif | |||
unsigned int mysize; //the number of valid items | }; | |||
unsigned int mycapacity; //the number of possible items | ||||
#endif | //This function DOES NOT delete the item it points to | |||
inline void erase(JSONNode ** & position){ | ||||
JSON_ASSERT(array, JSON_TEXT("erasing something from a null array | ||||
1")); | ||||
JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the | ||||
start of the array 1")); | ||||
JSON_ASSERT(position <= array + mysize, JSON_TEXT("erasing out of | ||||
bounds 1")); | ||||
memmove(position, position + 1, (mysize-- - (position - array) - | ||||
1) * sizeof(JSONNode *)); | ||||
iteratorKeeper ik(this, position); | ||||
shrink(); | ||||
} | ||||
//This function DOES NOT delete the item it points to | ||||
inline void erase(JSONNode ** & position, json_index_t number){ | ||||
doerase(position, number); | ||||
iteratorKeeper ik(this, position); | ||||
shrink(); | ||||
} | ||||
//This function DOES NOT delete the item it points to | ||||
inline void erase(JSONNode ** position, json_index_t number, JSONNode * | ||||
* & starter){ | ||||
doerase(position, number); | ||||
iteratorKeeper ik(this, starter); | ||||
shrink(); | ||||
} | ||||
#ifdef JSON_LIBRARY | ||||
void insert(JSONNode ** & position, JSONNode * item){ | ||||
#else | ||||
void insert(JSONNode ** & position, JSONNode * item, bool reverse | ||||
= false){ | ||||
#endif | ||||
//position isnt relative to array because of realloc | ||||
JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the | ||||
start of the array insert 1")); | ||||
JSON_ASSERT(position <= array + mysize, JSON_TEXT("position is ab | ||||
ove the end of the array insert 1")); | ||||
{ | ||||
#ifdef JSON_LIBRARY | ||||
iteratorKeeper ik(this, position); | ||||
#else | ||||
iteratorKeeper ik(this, position, reverse); | ||||
#endif | ||||
inc(); | ||||
} | ||||
memmove(position + 1, position, (mysize++ - (position - array)) * | ||||
sizeof(JSONNode *)); | ||||
*position = item; | ||||
} | ||||
void insert(JSONNode ** & position, JSONNode ** items, json_index_t num | ||||
){ | ||||
JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the | ||||
start of the array insert 2")); | ||||
JSON_ASSERT(position <= array + mysize, JSON_TEXT("position is ab | ||||
ove the end of the array insert 2")); | ||||
{ | ||||
iteratorKeeper ik(this, position); | ||||
inc(num); | ||||
} | ||||
const size_t ptrs = ((JSONNode **)(array + mysize)) - position; | ||||
memmove(position + num, position, ptrs * sizeof(JSONNode *)); | ||||
memcpy(position, items, num * sizeof(JSONNode *)); | ||||
mysize += num; | ||||
} | ||||
inline void reserve(json_index_t amount){ | ||||
JSON_ASSERT(!array, JSON_TEXT("reserve is not meant to expand a p | ||||
reexisting array")); | ||||
JSON_ASSERT(!mycapacity, JSON_TEXT("reservec is not meant to expa | ||||
nd a preexisting array")); | ||||
JSON_ASSERT(!mysize, JSON_TEXT("reserves is not meant to expand a | ||||
preexisting array")); | ||||
array = json_malloc<JSONNode*>(mycapacity = amount); | ||||
} | ||||
inline void reserve2(json_index_t amount){ | ||||
if (array){ | ||||
if (mycapacity < amount) inc(amount - mycapacity); | ||||
} else { | ||||
reserve(amount); | ||||
} | ||||
} | ||||
//shrinks the array to only as large as it needs to be to hold everythi | ||||
ng within it | ||||
inline void shrink(){ | ||||
if (mysize == 0){ //size is zero, we should completely free the | ||||
array | ||||
libjson_free<JSONNode*>(array); //free does checks for a | ||||
null pointer, so don't bother checking | ||||
array = 0; | ||||
#ifdef JSON_LESS_MEMORY | ||||
} else { //need to shrink it, using realloc | ||||
JSON_ASSERT(array, JSON_TEXT("shrinking a nu | ||||
ll array that is not size 0")); | ||||
array = json_realloc<JSONNode*>(array, mysiz | ||||
e); | ||||
#endif | ||||
} | ||||
mycapacity = mysize; | ||||
} | ||||
JSON_PRIVATE | ||||
//to make sure it's not copyable | ||||
jsonChildren(const jsonChildren &); | ||||
jsonChildren & operator = (const jsonChildren &); | ||||
void deleteAll(void); //implemented in JSONNode.cpp | ||||
void doerase(JSONNode ** position, json_index_t number); | ||||
JSONNode ** array; //the expandable array | ||||
json_index_t mysize; //the number of valid items | ||||
json_index_t mycapacity; //the number of possible items | ||||
}; | }; | |||
#endif | #endif | |||
End of changes. 20 change blocks. | ||||
162 lines changed or deleted | 247 lines changed or added | |||
JSONNode.h | JSONNode.h | |||
---|---|---|---|---|
#ifndef libJSON_NODE_H | #ifndef JSONNODE_H | |||
#define libJSON_NODE_H | #define JSONNODE_H | |||
#include <string> | #include "JSONDefs.h" //for string type | |||
#include "JSON_Strings.h" | #include "internalJSONNode.h" //internal structure for json value | |||
#include "JSONChildren.h" | #include <stdexcept> | |||
#include <cstdarg> //for the ... parameter | ||||
#define foreach(iterator, container)\ | #ifdef JSON_BINARY | |||
for (typeof(container.begin()) iterator = container.begin(), iterator## | #include "JSON_Base64.h" | |||
_end = container.end();\ | #endif | |||
iterator != iterator##_end;\ | ||||
++iterator) | ||||
using namespace std; | #ifndef JSON_REF_COUNT | |||
#define makeUniqueInternal() (void)0 | ||||
#endif | ||||
union value_union_t { | #define JSON_CHECK_INTERNAL() JSON_ASSERT(internal, JSON_TEXT("no internal" | |||
bool _bool; | )) | |||
#ifdef JSON_LESS_MEMORY | ||||
float _number; | #ifdef JSON_MUTEX_CALLBACKS | |||
size_t lastreal: 20; | #define JSON_MUTEX_COPY_DECL ,void * parentMutex | |||
#define JSON_MUTEX_COPY_DECL2 ,void * parentMutex = 0 | ||||
#else | ||||
#define JSON_MUTEX_COPY_DECL | ||||
#define JSON_MUTEX_COPY_DECL2 | ||||
#endif | ||||
#ifdef JSON_LIBRARY | ||||
#define JSON_PTR_LIB * | ||||
#define JSON_NEW(x) JSONNode::newJSONNode_Shallow(x) | ||||
#define DECLARE_FOR_ALL_TYPES(foo)\ | ||||
foo(long);\ | ||||
foo(json_number);\ | ||||
foo(bool);\ | ||||
foo(const json_string &); | ||||
#define DECLARE_FOR_ALL_TYPES_CONST(foo)\ | ||||
foo(long) const;\ | ||||
foo(json_number) const;\ | ||||
foo(bool) const;\ | ||||
foo(const json_string &) const;\ | ||||
foo(const JSONNode &) const; | ||||
#define IMPLEMENT_FOR_ALL_NUMBERS(foo)\ | ||||
foo(long)\ | ||||
foo(json_number) | ||||
#else | ||||
#define JSON_PTR_LIB | ||||
#define JSON_NEW(x) x | ||||
#define DECLARE_FOR_ALL_TYPES(foo)\ | ||||
foo(char); foo(unsigned char);\ | ||||
foo(short); foo(unsigned short);\ | ||||
foo(int); foo(unsigned int);\ | ||||
foo(long); foo(unsigned long);\ | ||||
foo(float); foo(double);\ | ||||
foo(bool);\ | ||||
foo(const json_string &);\ | ||||
foo(const json_char *); | ||||
#define DECLARE_FOR_ALL_TYPES_CONST(foo)\ | ||||
foo(char) const; foo(unsigned char) const;\ | ||||
foo(short) const; foo(unsigned short) const;\ | ||||
foo(int) const; foo(unsigned int) const;\ | ||||
foo(long) const; foo(unsigned long) const;\ | ||||
foo(float) const; foo(double) const;\ | ||||
foo(bool) const;\ | ||||
foo(const json_string &) const;\ | ||||
foo(const JSONNode &) const;\ | ||||
foo(const json_char *) const; | ||||
#define IMPLEMENT_FOR_ALL_NUMBERS(foo)\ | ||||
foo(char) foo(unsigned char)\ | ||||
foo(short) foo(unsigned short)\ | ||||
foo(int) foo(unsigned int)\ | ||||
foo(long) foo(unsigned long)\ | ||||
foo(float) foo(double) | ||||
#endif | ||||
#define IMPLEMENT_FOR_ALL_TYPES(foo)\ | ||||
IMPLEMENT_FOR_ALL_NUMBERS(foo)\ | ||||
foo(const json_string &)\ | ||||
foo(bool) | ||||
/* | ||||
This class is mostly just a wrapper class around internalJSONNode, this | ||||
class keeps | ||||
the reference count and handles copy on write and such. This class is | ||||
also responsible | ||||
for argument checking and throwing exceptions if needed. | ||||
*/ | ||||
class JSONNode { | ||||
public: | ||||
explicit JSONNode(char mytype = JSON_NODE); | ||||
#define DECLARE_CTOR(type) JSONNode(const json_string & name_t, type va | ||||
lue_t) | ||||
DECLARE_FOR_ALL_TYPES(DECLARE_CTOR) | ||||
JSONNode(const JSONNode & orig); | ||||
~JSONNode(void); | ||||
json_index_t size(void) const; | ||||
bool empty(void) const; | ||||
void clear(void); | ||||
unsigned char type(void) const; | ||||
json_string name(void) const; | ||||
void set_name(const json_string & newname); | ||||
#ifdef JSON_COMMENTS | ||||
void set_comment(const json_string & comment); | ||||
json_string get_comment(void) const; | ||||
#endif | ||||
#ifndef JSON_PREPARSE | ||||
void preparse(void); | ||||
#endif | ||||
#ifdef JSON_VALIDATE | ||||
#ifndef JSON_SAFE | ||||
#error JSON_VALIDATE also requires JSON_SAFE | ||||
#endif | ||||
bool validate(void); | ||||
#endif | ||||
json_string as_string(void) const; | ||||
long as_int(void) const; | ||||
json_number as_float(void) const; | ||||
bool as_bool(void) const; | ||||
JSONNode as_node(void) const; | ||||
JSONNode as_array(void) const; | ||||
#ifdef JSON_BINARY | ||||
std::string as_binary(void) const; | ||||
void set_binary(const unsigned char * bin, json_index_t bytes); | ||||
#endif | ||||
JSONNode & at(json_index_t pos); | ||||
const JSONNode & at(json_index_t pos) const; | ||||
JSONNode & operator[](json_index_t pos); | ||||
const JSONNode & operator[](json_index_t pos) const; | ||||
JSONNode & at(const json_string & name_t); | ||||
const JSONNode & at(const json_string & name_t) const; | ||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS | ||||
JSONNode & at_nocase(const json_string & name_t); | ||||
const JSONNode & at_nocase(const json_string & name_t) const; | ||||
#endif | ||||
JSONNode & operator[](const json_string & name_t); | ||||
const JSONNode & operator[](const json_string & name_t) const; | ||||
#ifdef JSON_LIBRARY | ||||
void push_back(JSONNode * node); | ||||
#else | #else | |||
double _number; | void push_back(const JSONNode & node); | |||
size_t lastreal; //This is used to determine the last real entry i | #endif | |||
n the Children, because it's possible to have comments at the end, we don't | void reserve(json_index_t size); | |||
want commas before them | JSONNode JSON_PTR_LIB pop_back(json_index_t pos); | |||
JSONNode JSON_PTR_LIB pop_back(const json_string & name_t); | ||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS | ||||
JSONNode JSON_PTR_LIB pop_back_nocase(const json_string & name_t) | ||||
; | ||||
#endif | #endif | |||
}; | ||||
class JSONNode { | DECLARE_FOR_ALL_TYPES(JSONNode & operator =) | |||
public: | JSONNode & operator = (const JSONNode &); | |||
JSONNode(const json_string & name_t, const json_string & value_t) | ||||
; | ||||
JSONNode(void){}; //Used ONLY for duplicating | ||||
JSONNode(JSONNode * parent); | ||||
~JSONNode(void); | ||||
void SetMyValue(const json_string & value_t); | ||||
void CloneTo(JSONNode * node); | ||||
json_string Write(unsigned int indent, bool & commaafter); //pas | ||||
s 0xFFFFFFFF to do no formatting | ||||
void Add(JSONNode * child); | ||||
#ifdef JSON_LESS_MEMORY | DECLARE_FOR_ALL_TYPES_CONST(bool operator ==) | |||
char type : 4; | DECLARE_FOR_ALL_TYPES_CONST(bool operator !=) | |||
#else | ||||
char type; //an enumerated type that tells the engine how to t | ||||
reat it | ||||
#endif | ||||
#ifndef JSON_PREPARSE | void nullify(void); | |||
void Fetch(void); | void swap(JSONNode & other); | |||
bool Fetched; //if the value has been parsed yet or not | void merge(JSONNode & other); | |||
#endif | void merge(unsigned int num, ...); | |||
JSONNode duplicate(void) const; | ||||
void cast(char newtype); | ||||
#ifndef JSON_DLL //These are the only methods you should actuall | //iterator | |||
y use | #ifdef JSON_ITERATORS | |||
#ifndef JSON_PREPARSE | #ifndef JSON_LIBRARY | |||
void Preparse(void); | #define json_iterator_ptr(iter) iter.it | |||
#endif | #define ptr_to_json_iterator(iter) json_iterator(iter) | |||
struct iterator { | ||||
inline iterator& operator ++(void){ ++it; return *t | ||||
his; } | ||||
inline iterator& operator --(void){ --it; return *t | ||||
his; } | ||||
inline iterator& operator +=(long i){ it += i; retu | ||||
rn *this; } | ||||
inline iterator& operator -=(long i){ it -= i; retu | ||||
rn *this; } | ||||
inline iterator operator ++(int){ | ||||
iterator result(*this); | ||||
++it; | ||||
return result; | ||||
} | ||||
inline iterator operator --(int){ | ||||
iterator result(*this); | ||||
--it; | ||||
return result; | ||||
} | ||||
inline iterator operator +(long i) const { | ||||
iterator result(*this); | ||||
result.it += i; | ||||
return result; | ||||
} | ||||
inline iterator operator -(long i) const { | ||||
iterator result(*this); | ||||
result.it -= i; | ||||
return result; | ||||
} | ||||
inline JSONNode& operator [](size_t pos) const { re | ||||
turn *it[pos]; }; | ||||
inline JSONNode& operator *(void) const { return *( | ||||
*it); } | ||||
inline bool operator == (const iterator & other) co | ||||
nst { return it == other.it; } | ||||
inline bool operator != (const iterator & other) co | ||||
nst { return it != other.it; } | ||||
inline bool operator > (const iterator & other) con | ||||
st { return it > other.it; } | ||||
inline bool operator >= (const iterator & other) co | ||||
nst { return it >= other.it; } | ||||
inline bool operator < (const iterator & other) con | ||||
st { return it < other.it; } | ||||
inline bool operator <= (const iterator & other) co | ||||
nst { return it <= other.it; } | ||||
inline iterator & operator = (const iterator & orig | ||||
){ it = orig.it; return *this; } | ||||
iterator (const iterator & orig) : it(orig.it) {} | ||||
private: | ||||
JSONNode ** it; | ||||
iterator(JSONNode ** starter) : it(starter) {} | ||||
friend class JSONNode; | ||||
}; | ||||
typedef iterator json_iterator; | ||||
JSONNode * GetNode(const json_string & name); | struct const_iterator { | |||
JSONNode * GetNode_NoCase(const json_string & name); | inline const_iterator& operator ++(void){ ++it; ret | |||
JSONNode * NodeAt(unsigned int position); | urn *this; } | |||
unsigned int NodeSize(void); | inline const_iterator& operator --(void){ --it; ret | |||
JSONNode * PopNode(const json_string & name); | urn *this; } | |||
JSONNode * PopNode_NoCase(const json_string & name); | inline const_iterator& operator +=(long i){ it += i | |||
JSONNode * PopNodeAt(unsigned int position); | ; return *this; } | |||
inline const_iterator& operator -=(long i){ it -= i | ||||
; return *this; } | ||||
inline const_iterator operator ++(int){ | ||||
const_iterator result(*this); | ||||
++it; | ||||
return result; | ||||
} | ||||
inline const_iterator operator --(int){ | ||||
const_iterator result(*this); | ||||
--it; | ||||
return result; | ||||
} | ||||
inline const_iterator operator +(long i) const { | ||||
const_iterator result(*this); | ||||
result.it += i; | ||||
return result; | ||||
} | ||||
inline const_iterator operator -(long i) const { | ||||
const_iterator result(*this); | ||||
result.it -= i; | ||||
return result; | ||||
} | ||||
inline const JSONNode& operator [](size_t pos) cons | ||||
t { return const_cast<const JSONNode&>(*it[pos]); }; | ||||
inline const JSONNode& operator *(void) const { ret | ||||
urn const_cast<const JSONNode&>(*(*it)); } | ||||
inline bool operator == (const const_iterator & oth | ||||
er) const { return it == other.it; } | ||||
inline bool operator != (const const_iterator & oth | ||||
er) const { return it != other.it; } | ||||
inline bool operator > (const const_iterator & othe | ||||
r) const { return it > other.it; } | ||||
inline bool operator >= (const const_iterator & oth | ||||
er) const { return it >= other.it; } | ||||
inline bool operator < (const const_iterator & othe | ||||
r) const { return it < other.it; } | ||||
inline bool operator <= (const const_iterator & oth | ||||
er) const { return it <= other.it; } | ||||
inline const_iterator & operator =(const const_iter | ||||
ator & orig){ it = orig.it; return *this; } | ||||
const_iterator (const const_iterator & orig) : it(o | ||||
rig.it) {} | ||||
private: | ||||
JSONNode ** it; | ||||
const_iterator(JSONNode ** starter) : it(starter) { | ||||
} | ||||
friend class JSONNode; | ||||
}; | ||||
const_iterator begin(void) const; | ||||
const_iterator end(void) const; | ||||
char NodeType(void); | struct reverse_iterator { | |||
const json_string & NodeName(void); | inline reverse_iterator& operator ++(void){ --it; r | |||
const json_string & NodeAsString(void); | eturn *this; } | |||
int NodeAsInt(void); | inline reverse_iterator& operator --(void){ ++it; r | |||
bool NodeAsBool(void); | eturn *this; } | |||
#ifdef JSON_LESS_MEMORY | inline reverse_iterator& operator +=(long i){ it -= | |||
float NodeAsFloat(void); | i; return *this; } | |||
#else | inline reverse_iterator& operator -=(long i){ it += | |||
double NodeAsFloat(void); | i; return *this; } | |||
#endif | inline reverse_iterator operator ++(int){ | |||
reverse_iterator result(*this); | ||||
--it; | ||||
return result; | ||||
} | ||||
inline reverse_iterator operator --(int){ | ||||
reverse_iterator result(*this); | ||||
++it; | ||||
return result; | ||||
} | ||||
inline reverse_iterator operator +(long i) const { | ||||
reverse_iterator result(*this); | ||||
result.it -= i; | ||||
return result; | ||||
} | ||||
inline reverse_iterator operator -(long i) const { | ||||
reverse_iterator result(*this); | ||||
result.it += i; | ||||
return result; | ||||
} | ||||
inline JSONNode& operator [](size_t pos) const { re | ||||
turn *it[pos]; }; | ||||
inline JSONNode& operator *(void) const { return *( | ||||
*it); } | ||||
inline bool operator == (const reverse_iterator & o | ||||
ther) const { return it == other.it; } | ||||
inline bool operator != (const reverse_iterator & o | ||||
ther) const { return it != other.it; } | ||||
inline bool operator < (const reverse_iterator & ot | ||||
her) const { return it > other.it; } | ||||
inline bool operator <= (const reverse_iterator & o | ||||
ther) const { return it >= other.it; } | ||||
inline bool operator > (const reverse_iterator & ot | ||||
her) const { return it < other.it; } | ||||
inline bool operator >= (const reverse_iterator & o | ||||
ther) const { return it <= other.it; } | ||||
inline reverse_iterator & operator = (const reverse | ||||
_iterator & orig){ it = orig.it; return *this; } | ||||
reverse_iterator (const reverse_iterator & orig) : | ||||
it(orig.it) {} | ||||
private: | ||||
JSONNode ** it; | ||||
reverse_iterator(JSONNode ** starter) : it(starter) | ||||
{} | ||||
friend class JSONNode; | ||||
}; | ||||
reverse_iterator rbegin(void); | ||||
reverse_iterator rend(void); | ||||
JSONNode * AddNewChild(const json_string & name, const jso | struct reverse_const_iterator { | |||
n_string & value); | inline reverse_const_iterator& operator ++(void){ - | |||
JSONNode * AddNewStringChild(const json_string & name, con | -it; return *this; } | |||
st json_string & value); | inline reverse_const_iterator& operator --(void){ + | |||
JSONNode * Duplicate(void); | +it; return *this; } | |||
inline reverse_const_iterator& operator +=(long i){ | ||||
it -= i; return *this; } | ||||
inline reverse_const_iterator& operator -=(long i){ | ||||
it += i; return *this; } | ||||
inline reverse_const_iterator operator ++(int){ | ||||
reverse_const_iterator result(*this); | ||||
--it; | ||||
return result; | ||||
} | ||||
inline reverse_const_iterator operator --(int){ | ||||
reverse_const_iterator result(*this); | ||||
++it; | ||||
return result; | ||||
} | ||||
inline reverse_const_iterator operator +(long i) co | ||||
nst { | ||||
reverse_const_iterator result(*this); | ||||
result.it -= i; | ||||
return result; | ||||
} | ||||
inline reverse_const_iterator operator -(long i) co | ||||
nst { | ||||
reverse_const_iterator result(*this); | ||||
result.it += i; | ||||
return result; | ||||
} | ||||
inline const JSONNode& operator [](size_t pos) cons | ||||
t { return const_cast<const JSONNode&>(*it[pos]); }; | ||||
inline const JSONNode& operator *(void) const { ret | ||||
urn const_cast<const JSONNode&>(*(*it)); } | ||||
inline bool operator == (const reverse_const_iterat | ||||
or & other) const { return it == other.it; } | ||||
inline bool operator != (const reverse_const_iterat | ||||
or & other) const { return it != other.it; } | ||||
inline bool operator < (const reverse_const_iterato | ||||
r & other) const { return it > other.it; } | ||||
inline bool operator <= (const reverse_const_iterat | ||||
or & other) const { return it >= other.it; } | ||||
inline bool operator > (const reverse_const_iterato | ||||
r & other) const { return it < other.it; } | ||||
inline bool operator >= (const reverse_const_iterat | ||||
or & other) const { return it <= other.it; } | ||||
inline reverse_const_iterator & operator = (const r | ||||
everse_const_iterator & orig){ it = orig.it; return *this; } | ||||
reverse_const_iterator (const reverse_const_iterato | ||||
r & orig) : it(orig.it) {} | ||||
private: | ||||
JSONNode ** it; | ||||
reverse_const_iterator(JSONNode ** starter) : it(st | ||||
arter) {} | ||||
friend class JSONNode; | ||||
}; | ||||
reverse_const_iterator rbegin(void) const; | ||||
reverse_const_iterator rend(void) const; | ||||
void AddChild(const JSONNode * node); | const_iterator find(const json_string & name_t) const; | |||
void SetValue(const json_string & value); | #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS | |||
void SetStringValue(const json_string & value); | const_iterator find_nocase(const json_string & name | |||
_t) const; | ||||
#endif | ||||
void AddComment(const json_string & comment); | reverse_iterator erase(reverse_iterator pos); | |||
json_string Write(unsigned int indent = 0xFFFFFFFF); | reverse_iterator erase(reverse_iterator start, const rever | |||
json_string WriteFormatted(void); | se_iterator & end); | |||
#ifdef DEBUG | iterator insert(iterator pos, const JSONNode & x); | |||
json_string Dump(void); | reverse_iterator insert(reverse_iterator pos, const JSONNo | |||
#endif | de & x); | |||
iterator insert(iterator pos, const reverse_iterator & _st | ||||
art, const reverse_iterator & _end); | ||||
reverse_iterator insert(reverse_iterator pos, const iterat | ||||
or & _start, const iterator & _end); | ||||
reverse_iterator insert(reverse_iterator pos, const revers | ||||
e_iterator & _start, const reverse_iterator & _end); | ||||
json_iterator insert(json_iterator pos, const const_iterat | ||||
or & _start, const const_iterator & _end); | ||||
reverse_iterator insert(reverse_iterator pos, const const_ | ||||
iterator & _start, const const_iterator & _end); | ||||
json_iterator insert(json_iterator pos, const reverse_cons | ||||
t_iterator & _start, const reverse_const_iterator & _end); | ||||
reverse_iterator insert(reverse_iterator pos, const revers | ||||
e_const_iterator & _start, const reverse_const_iterator & _end); | ||||
#else | ||||
typedef JSONNode** json_iterator; | ||||
#define json_iterator_ptr(iter) iter | ||||
#define ptr_to_json_iterator(iter) iter | ||||
json_iterator insert(json_iterator pos, JSONNode * x); | ||||
#endif | #endif | |||
#ifdef JSON_SAFE | json_iterator begin(void); | |||
void Nullify(void); | json_iterator end(void); | |||
json_iterator find(const json_string & name_t); | ||||
#ifdef JSON_CASE_INSENSITIVE_FUNCTIONS | ||||
json_iterator find_nocase(const json_string & name_t); | ||||
#endif | #endif | |||
json_iterator erase(json_iterator pos); | ||||
json_iterator erase(json_iterator start, const json_iterator & en | ||||
d); | ||||
json_iterator insert(json_iterator pos, const json_iterator & _st | ||||
art, const json_iterator & _end); | ||||
#endif | ||||
#ifdef DEBUG | #ifdef JSON_MUTEX_CALLBACKS | |||
unsigned int GetMemoryUsage(void); | static void register_mutex_callbacks(json_mutex_callback_t lock, | |||
json_string MemDump(unsigned int indent = 0); | json_mutex_callback_t unlock, void * manager_lock); | |||
#ifdef JSON_MUTEX_MANAGE | ||||
static void register_mutex_destructor(json_mutex_callback_ | ||||
t destroy); | ||||
#endif | #endif | |||
static void set_global_mutex(void * mutex); | ||||
void set_mutex(void * mutex); | ||||
void lock(int thread); | ||||
void unlock(int thread); | ||||
struct auto_lock { | ||||
public: | ||||
auto_lock(JSONNode & node, int thread) : mynode(&no | ||||
de), mythread(thread){ | ||||
mynode -> lock(mythread); | ||||
} | ||||
auto_lock(JSONNode * node, int thread) : mynode(nod | ||||
e), mythread(thread){ | ||||
mynode -> lock(mythread); | ||||
} | ||||
~auto_lock(void){ | ||||
mynode -> unlock(mythread); | ||||
} | ||||
private: | ||||
auto_lock & operator = (const auto_lock &); | ||||
auto_lock(const auto_lock &); | ||||
JSONNode * mynode; | ||||
int mythread; | ||||
}; | ||||
static void * getThisLock(JSONNode * pthis); | ||||
#endif | ||||
//This is the name of the node, the encoded flag tells the writer wh | #ifdef JSON_UNIT_TEST | |||
ether or not to re-escape it when it gets written | static int getNodeAllocationCount(void); | |||
json_string _name; bool name_encoded; | static int getNodeDeallocationCount(void); | |||
static int getInternalAllocationCount(void); | ||||
static int getInternalDeallocationCount(void); | ||||
static void incAllocCount(void); | ||||
static void decAllocCount(void); | ||||
static void incinternalAllocCount(void); | ||||
static void decinternalAllocCount(void); | ||||
#endif | ||||
//This is the json_string that is the value of the node, this mig | #ifdef JSON_WRITER | |||
ht be a json_string, a number, or even a set of nodes or array that hasn't | json_string write(void); | |||
been parsed yet | json_string write_formatted(void); | |||
json_string _string; bool string_encoded; | #endif | |||
//internal structure changes depending on type | #ifdef JSON_DEBUG | |||
value_union_t _value; | #ifndef JSON_LIBRARY | |||
JSONNode dump(void) const; | ||||
#endif | ||||
#endif | ||||
static void deleteJSONNode(JSONNode * ptr); | ||||
static JSONNode * newJSONNode_Shallow(const JSONNode & orig); | ||||
JSON_PRIVATE | ||||
static JSONNode * newJSONNode(const JSONNode & orig JSON_MUTEX_COPY | ||||
_DECL2); | ||||
static JSONNode * newJSONNode(internalJSONNode * internal_t); | ||||
//used by JSONWorker | ||||
JSONNode(const json_string & unparsed) : internal(internalJSONNode::new | ||||
Internal(unparsed)){ //root, specialized because it can only be array or no | ||||
de | ||||
incAllocCount(); | ||||
} | ||||
JSONNode(internalJSONNode * internal_t) : internal(internal_t){ //do no | ||||
t increment anything, this is only used in one case and it's already taken | ||||
care of | ||||
incAllocCount(); | ||||
} | ||||
JSONNode(bool, JSONNode & orig); | ||||
jsonChildren Children; | void decRef(void); //decrements internal's counter, deletes it if need | |||
private: | ed | |||
void FetchString(void); | #ifdef JSON_REF_COUNT | |||
void FetchNode(void); | void makeUniqueInternal(void); //makes internal it's own | |||
void FetchArray(void); | void merge(JSONNode * other); | |||
void FetchNumber(void); | #endif | |||
json_string WriteChildren(unsigned int indent); | #ifdef JSON_DEBUG | |||
json_string WriteName(bool formatted) const; | #ifndef JSON_LIBRARY | |||
json_string WriteComment(unsigned int indent) const; | JSONNode dump(size_t & totalmemory); | |||
#endif | ||||
#endif | ||||
#ifdef JSON_ITERATORS | ||||
#ifndef JSON_LIBRARY | ||||
json_iterator insertFRR(json_iterator pos, JSONNode ** con | ||||
st _start, JSONNode ** const _end); | ||||
reverse_iterator insertRRR(reverse_iterator pos, JSONNode | ||||
** const _start, JSONNode ** const _end); | ||||
reverse_iterator insertRFF(reverse_iterator pos, JSONNode | ||||
** const _start, JSONNode ** const _end); | ||||
#endif | ||||
json_iterator insertFFF(json_iterator pos, JSONNode ** const _sta | ||||
rt, JSONNode ** const _end); | ||||
#endif | ||||
mutable internalJSONNode * internal; | ||||
friend class JSONWorker; | ||||
friend class internalJSONNode; | ||||
}; | }; | |||
/* | ||||
Implementations are here to keep the class declaration cleaner. They c | ||||
an't be placed in a different | ||||
file because they are inlined. | ||||
*/ | ||||
inline JSONNode::JSONNode(char mytype) : internal(internalJSONNode::newInte | ||||
rnal(mytype)){ | ||||
JSON_ASSERT((mytype == JSON_NULL) || | ||||
(mytype == JSON_STRING) || | ||||
(mytype == JSON_NUMBER) || | ||||
(mytype == JSON_BOOL) || | ||||
(mytype == JSON_ARRAY) || | ||||
(mytype == JSON_NODE), JSON_TEXT("Not a proper JSON | ||||
type")); | ||||
incAllocCount(); | ||||
} | ||||
inline JSONNode::JSONNode(const JSONNode & orig): internal(orig.internal -> | ||||
incRef()){ | ||||
incAllocCount(); | ||||
} | ||||
//this allows a temp node to simply transfer its contents, even with ref co | ||||
unting off | ||||
inline JSONNode::JSONNode(bool, JSONNode & orig): internal(orig.internal){ | ||||
orig.internal = 0; | ||||
incAllocCount(); | ||||
} | ||||
inline JSONNode::~JSONNode(void){ | ||||
if (internal) decRef(); | ||||
decAllocCount(); | ||||
} | ||||
inline json_index_t JSONNode::size(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> size(); | ||||
} | ||||
inline bool JSONNode::empty(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> empty(); | ||||
} | ||||
inline void JSONNode::clear(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
if (!empty()){ | ||||
makeUniqueInternal(); | ||||
internal -> Children.clear(); | ||||
} | ||||
} | ||||
inline unsigned char JSONNode::type(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> type(); | ||||
} | ||||
inline json_string JSONNode::name(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> name(); | ||||
} | ||||
inline void JSONNode::set_name(const json_string & newname){ | ||||
JSON_CHECK_INTERNAL(); | ||||
makeUniqueInternal(); | ||||
internal -> setname(newname); | ||||
} | ||||
#ifdef JSON_COMMENTS | ||||
inline void JSONNode::set_comment(const json_string & newname){ | ||||
JSON_CHECK_INTERNAL(); | ||||
makeUniqueInternal(); | ||||
internal -> setcomment(newname); | ||||
} | ||||
inline json_string JSONNode::get_comment(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> getcomment(); | ||||
} | ||||
#endif | ||||
inline json_string JSONNode::as_string(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> as_string(); | ||||
} | ||||
inline long JSONNode::as_int(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> as_int(); | ||||
} | ||||
inline json_number JSONNode::as_float(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> as_float(); | ||||
} | ||||
inline bool JSONNode::as_bool(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> as_bool(); | ||||
} | ||||
#ifdef JSON_BINARY | ||||
inline void JSONNode::set_binary(const unsigned char * bin, json_index_ | ||||
t bytes){ | ||||
JSON_CHECK_INTERNAL(); | ||||
*this = JSONBase64::json_encode64(bin, bytes); | ||||
} | ||||
inline std::string JSONNode::as_binary(void) const { | ||||
JSON_ASSERT_SAFE(type() == JSON_STRING, JSON_TEXT("using as_binar | ||||
y for a non-string type"), return EMPTY_STRING2;); | ||||
JSON_CHECK_INTERNAL(); | ||||
return JSONBase64::json_decode64(as_string()); | ||||
} | ||||
#endif | ||||
inline JSONNode & JSONNode::operator[](const json_string & name_t){ | ||||
JSON_CHECK_INTERNAL(); | ||||
makeUniqueInternal(); | ||||
return *(*(internal -> at(name_t))); | ||||
} | ||||
inline const JSONNode & JSONNode::operator[](const json_string & name_t) co | ||||
nst { | ||||
JSON_CHECK_INTERNAL(); | ||||
return *(*(internal -> at(name_t))); | ||||
} | ||||
#ifdef JSON_LIBRARY | ||||
inline void JSONNode::push_back(JSONNode * child){ | ||||
#else | ||||
inline void JSONNode::push_back(const JSONNode & child){ | ||||
#endif | ||||
JSON_CHECK_INTERNAL(); | ||||
makeUniqueInternal(); | ||||
internal -> push_back(child); | ||||
} | ||||
inline void JSONNode::reserve(json_index_t size){ | ||||
makeUniqueInternal(); | ||||
internal -> reserve(size); | ||||
} | ||||
inline JSONNode & JSONNode::operator = (const JSONNode & orig){ | ||||
JSON_CHECK_INTERNAL(); | ||||
#ifdef JSON_REF_COUNT | ||||
if (internal == orig.internal) return *this; //don't want it acc | ||||
identally deleting itself | ||||
#endif | ||||
decRef(); //dereference my current one | ||||
internal = orig.internal -> incRef(); //increase reference of original | ||||
return *this; | ||||
} | ||||
#ifndef JSON_LIBRARY | ||||
inline JSONNode & JSONNode::operator = (const json_char * val){ | ||||
JSON_CHECK_INTERNAL(); | ||||
*this = json_string(val); | ||||
return *this; | ||||
} | ||||
#endif | ||||
#define NODE_SET_TYPED(type)\ | ||||
inline JSONNode & JSONNode::operator = (type val){\ | ||||
JSON_CHECK_INTERNAL();\ | ||||
makeUniqueInternal();\ | ||||
internal -> Set(val);\ | ||||
return *this;\ | ||||
} | ||||
IMPLEMENT_FOR_ALL_TYPES(NODE_SET_TYPED) | ||||
/* | ||||
This section is the equality operators | ||||
*/ | ||||
#define NODE_CHECK_EQUALITY(type)\ | ||||
inline bool JSONNode::operator == (type val) const {\ | ||||
JSON_CHECK_INTERNAL();\ | ||||
return internal -> IsEqualToNum<type>(val);\ | ||||
} | ||||
IMPLEMENT_FOR_ALL_NUMBERS(NODE_CHECK_EQUALITY) | ||||
inline bool JSONNode::operator == (const json_string & val) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> IsEqualTo(val); | ||||
} | ||||
#ifndef JSON_LIBRARY | ||||
inline bool JSONNode::operator == (const json_char * val) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return *this == json_string(val); | ||||
} | ||||
#endif | ||||
inline bool JSONNode::operator == (bool val) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> IsEqualTo(val); | ||||
} | ||||
inline bool JSONNode::operator == (const JSONNode & val) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
return internal -> IsEqualTo(val.internal); | ||||
} | ||||
/* | ||||
This section is the inequality operators | ||||
*/ | ||||
#define NODE_CHECK_INEQUALITY(type)\ | ||||
inline bool JSONNode::operator != (type val) const {\ | ||||
JSON_CHECK_INTERNAL();\ | ||||
return !(*this == val);\ | ||||
} | ||||
IMPLEMENT_FOR_ALL_TYPES(NODE_CHECK_INEQUALITY) | ||||
NODE_CHECK_INEQUALITY(const JSONNode &) | ||||
#ifndef JSON_LIBRARY | ||||
NODE_CHECK_INEQUALITY(const json_char * ) | ||||
#endif | ||||
inline void JSONNode::nullify(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
makeUniqueInternal(); | ||||
internal -> Nullify(); | ||||
} | ||||
inline void JSONNode::swap(JSONNode & other){ | ||||
JSON_CHECK_INTERNAL(); | ||||
internalJSONNode * temp = other.internal; | ||||
other.internal = internal; | ||||
internal = temp; | ||||
JSON_CHECK_INTERNAL(); | ||||
} | ||||
inline void JSONNode::decRef(void){ //decrements internal's counter, delete | ||||
s it if needed | ||||
JSON_CHECK_INTERNAL(); | ||||
#ifdef JSON_REF_COUNT | ||||
internal -> decRef(); | ||||
if (internal -> hasNoReferences()){ | ||||
internalJSONNode::deleteInternal(internal); | ||||
} | ||||
#else | ||||
internalJSONNode::deleteInternal(internal); | ||||
#endif | ||||
} | ||||
#ifdef JSON_REF_COUNT | ||||
inline void JSONNode::makeUniqueInternal(){ //makes internal it's own | ||||
JSON_CHECK_INTERNAL(); | ||||
internal = internal -> makeUnique(); //might return itself or a | ||||
new one that's exactly the same | ||||
} | ||||
#endif | ||||
#ifdef JSON_ITERATORS | ||||
inline JSONNode::json_iterator JSONNode::begin(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEX | ||||
T("iterating a non-iteratable node")); | ||||
makeUniqueInternal(); | ||||
return json_iterator(internal -> begin()); | ||||
} | ||||
inline JSONNode::json_iterator JSONNode::end(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, JSON_TEX | ||||
T("iterating a non-iteratable node")); | ||||
makeUniqueInternal(); | ||||
return json_iterator(internal -> end()); | ||||
} | ||||
#ifndef JSON_LIBRARY | ||||
inline JSONNode::const_iterator JSONNode::begin(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, J | ||||
SON_TEXT("iterating a non-iteratable node")); | ||||
return JSONNode::const_iterator(internal -> begin()); | ||||
} | ||||
inline JSONNode::const_iterator JSONNode::end(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, J | ||||
SON_TEXT("iterating a non-iteratable node")); | ||||
return JSONNode::const_iterator(internal -> end()); | ||||
} | ||||
inline JSONNode::reverse_iterator JSONNode::rbegin(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, J | ||||
SON_TEXT("iterating a non-iteratable node")); | ||||
makeUniqueInternal(); | ||||
return JSONNode::reverse_iterator(internal -> end() - 1); | ||||
} | ||||
inline JSONNode::reverse_iterator JSONNode::rend(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, J | ||||
SON_TEXT("iterating a non-iteratable node")); | ||||
makeUniqueInternal(); | ||||
return JSONNode::reverse_iterator(internal -> begin() - 1) | ||||
; | ||||
} | ||||
inline JSONNode::reverse_const_iterator JSONNode::rbegin(void) co | ||||
nst { | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, J | ||||
SON_TEXT("iterating a non-iteratable node")); | ||||
return JSONNode::reverse_const_iterator(internal -> end() | ||||
- 1); | ||||
} | ||||
inline JSONNode::reverse_const_iterator JSONNode::rend(void) cons | ||||
t { | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT(type() == JSON_NODE || type() == JSON_ARRAY, J | ||||
SON_TEXT("iterating a non-iteratable node")); | ||||
return JSONNode::reverse_const_iterator(internal -> begin( | ||||
) - 1); | ||||
} | ||||
inline JSONNode::iterator JSONNode::insert(json_iterator pos, con | ||||
st const_iterator & _start, const const_iterator & _end){ | ||||
return insertFFF(pos, _start.it, _end.it); | ||||
} | ||||
inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterat | ||||
or pos, const const_iterator & _start, const const_iterator & _end){ | ||||
return insertRFF(pos, _start.it, _end.it); | ||||
} | ||||
inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterat | ||||
or pos, const iterator & _start, const iterator & _end){ | ||||
return insertRFF(pos, _start.it, _end.it); | ||||
} | ||||
inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterat | ||||
or pos, const reverse_const_iterator & _start, const reverse_const_iterator | ||||
& _end){ | ||||
return insertRRR(pos, _start.it, _end.it); | ||||
} | ||||
inline JSONNode::reverse_iterator JSONNode::insert(reverse_iterat | ||||
or pos, const reverse_iterator & _start, const reverse_iterator & _end){ | ||||
return insertRRR(pos, _start.it, _end.it); | ||||
} | ||||
inline JSONNode::iterator JSONNode::insert(json_iterator pos, con | ||||
st reverse_const_iterator & _start, const reverse_const_iterator & _end){ | ||||
return insertFRR(pos, _start.it, _end.it); | ||||
} | ||||
inline JSONNode::iterator JSONNode::insert(iterator pos, const re | ||||
verse_iterator & _start, const reverse_iterator & _end){ | ||||
return insertFRR(pos, _start.it, _end.it); | ||||
} | ||||
#endif | ||||
inline JSONNode::json_iterator JSONNode::insert(json_iterator pos, cons | ||||
t json_iterator & _start, const json_iterator & _end){ | ||||
return insertFFF(pos, json_iterator_ptr(_start), json_iterator_pt | ||||
r(_end)); | ||||
} | ||||
#endif | ||||
#ifdef JSON_WRITER | ||||
inline json_string JSONNode::write(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSO | ||||
N_TEXT("Writing a non-writable node"), return JSON_TEXT("");); | ||||
return internal -> Write(0xFFFFFFFF, true); | ||||
} | ||||
inline json_string JSONNode::write_formatted(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSO | ||||
N_TEXT("Writing a non-writable node"), return JSON_TEXT("");); | ||||
return internal -> Write(0, true); | ||||
} | ||||
#endif | ||||
#ifndef JSON_PREPARSE | ||||
inline void JSONNode::preparse(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
internal -> preparse(); | ||||
} | ||||
#endif | ||||
#ifdef JSON_VALIDATE | ||||
inline bool JSONNode::validate(void){ | ||||
JSON_CHECK_INTERNAL(); | ||||
if (type() == JSON_NULL) return false; | ||||
JSON_ASSERT_SAFE(type() == JSON_NODE || type() == JSON_ARRAY, JSO | ||||
N_TEXT("Validating non root node"), return false;); | ||||
#ifndef JSON_PREPARSE | ||||
internal -> Fetch(); //will nullify it if it's bad | ||||
#endif | ||||
if (type() == JSON_NULL) return false; | ||||
return internal -> validate(); | ||||
} | ||||
#endif | ||||
#ifdef JSON_DEBUG | ||||
#ifndef JSON_LIBRARY | ||||
inline JSONNode JSONNode::dump(void) const { | ||||
JSON_CHECK_INTERNAL(); | ||||
JSONNode dumpage(JSON_NODE); | ||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (lo | ||||
ng)this))); | ||||
size_t total = 0; | ||||
JSONNode node = internal -> Dump(total); | ||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("total bytes | ||||
used"), total))); | ||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("bytes used" | ||||
), sizeof(JSONNode)))); | ||||
dumpage.push_back(JSON_NEW(node)); | ||||
return dumpage; | ||||
} | ||||
inline JSONNode JSONNode::dump(size_t & totalmemory){ | ||||
JSON_CHECK_INTERNAL(); | ||||
JSONNode dumpage(JSON_NODE); | ||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("this"), (lo | ||||
ng)this))); | ||||
dumpage.push_back(JSON_NEW(JSONNode(JSON_TEXT("bytes used" | ||||
), sizeof(JSONNode)))); | ||||
dumpage.push_back(JSON_NEW(internal -> Dump(totalmemory))) | ||||
; | ||||
return dumpage; | ||||
} | ||||
#endif | ||||
#endif | ||||
inline void JSONNode::deleteJSONNode(JSONNode * ptr){ | ||||
#ifdef JSON_MEMORY_CALLBACKS | ||||
ptr -> ~JSONNode(); | ||||
libjson_free<JSONNode>(ptr); | ||||
#else | ||||
delete ptr; | ||||
#endif | ||||
} | ||||
inline JSONNode * _newJSONNode(const JSONNode & orig){ | ||||
#ifdef JSON_MEMORY_CALLBACKS | ||||
return new(json_malloc<JSONNode>(1)) JSONNode(orig); | ||||
#else | ||||
return new JSONNode(orig); | ||||
#endif | ||||
} | ||||
inline JSONNode * JSONNode::newJSONNode(const JSONNode & orig JSON_MUTEX | ||||
_COPY_DECL){ | ||||
#ifdef JSON_MUTEX_CALLBACKS | ||||
if (parentMutex){ | ||||
JSONNode * temp = _newJSONNode(orig); | ||||
temp -> set_mutex(parentMutex); | ||||
return temp; | ||||
} | ||||
#endif | ||||
return _newJSONNode(orig); | ||||
} | ||||
inline JSONNode * JSONNode::newJSONNode(internalJSONNode * internal_t){ | ||||
#ifdef JSON_MEMORY_CALLBACKS | ||||
return new(json_malloc<JSONNode>(1)) JSONNode(internal_t); | ||||
#else | ||||
return new JSONNode(internal_t); | ||||
#endif | ||||
} | ||||
inline JSONNode * JSONNode::newJSONNode_Shallow(const JSONNode & orig){ | ||||
#ifdef JSON_MEMORY_CALLBACKS | ||||
return new(json_malloc<JSONNode>(1)) JSONNode(true, const_cast<JS | ||||
ONNode &>(orig)); | ||||
#else | ||||
return new JSONNode(true, const_cast<JSONNode &>(orig)); | ||||
#endif | ||||
} | ||||
#endif | #endif | |||
End of changes. 27 change blocks. | ||||
102 lines changed or deleted | 1019 lines changed or added | |||