| 57 "\t\"alive\":true\n" |
57 "\t\"alive\":true\n" |
| 58 "}" |
58 "}" |
| 59 ); |
59 ); |
| 60 |
60 |
| 61 CX_TEST_DO { |
61 CX_TEST_DO { |
| 62 int result; |
62 CxJsonStatus result; |
| 63 |
63 |
| 64 CxJson json; |
64 CxJson json; |
| 65 cxJsonInit(&json, NULL); |
65 cxJsonInit(&json, NULL); |
| 66 cxJsonFill(&json, text); |
66 cxJsonFill(&json, text); |
| 67 |
67 |
| 68 // parse the big fat object |
68 // parse the big fat object |
| 69 CxJsonValue *obj; |
69 CxJsonValue *obj; |
| 70 result = cxJsonNext(&json, &obj); |
70 result = cxJsonNext(&json, &obj); |
| 71 CX_TEST_ASSERT(result == 1); |
71 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 72 |
72 |
| 73 // check the contents |
73 // check the contents |
| 74 CX_TEST_ASSERT(cxJsonIsObject(obj)); |
74 CX_TEST_ASSERT(cxJsonIsObject(obj)); |
| 75 |
75 |
| 76 CxJsonValue *message = cxJsonObjGet(obj, "message"); |
76 CxJsonValue *message = cxJsonObjGet(obj, "message"); |
| 124 for(size_t i=0;i<text.length;i+=4) { |
124 for(size_t i=0;i<text.length;i+=4) { |
| 125 parts[nparts++] = cx_strsubsl(text, i, 4); |
125 parts[nparts++] = cx_strsubsl(text, i, 4); |
| 126 } |
126 } |
| 127 |
127 |
| 128 CX_TEST_DO { |
128 CX_TEST_DO { |
| 129 int result; |
129 CxJsonStatus result; |
| 130 |
130 |
| 131 CxJson json; |
131 CxJson json; |
| 132 cxJsonInit(&json, NULL); |
132 cxJsonInit(&json, NULL); |
| 133 CxJsonValue *obj; |
133 CxJsonValue *obj; |
| 134 |
134 |
| 135 size_t part = 0; |
135 size_t part = 0; |
| 136 while(part < nparts) { |
136 while(part < nparts - 1) { |
| 137 cxJsonFill(&json, parts[part]); |
137 cxJsonFill(&json, parts[part]); |
| 138 part++; |
138 part++; |
| 139 result = cxJsonNext(&json, &obj); |
139 result = cxJsonNext(&json, &obj); |
| 140 |
140 CX_TEST_ASSERT(result == CX_JSON_INCOMPLETE_DATA); |
| 141 if(result != 0) { |
|
| 142 break; |
|
| 143 } |
|
| 144 } |
141 } |
| 145 |
142 cxJsonFill(&json, parts[nparts - 1]); |
| 146 CX_TEST_ASSERT(result == 1); |
143 result = cxJsonNext(&json, &obj); |
| 147 CX_TEST_ASSERT(part == nparts); |
144 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 148 CX_TEST_ASSERT(obj); |
145 CX_TEST_ASSERT(obj); |
| 149 |
146 |
| 150 CxJsonValue *message = cxJsonObjGet(obj, "message"); |
147 CxJsonValue *message = cxJsonObjGet(obj, "message"); |
| 151 CX_TEST_ASSERT(cxJsonIsString(message)); |
148 CX_TEST_ASSERT(cxJsonIsString(message)); |
| 152 CX_TEST_ASSERT(0 == cx_strcmp( |
149 CX_TEST_ASSERT(0 == cx_strcmp( |
| 185 cxstring text2 = cx_str("{ \"a\" : }"); |
182 cxstring text2 = cx_str("{ \"a\" : }"); |
| 186 cxstring text3 = cx_str("{ \"a\" : \"b\" ]"); |
183 cxstring text3 = cx_str("{ \"a\" : \"b\" ]"); |
| 187 cxstring text4 = cx_str("{ \"name\": \"value\" ]"); |
184 cxstring text4 = cx_str("{ \"name\": \"value\" ]"); |
| 188 |
185 |
| 189 cxstring tests[] = { text0, text1, text2, text3, text4 }; |
186 cxstring tests[] = { text0, text1, text2, text3, text4 }; |
| |
187 CxJsonStatus errors[] = { |
| |
188 CX_JSON_FORMAT_ERROR_NUMBER, |
| |
189 CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN, |
| |
190 CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN, |
| |
191 CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN, |
| |
192 CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN |
| |
193 }; |
| 190 |
194 |
| 191 CX_TEST_DO { |
195 CX_TEST_DO { |
| 192 int result; |
196 CxJsonStatus result; |
| 193 CxJson json; |
197 CxJson json; |
| 194 CxJsonValue *obj = NULL; |
198 CxJsonValue *obj = NULL; |
| 195 |
199 |
| 196 for(int i=0;i<5;i++) { |
200 for(int i=0;i<5;i++) { |
| 197 cxJsonInit(&json, NULL); |
201 cxJsonInit(&json, NULL); |
| 198 cxJsonFill(&json, tests[i]); |
202 cxJsonFill(&json, tests[i]); |
| 199 result = cxJsonNext(&json, &obj); |
203 result = cxJsonNext(&json, &obj); |
| 200 |
204 |
| 201 CX_TEST_ASSERT(result == -1); |
205 CX_TEST_ASSERT(result == errors[i]); |
| 202 CX_TEST_ASSERT(obj != NULL && obj->type == CX_JSON_NOTHING); |
206 CX_TEST_ASSERT(obj != NULL && obj->type == CX_JSON_NOTHING); |
| 203 cxJsonDestroy(&json); |
207 cxJsonDestroy(&json); |
| 204 } |
208 } |
| 205 } |
209 } |
| 206 } |
210 } |
| 255 CxJson json; |
259 CxJson json; |
| 256 cxJsonInit(&json, NULL); |
260 cxJsonInit(&json, NULL); |
| 257 CX_TEST_DO { |
261 CX_TEST_DO { |
| 258 // TODO: find a better way to terminate values that are not arrays/objects |
262 // TODO: find a better way to terminate values that are not arrays/objects |
| 259 CxJsonValue *v; |
263 CxJsonValue *v; |
| 260 int result; |
264 CxJsonStatus result; |
| 261 cxJsonFill(&json, "3.1415 "); |
265 cxJsonFill(&json, "3.1415 "); |
| 262 result = cxJsonNext(&json, &v); |
266 result = cxJsonNext(&json, &v); |
| 263 CX_TEST_ASSERT(result == 1); |
267 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 264 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
268 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
| 265 CX_TEST_ASSERT(cxJsonAsDouble(v) == 3.1415); |
269 CX_TEST_ASSERT(cxJsonAsDouble(v) == 3.1415); |
| 266 cxJsonValueFree(v); |
270 cxJsonValueFree(v); |
| 267 cxJsonFill(&json, "-47.11e2 "); |
271 cxJsonFill(&json, "-47.11e2 "); |
| 268 result = cxJsonNext(&json, &v); |
272 result = cxJsonNext(&json, &v); |
| 269 CX_TEST_ASSERT(result == 1); |
273 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 270 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
274 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
| 271 CX_TEST_ASSERT(cxJsonAsDouble(v) == -4711.0); |
275 CX_TEST_ASSERT(cxJsonAsDouble(v) == -4711.0); |
| 272 cxJsonValueFree(v); |
276 cxJsonValueFree(v); |
| 273 } |
277 } |
| 274 cxJsonDestroy(&json); |
278 cxJsonDestroy(&json); |
| 277 CX_TEST(test_json_multiple_values) { |
281 CX_TEST(test_json_multiple_values) { |
| 278 CxJson json; |
282 CxJson json; |
| 279 cxJsonInit(&json, NULL); |
283 cxJsonInit(&json, NULL); |
| 280 CX_TEST_DO { |
284 CX_TEST_DO { |
| 281 CxJsonValue *v; |
285 CxJsonValue *v; |
| 282 int result; |
286 CxJsonStatus result; |
| 283 |
287 |
| 284 // read number |
288 // read number |
| 285 cxJsonFill(&json, "10\n"); |
289 cxJsonFill(&json, "10\n"); |
| 286 result = cxJsonNext(&json, &v); |
290 result = cxJsonNext(&json, &v); |
| 287 CX_TEST_ASSERT(result == 1); |
291 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 288 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
292 CX_TEST_ASSERT(cxJsonIsNumber(v)); |
| 289 CX_TEST_ASSERT(cxJsonAsInteger(v) == 10); |
293 CX_TEST_ASSERT(cxJsonAsInteger(v) == 10); |
| 290 cxJsonValueFree(v); |
294 cxJsonValueFree(v); |
| 291 // read remaining '\n' |
295 // read remaining '\n' |
| 292 result = cxJsonNext(&json, &v); |
296 result = cxJsonNext(&json, &v); |
| 293 CX_TEST_ASSERT(result == 0); |
297 CX_TEST_ASSERT(result == CX_JSON_INCOMPLETE_DATA); |
| 294 // read string |
298 // read string |
| 295 cxJsonFill(&json, "\"hello world\"\n"); |
299 cxJsonFill(&json, "\"hello world\"\n"); |
| 296 result = cxJsonNext(&json, &v); |
300 result = cxJsonNext(&json, &v); |
| 297 CX_TEST_ASSERT(result == 1); |
301 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 298 CX_TEST_ASSERT(cxJsonIsString(v)); |
302 CX_TEST_ASSERT(cxJsonIsString(v)); |
| 299 CX_TEST_ASSERT(!cx_strcmp(cxJsonAsCxString(v), CX_STR("hello world"))); |
303 CX_TEST_ASSERT(!cx_strcmp(cxJsonAsCxString(v), CX_STR("hello world"))); |
| 300 cxJsonValueFree(v); |
304 cxJsonValueFree(v); |
| 301 // don't process the remaining newline this time |
305 // don't process the remaining newline this time |
| 302 // read obj |
306 // read obj |
| 303 cxJsonFill(&json, "{ \"value\": \"test\" }\n"); |
307 cxJsonFill(&json, "{ \"value\": \"test\" }\n"); |
| 304 result = cxJsonNext(&json, &v); |
308 result = cxJsonNext(&json, &v); |
| 305 CX_TEST_ASSERT(result == 1); |
309 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 306 CX_TEST_ASSERT(cxJsonIsObject(v)); |
310 CX_TEST_ASSERT(cxJsonIsObject(v)); |
| 307 CxJsonValue *value = cxJsonObjGet(v, "value"); |
311 CxJsonValue *value = cxJsonObjGet(v, "value"); |
| 308 CX_TEST_ASSERT(cxJsonAsString(value)); |
312 CX_TEST_ASSERT(cxJsonAsString(value)); |
| 309 cxJsonValueFree(v); |
313 cxJsonValueFree(v); |
| 310 // read array |
314 // read array |
| 311 cxJsonFill(&json, "[ 0, 1, 2, 3, 4, 5 ]\n"); |
315 cxJsonFill(&json, "[ 0, 1, 2, 3, 4, 5 ]\n"); |
| 312 result = cxJsonNext(&json, &v); |
316 result = cxJsonNext(&json, &v); |
| 313 CX_TEST_ASSERT(result == 1); |
317 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 314 CX_TEST_ASSERT(cxJsonIsArray(v)); |
318 CX_TEST_ASSERT(cxJsonIsArray(v)); |
| 315 CxJsonValue *a0 = cxJsonArrGet(v, 0); |
319 CxJsonValue *a0 = cxJsonArrGet(v, 0); |
| 316 CxJsonValue *a3 = cxJsonArrGet(v, 3); |
320 CxJsonValue *a3 = cxJsonArrGet(v, 3); |
| 317 CX_TEST_ASSERT(cxJsonIsNumber(a0)); |
321 CX_TEST_ASSERT(cxJsonIsNumber(a0)); |
| 318 CX_TEST_ASSERT(cxJsonAsInteger(a0) == 0); |
322 CX_TEST_ASSERT(cxJsonAsInteger(a0) == 0); |
| 320 CX_TEST_ASSERT(cxJsonAsInteger(a3) == 3); |
324 CX_TEST_ASSERT(cxJsonAsInteger(a3) == 3); |
| 321 cxJsonValueFree(v); |
325 cxJsonValueFree(v); |
| 322 // read literal |
326 // read literal |
| 323 cxJsonFill(&json, "true\n"); |
327 cxJsonFill(&json, "true\n"); |
| 324 result = cxJsonNext(&json, &v); |
328 result = cxJsonNext(&json, &v); |
| 325 CX_TEST_ASSERT(result == 1); |
329 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 326 CX_TEST_ASSERT(cxJsonIsLiteral(v)); |
330 CX_TEST_ASSERT(cxJsonIsLiteral(v)); |
| 327 CX_TEST_ASSERT(cxJsonAsBool(v)); |
331 CX_TEST_ASSERT(cxJsonAsBool(v)); |
| 328 cxJsonValueFree(v); |
332 cxJsonValueFree(v); |
| 329 // read null |
333 // read null |
| 330 cxJsonFill(&json, "null\n"); |
334 cxJsonFill(&json, "null\n"); |
| 331 result = cxJsonNext(&json, &v); |
335 result = cxJsonNext(&json, &v); |
| 332 CX_TEST_ASSERT(result == 1); |
336 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 333 CX_TEST_ASSERT(cxJsonIsNull(v)); |
337 CX_TEST_ASSERT(cxJsonIsNull(v)); |
| 334 cxJsonValueFree(v); |
338 cxJsonValueFree(v); |
| 335 } |
339 } |
| 336 cxJsonDestroy(&json); |
340 cxJsonDestroy(&json); |
| 337 } |
341 } |
| 352 CxJson json; |
356 CxJson json; |
| 353 cxJsonInit(&json, allocator); |
357 cxJsonInit(&json, allocator); |
| 354 cxJsonFill(&json, text); |
358 cxJsonFill(&json, text); |
| 355 |
359 |
| 356 CxJsonValue *obj; |
360 CxJsonValue *obj; |
| 357 int result = cxJsonNext(&json, &obj); |
361 CxJsonStatus result = cxJsonNext(&json, &obj); |
| 358 CX_TEST_ASSERT(result == 1); |
362 CX_TEST_ASSERT(result == CX_JSON_NO_ERROR); |
| 359 CX_TEST_ASSERT(obj->allocator == allocator); |
363 CX_TEST_ASSERT(obj->allocator == allocator); |
| 360 |
364 |
| 361 // this recursively frees everything |
365 // this recursively frees everything |
| 362 cxJsonValueFree(obj); |
366 cxJsonValueFree(obj); |
| 363 cxJsonDestroy(&json); |
367 cxJsonDestroy(&json); |
| 383 CxJson json; |
387 CxJson json; |
| 384 cxJsonInit(&json, allocator); |
388 cxJsonInit(&json, allocator); |
| 385 cxJsonFill(&json, text); |
389 cxJsonFill(&json, text); |
| 386 |
390 |
| 387 CxJsonValue *obj = NULL; |
391 CxJsonValue *obj = NULL; |
| 388 int result = cxJsonNext(&json, &obj); |
392 CxJsonStatus result = cxJsonNext(&json, &obj); |
| 389 CX_TEST_ASSERT(result == -1); |
393 CX_TEST_ASSERT(result == CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN); |
| 390 CX_TEST_ASSERT(obj != NULL && obj->type == CX_JSON_NOTHING); |
394 CX_TEST_ASSERT(obj != NULL && obj->type == CX_JSON_NOTHING); |
| 391 |
395 |
| 392 // clean-up any left-over memory |
396 // clean-up any left-over memory |
| 393 cxJsonDestroy(&json); |
397 cxJsonDestroy(&json); |
| 394 |
398 |