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

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/