src/cx/json.h

changeset 1012
21884374edbb
parent 1009
7650e722437e
child 1013
add8358fc3c3
equal deleted inserted replaced
1011:838b096c1d08 1012:21884374edbb
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 *
159 /** 358 /**
160 * Internally reserved memory for the value buffer stack. 359 * Internally reserved memory for the value buffer stack.
161 */ 360 */
162 CxJsonValue* vbuf_internal[8]; 361 CxJsonValue* vbuf_internal[8];
163 362
164 int error; // TODO: currently unused 363 /**
364 * Used internally.
365 */
165 bool tokenizer_escape; // TODO: check if it can be replaced with look-behind 366 bool tokenizer_escape; // TODO: check if it can be replaced with look-behind
166 }; 367 };
167 368
168 /** 369 /**
169 * Status codes for the json interface. 370 * Status codes for the json interface.
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

mercurial