src/cx/json.h

changeset 1424
563033aa998c
parent 1417
b97faf8b7ab7
equal deleted inserted replaced
1423:9a72258446cd 1424:563033aa998c
88 /** 88 /**
89 * A string token. 89 * A string token.
90 */ 90 */
91 CX_JSON_TOKEN_STRING, 91 CX_JSON_TOKEN_STRING,
92 /** 92 /**
93 * A number token that can be represented as integer. 93 * A number token that can be represented as an integer.
94 */ 94 */
95 CX_JSON_TOKEN_INTEGER, 95 CX_JSON_TOKEN_INTEGER,
96 /** 96 /**
97 * A number token that cannot be represented as integer. 97 * A number token that cannot be represented as an integer.
98 */ 98 */
99 CX_JSON_TOKEN_NUMBER, 99 CX_JSON_TOKEN_NUMBER,
100 /** 100 /**
101 * A literal token. 101 * A literal token.
102 */ 102 */
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
375 */ 375 */
376 CxJsonValue* vbuf_internal[8]; 376 CxJsonValue* vbuf_internal[8];
377 }; 377 };
378 378
379 /** 379 /**
380 * Status codes for the json interface. 380 * Status codes for the JSON interface.
381 */ 381 */
382 enum cx_json_status { 382 enum cx_json_status {
383 /** 383 /**
384 * Everything is fine. 384 * Everything is fine.
385 */ 385 */
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 */
424 */ 424 */
425 CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN 425 CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN
426 }; 426 };
427 427
428 /** 428 /**
429 * Typedef for the json status enum. 429 * Typedef for the JSON status enum.
430 */ 430 */
431 typedef enum cx_json_status CxJsonStatus; 431 typedef enum cx_json_status CxJsonStatus;
432 432
433 /** 433 /**
434 * The JSON writer settings. 434 * The JSON writer settings.
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.
463 */ 463 */
464 bool escape_slash; 464 bool escape_slash;
465 }; 465 };
466 466
467 /** 467 /**
468 * Typedef for the json writer. 468 * Typedef for the JSON writer.
469 */ 469 */
470 typedef struct cx_json_writer_s CxJsonWriter; 470 typedef struct cx_json_writer_s CxJsonWriter;
471 471
472 /** 472 /**
473 * Creates a default writer configuration for compact output. 473 * Creates a default writer configuration for compact 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

mercurial