-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtinyjsonpp.cpp
More file actions
331 lines (272 loc) · 10.5 KB
/
tinyjsonpp.cpp
File metadata and controls
331 lines (272 loc) · 10.5 KB
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/*
* tinyjsonpp.cpp
*
* Created: 11-Sept-17 12:25:10
* Author : hydroflax
*/
#include <avr/io.h>
#include <string.h>
#include "tinyjsonpp.h"
tinyjsonpp::tinyjsonpp(bool store, unsigned int maxSize) {
this->json = static_cast<char*>(calloc(maxSize, sizeof(char)));
this->maxSize = maxSize;
this->jsonSize = 0;
}
tinyjsonpp::tinyjsonpp(bool store, bool ignoreQuotes, unsigned int maxSize) {
this->json = static_cast<char*>(calloc(maxSize, sizeof(char)));
this->maxSize = maxSize;
this->jsonSize = 0;
}
void* tinyjsonpp::operator new(size_t objsize) {
return malloc(objsize);
}
void tinyjsonpp::operator delete(void* obj) {
free(obj);
}
void tinyjsonpp::empty() {
this->jsonSize = 0;
memset(this->json, 0, this->maxSize);
// Alternative to save compute time is to just set the first character to 0.
}
void tinyjsonpp::reset() {
this->jsonSize = 2;
memset(this->json, 0, this->maxSize);
this->json[0] = '{';
this->json[1] = '}';
}
void tinyjsonpp::addCharToJSONString(const char c) {
// Ignore Newline, Space, Return Carriage Characters.
if (c <= 0x20) {
return;
}
this->json[this->jsonSize] = c;
++this->jsonSize;
}
Value tinyjsonpp::getValue(const char* key, const char* searchStart, const unsigned int searchSize) const {
Key k;
Value v;
k.start = static_cast<char*>(memmem(searchStart, searchSize, key, strlen(key)));
// The key was found in the JSON. (If not, key will be set to NULL).
if(k.start) {
k.size = strlen(key);
// Set the current location
unsigned int location = k.start - this->json;
// Set the values key pointer (and vice versa).
v.key = &k;
k.value = &v;
// Get the entire value.
// loop through each char in the string until a "," or "}" is found or if an opening "[", then a "]" is found.
bool valueFound = false;
bool array = false;
bool embeddedJSON = false;
while(!valueFound) {
// Start of Value after ':' or ':'
if(this->json[location] == ':' && !embeddedJSON) {
v.start = &this->json[location + 1];
if (this->json[location + 2] >= '0' && this->json[location + 2] <= '9') {
// A int has been found (based off first letter).
v.type = 'i';
} else if(this->json[location + 1] == '[') {
// An array has been found.
array = true;
v.type = 'a';
} else if(this->json[location + 1] == '{') {
// An embeddedJSON object has been found.
embeddedJSON = true;
v.type = 'e';
} else {
v.type = 's';
}
}
if((this->json[location] == ',' || this->json[location] == '}') && !embeddedJSON) {
if(!array) {
v.size = &this->json[location] - v.start;
valueFound = true;
}
}
// Embedded JSON
if(this->json[location] == '}' && embeddedJSON) {
v.size = &this->json[location] - v.start + 1;
valueFound = true;
}
// Array
if(this->json[location] == ']') {
v.size = &this->json[location] - v.start + 1;
valueFound = true;
}
++location;
}
} else {
v.start = NULL;
v.size = 0;
v.type = 'n';
v.key = NULL;
}
return v;
}
Value tinyjsonpp::getValue(const char* key) const {
Value v = getValue(key, this->json, this->jsonSize);
return v;
}
Value tinyjsonpp::getValue(const char* key, const char* parent) const {
Value v;
Key k;
// Set initial memmem string search parameters.
v.start = this->json;
v.size = this->jsonSize;
char* originalParent = static_cast<char*>(calloc(strlen(parent + 1), sizeof(char)));
originalParent = strcpy(originalParent, parent);
char *token = strtok(originalParent, "/");
while (token != NULL) {
k.start = static_cast<char*>(memmem(v.start, v.size, token, strlen(token)));
// The key was found in the JSON.
if (k.start) {
// Set the correct values.
unsigned int location = k.start - this->json;
v.start = &this->json[location + 2];
// Faking the value size. Good enough for simple cases.
v.size = this->jsonSize - (location + 2);
} else {
v.start = NULL;
v.size = 0;
v.type = 'n';
v.key = NULL;
return v;
}
token = strtok(NULL, "/");
}
// Standard getValue() can be called passing the key to be found along with the search range.
v = getValue(key, v.start, v.size);
free(originalParent);
return v;
}
//void tinyjsonpp::insert(const char* key, const char* value) {
// Insert the key-value pair into the root JSON object.
//}
void tinyjsonpp::insert(const char* key, const char* value, const char* parent) {
Value v;
v.start = NULL;
v.size = 0;
Value val;
unsigned int location = 0;
//Key k;
// Uses getValue() for the insert place. e.g. if the parent was "3/user"and the k-v to insert was "hello": "world" then can getvalue of "user" in parent "3".
// No parent has been specified, i.e. add to the root domain.
if (parent != '\0') {
// Separate the parent string into the parent and the key to get the value of.
unsigned int forwardSlash = 0;
while(location < strlen(parent)) {
// Store the location of the last known '/'
if(parent[location] == '/') {
forwardSlash = location;
}
++location;
}
// Set the forwardSlash to the end of the parent string.
char* originalParent = static_cast<char*>(calloc(strlen(parent + 1), sizeof(char)));
originalParent = strcpy(originalParent, parent);
// The root JSON object is to be inserted into/an object in the root object.
if(forwardSlash == 0) {
val = getValue(originalParent);
} else {
originalParent[forwardSlash] = 0;
// Creating a temporary value as if the key not in the value, this will be set to NULL.
val = getValue(&originalParent[forwardSlash + 1], originalParent);
}
free(originalParent);
// If no value was found in the current string. return.
if (val.size == 0) {
return;
}
// If the key is already in the JSON string then just change the value, else add the k-v pair to the JSON string.
v = getValue(key, val.start, val.size);
} else {
// No parent has been specified, insert the value in the root JSON object.
val.start = &this->json[location];
val.size = this->jsonSize;
}
// The key does not already exists in the object.
if (v.start == NULL) {
// The space which will be freed up. (i.e. "<key>":"x").
// If the current first thing is a {"key":"val"} then {"<key>":"x","key":"val"}
// If the current first thing is a {"key":["val1", val2"]} then {"<key>":"x","key":["val1", val2"]}
// If the value is an embedded/array then the value will have a starter of {
// If it is not then it will be ".
location = val.start - this->json + strlen(key) + 7;
// If the key is the first to be inserted into the parent then no need for ,
if(val.size > 2) {
++location;
}
// Move original information to make space for new key.
memmove(&this->json[location], &this->json[val.start - this->json + 1], (this->jsonSize - (val.start - this->json + 1)));
location = val.start - this->json + 1;
this->json[location] = '"';
memcpy(&this->json[location + 1], key, strlen(key));
this->json[location + strlen(key) + 1] = '"';
this->json[location + strlen(key) + 2] = ':';
this->json[location + strlen(key) + 3] = '"';
this->json[location + strlen(key) + 4] = 'x';
this->json[location + strlen(key) + 5] = '"';
if(val.size > 2) {
this->json[location + strlen(key) + 6] = ',';
}
//k.start = &this->json[location + 1];
//k.size = strlen(key);
v.start = &this->json[location + strlen(key) + 3];
v.size = 3;
v.type = 's';
// Set the values key pointer (and vice versa).
//v.key = &k;
//k.value = &v;
}
// The key previously existed in the object/it does now.
// See what the length of the new value is. strlen(value)
// See what length of old value was. this->value.size
// Move original information to make space for new value.
location = v.start - this->json;
// Increase jsonSize. (Technically not correct but close enough).
this->jsonSize = this->jsonSize + strlen(key) + 6;
if(value[0] == '{' || value[0] == '[') {
// If we have a "{ value }" OR a "[ value1, value2] then insert into key.
memmove(&this->json[location + strlen(value)], &this->json[v.start - this->json + v.size], (this->jsonSize - (v.start - this->json)));
//if (value[0] == '[') {
//this->json[location + strlen(value)] = ']';
//} else if(value[0] == '{') {
//// If an embedded JSON object, do nothing.
//this->json[location + strlen(value)] = '}';
//}
// Replace old value with new value.
memcpy(&this->json[location], value, strlen(value));
} else {
// We have a value string and this should be surrounded by the "".
memmove(&this->json[location + strlen(value) + 2], &this->json[v.start - this->json + v.size], (this->jsonSize - (v.start - this->json + 2)));
this->json[location] = '"';
this->json[location + strlen(value) + 1] = '"';
// Replace old value with new value.
memcpy(&this->json[location + 1], value, strlen(value));
}
this->jsonSize = strlen(this->json);
}
char tinyjsonpp::getChar(const unsigned int i) {
return this->json[i];
}
const char* const tinyjsonpp::getJSONString() {
return this->json;
}
unsigned int tinyjsonpp::convertValueToInt(const Value v) const {
if(v.type != 'i') {
return 0;
} else {
// Extra space for Terminating character \0.
char* value = static_cast<char*>(calloc(v.size - 1, sizeof(char)));
memcpy(value, &this->json[v.start - this->json + 1], v.size - 2);
value[v.size - 1] = 0;
// We now have the value as a string.
unsigned int val = atoi(value);
free(value);
return val;
}
}
unsigned int tinyjsonpp::getJSONSize() const {
return this->jsonSize;
}