Jamoma API  0.6.0.a19
internalJSONNode.h
1 #ifndef INTERNAL_JSONNODE_H
2 #define INTERNAL_JSONNODE_H
3 
4 #include "JSONDebug.h"
5 #include "JSONChildren.h"
6 #include "JSONMemory.h"
7 #include "JSONGlobals.h"
8 #ifdef JSON_DEBUG
9  #include <climits> //to check int value
10 #endif
11 #include "JSONSharedString.h"
12 
13 #ifdef JSON_LESS_MEMORY
14  #ifdef __GNUC__
15  #pragma pack(push, 1)
16  #elif _MSC_VER
17  #pragma pack(push, internalJSONNode_pack, 1)
18  #endif
19 #endif
20 
21 /*
22  This class is the work horse of libjson, it handles all of the
23  functinality of JSONNode. This object is reference counted for
24  speed and memory reasons.
25 
26  If JSON_REF_COUNT is not on, this internal structure still has an important
27  purpose, as it can be passed around by JSONNoders that are flagged as temporary
28 */
29 
30 class JSONNode; //forward declaration
31 
32 #ifndef JSON_LIBRARY
33  #define DECL_SET_INTEGER(type) void Set(type) json_nothrow json_write_priority; void Set(unsigned type) json_nothrow json_write_priority;
34  #define DECL_CAST_OP(type) operator type() const json_nothrow; operator unsigned type() const json_nothrow;
35 #endif
36 
37 #ifdef JSON_MUTEX_CALLBACKS
38  #define initializeMutex(x) ,mylock(x)
39 #else
40  #define initializeMutex(x)
41 #endif
42 
43 #if defined(JSON_PREPARSE) || !defined(JSON_READ_PRIORITY)
44  #define SetFetched(b) (void)0
45  #define Fetch() (void)0
46  #define initializeFetch(x)
47 #else
48  #define initializeFetch(x) ,fetched(x)
49 #endif
50 
51 #ifdef JSON_REF_COUNT
52  #define initializeRefCount(x) ,refcount(x)
53 #else
54  #define initializeRefCount(x)
55 #endif
56 
57 #ifdef JSON_COMMENTS
58  #define initializeComment(x) ,_comment(x)
59 #else
60  #define initializeComment(x)
61 #endif
62 
63 #ifdef JSON_LESS_MEMORY
64  #define CHILDREN _value.Children
65  #define DELETE_CHILDREN()\
66  if (isContainer()){\
67  jsonChildren::deleteChildren(CHILDREN);\
68  }
69  #define CHILDREN_TO_NULL() (void)0
70  #define initializeChildren(x)
71 #else
72  #define CHILDREN Children
73  #define DELETE_CHILDREN()\
74  if (CHILDREN != 0) jsonChildren::deleteChildren(CHILDREN);
75  #define CHILDREN_TO_NULL() CHILDREN = 0
76  #define makeNotContainer() (void)0
77  #define makeContainer() if (!CHILDREN) CHILDREN = jsonChildren::newChildren()
78  #define initializeChildren(x) ,CHILDREN(x)
79 #endif
80 
81 class internalJSONNode {
82 public:
83  LIBJSON_OBJECT(internalJSONNode);
84  internalJSONNode(char mytype = JSON_NULL) json_nothrow json_hot;
85  #ifdef JSON_READ_PRIORITY
86  internalJSONNode(const json_string & unparsed) json_nothrow json_hot;
87  internalJSONNode(const json_string & name_t, const json_string & value_t) json_nothrow json_read_priority;
88  #endif
89  internalJSONNode(const internalJSONNode & orig) json_nothrow json_hot;
90  internalJSONNode & operator = (const internalJSONNode &) json_nothrow json_hot;
91  ~internalJSONNode(void) json_nothrow json_hot;
92 
93  static internalJSONNode * newInternal(char mytype = JSON_NULL) json_hot;
94  #ifdef JSON_READ_PRIORITY
95  static internalJSONNode * newInternal(const json_string & unparsed) json_hot;
96  static internalJSONNode * newInternal(const json_string & name_t, const json_string & value_t) json_hot;
97  #endif
98  static internalJSONNode * newInternal(const internalJSONNode & orig) json_hot; //not copyable, only by this class
99  static void deleteInternal(internalJSONNode * ptr) json_nothrow json_hot;
100 
101  json_index_t size(void) const json_nothrow json_read_priority;
102  bool empty(void) const json_nothrow;
103  unsigned char type(void) const json_nothrow json_read_priority;
104 
105  json_string name(void) const json_nothrow json_read_priority;
106  void setname(const json_string & newname) json_nothrow json_write_priority;
107  #ifdef JSON_COMMENTS
108  void setcomment(const json_string & comment) json_nothrow;
109  json_string getcomment(void) const json_nothrow;
110  #endif
111 
112  #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
113  void preparse(void) json_nothrow;
114  #endif
115 
116  #ifdef JSON_LIBRARY
117  void push_back(JSONNode * node) json_nothrow;
118  #else
119  void push_back(const JSONNode & node) json_nothrow;
120  #endif
121  void reserve(json_index_t siz) json_nothrow;
122  void push_front(const JSONNode & node) json_nothrow;
123  JSONNode * pop_back(json_index_t pos) json_nothrow;
124  JSONNode * pop_back(const json_string & name_t) json_nothrow;
125  #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
126  JSONNode * pop_back_nocase(const json_string & name_t) json_nothrow;
127  #endif
128 
129  JSONNode * at(json_index_t pos) json_nothrow;
130  //These return ** because pop_back needs them
131  JSONNode ** at(const json_string & name_t) json_nothrow;
132  #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
133  JSONNode ** at_nocase(const json_string & name_t) json_nothrow;
134  #endif
135 
136  void Set(const json_string & val) json_nothrow json_write_priority;
137  #ifdef JSON_LIBRARY
138  void Set(json_number val) json_nothrow json_write_priority;
139  void Set(json_int_t val) json_nothrow json_write_priority;
140  operator json_int_t() const json_nothrow;
141  operator json_number() const json_nothrow;
142  #else
143  DECL_SET_INTEGER(char)
144  DECL_SET_INTEGER(short)
145  DECL_SET_INTEGER(int)
146  DECL_SET_INTEGER(long)
147  #ifndef JSON_ISO_STRICT
148  DECL_SET_INTEGER(long long)
149  void Set(long double val) json_nothrow json_write_priority;
150  #endif
151  void Set(float val) json_nothrow json_write_priority;
152  void Set(double val) json_nothrow json_write_priority;
153 
154 
155  DECL_CAST_OP(char)
156  DECL_CAST_OP(short)
157  DECL_CAST_OP(int)
158  DECL_CAST_OP(long)
159  #ifndef JSON_ISO_STRICT
160  DECL_CAST_OP(long long)
161  operator long double() const json_nothrow;
162  #endif
163  operator float() const json_nothrow;
164  operator double() const json_nothrow;
165  #endif
166  operator json_string()const json_nothrow;
167  operator bool() const json_nothrow;
168  void Set(bool val) json_nothrow;
169 
170  bool IsEqualTo(const json_string & val) const json_nothrow;
171  bool IsEqualTo(bool val) const json_nothrow;
172  bool IsEqualTo(const internalJSONNode * val) const json_nothrow;
173 
174  template<typename T>
175  bool IsEqualToNum(T val) const json_nothrow;
176 
177  internalJSONNode * incRef(void) json_nothrow;
178  #ifdef JSON_REF_COUNT
179  void decRef(void) json_nothrow json_hot;
180  bool hasNoReferences(void) json_nothrow json_hot;
181  #endif
182  internalJSONNode * makeUnique(void) json_nothrow json_hot;
183 
184  JSONNode ** begin(void) const json_nothrow;
185  JSONNode ** end(void) const json_nothrow;
186  bool Fetched(void) const json_nothrow json_hot;
187  #ifdef JSON_MUTEX_CALLBACKS
188  void _set_mutex(void * mutex, bool unset = true) json_nothrow json_cold;
189  void _unset_mutex(void) json_nothrow json_cold;
190  #endif
191 
192  #ifdef JSON_WRITE_PRIORITY
193  void DumpRawString(json_string & output) const json_nothrow json_write_priority;
194  void WriteName(bool formatted, bool arrayChild, json_string & output) const json_nothrow json_write_priority;
195  #ifdef JSON_ARRAY_SIZE_ON_ONE_LINE
196  void WriteChildrenOneLine(unsigned int indent, json_string & output) const json_nothrow json_write_priority;
197  #endif
198  void WriteChildren(unsigned int indent, json_string & output) const json_nothrow json_write_priority;
199  void WriteComment(unsigned int indent, json_string & output) const json_nothrow json_write_priority;
200  void Write(unsigned int indent, bool arrayChild, json_string & output) const json_nothrow json_write_priority;
201  #endif
202 
203 
204  inline bool isContainer(void) const json_nothrow {
205  return (_type == JSON_NODE || _type == JSON_ARRAY);
206  }
207  inline bool isNotContainer(void) const json_nothrow {
208  return (_type != JSON_NODE && _type != JSON_ARRAY);
209  }
210 
211  #ifdef JSON_LESS_MEMORY
212  inline void makeNotContainer(void){
213  if (isContainer()){
214  jsonChildren::deleteChildren(CHILDREN);
215  }
216  }
217  inline void makeContainer(void){
218  if (isNotContainer()){
219  CHILDREN = jsonChildren::newChildren();
220  }
221  }
222  #endif
223 
224  void Nullify(void) const json_nothrow;
225 
226  #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
227  void SetFetched(bool val) const json_nothrow json_hot;
228  void Fetch(void) const json_nothrow json_hot; //it's const because it doesn't change the VALUE of the function
229  #endif
230 
231  #ifdef JSON_READ_PRIORITY
232  void FetchString(void) const json_nothrow json_read_priority;
233  void FetchNode(void) const json_nothrow json_read_priority;
234  void FetchArray(void) const json_nothrow json_read_priority;
235  #endif
236  void FetchNumber(void) const json_nothrow json_read_priority;
237 
238  #ifdef JSON_CASE_INSENSITIVE_FUNCTIONS
239  static bool AreEqualNoCase(const json_char * ch_one, const json_char * ch_two) json_nothrow json_read_priority;
240  #endif
241 
242  inline void clearname(void) json_nothrow {
243  clearString(_name);
244  }
245 
246  #ifdef JSON_DEBUG
247  #ifndef JSON_LIBRARY
248  JSONNode Dump(size_t & totalmemory) const json_nothrow;
249  JSONNode DumpMutex(void) const json_nothrow;
250  #endif
251  #endif
252 
253 
254  mutable unsigned char _type BITS(3);
255 
256  json_string _name;
257  mutable bool _name_encoded BITS(1); //must be above name due to initialization list order
258 
259  mutable json_string _string; //these are both mutable because the string can change when it's fetched
260  mutable bool _string_encoded BITS(1);
261 
262  //the value of the json
263  union value_union_t {
264  bool _bool BITS(1);
265  json_number _number;
266  #ifdef JSON_LESS_MEMORY
267  jsonChildren * Children;
268  #endif
269  };
270  mutable value_union_t _value; //internal structure changes depending on type
271 
272  #ifdef JSON_MUTEX_CALLBACKS
273  void * mylock;
274  #endif
275 
276  #ifdef JSON_REF_COUNT
277  size_t refcount PACKED(20);
278  #endif
279 
280  #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
281  mutable bool fetched BITS(1);
282  #endif
283 
284  #ifdef JSON_COMMENTS
285  json_string _comment;
286  #endif
287 
288  #ifndef JSON_LESS_MEMORY
289  jsonChildren * CHILDREN;
290  #endif
291 };
292 
293 inline internalJSONNode::internalJSONNode(char mytype) json_nothrow : _type(mytype), _name(), _name_encoded(), _string(), _string_encoded(), _value()
294  initializeMutex(0)
295  initializeRefCount(1)
296  initializeFetch(true)
297  initializeComment(json_global(EMPTY_JSON_STRING))
298  initializeChildren((_type == JSON_NODE || _type == JSON_ARRAY) ? jsonChildren::newChildren() : 0){
299 
300  LIBJSON_CTOR;
301 
302  #ifdef JSON_LESS_MEMORY
303  //if not less memory, its in the initialization list
304  if (isContainer()){
305  CHILDREN = jsonChildren::newChildren();
306  }
307  #endif
308 }
309 
310 inline internalJSONNode * internalJSONNode::incRef(void) json_nothrow {
311  #ifdef JSON_REF_COUNT
312  ++refcount;
313  return this;
314  #else
315  return makeUnique();
316  #endif
317 }
318 
319 inline json_index_t internalJSONNode::size(void) const json_nothrow {
320  if (isNotContainer()) return 0;
321  Fetch();
322  return CHILDREN -> size();
323 }
324 
325 inline bool internalJSONNode::empty(void) const json_nothrow {
326  if (isNotContainer()) return true;
327  Fetch();
328  return CHILDREN -> empty();
329 }
330 
331 inline unsigned char internalJSONNode::type(void) const json_nothrow {
332  return _type;
333 }
334 
335 inline json_string internalJSONNode::name(void) const json_nothrow {
336  return _name;
337 }
338 
339 inline void internalJSONNode::setname(const json_string & newname) json_nothrow {
340  #ifdef JSON_LESS_MEMORY
341  JSON_ASSERT(newname.capacity() == newname.length(), JSON_TEXT("name object too large"));
342  #endif
343  _name = newname;
344  _name_encoded = true;
345 }
346 
347 #ifdef JSON_COMMENTS
348  inline void internalJSONNode::setcomment(const json_string & comment) json_nothrow {
349  _comment = comment;
350  }
351 
352  inline json_string internalJSONNode::getcomment(void) const json_nothrow {
353  return _comment;
354  }
355 #endif
356 
357 inline bool internalJSONNode::IsEqualTo(const json_string & val) const json_nothrow {
358  if (type() != JSON_STRING) return false;
359  Fetch();
360  return _string == val;
361 }
362 
363 inline bool internalJSONNode::IsEqualTo(bool val) const json_nothrow {
364  if (type() != JSON_BOOL) return false;
365  Fetch();
366  return val == _value._bool;
367 }
368 
369 template<typename T>
370 inline bool internalJSONNode::IsEqualToNum(T val) const json_nothrow {
371  if (type() != JSON_NUMBER) return false;
372  Fetch();
373  return (json_number)val == _value._number;
374 }
375 
376 #ifdef JSON_REF_COUNT
377  inline void internalJSONNode::decRef(void) json_nothrow {
378  JSON_ASSERT(refcount != 0, JSON_TEXT("decRef on a 0 refcount internal"));
379  --refcount;
380  }
381 
382  inline bool internalJSONNode::hasNoReferences(void) json_nothrow {
383  return refcount == 0;
384  }
385 #endif
386 
387 inline internalJSONNode * internalJSONNode::makeUnique(void) json_nothrow {
388  #ifdef JSON_REF_COUNT
389  if (refcount > 1){
390  decRef();
391  return newInternal(*this);
392  }
393  JSON_ASSERT(refcount == 1, JSON_TEXT("makeUnique on a 0 refcount internal"));
394  return this;
395  #else
396  return newInternal(*this);
397  #endif
398 }
399 
400 #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
401  inline void internalJSONNode::SetFetched(bool val) const json_nothrow {
402  fetched = val;
403  }
404 #endif
405 
406 inline bool internalJSONNode::Fetched(void) const json_nothrow {
407  #if !defined(JSON_PREPARSE) && defined(JSON_READ_PRIORITY)
408  return fetched;
409  #else
410  return true;
411  #endif
412 }
413 
414 inline JSONNode ** internalJSONNode::begin(void) const json_nothrow {
415  JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("begin"), return 0;);
416  Fetch();
417  return CHILDREN -> begin();
418 }
419 
420 inline JSONNode ** internalJSONNode::end(void) const json_nothrow {
421  JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("end"), return 0;);
422  Fetch();
423  return CHILDREN -> end();
424 }
425 
426 inline JSONNode * internalJSONNode::at(json_index_t pos) json_nothrow {
427  JSON_ASSERT_SAFE(isContainer(), JSON_TEXT("calling at on non-container type"), return 0;);
428  Fetch();
429  return (*CHILDREN)[pos];
430 }
431 
432 #if defined(JSON_LESS_MEMORY) && defined(__GNUC__)
433  inline void internalJSONNode::reserve(json_index_t __attribute__((unused)) siz) json_nothrow
434 #else
435  inline void internalJSONNode::reserve(json_index_t siz) json_nothrow
436 #endif
437 {
438  JSON_ASSERT_SAFE(isContainer(), json_global(ERROR_NON_CONTAINER) + JSON_TEXT("reserve"), return;);
439  Fetch();
440  jsonChildren::reserve2(CHILDREN, siz);
441 }
442 
443 
444 
445 /*
446  cast operators
447 */
448 #ifndef JSON_LIBRARY
449  #ifdef JSON_ISO_STRICT
450  #define BASE_CONVERT_TYPE long
451  #else
452  #define BASE_CONVERT_TYPE long long
453  #endif
454 
455  #define IMP_SMALLER_INT_CAST_OP(_type, type_max, type_min)\
456  inline internalJSONNode::operator _type() const json_nothrow {\
457  JSON_ASSERT(_value._number > type_min, _string + json_global(ERROR_LOWER_RANGE) + JSON_TEXT(#_type));\
458  JSON_ASSERT(_value._number < type_max, _string + json_global(ERROR_UPPER_RANGE) + JSON_TEXT(#_type));\
459  JSON_ASSERT(_value._number == (json_number)((_type)(_value._number)), json_string(JSON_TEXT("(")) + json_string(JSON_TEXT(#_type)) + json_string(JSON_TEXT(") will truncate ")) + _string);\
460  return (_type)static_cast<BASE_CONVERT_TYPE>(*this);\
461  }
462 
463  IMP_SMALLER_INT_CAST_OP(char, CHAR_MAX, CHAR_MIN)
464  IMP_SMALLER_INT_CAST_OP(unsigned char, UCHAR_MAX, 0)
465  IMP_SMALLER_INT_CAST_OP(short, SHRT_MAX, SHRT_MIN)
466  IMP_SMALLER_INT_CAST_OP(unsigned short, USHRT_MAX, 0)
467  IMP_SMALLER_INT_CAST_OP(int, INT_MAX, INT_MIN)
468  IMP_SMALLER_INT_CAST_OP(unsigned int, UINT_MAX, 0)
469 
470  #ifndef JSON_ISO_STRICT
471  IMP_SMALLER_INT_CAST_OP(long, LONG_MAX, LONG_MIN)
472  IMP_SMALLER_INT_CAST_OP(unsigned long, ULONG_MAX, 0)
473  #endif
474 #endif
475 
476 inline internalJSONNode::operator json_string() const json_nothrow {
477  Fetch();
478  return _string;
479 }
480 
481 
482 #ifndef JSON_LIBRARY
483  #ifndef JSON_ISO_STRICT
484  inline internalJSONNode::operator float() const json_nothrow {
485  return static_cast<float>(static_cast<long double>(*this));
486  }
487  inline internalJSONNode::operator double() const json_nothrow {
488  return static_cast<double>(static_cast<long double>(*this));
489  }
490  #else
491  inline internalJSONNode::operator float() const json_nothrow {
492  return static_cast<float>(static_cast<double>(*this));
493  }
494  #endif
495 #endif
496 
497 #ifdef JSON_LESS_MEMORY
498  #ifdef __GNUC__
499  #pragma pack(pop)
500  #elif _MSC_VER
501  #pragma pack(pop, internalJSONNode_pack,)
502  #endif
503 #endif
504 #endif