44 |
44 |
45 #ifdef __cplusplus |
45 #ifdef __cplusplus |
46 extern "C" { |
46 extern "C" { |
47 #endif |
47 #endif |
48 |
48 |
|
49 |
|
50 /** |
|
51 * The type of the parsed token. |
|
52 */ |
49 enum cx_json_token_type { |
53 enum cx_json_token_type { |
|
54 /** |
|
55 * No complete token parsed, yet. |
|
56 */ |
50 CX_JSON_NO_TOKEN, |
57 CX_JSON_NO_TOKEN, |
|
58 /** |
|
59 * The presumed token contains syntactical errors. |
|
60 */ |
51 CX_JSON_TOKEN_ERROR, |
61 CX_JSON_TOKEN_ERROR, |
|
62 /** |
|
63 * A "begin of array" '[' token. |
|
64 */ |
52 CX_JSON_TOKEN_BEGIN_ARRAY, |
65 CX_JSON_TOKEN_BEGIN_ARRAY, |
|
66 /** |
|
67 * A "begin of object" '{' token. |
|
68 */ |
53 CX_JSON_TOKEN_BEGIN_OBJECT, |
69 CX_JSON_TOKEN_BEGIN_OBJECT, |
|
70 /** |
|
71 * An "end of array" ']' token. |
|
72 */ |
54 CX_JSON_TOKEN_END_ARRAY, |
73 CX_JSON_TOKEN_END_ARRAY, |
|
74 /** |
|
75 * An "end of object" '}' token. |
|
76 */ |
55 CX_JSON_TOKEN_END_OBJECT, |
77 CX_JSON_TOKEN_END_OBJECT, |
|
78 /** |
|
79 * A colon ':' token separating names and values. |
|
80 */ |
56 CX_JSON_TOKEN_NAME_SEPARATOR, |
81 CX_JSON_TOKEN_NAME_SEPARATOR, |
|
82 /** |
|
83 * A comma ',' token separating object entries or array elements. |
|
84 */ |
57 CX_JSON_TOKEN_VALUE_SEPARATOR, |
85 CX_JSON_TOKEN_VALUE_SEPARATOR, |
|
86 /** |
|
87 * A string token. |
|
88 */ |
58 CX_JSON_TOKEN_STRING, |
89 CX_JSON_TOKEN_STRING, |
|
90 /** |
|
91 * A number token that can be represented as integer. |
|
92 */ |
59 CX_JSON_TOKEN_INTEGER, |
93 CX_JSON_TOKEN_INTEGER, |
|
94 /** |
|
95 * A number token that cannot be represented as integer. |
|
96 */ |
60 CX_JSON_TOKEN_NUMBER, |
97 CX_JSON_TOKEN_NUMBER, |
|
98 /** |
|
99 * A literal token. |
|
100 */ |
61 CX_JSON_TOKEN_LITERAL, |
101 CX_JSON_TOKEN_LITERAL, |
|
102 /** |
|
103 * A white-space token. |
|
104 */ |
62 CX_JSON_TOKEN_SPACE |
105 CX_JSON_TOKEN_SPACE |
63 }; |
106 }; |
64 |
107 |
|
108 /** |
|
109 * The type of some JSON value. |
|
110 */ |
65 enum cx_json_value_type { |
111 enum cx_json_value_type { |
|
112 /** |
|
113 * Reserved. |
|
114 */ |
66 CX_JSON_NOTHING, // this allows us to always return non-NULL values |
115 CX_JSON_NOTHING, // this allows us to always return non-NULL values |
|
116 /** |
|
117 * A JSON object. |
|
118 */ |
67 CX_JSON_OBJECT, |
119 CX_JSON_OBJECT, |
|
120 /** |
|
121 * A JSON array. |
|
122 */ |
68 CX_JSON_ARRAY, |
123 CX_JSON_ARRAY, |
|
124 /** |
|
125 * A string. |
|
126 */ |
69 CX_JSON_STRING, |
127 CX_JSON_STRING, |
|
128 /** |
|
129 * A number that contains an integer. |
|
130 */ |
70 CX_JSON_INTEGER, |
131 CX_JSON_INTEGER, |
|
132 /** |
|
133 * A number, not necessarily an integer. |
|
134 */ |
71 CX_JSON_NUMBER, |
135 CX_JSON_NUMBER, |
|
136 /** |
|
137 * A literal (true, false, null). |
|
138 */ |
72 CX_JSON_LITERAL |
139 CX_JSON_LITERAL |
73 }; |
140 }; |
74 |
141 |
|
142 /** |
|
143 * JSON literal types. |
|
144 */ |
75 enum cx_json_literal { |
145 enum cx_json_literal { |
|
146 /** |
|
147 * The \c null literal. |
|
148 */ |
76 CX_JSON_NULL, |
149 CX_JSON_NULL, |
|
150 /** |
|
151 * The \c true literal. |
|
152 */ |
77 CX_JSON_TRUE, |
153 CX_JSON_TRUE, |
|
154 /** |
|
155 * The \c false literal. |
|
156 */ |
78 CX_JSON_FALSE |
157 CX_JSON_FALSE |
79 }; |
158 }; |
80 |
159 |
|
160 /** |
|
161 * Type alias for the token type enum. |
|
162 */ |
81 typedef enum cx_json_token_type CxJsonTokenType; |
163 typedef enum cx_json_token_type CxJsonTokenType; |
|
164 /** |
|
165 * Type alias for the value type enum. |
|
166 */ |
82 typedef enum cx_json_value_type CxJsonValueType; |
167 typedef enum cx_json_value_type CxJsonValueType; |
83 |
168 |
|
169 /** |
|
170 * Type alias for the JSON parser interface. |
|
171 */ |
84 typedef struct cx_json_s CxJson; |
172 typedef struct cx_json_s CxJson; |
|
173 |
|
174 /** |
|
175 * Type alias for the token struct. |
|
176 */ |
85 typedef struct cx_json_token_s CxJsonToken; |
177 typedef struct cx_json_token_s CxJsonToken; |
86 |
178 |
|
179 /** |
|
180 * Type alias for the JSON value struct. |
|
181 */ |
87 typedef struct cx_json_value_s CxJsonValue; |
182 typedef struct cx_json_value_s CxJsonValue; |
88 |
183 |
|
184 /** |
|
185 * Type alias for the JSON array struct. |
|
186 */ |
89 typedef struct cx_json_array_s CxJsonArray; |
187 typedef struct cx_json_array_s CxJsonArray; |
|
188 /** |
|
189 * Type alias for the JSON object struct. |
|
190 */ |
90 typedef struct cx_json_object_s CxJsonObject; |
191 typedef struct cx_json_object_s CxJsonObject; |
|
192 /** |
|
193 * Type alias for a JSON string. |
|
194 */ |
91 typedef struct cx_mutstr_s CxJsonString; |
195 typedef struct cx_mutstr_s CxJsonString; |
|
196 /** |
|
197 * Type alias for a number that can be represented as 64-bit signed integer. |
|
198 */ |
92 typedef int64_t CxJsonInteger; |
199 typedef int64_t CxJsonInteger; |
|
200 /** |
|
201 * Type alias for number that is not an integer. |
|
202 */ |
93 typedef double CxJsonNumber; |
203 typedef double CxJsonNumber; |
|
204 /** |
|
205 * Type alias for a JSON literal. |
|
206 */ |
94 typedef enum cx_json_literal CxJsonLiteral; |
207 typedef enum cx_json_literal CxJsonLiteral; |
95 |
208 |
|
209 /** |
|
210 * Type alias for a key/value pair in a JSON object. |
|
211 */ |
96 typedef struct cx_json_obj_value_s CxJsonObjValue; |
212 typedef struct cx_json_obj_value_s CxJsonObjValue; |
97 |
213 |
98 |
214 /** |
|
215 * JSON array structure. |
|
216 */ |
99 struct cx_json_array_s { |
217 struct cx_json_array_s { |
|
218 /** |
|
219 * The array data. |
|
220 */ |
100 CX_ARRAY_DECLARE(CxJsonValue*, array); |
221 CX_ARRAY_DECLARE(CxJsonValue*, array); |
101 }; |
222 }; |
102 |
223 |
|
224 /** |
|
225 * JSON object structure. |
|
226 */ |
103 struct cx_json_object_s { |
227 struct cx_json_object_s { |
|
228 /** |
|
229 * The key/value entries. |
|
230 */ |
104 CX_ARRAY_DECLARE(CxJsonObjValue, values); |
231 CX_ARRAY_DECLARE(CxJsonObjValue, values); |
105 }; |
232 }; |
106 |
233 |
|
234 /** |
|
235 * Structure for a key/value entry in a JSON object. |
|
236 */ |
107 struct cx_json_obj_value_s { |
237 struct cx_json_obj_value_s { |
|
238 /** |
|
239 * The key a.k.a. name of the value. |
|
240 */ |
108 char *name; |
241 char *name; |
|
242 /** |
|
243 * The value. |
|
244 */ |
109 CxJsonValue *value; |
245 CxJsonValue *value; |
110 }; |
246 }; |
111 |
247 |
|
248 /** |
|
249 * Structure for a JSON value. |
|
250 */ |
112 struct cx_json_value_s { |
251 struct cx_json_value_s { |
|
252 /** |
|
253 * The allocator with which the value was allocated. |
|
254 * |
|
255 * Required for recursively deallocating memory of objects and arrays. |
|
256 */ |
113 const CxAllocator *allocator; |
257 const CxAllocator *allocator; |
|
258 /** |
|
259 * The type of this value. |
|
260 * |
|
261 * Specifies how the \c value union shall be resolved. |
|
262 */ |
114 CxJsonValueType type; |
263 CxJsonValueType type; |
|
264 /** |
|
265 * The value data. |
|
266 */ |
115 union { |
267 union { |
|
268 /** |
|
269 * The array data if type is #CX_JSON_ARRAY. |
|
270 */ |
116 CxJsonArray array; |
271 CxJsonArray array; |
|
272 /** |
|
273 * The object data if type is #CX_JSON_OBJECT. |
|
274 */ |
117 CxJsonObject object; |
275 CxJsonObject object; |
|
276 /** |
|
277 * The string data if type is #CX_JSON_STRING. |
|
278 */ |
118 CxJsonString string; |
279 CxJsonString string; |
|
280 /** |
|
281 * The integer if type is #CX_JSON_INTEGER. |
|
282 */ |
119 CxJsonInteger integer; |
283 CxJsonInteger integer; |
|
284 /** |
|
285 * The number if type is #CX_JSON_NUMBER. |
|
286 */ |
120 CxJsonNumber number; |
287 CxJsonNumber number; |
|
288 /** |
|
289 * The literal type if type is #CX_JSON_LITERAL. |
|
290 */ |
121 CxJsonLiteral literal; |
291 CxJsonLiteral literal; |
122 } value; |
292 } value; |
123 }; |
293 }; |
124 |
294 |
|
295 /** |
|
296 * Structure for a parsed token. |
|
297 */ |
125 struct cx_json_token_s { |
298 struct cx_json_token_s { |
|
299 /** |
|
300 * The token type. |
|
301 */ |
126 CxJsonTokenType tokentype; |
302 CxJsonTokenType tokentype; |
|
303 /** |
|
304 * True, iff the \c content must be passed to cx_strfree(). |
|
305 */ |
127 bool allocated; |
306 bool allocated; |
|
307 /** |
|
308 * The token text, if any. |
|
309 * |
|
310 * This is not necessarily set when the token type already |
|
311 * uniquely identifies the content. |
|
312 */ |
128 cxmutstr content; |
313 cxmutstr content; |
129 }; |
314 }; |
130 |
315 |
|
316 /** |
|
317 * The JSON parser interface. |
|
318 */ |
131 struct cx_json_s { |
319 struct cx_json_s { |
|
320 /** |
|
321 * The allocator used for produced JSON values. |
|
322 */ |
132 const CxAllocator *allocator; |
323 const CxAllocator *allocator; |
|
324 /** |
|
325 * The input buffer. |
|
326 */ |
133 CxBuffer buffer; |
327 CxBuffer buffer; |
134 |
328 |
|
329 /** |
|
330 * Used internally. |
|
331 * |
|
332 * Remembers the prefix of the last uncompleted token. |
|
333 */ |
135 CxJsonToken uncompleted; |
334 CxJsonToken uncompleted; |
136 |
335 |
137 /** |
336 /** |
138 * A pointer to an intermediate state of the currently parsed value. |
337 * A pointer to an intermediate state of the currently parsed value. |
139 * |
338 * |
213 /** |
414 /** |
214 * Typedef for the json status enum. |
415 * Typedef for the json status enum. |
215 */ |
416 */ |
216 typedef enum cx_json_status CxJsonStatus; |
417 typedef enum cx_json_status CxJsonStatus; |
217 |
418 |
|
419 /** |
|
420 * Initializes the json interface. |
|
421 * |
|
422 * @param json the json interface |
|
423 * @param allocator the allocator that shall be used for the produced values |
|
424 * @see cxJsonDestroy() |
|
425 */ |
218 cx_attr_nonnull_arg(1) |
426 cx_attr_nonnull_arg(1) |
219 void cxJsonInit(CxJson *json, const CxAllocator *allocator); |
427 void cxJsonInit(CxJson *json, const CxAllocator *allocator); |
220 |
428 |
|
429 /** |
|
430 * Destroys the json interface. |
|
431 * |
|
432 * @param json the json interface |
|
433 * @see cxJsonInit() |
|
434 */ |
221 cx_attr_nonnull |
435 cx_attr_nonnull |
222 void cxJsonDestroy(CxJson *json); |
436 void cxJsonDestroy(CxJson *json); |
223 |
437 |
|
438 /** |
|
439 * Adds more data to the input buffer. |
|
440 * |
|
441 * The data will be copied. |
|
442 * |
|
443 * @param json the json interface |
|
444 * @param buf the source buffer |
|
445 * @param len the length of the source buffer |
|
446 * @return zero on success, non-zero on internal allocation error |
|
447 * @see cxJsonFill() |
|
448 */ |
224 cx_attr_nonnull |
449 cx_attr_nonnull |
225 cx_attr_access_r(2, 3) |
450 cx_attr_access_r(2, 3) |
226 int cxJsonFilln(CxJson *json, const char *buf, size_t len); |
451 int cxJsonFilln(CxJson *json, const char *buf, size_t len); |
227 |
452 |
228 #ifdef __cplusplus |
453 #ifdef __cplusplus |
229 } // extern "C" |
454 } // extern "C" |
230 |
455 |
|
456 /** |
|
457 * Adds more data to the input buffer. |
|
458 * |
|
459 * The data will be copied. |
|
460 * |
|
461 * @param json the json interface |
|
462 * @param str the string to add to the buffer |
|
463 * @return zero on success, non-zero on internal allocation error |
|
464 * @see cxJsonFilln() |
|
465 */ |
231 cx_attr_nonnull |
466 cx_attr_nonnull |
232 static inline int cxJsonFill( |
467 static inline int cxJsonFill( |
233 CxJson *json, |
468 CxJson *json, |
234 cxstring str |
469 cxstring str |
235 ) { |
470 ) { |
236 return cxJsonFilln(json, str.ptr, str.length); |
471 return cxJsonFilln(json, str.ptr, str.length); |
237 } |
472 } |
238 |
473 |
|
474 /** |
|
475 * Adds more data to the input buffer. |
|
476 * |
|
477 * The data will be copied. |
|
478 * |
|
479 * @param json the json interface |
|
480 * @param str the string to add to the buffer |
|
481 * @return zero on success, non-zero on internal allocation error |
|
482 * @see cxJsonFilln() |
|
483 */ |
239 cx_attr_nonnull |
484 cx_attr_nonnull |
240 static inline int cxJsonFill( |
485 static inline int cxJsonFill( |
241 CxJson *json, |
486 CxJson *json, |
242 cxmutstr str |
487 cxmutstr str |
243 ) { |
488 ) { |
244 return cxJsonFilln(json, str.ptr, str.length); |
489 return cxJsonFilln(json, str.ptr, str.length); |
245 } |
490 } |
246 |
491 |
|
492 /** |
|
493 * Adds more data to the input buffer. |
|
494 * |
|
495 * The data will be copied. |
|
496 * |
|
497 * @param json the json interface |
|
498 * @param str the string to add to the buffer |
|
499 * @return zero on success, non-zero on internal allocation error |
|
500 * @see cxJsonFilln() |
|
501 */ |
247 cx_attr_nonnull |
502 cx_attr_nonnull |
248 cx_attr_cstr_arg(2) |
503 cx_attr_cstr_arg(2) |
249 static inline int cxJsonFill( |
504 static inline int cxJsonFill( |
250 CxJson *json, |
505 CxJson *json, |
251 const char *str |
506 const char *str |
253 return cxJsonFilln(json, str, strlen(str)); |
508 return cxJsonFilln(json, str, strlen(str)); |
254 } |
509 } |
255 |
510 |
256 extern "C" { |
511 extern "C" { |
257 #else // __cplusplus |
512 #else // __cplusplus |
|
513 /** |
|
514 * Adds more data to the input buffer. |
|
515 * |
|
516 * The data will be copied. |
|
517 * |
|
518 * @param json the json interface |
|
519 * @param str the string to add to the buffer |
|
520 * @return zero on success, non-zero on internal allocation error |
|
521 * @see cxJsonFilln() |
|
522 */ |
258 #define cxJsonFill(json, str) _Generic((str), \ |
523 #define cxJsonFill(json, str) _Generic((str), \ |
259 cxstring: cx_json_fill_cxstr, \ |
524 cxstring: cx_json_fill_cxstr, \ |
260 cxmutstr: cx_json_fill_mutstr, \ |
525 cxmutstr: cx_json_fill_mutstr, \ |
261 char*: cx_json_fill_str, \ |
526 char*: cx_json_fill_str, \ |
262 const char*: cx_json_fill_str) \ |
527 const char*: cx_json_fill_str) \ |
263 (json, str) |
528 (json, str) |
264 |
529 |
|
530 /** |
|
531 * Adds more data to the input buffer. |
|
532 * |
|
533 * Internal function - please use the #cxJsonFill() macro. |
|
534 * |
|
535 * @param json the json interface |
|
536 * @param str the string to add to the buffer |
|
537 * @return zero on success, non-zero on internal allocation error |
|
538 * @see cxJsonFill() |
|
539 */ |
265 cx_attr_nonnull |
540 cx_attr_nonnull |
266 static inline int cx_json_fill_cxstr( |
541 static inline int cx_json_fill_cxstr( |
267 CxJson *json, |
542 CxJson *json, |
268 cxstring str |
543 cxstring str |
269 ) { |
544 ) { |
270 return cxJsonFilln(json, str.ptr, str.length); |
545 return cxJsonFilln(json, str.ptr, str.length); |
271 } |
546 } |
272 |
547 |
|
548 /** |
|
549 * Adds more data to the input buffer. |
|
550 * |
|
551 * Internal function - please use the #cxJsonFill() macro. |
|
552 * |
|
553 * @param json the json interface |
|
554 * @param str the string to add to the buffer |
|
555 * @return zero on success, non-zero on internal allocation error |
|
556 * @see cxJsonFill() |
|
557 */ |
273 cx_attr_nonnull |
558 cx_attr_nonnull |
274 static inline int cx_json_fill_mutstr( |
559 static inline int cx_json_fill_mutstr( |
275 CxJson *json, |
560 CxJson *json, |
276 cxmutstr str |
561 cxmutstr str |
277 ) { |
562 ) { |
278 return cxJsonFilln(json, str.ptr, str.length); |
563 return cxJsonFilln(json, str.ptr, str.length); |
279 } |
564 } |
280 |
565 |
|
566 /** |
|
567 * Adds more data to the input buffer. |
|
568 * |
|
569 * Internal function - please use the #cxJsonFill() macro. |
|
570 * |
|
571 * @param json the json interface |
|
572 * @param str the string to add to the buffer |
|
573 * @return zero on success, non-zero on internal allocation error |
|
574 * @see cxJsonFill() |
|
575 */ |
281 cx_attr_nonnull |
576 cx_attr_nonnull |
282 cx_attr_cstr_arg(2) |
577 cx_attr_cstr_arg(2) |
283 static inline int cx_json_fill_str( |
578 static inline int cx_json_fill_str( |
284 CxJson *json, |
579 CxJson *json, |
285 const char *str |
580 const char *str |
286 ) { |
581 ) { |
287 return cxJsonFilln(json, str, strlen(str)); |
582 return cxJsonFilln(json, str, strlen(str)); |
288 } |
583 } |
289 #endif |
584 #endif |
290 |
585 |
|
586 /** |
|
587 * Recursively deallocates the memory of a JSON value. |
|
588 * |
|
589 * \remark The type of each deallocated value will be changed |
|
590 * to #CX_JSON_NOTHING and values of such type will be skipped |
|
591 * by the de-allocation. That means, this function protects |
|
592 * you from double-frees when you are accidentally freeing |
|
593 * a nested value and then the parent value (or vice versa). |
|
594 * |
|
595 * @param value the value |
|
596 */ |
291 void cxJsonValueFree(CxJsonValue *value); |
597 void cxJsonValueFree(CxJsonValue *value); |
292 |
598 |
293 cx_attr_nonnull |
599 /** |
|
600 * Tries to obtain the next JSON value. |
|
601 * |
|
602 * |
|
603 * @param json the json interface |
|
604 * @param value a pointer where the next value shall be stored |
|
605 * @return a status code |
|
606 */ |
|
607 cx_attr_nonnull |
|
608 cx_attr_access_w(2) |
294 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value); |
609 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value); |
295 |
610 |
|
611 /** |
|
612 * Checks if the specified value is a JSON object. |
|
613 * |
|
614 * @param value a pointer to the value |
|
615 * @return true if the value is a JSON object, false otherwise |
|
616 */ |
296 cx_attr_nonnull |
617 cx_attr_nonnull |
297 static inline bool cxJsonIsObject(const CxJsonValue *value) { |
618 static inline bool cxJsonIsObject(const CxJsonValue *value) { |
298 return value->type == CX_JSON_OBJECT; |
619 return value->type == CX_JSON_OBJECT; |
299 } |
620 } |
300 |
621 |
|
622 /** |
|
623 * Checks if the specified value is a JSON array. |
|
624 * |
|
625 * @param value a pointer to the value |
|
626 * @return true if the value is a JSON array, false otherwise |
|
627 */ |
301 cx_attr_nonnull |
628 cx_attr_nonnull |
302 static inline bool cxJsonIsArray(const CxJsonValue *value) { |
629 static inline bool cxJsonIsArray(const CxJsonValue *value) { |
303 return value->type == CX_JSON_ARRAY; |
630 return value->type == CX_JSON_ARRAY; |
304 } |
631 } |
305 |
632 |
|
633 /** |
|
634 * Checks if the specified value is a string. |
|
635 * |
|
636 * @param value a pointer to the value |
|
637 * @return true if the value is a string, false otherwise |
|
638 */ |
306 cx_attr_nonnull |
639 cx_attr_nonnull |
307 static inline bool cxJsonIsString(const CxJsonValue *value) { |
640 static inline bool cxJsonIsString(const CxJsonValue *value) { |
308 return value->type == CX_JSON_STRING; |
641 return value->type == CX_JSON_STRING; |
309 } |
642 } |
310 |
643 |
|
644 /** |
|
645 * Checks if the specified value is a JSON number. |
|
646 * |
|
647 * This function will return true for both floating point and |
|
648 * integer numbers. |
|
649 * |
|
650 * @param value a pointer to the value |
|
651 * @return true if the value is a JSON number, false otherwise |
|
652 * @see cxJsonIsInteger() |
|
653 */ |
311 cx_attr_nonnull |
654 cx_attr_nonnull |
312 static inline bool cxJsonIsNumber(const CxJsonValue *value) { |
655 static inline bool cxJsonIsNumber(const CxJsonValue *value) { |
313 return value->type == CX_JSON_NUMBER || value->type == CX_JSON_INTEGER; |
656 return value->type == CX_JSON_NUMBER || value->type == CX_JSON_INTEGER; |
314 } |
657 } |
315 |
658 |
|
659 /** |
|
660 * Checks if the specified value is an integer number. |
|
661 * |
|
662 * @param value a pointer to the value |
|
663 * @return true if the value is an integer number, false otherwise |
|
664 * @see cxJsonIsNumber() |
|
665 */ |
316 cx_attr_nonnull |
666 cx_attr_nonnull |
317 static inline bool cxJsonIsInteger(const CxJsonValue *value) { |
667 static inline bool cxJsonIsInteger(const CxJsonValue *value) { |
318 return value->type == CX_JSON_INTEGER; |
668 return value->type == CX_JSON_INTEGER; |
319 } |
669 } |
320 |
670 |
|
671 /** |
|
672 * Checks if the specified value is a JSON literal. |
|
673 * |
|
674 * JSON literals are \c true, \c false, and \c null. |
|
675 * |
|
676 * @param value a pointer to the value |
|
677 * @return true if the value is a JSON literal, false otherwise |
|
678 * @see cxJsonIsTrue() |
|
679 * @see cxJsonIsFalse() |
|
680 * @see cxJsonIsNull() |
|
681 */ |
321 cx_attr_nonnull |
682 cx_attr_nonnull |
322 static inline bool cxJsonIsLiteral(const CxJsonValue *value) { |
683 static inline bool cxJsonIsLiteral(const CxJsonValue *value) { |
323 return value->type == CX_JSON_LITERAL; |
684 return value->type == CX_JSON_LITERAL; |
324 } |
685 } |
325 |
686 |
|
687 /** |
|
688 * Checks if the specified value is a Boolean literal. |
|
689 * |
|
690 * @param value a pointer to the value |
|
691 * @return true if the value is either \c true or \c false, false otherwise |
|
692 * @see cxJsonIsTrue() |
|
693 * @see cxJsonIsFalse() |
|
694 */ |
326 cx_attr_nonnull |
695 cx_attr_nonnull |
327 static inline bool cxJsonIsBool(const CxJsonValue *value) { |
696 static inline bool cxJsonIsBool(const CxJsonValue *value) { |
328 return cxJsonIsLiteral(value) && value->value.literal != CX_JSON_NULL; |
697 return cxJsonIsLiteral(value) && value->value.literal != CX_JSON_NULL; |
329 } |
698 } |
330 |
699 |
|
700 /** |
|
701 * Checks if the specified value is \c true. |
|
702 * |
|
703 * \remark Be advised, that this is not the same as |
|
704 * testing \c !cxJsonIsFalse(v). |
|
705 * |
|
706 * @param value a pointer to the value |
|
707 * @return true if the value is \c true, false otherwise |
|
708 * @see cxJsonIsBool() |
|
709 * @see cxJsonIsFalse() |
|
710 */ |
331 cx_attr_nonnull |
711 cx_attr_nonnull |
332 static inline bool cxJsonIsTrue(const CxJsonValue *value) { |
712 static inline bool cxJsonIsTrue(const CxJsonValue *value) { |
333 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_TRUE; |
713 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_TRUE; |
334 } |
714 } |
335 |
715 |
|
716 /** |
|
717 * Checks if the specified value is \c false. |
|
718 * |
|
719 * \remark Be advised, that this is not the same as |
|
720 * testing \c !cxJsonIsTrue(v). |
|
721 * |
|
722 * @param value a pointer to the value |
|
723 * @return true if the value is \c false, false otherwise |
|
724 * @see cxJsonIsBool() |
|
725 * @see cxJsonIsTrue() |
|
726 */ |
336 cx_attr_nonnull |
727 cx_attr_nonnull |
337 static inline bool cxJsonIsFalse(const CxJsonValue *value) { |
728 static inline bool cxJsonIsFalse(const CxJsonValue *value) { |
338 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_FALSE; |
729 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_FALSE; |
339 } |
730 } |
340 |
731 |
|
732 /** |
|
733 * Checks if the specified value is \c null. |
|
734 * |
|
735 * @param value a pointer to the value |
|
736 * @return true if the value is \c null, false otherwise |
|
737 * @see cxJsonIsLiteral() |
|
738 */ |
341 cx_attr_nonnull |
739 cx_attr_nonnull |
342 static inline bool cxJsonIsNull(const CxJsonValue *value) { |
740 static inline bool cxJsonIsNull(const CxJsonValue *value) { |
343 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_NULL; |
741 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_NULL; |
344 } |
742 } |
345 |
743 |
|
744 /** |
|
745 * Obtains a C string from the given JSON value. |
|
746 * |
|
747 * If the value is not a string, the behavior is undefined. |
|
748 * |
|
749 * @param value the JSON value |
|
750 * @return the value represented as C string |
|
751 * @see cxJsonIsString() |
|
752 */ |
346 cx_attr_nonnull |
753 cx_attr_nonnull |
347 cx_attr_returns_nonnull |
754 cx_attr_returns_nonnull |
348 static inline char *cxJsonAsString(const CxJsonValue *value) { |
755 static inline char *cxJsonAsString(const CxJsonValue *value) { |
349 return value->value.string.ptr; |
756 return value->value.string.ptr; |
350 } |
757 } |
351 |
758 |
|
759 /** |
|
760 * Obtains a UCX string from the given JSON value. |
|
761 * |
|
762 * If the value is not a string, the behavior is undefined. |
|
763 * |
|
764 * @param value the JSON value |
|
765 * @return the value represented as UCX string |
|
766 * @see cxJsonIsString() |
|
767 */ |
352 cx_attr_nonnull |
768 cx_attr_nonnull |
353 static inline cxstring cxJsonAsCxString(const CxJsonValue *value) { |
769 static inline cxstring cxJsonAsCxString(const CxJsonValue *value) { |
354 return cx_strcast(value->value.string); |
770 return cx_strcast(value->value.string); |
355 } |
771 } |
356 |
772 |
|
773 /** |
|
774 * Obtains a mutable UCX string from the given JSON value. |
|
775 * |
|
776 * If the value is not a string, the behavior is undefined. |
|
777 * |
|
778 * @param value the JSON value |
|
779 * @return the value represented as mutable UCX string |
|
780 * @see cxJsonIsString() |
|
781 */ |
357 cx_attr_nonnull |
782 cx_attr_nonnull |
358 static inline cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value) { |
783 static inline cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value) { |
359 return value->value.string; |
784 return value->value.string; |
360 } |
785 } |
361 |
786 |
|
787 /** |
|
788 * Obtains a double-precision floating point value from the given JSON value. |
|
789 * |
|
790 * If the value is not a JSON number, the behavior is undefined. |
|
791 * |
|
792 * @param value the JSON value |
|
793 * @return the value represented as double |
|
794 * @see cxJsonIsNumber() |
|
795 */ |
362 cx_attr_nonnull |
796 cx_attr_nonnull |
363 static inline double cxJsonAsDouble(const CxJsonValue *value) { |
797 static inline double cxJsonAsDouble(const CxJsonValue *value) { |
364 if (value->type == CX_JSON_INTEGER) { |
798 if (value->type == CX_JSON_INTEGER) { |
365 return (double) value->value.integer; |
799 return (double) value->value.integer; |
366 } else { |
800 } else { |
367 return value->value.number; |
801 return value->value.number; |
368 } |
802 } |
369 } |
803 } |
370 |
804 |
|
805 /** |
|
806 * Obtains a 64-bit signed integer from the given JSON value. |
|
807 * |
|
808 * If the value is not a JSON number, the behavior is undefined. |
|
809 * If it is a JSON number, but not an integer, the value will be |
|
810 * converted to an integer, possibly losing precision. |
|
811 * |
|
812 * @param value the JSON value |
|
813 * @return the value represented as double |
|
814 * @see cxJsonIsNumber() |
|
815 * @see cxJsonIsInteger() |
|
816 */ |
371 cx_attr_nonnull |
817 cx_attr_nonnull |
372 static inline int64_t cxJsonAsInteger(const CxJsonValue *value) { |
818 static inline int64_t cxJsonAsInteger(const CxJsonValue *value) { |
373 if (value->type == CX_JSON_INTEGER) { |
819 if (value->type == CX_JSON_INTEGER) { |
374 return value->value.integer; |
820 return value->value.integer; |
375 } else { |
821 } else { |
376 return (int64_t) value->value.number; |
822 return (int64_t) value->value.number; |
377 } |
823 } |
378 } |
824 } |
379 |
825 |
|
826 /** |
|
827 * Obtains a Boolean value from the given JSON value. |
|
828 * |
|
829 * If the value is not a JSON literal, the behavior is undefined. |
|
830 * The \c null literal is interpreted as \c false. |
|
831 * |
|
832 * @param value the JSON value |
|
833 * @return the value represented as double |
|
834 * @see cxJsonIsLiteral() |
|
835 */ |
380 cx_attr_nonnull |
836 cx_attr_nonnull |
381 static inline bool cxJsonAsBool(const CxJsonValue *value) { |
837 static inline bool cxJsonAsBool(const CxJsonValue *value) { |
382 return value->value.literal == CX_JSON_TRUE; |
838 return value->value.literal == CX_JSON_TRUE; |
383 } |
839 } |
384 |
840 |
|
841 /** |
|
842 * Returns the size of a JSON array. |
|
843 * |
|
844 * If the value is not a JSON array, the behavior is undefined. |
|
845 * |
|
846 * @param value the JSON value |
|
847 * @return the size of the array |
|
848 * @see cxJsonIsArray() |
|
849 */ |
385 cx_attr_nonnull |
850 cx_attr_nonnull |
386 static inline size_t cxJsonArrSize(const CxJsonValue *value) { |
851 static inline size_t cxJsonArrSize(const CxJsonValue *value) { |
387 return value->value.array.array_size; |
852 return value->value.array.array_size; |
388 } |
853 } |
389 |
854 |
|
855 /** |
|
856 * Returns an element from a JSON array. |
|
857 * |
|
858 * If the value is not a JSON array, the behavior is undefined. |
|
859 * |
|
860 * This function guarantees to return a value. If the index is |
|
861 * out of bounds, the returned value will be of type |
|
862 * #CX_JSON_NOTHING, but never \c NULL. |
|
863 * |
|
864 * @param value the JSON value |
|
865 * @param index the index in the array |
|
866 * @return the value at the specified index |
|
867 * @see cxJsonIsArray() |
|
868 */ |
390 cx_attr_nonnull |
869 cx_attr_nonnull |
391 cx_attr_returns_nonnull |
870 cx_attr_returns_nonnull |
392 CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index); |
871 CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index); |
393 |
872 |
394 // TODO: add cxJsonArrIter() |
873 /** |
395 |
874 * Returns a value corresponding to a key in a JSON object. |
396 // TODO: implement cxJsonObjGet as a _Generic with support for cxstring |
875 * |
|
876 * If the value is not a JSON object, the behavior is undefined. |
|
877 * |
|
878 * This function guarantees to return a JSON value. If the |
|
879 * object does not contain \p name, the returned JSON value |
|
880 * will be of type #CX_JSON_NOTHING, but never \c NULL. |
|
881 * |
|
882 * @param value the JSON object |
|
883 * @param name the key to look up |
|
884 * @return the value corresponding to the key |
|
885 * @see cxJsonIsObject() |
|
886 */ |
397 cx_attr_nonnull |
887 cx_attr_nonnull |
398 cx_attr_returns_nonnull |
888 cx_attr_returns_nonnull |
399 cx_attr_cstr_arg(2) |
889 cx_attr_cstr_arg(2) |
400 CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char* name); |
890 CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char* name); |
401 |
891 |