194 /** |
194 /** |
195 * Type alias for a JSON string. |
195 * Type alias for a JSON string. |
196 */ |
196 */ |
197 typedef struct cx_mutstr_s CxJsonString; |
197 typedef struct cx_mutstr_s CxJsonString; |
198 /** |
198 /** |
199 * Type alias for a number that can be represented as 64-bit signed integer. |
199 * Type alias for a number that can be represented as a 64-bit signed integer. |
200 */ |
200 */ |
201 typedef int64_t CxJsonInteger; |
201 typedef int64_t CxJsonInteger; |
202 /** |
202 /** |
203 * Type alias for number that is not an integer. |
203 * Type alias for a number that is not an integer. |
204 */ |
204 */ |
205 typedef double CxJsonNumber; |
205 typedef double CxJsonNumber; |
206 /** |
206 /** |
207 * Type alias for a JSON literal. |
207 * Type alias for a JSON literal. |
208 */ |
208 */ |
270 /** |
270 /** |
271 * The value data. |
271 * The value data. |
272 */ |
272 */ |
273 union { |
273 union { |
274 /** |
274 /** |
275 * The array data if type is #CX_JSON_ARRAY. |
275 * The array data if the type is #CX_JSON_ARRAY. |
276 */ |
276 */ |
277 CxJsonArray array; |
277 CxJsonArray array; |
278 /** |
278 /** |
279 * The object data if type is #CX_JSON_OBJECT. |
279 * The object data if the type is #CX_JSON_OBJECT. |
280 */ |
280 */ |
281 CxJsonObject object; |
281 CxJsonObject object; |
282 /** |
282 /** |
283 * The string data if type is #CX_JSON_STRING. |
283 * The string data if the type is #CX_JSON_STRING. |
284 */ |
284 */ |
285 CxJsonString string; |
285 CxJsonString string; |
286 /** |
286 /** |
287 * The integer if type is #CX_JSON_INTEGER. |
287 * The integer if the type is #CX_JSON_INTEGER. |
288 */ |
288 */ |
289 CxJsonInteger integer; |
289 CxJsonInteger integer; |
290 /** |
290 /** |
291 * The number if type is #CX_JSON_NUMBER. |
291 * The number if the type is #CX_JSON_NUMBER. |
292 */ |
292 */ |
293 CxJsonNumber number; |
293 CxJsonNumber number; |
294 /** |
294 /** |
295 * The literal type if type is #CX_JSON_LITERAL. |
295 * The literal type if the type is #CX_JSON_LITERAL. |
296 */ |
296 */ |
297 CxJsonLiteral literal; |
297 CxJsonLiteral literal; |
298 } value; |
298 } value; |
299 }; |
299 }; |
300 |
300 |
389 */ |
389 */ |
390 CX_JSON_NO_DATA, |
390 CX_JSON_NO_DATA, |
391 /** |
391 /** |
392 * The input ends unexpectedly. |
392 * The input ends unexpectedly. |
393 * |
393 * |
394 * Refill the buffer with cxJsonFill() to complete the json data. |
394 * Refill the buffer with cxJsonFill() to complete the JSON data. |
395 */ |
395 */ |
396 CX_JSON_INCOMPLETE_DATA, |
396 CX_JSON_INCOMPLETE_DATA, |
397 /** |
397 /** |
398 * Not used as a status and never returned by any function. |
398 * Not used as a status and never returned by any function. |
399 * |
399 * |
400 * You can use this enumerator to check for all "good" status results |
400 * You can use this enumerator to check for all "good" status results |
401 * by checking if the status is less than @c CX_JSON_OK. |
401 * by checking if the status is less than @c CX_JSON_OK. |
402 * |
402 * |
403 * A "good" status means, that you can refill data and continue parsing. |
403 * A "good" status means that you can refill data and continue parsing. |
404 */ |
404 */ |
405 CX_JSON_OK, |
405 CX_JSON_OK, |
406 /** |
406 /** |
407 * The input buffer has never been filled. |
407 * The input buffer has never been filled. |
408 */ |
408 */ |
410 /** |
410 /** |
411 * Allocating memory for the internal buffer failed. |
411 * Allocating memory for the internal buffer failed. |
412 */ |
412 */ |
413 CX_JSON_BUFFER_ALLOC_FAILED, |
413 CX_JSON_BUFFER_ALLOC_FAILED, |
414 /** |
414 /** |
415 * Allocating memory for a json value failed. |
415 * Allocating memory for a JSON value failed. |
416 */ |
416 */ |
417 CX_JSON_VALUE_ALLOC_FAILED, |
417 CX_JSON_VALUE_ALLOC_FAILED, |
418 /** |
418 /** |
419 * A number value is incorrectly formatted. |
419 * A number value is incorrectly formatted. |
420 */ |
420 */ |
443 */ |
443 */ |
444 bool sort_members; |
444 bool sort_members; |
445 /** |
445 /** |
446 * The maximum number of fractional digits in a number value. |
446 * The maximum number of fractional digits in a number value. |
447 * The default value is 6 and values larger than 15 are reduced to 15. |
447 * The default value is 6 and values larger than 15 are reduced to 15. |
448 * Note, that the actual number of digits may be lower, depending on the concrete number. |
448 * Note that the actual number of digits may be lower, depending on the concrete number. |
449 */ |
449 */ |
450 uint8_t frac_max_digits; |
450 uint8_t frac_max_digits; |
451 /** |
451 /** |
452 * Set true to use spaces instead of tab characters. |
452 * Set true to use spaces instead of tab characters. |
453 * Indentation is only used in pretty output. |
453 * Indentation is only used in pretty output. |
494 * This function blocks until either all data is written, or an error occurs. |
494 * This function blocks until either all data is written, or an error occurs. |
495 * The write operation is not atomic in the sense that it might happen |
495 * The write operation is not atomic in the sense that it might happen |
496 * that the data is only partially written when an error occurs with no |
496 * that the data is only partially written when an error occurs with no |
497 * way to indicate how much data was written. |
497 * way to indicate how much data was written. |
498 * To avoid this problem, you can use a CxBuffer as @p target which is |
498 * To avoid this problem, you can use a CxBuffer as @p target which is |
499 * unlikely to fail a write operation and either use the buffer's flush |
499 * unlikely to fail a write operation. You can, for example, use the buffer's flush |
500 * feature to relay the data or use the data in the buffer manually to |
500 * feature to relay the data. |
501 * write it to the actual target. |
|
502 * |
501 * |
503 * @param target the buffer or stream where to write to |
502 * @param target the buffer or stream where to write to |
504 * @param value the value that shall be written |
503 * @param value the value that shall be written |
505 * @param wfunc the write function to use |
504 * @param wfunc the write function to use |
506 * @param settings formatting settings (or @c NULL to use a compact default) |
505 * @param settings formatting settings (or @c NULL to use a compact default) |
515 cx_write_func wfunc, |
514 cx_write_func wfunc, |
516 const CxJsonWriter* settings |
515 const CxJsonWriter* settings |
517 ); |
516 ); |
518 |
517 |
519 /** |
518 /** |
520 * Initializes the json interface. |
519 * Initializes the JSON interface. |
521 * |
520 * |
522 * @param json the json interface |
521 * @param json the JSON interface |
523 * @param allocator the allocator that shall be used for the produced values |
522 * @param allocator the allocator that shall be used for the produced values |
524 * @see cxJsonDestroy() |
523 * @see cxJsonDestroy() |
525 */ |
524 */ |
526 cx_attr_nonnull_arg(1) |
525 cx_attr_nonnull_arg(1) |
527 cx_attr_export |
526 cx_attr_export |
528 void cxJsonInit(CxJson *json, const CxAllocator *allocator); |
527 void cxJsonInit(CxJson *json, const CxAllocator *allocator); |
529 |
528 |
530 /** |
529 /** |
531 * Destroys the json interface. |
530 * Destroys the JSON interface. |
532 * |
531 * |
533 * @param json the json interface |
532 * @param json the JSON interface |
534 * @see cxJsonInit() |
533 * @see cxJsonInit() |
535 */ |
534 */ |
536 cx_attr_nonnull |
535 cx_attr_nonnull |
537 cx_attr_export |
536 cx_attr_export |
538 void cxJsonDestroy(CxJson *json); |
537 void cxJsonDestroy(CxJson *json); |
539 |
538 |
540 /** |
539 /** |
541 * Destroys and re-initializes the json interface. |
540 * Destroys and re-initializes the JSON interface. |
542 * |
541 * |
543 * You might want to use this, to reset the parser after |
542 * You might want to use this to reset the parser after |
544 * encountering a syntax error. |
543 * encountering a syntax error. |
545 * |
544 * |
546 * @param json the json interface |
545 * @param json the JSON interface |
547 */ |
546 */ |
548 cx_attr_nonnull |
547 cx_attr_nonnull |
549 static inline void cxJsonReset(CxJson *json) { |
548 static inline void cxJsonReset(CxJson *json) { |
550 const CxAllocator *allocator = json->allocator; |
549 const CxAllocator *allocator = json->allocator; |
551 cxJsonDestroy(json); |
550 cxJsonDestroy(json); |
561 * pointer to the data in that case. When you invoke the fill |
560 * pointer to the data in that case. When you invoke the fill |
562 * function more than once before calling cxJsonNext(), |
561 * function more than once before calling cxJsonNext(), |
563 * the additional data is appended - inevitably leading to |
562 * the additional data is appended - inevitably leading to |
564 * an allocation of a new buffer and copying the previous contents. |
563 * an allocation of a new buffer and copying the previous contents. |
565 * |
564 * |
566 * @param json the json interface |
565 * @param json the JSON interface |
567 * @param buf the source buffer |
566 * @param buf the source buffer |
568 * @param len the length of the source buffer |
567 * @param len the length of the source buffer |
569 * @retval zero success |
568 * @retval zero success |
570 * @retval non-zero internal allocation error |
569 * @retval non-zero internal allocation error |
571 * @see cxJsonFill() |
570 * @see cxJsonFill() |
577 |
576 |
578 |
577 |
579 /** |
578 /** |
580 * Internal function, do not use. |
579 * Internal function, do not use. |
581 * |
580 * |
582 * @param json the json interface |
581 * @param json the JSON interface |
583 * @param str the string |
582 * @param str the string |
584 * @retval zero success |
583 * @retval zero success |
585 * @retval non-zero internal allocation error |
584 * @retval non-zero internal allocation error |
586 */ |
585 */ |
587 cx_attr_nonnull |
586 cx_attr_nonnull |
598 * pointer to the data in that case. When you invoke the fill |
597 * pointer to the data in that case. When you invoke the fill |
599 * function more than once before calling cxJsonNext(), |
598 * function more than once before calling cxJsonNext(), |
600 * the additional data is appended - inevitably leading to |
599 * the additional data is appended - inevitably leading to |
601 * an allocation of a new buffer and copying the previous contents. |
600 * an allocation of a new buffer and copying the previous contents. |
602 * |
601 * |
603 * @param json the json interface |
602 * @param json the JSON interface |
604 * @param str the source string |
603 * @param str the source string |
605 * @retval zero success |
604 * @retval zero success |
606 * @retval non-zero internal allocation error |
605 * @retval non-zero internal allocation error |
607 * @see cxJsonFilln() |
606 * @see cxJsonFilln() |
608 */ |
607 */ |
915 |
914 |
916 /** |
915 /** |
917 * Recursively deallocates the memory of a JSON value. |
916 * Recursively deallocates the memory of a JSON value. |
918 * |
917 * |
919 * @remark The type of each deallocated value will be changed |
918 * @remark The type of each deallocated value will be changed |
920 * to #CX_JSON_NOTHING and values of such type will be skipped |
919 * to #CX_JSON_NOTHING, and values of such a type will be skipped |
921 * by the de-allocation. That means, this function protects |
920 * by the deallocation. That means this function protects |
922 * you from double-frees when you are accidentally freeing |
921 * you from double-frees when you are accidentally freeing |
923 * a nested value and then the parent value (or vice versa). |
922 * a nested value and then the parent value (or vice versa). |
924 * |
923 * |
925 * @param value the value |
924 * @param value the value |
926 */ |
925 */ |
935 * |
934 * |
936 * When this function returns #CX_JSON_INCOMPLETE_DATA, you can |
935 * When this function returns #CX_JSON_INCOMPLETE_DATA, you can |
937 * add the missing data with another invocation of cxJsonFill() |
936 * add the missing data with another invocation of cxJsonFill() |
938 * and then repeat the call to cxJsonNext(). |
937 * and then repeat the call to cxJsonNext(). |
939 * |
938 * |
940 * @param json the json interface |
939 * @param json the JSON interface |
941 * @param value a pointer where the next value shall be stored |
940 * @param value a pointer where the next value shall be stored |
942 * @retval CX_JSON_NO_ERROR successfully retrieve the @p value |
941 * @retval CX_JSON_NO_ERROR successfully retrieve the @p value |
943 * @retval CX_JSON_NO_DATA there is no (more) data in the buffer to read from |
942 * @retval CX_JSON_NO_DATA there is no (more) data in the buffer to read from |
944 * @retval CX_JSON_INCOMPLETE_DATA an incomplete value was read |
943 * @retval CX_JSON_INCOMPLETE_DATA an incomplete value was read |
945 * and more data needs to be filled |
944 * and more data needs to be filled |
991 } |
990 } |
992 |
991 |
993 /** |
992 /** |
994 * Checks if the specified value is a JSON number. |
993 * Checks if the specified value is a JSON number. |
995 * |
994 * |
996 * This function will return true for both floating point and |
995 * This function will return true for both floating-point and |
997 * integer numbers. |
996 * integer numbers. |
998 * |
997 * |
999 * @param value a pointer to the value |
998 * @param value a pointer to the value |
1000 * @retval true the value is a JSON number |
999 * @retval true the value is a JSON number |
1001 * @retval false otherwise |
1000 * @retval false otherwise |
1051 } |
1050 } |
1052 |
1051 |
1053 /** |
1052 /** |
1054 * Checks if the specified value is @c true. |
1053 * Checks if the specified value is @c true. |
1055 * |
1054 * |
1056 * @remark Be advised, that this is not the same as |
1055 * @remark Be advised that this is different from |
1057 * testing @c !cxJsonIsFalse(v). |
1056 * testing @c !cxJsonIsFalse(v). |
1058 * |
1057 * |
1059 * @param value a pointer to the value |
1058 * @param value a pointer to the value |
1060 * @retval true the value is @c true |
1059 * @retval true the value is @c true |
1061 * @retval false otherwise |
1060 * @retval false otherwise |
1068 } |
1067 } |
1069 |
1068 |
1070 /** |
1069 /** |
1071 * Checks if the specified value is @c false. |
1070 * Checks if the specified value is @c false. |
1072 * |
1071 * |
1073 * @remark Be advised, that this is not the same as |
1072 * @remark Be advised that this is different from |
1074 * testing @c !cxJsonIsTrue(v). |
1073 * testing @c !cxJsonIsTrue(v). |
1075 * |
1074 * |
1076 * @param value a pointer to the value |
1075 * @param value a pointer to the value |
1077 * @retval true the value is @c false |
1076 * @retval true the value is @c false |
1078 * @retval false otherwise |
1077 * @retval false otherwise |
1139 static inline cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value) { |
1138 static inline cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value) { |
1140 return value->value.string; |
1139 return value->value.string; |
1141 } |
1140 } |
1142 |
1141 |
1143 /** |
1142 /** |
1144 * Obtains a double-precision floating point value from the given JSON value. |
1143 * Obtains a double-precision floating-point value from the given JSON value. |
1145 * |
1144 * |
1146 * If the @p value is not a JSON number, the behavior is undefined. |
1145 * If the @p value is not a JSON number, the behavior is undefined. |
1147 * |
1146 * |
1148 * @param value the JSON value |
1147 * @param value the JSON value |
1149 * @return the value represented as double |
1148 * @return the value represented as double |