1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
|
#ifndef JSONCHILDREN_H
#define JSONCHILDREN_H
#include "JSONMemory.h"
#include "JSONDebug.h" //for JSON_ASSERT macro
#define json_foreach(children, iterator)\
JSONNode ** iterator = children.begin();\
for(JSONNode ** iterator##_end = children.end(); iterator != iterator##_end; ++iterator)
/*
This class is essentially a vector that has been heavily optimized for the specific purpose
of holding JSONNode children. It acts the same way as a vector, it has a automatically
expanding array. On destruction, this container automatically destroys everything contained
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 uses this container, and because
the container deletes the children automatically, forward declaration can't be used
*/
class JSONNode; //forward declaration
class jsonChildren {
public:
//starts completely empty and the array is not allocated
jsonChildren(void) : array(0), mysize(0), mycapacity(0) { }
//deletes the array and everything that is contained within it (using delete)
~jsonChildren(void){
if (array){ //the following function calls are safe, but take more time than a check here
deleteAll();
libjson_free<JSONNode*>(array);
}
}
//increase the size of the array
void inc(json_index_t amount);
void inc(void);
//Adds something to the vector, doubling the array if necessary
void push_back(JSONNode * item){
inc();
array[mysize++] = item;
}
//Adds something to the front of the vector, doubling the array if necessary
void push_front(JSONNode * item){
inc();
memmove(array + 1, array, mysize++ * sizeof(JSONNode *));
array[0] = item;
}
//gets an item out of the vector by it's position
inline JSONNode * operator[] (json_index_t position) const {
JSON_ASSERT(position < mysize, JSON_TEXT("Using [] out of bounds"));
JSON_ASSERT(position < mycapacity, JSON_TEXT("Using [] out of bounds"));
JSON_ASSERT(array, JSON_TEXT("Array is null"));
return array[position];
}
//returns the allocated capacity, but keep in mind that some might not be valid
inline json_index_t capacity() const {
return mycapacity;
}
//returns the number of valid objects within the vector
inline json_index_t size() const {
return mysize;
}
//tests whether or not the vector is empty
inline bool empty() const {
return mysize == 0;
}
//clears (and deletes) everything from the vector and sets it's size to 0
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 clear"));
}
//returns the beginning of the array
inline JSONNode ** begin(void) const {
return array;
}
//returns the end of the array
inline JSONNode ** end(void) const {
return array + mysize;
}
//makes sure that even after shirnking and expanding, the iterator is in same relative position
struct iteratorKeeper {
public:
#ifdef JSON_LIBRARY
iteratorKeeper(jsonChildren * pthis, JSONNode ** & position) :
myRelativeOffset((json_index_t)(position - pthis -> array)),
#else
iteratorKeeper(jsonChildren * pthis, JSONNode ** & position, bool reverse = false) :
myRelativeOffset(reverse ? (json_index_t)(pthis -> array + (size_t)pthis -> mysize - position) : (json_index_t)(position - pthis -> array)),
myReverse(reverse),
#endif
myChildren(pthis),
myPos(position){}
~iteratorKeeper(void){
#ifdef JSON_LIBRARY
myPos = myChildren -> array + myRelativeOffset;
#else
if (myReverse){
myPos = myChildren -> array + myChildren -> mysize - myRelativeOffset;
} else {
myPos = myChildren -> array + myRelativeOffset;
}
#endif
}
private:
iteratorKeeper(const iteratorKeeper &);
iteratorKeeper & operator=(const iteratorKeeper &);
jsonChildren * myChildren;
JSONNode ** & myPos;
json_index_t myRelativeOffset;
#ifndef JSON_LIBRARY
bool myReverse BITS(1);
#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 above 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 above 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 preexisting array"));
JSON_ASSERT(!mycapacity, JSON_TEXT("reservec is not meant to expand 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 everything 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 null array that is not size 0"));
array = json_realloc<JSONNode*>(array, mysize);
#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
|