Jamoma API  0.6.0.a19
JSONChildren.h
1 #ifndef JSONCHILDREN_H
2 #define JSONCHILDREN_H
3 
4 #include "JSONMemory.h"
5 #include "JSONDebug.h" //for JSON_ASSERT macro
6 
7 #ifdef JSON_LESS_MEMORY
8  #ifdef __GNUC__
9  #pragma pack(push, 1)
10  #elif _MSC_VER
11  #pragma pack(push, jsonChildren, 1)
12  #endif
13 #endif
14 
15 #define json_foreach(chldrn, itrtr)\
16  JSONNode ** itrtr = chldrn -> begin();\
17  for(JSONNode ** itrtr##_end = chldrn -> end(); itrtr != itrtr##_end; ++itrtr)
18 
19 /*
20  This class is essentially a vector that has been heavily optimized for the specific purpose
21  of holding JSONNode children. It acts the same way as a vector, it has a automatically
22  expanding array. On destruction, this container automatically destroys everything contained
23  in it as well, so that you libjson doesn't have to do that.
24 
25  T is JSONNode*, I can't define it that way directly because JSONNode uses this container, and because
26  the container deletes the children automatically, forward declaration can't be used
27  */
28 
29 class JSONNode; //forward declaration
30 
31 #ifdef JSON_LESS_MEMORY
32  #define childrenVirtual virtual
33 #else
34  #define childrenVirtual
35 #endif
36 
37 class jsonChildren {
38 public:
39  LIBJSON_OBJECT(jsonChildren);
40  //starts completely empty and the array is not allocated
41  jsonChildren(void) json_nothrow : array(0), mysize(0), mycapacity(0) {
42  LIBJSON_CTOR;
43  }
44 
45  #ifdef JSON_LESS_MEMORY
46  jsonChildren(JSONNode** ar, json_index_t si, json_index_t ca) json_nothrow : array(ar), mysize(si), mycapacity(ca) {
47  LIBJSON_CTOR;
48  }
49  #endif
50 
51  //deletes the array and everything that is contained within it (using delete)
52  childrenVirtual ~jsonChildren(void) json_nothrow {
53  if (json_unlikely(array != 0)){ //the following function calls are safe, but take more time than a check here
54  deleteAll();
55  libjson_free<JSONNode*>(array);
56  }
57  LIBJSON_DTOR;
58  }
59 
60  //increase the size of the array
61  void inc(json_index_t amount) json_nothrow;
62  void inc(void) json_nothrow;
63 
64  //Adds something to the vector, doubling the array if necessary
65  void push_back(JSONNode * item) json_nothrow {
66  JSON_ASSERT(this != 0, JSON_TEXT("Children is null push_back"));
67  inc();
68  array[mysize++] = item;
69  }
70 
71  //Adds something to the front of the vector, doubling the array if necessary
72  void push_front(JSONNode * item) json_nothrow {
73  JSON_ASSERT(this != 0, JSON_TEXT("Children is null push_front"));
74  inc();
75  std::memmove(array + 1, array, mysize++ * sizeof(JSONNode *));
76  array[0] = item;
77  }
78 
79  //gets an item out of the vector by it's position
80  inline JSONNode * operator[] (json_index_t position) const json_nothrow {
81  JSON_ASSERT(this != 0, JSON_TEXT("Children is null []"));
82  JSON_ASSERT(position < mysize, JSON_TEXT("Using [] out of bounds"));
83  JSON_ASSERT(position < mycapacity, JSON_TEXT("Using [] out of bounds"));
84  JSON_ASSERT(array != 0, JSON_TEXT("Array is null"));
85  return array[position];
86  }
87 
88  //returns the allocated capacity, but keep in mind that some might not be valid
89  inline json_index_t capacity() const json_nothrow {
90  JSON_ASSERT(this != 0, JSON_TEXT("Children is null capacity"));
91  return mycapacity;
92  }
93 
94  //returns the number of valid objects within the vector
95  inline json_index_t size() const json_nothrow {
96  JSON_ASSERT(this != 0, JSON_TEXT("Children is null size"));
97  return mysize;
98  }
99 
100  //tests whether or not the vector is empty
101  inline bool empty() const json_nothrow {
102  JSON_ASSERT(this != 0, JSON_TEXT("Children is null empty"));
103  return mysize == 0;
104  }
105 
106  //clears (and deletes) everything from the vector and sets it's size to 0
107  inline void clear() json_nothrow {
108  JSON_ASSERT(this != 0, JSON_TEXT("Children is null clear"));
109  if (json_likely(array != 0)){ //don't bother clearing anything if there is nothing in it
110  JSON_ASSERT(mycapacity != 0, JSON_TEXT("mycapacity is not zero, but array is null"));
111  deleteAll();
112  mysize = 0;
113  }
114  JSON_ASSERT(mysize == 0, JSON_TEXT("mysize is not zero after clear"));
115  }
116 
117  //returns the beginning of the array
118  inline JSONNode ** begin(void) const json_nothrow {
119  JSON_ASSERT(this != 0, JSON_TEXT("Children is null begin"));
120  return array;
121  }
122 
123  //returns the end of the array
124  inline JSONNode ** end(void) const json_nothrow {
125  JSON_ASSERT(this != 0, JSON_TEXT("Children is null end"));
126  return array + mysize;
127  }
128 
129  //makes sure that even after shirnking and expanding, the iterator is in same relative position
130  template <bool reverse>
131  struct iteratorKeeper {
132  public:
133  LIBJSON_OBJECT(jsonChildren::iteratorKeeper);
134  iteratorKeeper(jsonChildren * pthis, JSONNode ** & position) json_nothrow :
135  myRelativeOffset(reverse ? (json_index_t)(pthis -> array + (size_t)pthis -> mysize - position) : (json_index_t)(position - pthis -> array)),
136  myChildren(pthis),
137  myPos(position){
138  LIBJSON_CTOR;
139  }
140 
141  ~iteratorKeeper(void) json_nothrow {
142  LIBJSON_DTOR;
143  if (reverse){
144  myPos = myChildren -> array + myChildren -> mysize - myRelativeOffset;
145  } else {
146  myPos = myChildren -> array + myRelativeOffset;
147  }
148  }
149  private:
150  iteratorKeeper(const iteratorKeeper &);
151  iteratorKeeper & operator = (const iteratorKeeper &);
152 
153  json_index_t myRelativeOffset;
154  jsonChildren * myChildren;
155  JSONNode ** & myPos;
156  };
157 
158  //This function DOES NOT delete the item it points to
159  inline void erase(JSONNode ** & position) json_nothrow {
160  JSON_ASSERT(this != 0, JSON_TEXT("Children is null erase"));
161  JSON_ASSERT(array != 0, JSON_TEXT("erasing something from a null array 1"));
162  JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array 1"));
163  JSON_ASSERT(position <= array + mysize, JSON_TEXT("erasing out of bounds 1"));
164  std::memmove(position, position + 1, (mysize-- - (position - array) - 1) * sizeof(JSONNode *));
165  iteratorKeeper<false> ik(this, position);
166  shrink();
167  }
168 
169  //This function DOES NOT delete the item it points to
170  inline void erase(JSONNode ** & position, json_index_t number) json_nothrow {
171  JSON_ASSERT(this != 0, JSON_TEXT("Children is null erase 2"));
172  doerase(position, number);
173  iteratorKeeper<false> ik(this, position);
174  shrink();
175  }
176 
177 
178  //This function DOES NOT delete the item it points to
179  inline void erase(JSONNode ** position, json_index_t number, JSONNode ** & starter) json_nothrow {
180  JSON_ASSERT(this != 0, JSON_TEXT("Children is null erase 3"));
181  doerase(position, number);
182  iteratorKeeper<false> ik(this, starter);
183  shrink();
184  }
185 
186  #ifdef JSON_LIBRARY
187  void insert(JSONNode ** & position, JSONNode * item) json_nothrow{
188  #else
189  void insert(JSONNode ** & position, JSONNode * item, bool reverse = false) json_nothrow {
190  #endif
191  JSON_ASSERT(this != 0, JSON_TEXT("Children is null insert"));
192  //position isnt relative to array because of realloc
193  JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array insert 1"));
194  JSON_ASSERT(position <= array + mysize, JSON_TEXT("position is above the end of the array insert 1"));
195  #ifndef JSON_LIBRARY
196  if (reverse){
197  iteratorKeeper<true> ik(this, position);
198  inc();
199  } else
200  #endif
201  {
202  iteratorKeeper<false> ik(this, position);
203  inc();
204  }
205 
206  std::memmove(position + 1, position, (mysize++ - (position - array)) * sizeof(JSONNode *));
207  *position = item;
208  }
209 
210  void insert(JSONNode ** & position, JSONNode ** items, json_index_t num) json_nothrow {
211  JSON_ASSERT(this != 0, JSON_TEXT("Children is null insert 2"));
212  JSON_ASSERT(position >= array, JSON_TEXT("position is beneath the start of the array insert 2"));
213  JSON_ASSERT(position <= array + mysize, JSON_TEXT("position is above the end of the array insert 2"));
214  {
215  iteratorKeeper<false> ik(this, position);
216  inc(num);
217  }
218  const size_t ptrs = ((JSONNode **)(array + mysize)) - position;
219  std::memmove(position + num, position, ptrs * sizeof(JSONNode *));
220  std::memcpy(position, items, num * sizeof(JSONNode *));
221  mysize += num;
222  }
223 
224  inline void reserve(json_index_t amount) json_nothrow {
225  JSON_ASSERT(this != 0, JSON_TEXT("Children is null reserve"));
226  JSON_ASSERT(array == 0, JSON_TEXT("reserve is not meant to expand a preexisting array"));
227  JSON_ASSERT(mycapacity == 0, JSON_TEXT("reservec is not meant to expand a preexisting array"));
228  JSON_ASSERT(mysize == 0, JSON_TEXT("reserves is not meant to expand a preexisting array"));
229  array = json_malloc<JSONNode*>(mycapacity = amount);
230  }
231 
232  //it is static because mine might change pointers entirely
233  static void reserve2(jsonChildren *& mine, json_index_t amount) json_nothrow;
234 
235  //shrinks the array to only as large as it needs to be to hold everything within it
236  inline childrenVirtual void shrink() json_nothrow {
237  JSON_ASSERT(this != 0, JSON_TEXT("Children is null shrink"));
238  if (json_unlikely(mysize == 0)){ //size is zero, we should completely free the array
239  libjson_free<JSONNode*>(array); //free does checks for a null pointer, so don't bother checking
240  array = 0;
241  #ifdef JSON_LESS_MEMORY
242  } else { //need to shrink it, using realloc
243  JSON_ASSERT(array != 0, JSON_TEXT("shrinking a null array that is not size 0"));
244  array = json_realloc<JSONNode*>(array, mysize);
245  #endif
246  }
247  mycapacity = mysize;
248  }
249 
250 
251  inline static void deleteChildren(jsonChildren * ptr) json_nothrow {
252  #ifdef JSON_MEMORY_CALLBACKS
253  ptr -> ~jsonChildren();
254  libjson_free<jsonChildren>(ptr);
255  #else
256  delete ptr;
257  #endif
258  }
259 
260  inline static jsonChildren * newChildren(void) {
261  #ifdef JSON_MEMORY_CALLBACKS
262  return new(json_malloc<jsonChildren>(1)) jsonChildren();
263  #else
264  return new jsonChildren();
265  #endif
266  }
267 
268  JSONNode ** array; //the expandable array
269 
270  json_index_t mysize; //the number of valid items
271  json_index_t mycapacity; //the number of possible items
272 JSON_PROTECTED
273  //to make sure it's not copyable
274  jsonChildren(const jsonChildren &);
275  jsonChildren & operator = (const jsonChildren &);
276 
277  void deleteAll(void) json_nothrow json_hot; //implemented in JSONNode.cpp
278  void doerase(JSONNode ** position, json_index_t number) json_nothrow;
279 };
280 
281 #ifdef JSON_LESS_MEMORY
282  class jsonChildren_Reserved : public jsonChildren {
283  public:
284  LIBJSON_OBJECT(jsonChildren_Reserved);
285  jsonChildren_Reserved(jsonChildren * orig, json_index_t siz) json_nothrow : jsonChildren(orig -> array, orig -> mysize, orig -> mycapacity), myreserved(siz) {
286  orig -> array = 0;
287  deleteChildren(orig);
288  LIBJSON_CTOR;
289  }
290  jsonChildren_Reserved(const jsonChildren_Reserved & orig) json_nothrow : jsonChildren(orig.array, orig.mysize, orig.mycapacity), myreserved(orig.myreserved){
291  LIBJSON_COPY_CTOR;
292  }
293  inline virtual ~jsonChildren_Reserved() json_nothrow {
294  LIBJSON_DTOR;
295  };
296  inline virtual void shrink() json_nothrow {
297  JSON_ASSERT(this != 0, JSON_TEXT("Children is null shrink reserved"));
298  if (json_unlikely(mysize == 0)){ //size is zero, we should completely free the array
299  libjson_free<JSONNode*>(array); //free does checks for a null pointer, so don't bother checking
300  array = 0;
301  } else if (mysize > myreserved){
302  JSON_ASSERT(array != 0, JSON_TEXT("shrinking a null array that is not size 0"));
303  array = json_realloc<JSONNode*>(array, mysize);
304  }
305  }
306 
307  #ifdef JSON_LESS_MEMORY
308  inline static jsonChildren * newChildren_Reserved(jsonChildren * orig, json_index_t siz) json_nothrow {
309  #ifdef JSON_MEMORY_CALLBACKS
310  return new(json_malloc<jsonChildren_Reserved>(1)) jsonChildren_Reserved(orig, siz);
311  #else
312  return new jsonChildren_Reserved(orig, siz);
313  #endif
314  }
315  #endif
316  JSON_PRIVATE
317  jsonChildren_Reserved & operator = (const jsonChildren_Reserved &);
318  json_index_t myreserved;
319  };
320 #endif
321 
322 #ifdef JSON_LESS_MEMORY
323  #ifdef __GNUC__
324  #pragma pack(pop)
325  #elif _MSC_VER
326  #pragma pack(pop, jsonChildren)
327  #endif
328 #endif
329 #endif