JSONChildren.h 12 KB

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