| 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. |
| 474 * |
474 * |
| 475 * @return new JSON writer settings |
475 * @return new JSON writer settings |
| 476 */ |
476 */ |
| 477 cx_attr_nodiscard |
477 cx_attr_nodiscard |
| 478 cx_attr_export |
478 CX_EXPORT CxJsonWriter cxJsonWriterCompact(void); |
| 479 CxJsonWriter cxJsonWriterCompact(void); |
|
| 480 |
479 |
| 481 /** |
480 /** |
| 482 * Creates a default writer configuration for pretty output. |
481 * Creates a default writer configuration for pretty output. |
| 483 * |
482 * |
| 484 * @param use_spaces false if you want tabs, true if you want four spaces instead |
483 * @param use_spaces false if you want tabs, true if you want four spaces instead |
| 485 * @return new JSON writer settings |
484 * @return new JSON writer settings |
| 486 */ |
485 */ |
| 487 cx_attr_nodiscard |
486 cx_attr_nodiscard |
| 488 cx_attr_export |
487 CX_EXPORT CxJsonWriter cxJsonWriterPretty(bool use_spaces); |
| 489 CxJsonWriter cxJsonWriterPretty(bool use_spaces); |
|
| 490 |
488 |
| 491 /** |
489 /** |
| 492 * Writes a JSON value to a buffer or stream. |
490 * Writes a JSON value to a buffer or stream. |
| 493 * |
491 * |
| 494 * This function blocks until either all data is written, or an error occurs. |
492 * 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 |
493 * 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 |
494 * that the data is only partially written when an error occurs with no |
| 497 * way to indicate how much data was written. |
495 * way to indicate how much data was written. |
| 498 * To avoid this problem, you can use a CxBuffer as @p target which is |
496 * 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 |
497 * 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 |
498 * feature to relay the data. |
| 501 * write it to the actual target. |
|
| 502 * |
499 * |
| 503 * @param target the buffer or stream where to write to |
500 * @param target the buffer or stream where to write to |
| 504 * @param value the value that shall be written |
501 * @param value the value that shall be written |
| 505 * @param wfunc the write function to use |
502 * @param wfunc the write function to use |
| 506 * @param settings formatting settings (or @c NULL to use a compact default) |
503 * @param settings formatting settings (or @c NULL to use a compact default) |
| 507 * @retval zero success |
504 * @retval zero success |
| 508 * @retval non-zero when no or not all data could be written |
505 * @retval non-zero when no or not all data could be written |
| 509 */ |
506 */ |
| 510 cx_attr_nonnull_arg(1, 2, 3) |
507 cx_attr_nonnull_arg(1, 2, 3) |
| 511 cx_attr_export |
508 CX_EXPORT int cxJsonWrite(void* target, const CxJsonValue* value, |
| 512 int cxJsonWrite( |
509 cx_write_func wfunc, const CxJsonWriter* settings); |
| 513 void* target, |
510 |
| 514 const CxJsonValue* value, |
511 /** |
| 515 cx_write_func wfunc, |
512 * Initializes the JSON interface. |
| 516 const CxJsonWriter* settings |
513 * |
| 517 ); |
514 * @param json the JSON interface |
| 518 |
|
| 519 /** |
|
| 520 * Initializes the json interface. |
|
| 521 * |
|
| 522 * @param json the json interface |
|
| 523 * @param allocator the allocator that shall be used for the produced values |
515 * @param allocator the allocator that shall be used for the produced values |
| 524 * @see cxJsonDestroy() |
516 * @see cxJsonDestroy() |
| 525 */ |
517 */ |
| 526 cx_attr_nonnull_arg(1) |
518 cx_attr_nonnull_arg(1) |
| 527 cx_attr_export |
519 CX_EXPORT void cxJsonInit(CxJson *json, const CxAllocator *allocator); |
| 528 void cxJsonInit(CxJson *json, const CxAllocator *allocator); |
520 |
| 529 |
521 /** |
| 530 /** |
522 * Destroys the JSON interface. |
| 531 * Destroys the json interface. |
523 * |
| 532 * |
524 * @param json the JSON interface |
| 533 * @param json the json interface |
|
| 534 * @see cxJsonInit() |
525 * @see cxJsonInit() |
| 535 */ |
526 */ |
| 536 cx_attr_nonnull |
527 cx_attr_nonnull |
| 537 cx_attr_export |
528 CX_EXPORT void cxJsonDestroy(CxJson *json); |
| 538 void cxJsonDestroy(CxJson *json); |
529 |
| 539 |
530 /** |
| 540 /** |
531 * Destroys and re-initializes the JSON interface. |
| 541 * Destroys and re-initializes the json interface. |
532 * |
| 542 * |
533 * You might want to use this to reset the parser after |
| 543 * You might want to use this, to reset the parser after |
|
| 544 * encountering a syntax error. |
534 * encountering a syntax error. |
| 545 * |
535 * |
| 546 * @param json the json interface |
536 * @param json the JSON interface |
| 547 */ |
537 */ |
| 548 cx_attr_nonnull |
538 cx_attr_nonnull |
| 549 static inline void cxJsonReset(CxJson *json) { |
539 CX_EXPORT void cxJsonReset(CxJson *json); |
| 550 const CxAllocator *allocator = json->allocator; |
|
| 551 cxJsonDestroy(json); |
|
| 552 cxJsonInit(json, allocator); |
|
| 553 } |
|
| 554 |
540 |
| 555 /** |
541 /** |
| 556 * Fills the input buffer. |
542 * Fills the input buffer. |
| 557 * |
543 * |
| 558 * @remark The JSON interface tries to avoid copying the input data. |
544 * @remark The JSON interface tries to avoid copying the input data. |
| 561 * pointer to the data in that case. When you invoke the fill |
547 * pointer to the data in that case. When you invoke the fill |
| 562 * function more than once before calling cxJsonNext(), |
548 * function more than once before calling cxJsonNext(), |
| 563 * the additional data is appended - inevitably leading to |
549 * the additional data is appended - inevitably leading to |
| 564 * an allocation of a new buffer and copying the previous contents. |
550 * an allocation of a new buffer and copying the previous contents. |
| 565 * |
551 * |
| 566 * @param json the json interface |
552 * @param json the JSON interface |
| 567 * @param buf the source buffer |
553 * @param buf the source buffer |
| 568 * @param len the length of the source buffer |
554 * @param len the length of the source buffer |
| 569 * @retval zero success |
555 * @retval zero success |
| 570 * @retval non-zero internal allocation error |
556 * @retval non-zero internal allocation error |
| 571 * @see cxJsonFill() |
557 * @see cxJsonFill() |
| 572 */ |
558 */ |
| 573 cx_attr_nonnull |
559 cx_attr_nonnull cx_attr_access_r(2, 3) |
| 574 cx_attr_access_r(2, 3) |
560 CX_EXPORT int cxJsonFilln(CxJson *json, const char *buf, size_t len); |
| 575 cx_attr_export |
561 |
| 576 int cxJsonFilln(CxJson *json, const char *buf, size_t len); |
562 |
| 577 |
563 /** |
| 578 #ifdef __cplusplus |
564 * Internal function, do not use. |
| 579 } // extern "C" |
565 * |
| 580 |
566 * @param json the JSON interface |
| 581 cx_attr_nonnull |
567 * @param str the string |
| 582 static inline int cxJsonFill( |
568 * @retval zero success |
| 583 CxJson *json, |
569 * @retval non-zero internal allocation error |
| 584 cxstring str |
570 */ |
| 585 ) { |
571 cx_attr_nonnull |
| |
572 CX_INLINE int cx_json_fill(CxJson *json, cxstring str) { |
| 586 return cxJsonFilln(json, str.ptr, str.length); |
573 return cxJsonFilln(json, str.ptr, str.length); |
| 587 } |
574 } |
| 588 |
575 |
| 589 cx_attr_nonnull |
|
| 590 static inline int cxJsonFill( |
|
| 591 CxJson *json, |
|
| 592 cxmutstr str |
|
| 593 ) { |
|
| 594 return cxJsonFilln(json, str.ptr, str.length); |
|
| 595 } |
|
| 596 |
|
| 597 cx_attr_nonnull |
|
| 598 cx_attr_cstr_arg(2) |
|
| 599 static inline int cxJsonFill( |
|
| 600 CxJson *json, |
|
| 601 const char *str |
|
| 602 ) { |
|
| 603 return cxJsonFilln(json, str, strlen(str)); |
|
| 604 } |
|
| 605 |
|
| 606 extern "C" { |
|
| 607 #else // __cplusplus |
|
| 608 /** |
576 /** |
| 609 * Fills the input buffer. |
577 * Fills the input buffer. |
| 610 * |
578 * |
| 611 * The JSON interface tries to avoid copying the input data. |
579 * The JSON interface tries to avoid copying the input data. |
| 612 * When you use this function and cxJsonNext() interleaving, |
580 * When you use this function and cxJsonNext() interleaving, |
| 614 * pointer to the data in that case. When you invoke the fill |
582 * pointer to the data in that case. When you invoke the fill |
| 615 * function more than once before calling cxJsonNext(), |
583 * function more than once before calling cxJsonNext(), |
| 616 * the additional data is appended - inevitably leading to |
584 * the additional data is appended - inevitably leading to |
| 617 * an allocation of a new buffer and copying the previous contents. |
585 * an allocation of a new buffer and copying the previous contents. |
| 618 * |
586 * |
| 619 * @param json the json interface |
587 * @param json the JSON interface |
| 620 * @param str the source string |
588 * @param str the source string |
| 621 * @retval zero success |
589 * @retval zero success |
| 622 * @retval non-zero internal allocation error |
590 * @retval non-zero internal allocation error |
| 623 * @see cxJsonFilln() |
591 * @see cxJsonFilln() |
| 624 */ |
592 */ |
| 625 #define cxJsonFill(json, str) _Generic((str), \ |
593 #define cxJsonFill(json, str) cx_json_fill(json, cx_strcast(str)) |
| 626 cxstring: cx_json_fill_cxstr, \ |
|
| 627 cxmutstr: cx_json_fill_mutstr, \ |
|
| 628 char*: cx_json_fill_str, \ |
|
| 629 const char*: cx_json_fill_str) \ |
|
| 630 (json, str) |
|
| 631 |
|
| 632 /** |
|
| 633 * @copydoc cxJsonFill() |
|
| 634 */ |
|
| 635 cx_attr_nonnull |
|
| 636 static inline int cx_json_fill_cxstr( |
|
| 637 CxJson *json, |
|
| 638 cxstring str |
|
| 639 ) { |
|
| 640 return cxJsonFilln(json, str.ptr, str.length); |
|
| 641 } |
|
| 642 |
|
| 643 /** |
|
| 644 * @copydoc cxJsonFill() |
|
| 645 */ |
|
| 646 cx_attr_nonnull |
|
| 647 static inline int cx_json_fill_mutstr( |
|
| 648 CxJson *json, |
|
| 649 cxmutstr str |
|
| 650 ) { |
|
| 651 return cxJsonFilln(json, str.ptr, str.length); |
|
| 652 } |
|
| 653 |
|
| 654 /** |
|
| 655 * @copydoc cxJsonFill() |
|
| 656 */ |
|
| 657 cx_attr_nonnull |
|
| 658 cx_attr_cstr_arg(2) |
|
| 659 static inline int cx_json_fill_str( |
|
| 660 CxJson *json, |
|
| 661 const char *str |
|
| 662 ) { |
|
| 663 return cxJsonFilln(json, str, strlen(str)); |
|
| 664 } |
|
| 665 #endif |
|
| 666 |
594 |
| 667 /** |
595 /** |
| 668 * Creates a new (empty) JSON object. |
596 * Creates a new (empty) JSON object. |
| 669 * |
597 * |
| 670 * @param allocator the allocator to use |
598 * @param allocator the allocator to use |
| 671 * @return the new JSON object or @c NULL if allocation fails |
599 * @return the new JSON object or @c NULL if allocation fails |
| 672 * @see cxJsonObjPutObj() |
600 * @see cxJsonObjPutObj() |
| 673 * @see cxJsonArrAddValues() |
601 * @see cxJsonArrAddValues() |
| 674 */ |
602 */ |
| 675 cx_attr_nodiscard |
603 cx_attr_nodiscard |
| 676 cx_attr_export |
604 CX_EXPORT CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator); |
| 677 CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator); |
|
| 678 |
605 |
| 679 /** |
606 /** |
| 680 * Creates a new (empty) JSON array. |
607 * Creates a new (empty) JSON array. |
| 681 * |
608 * |
| 682 * @param allocator the allocator to use |
609 * @param allocator the allocator to use |
| 683 * @return the new JSON array or @c NULL if allocation fails |
610 * @return the new JSON array or @c NULL if allocation fails |
| 684 * @see cxJsonObjPutArr() |
611 * @see cxJsonObjPutArr() |
| 685 * @see cxJsonArrAddValues() |
612 * @see cxJsonArrAddValues() |
| 686 */ |
613 */ |
| 687 cx_attr_nodiscard |
614 cx_attr_nodiscard |
| 688 cx_attr_export |
615 CX_EXPORT CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator); |
| 689 CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator); |
|
| 690 |
616 |
| 691 /** |
617 /** |
| 692 * Creates a new JSON number value. |
618 * Creates a new JSON number value. |
| 693 * |
619 * |
| 694 * @param allocator the allocator to use |
620 * @param allocator the allocator to use |
| 752 * @return the new JSON value or @c NULL if allocation fails |
672 * @return the new JSON value or @c NULL if allocation fails |
| 753 * @see cxJsonObjPutLiteral() |
673 * @see cxJsonObjPutLiteral() |
| 754 * @see cxJsonArrAddLiterals() |
674 * @see cxJsonArrAddLiterals() |
| 755 */ |
675 */ |
| 756 cx_attr_nodiscard |
676 cx_attr_nodiscard |
| 757 cx_attr_export |
677 CX_EXPORT CxJsonValue* cxJsonCreateLiteral(const CxAllocator* allocator, CxJsonLiteral lit); |
| 758 CxJsonValue* cxJsonCreateLiteral(const CxAllocator* allocator, CxJsonLiteral lit); |
|
| 759 |
678 |
| 760 /** |
679 /** |
| 761 * Adds number values to a JSON array. |
680 * Adds number values to a JSON array. |
| 762 * |
681 * |
| 763 * @param arr the JSON array |
682 * @param arr the JSON array |
| 764 * @param num the array of values |
683 * @param num the array of values |
| 765 * @param count the number of elements |
684 * @param count the number of elements |
| 766 * @retval zero success |
685 * @retval zero success |
| 767 * @retval non-zero allocation failure |
686 * @retval non-zero allocation failure |
| 768 */ |
687 */ |
| 769 cx_attr_nonnull |
688 cx_attr_nonnull cx_attr_access_r(2, 3) |
| 770 cx_attr_access_r(2, 3) |
689 CX_EXPORT int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count); |
| 771 cx_attr_export |
|
| 772 int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count); |
|
| 773 |
690 |
| 774 /** |
691 /** |
| 775 * Adds number values, of which all are integers, to a JSON array. |
692 * Adds number values, of which all are integers, to a JSON array. |
| 776 * |
693 * |
| 777 * @param arr the JSON array |
694 * @param arr the JSON array |
| 778 * @param num the array of values |
695 * @param num the array of values |
| 779 * @param count the number of elements |
696 * @param count the number of elements |
| 780 * @retval zero success |
697 * @retval zero success |
| 781 * @retval non-zero allocation failure |
698 * @retval non-zero allocation failure |
| 782 */ |
699 */ |
| 783 cx_attr_nonnull |
700 cx_attr_nonnull cx_attr_access_r(2, 3) |
| 784 cx_attr_access_r(2, 3) |
701 CX_EXPORT int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count); |
| 785 cx_attr_export |
|
| 786 int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count); |
|
| 787 |
702 |
| 788 /** |
703 /** |
| 789 * Adds strings to a JSON array. |
704 * Adds strings to a JSON array. |
| 790 * |
705 * |
| 791 * The strings will be copied with the allocator of the array. |
706 * The strings will be copied with the allocator of the array. |
| 812 * @param count the number of elements |
725 * @param count the number of elements |
| 813 * @retval zero success |
726 * @retval zero success |
| 814 * @retval non-zero allocation failure |
727 * @retval non-zero allocation failure |
| 815 * @see cxJsonArrAddStrings() |
728 * @see cxJsonArrAddStrings() |
| 816 */ |
729 */ |
| 817 cx_attr_nonnull |
730 cx_attr_nonnull cx_attr_access_r(2, 3) |
| 818 cx_attr_access_r(2, 3) |
731 CX_EXPORT int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count); |
| 819 cx_attr_export |
|
| 820 int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count); |
|
| 821 |
732 |
| 822 /** |
733 /** |
| 823 * Adds literals to a JSON array. |
734 * Adds literals to a JSON array. |
| 824 * |
735 * |
| 825 * @param arr the JSON array |
736 * @param arr the JSON array |
| 826 * @param lit the array of literal types |
737 * @param lit the array of literal types |
| 827 * @param count the number of elements |
738 * @param count the number of elements |
| 828 * @retval zero success |
739 * @retval zero success |
| 829 * @retval non-zero allocation failure |
740 * @retval non-zero allocation failure |
| 830 */ |
741 */ |
| 831 cx_attr_nonnull |
742 cx_attr_nonnull cx_attr_access_r(2, 3) |
| 832 cx_attr_access_r(2, 3) |
743 CX_EXPORT int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count); |
| 833 cx_attr_export |
|
| 834 int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count); |
|
| 835 |
744 |
| 836 /** |
745 /** |
| 837 * Add arbitrary values to a JSON array. |
746 * Add arbitrary values to a JSON array. |
| 838 * |
747 * |
| 839 * @attention In contrast to all other add functions, this function adds the values |
748 * @attention In contrast to all other add functions, this function adds the values |
| 964 * @return the new value or @c NULL if allocation fails |
863 * @return the new value or @c NULL if allocation fails |
| 965 * @see cxJsonObjPut() |
864 * @see cxJsonObjPut() |
| 966 * @see cxJsonCreateLiteral() |
865 * @see cxJsonCreateLiteral() |
| 967 */ |
866 */ |
| 968 cx_attr_nonnull |
867 cx_attr_nonnull |
| 969 cx_attr_export |
868 CX_EXPORT CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, cxstring name, CxJsonLiteral lit); |
| 970 CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, cxstring name, CxJsonLiteral lit); |
|
| 971 |
869 |
| 972 /** |
870 /** |
| 973 * Recursively deallocates the memory of a JSON value. |
871 * Recursively deallocates the memory of a JSON value. |
| 974 * |
872 * |
| 975 * @remark The type of each deallocated value will be changed |
873 * @remark The type of each deallocated value will be changed |
| 976 * to #CX_JSON_NOTHING and values of such type will be skipped |
874 * to #CX_JSON_NOTHING, and values of such a type will be skipped |
| 977 * by the de-allocation. That means, this function protects |
875 * by the deallocation. That means this function protects |
| 978 * you from double-frees when you are accidentally freeing |
876 * you from double-frees when you are accidentally freeing |
| 979 * a nested value and then the parent value (or vice versa). |
877 * a nested value and then the parent value (or vice versa). |
| 980 * |
878 * |
| 981 * @param value the value |
879 * @param value the value |
| 982 */ |
880 */ |
| 983 cx_attr_export |
881 CX_EXPORT void cxJsonValueFree(CxJsonValue *value); |
| 984 void cxJsonValueFree(CxJsonValue *value); |
|
| 985 |
882 |
| 986 /** |
883 /** |
| 987 * Tries to obtain the next JSON value. |
884 * Tries to obtain the next JSON value. |
| 988 * |
885 * |
| 989 * Before this function can be called, the input buffer needs |
886 * Before this function can be called, the input buffer needs |
| 991 * |
888 * |
| 992 * When this function returns #CX_JSON_INCOMPLETE_DATA, you can |
889 * When this function returns #CX_JSON_INCOMPLETE_DATA, you can |
| 993 * add the missing data with another invocation of cxJsonFill() |
890 * add the missing data with another invocation of cxJsonFill() |
| 994 * and then repeat the call to cxJsonNext(). |
891 * and then repeat the call to cxJsonNext(). |
| 995 * |
892 * |
| 996 * @param json the json interface |
893 * @param json the JSON interface |
| 997 * @param value a pointer where the next value shall be stored |
894 * @param value a pointer where the next value shall be stored |
| 998 * @retval CX_JSON_NO_ERROR successfully retrieve the @p value |
895 * @retval CX_JSON_NO_ERROR successfully retrieve the @p value |
| 999 * @retval CX_JSON_NO_DATA there is no (more) data in the buffer to read from |
896 * @retval CX_JSON_NO_DATA there is no (more) data in the buffer to read from |
| 1000 * @retval CX_JSON_INCOMPLETE_DATA an incomplete value was read |
897 * @retval CX_JSON_INCOMPLETE_DATA an incomplete value was read |
| 1001 * and more data needs to be filled |
898 * and more data needs to be filled |
| 1003 * @retval CX_JSON_BUFFER_ALLOC_FAILED allocating internal buffer space failed |
900 * @retval CX_JSON_BUFFER_ALLOC_FAILED allocating internal buffer space failed |
| 1004 * @retval CX_JSON_VALUE_ALLOC_FAILED allocating memory for a CxJsonValue failed |
901 * @retval CX_JSON_VALUE_ALLOC_FAILED allocating memory for a CxJsonValue failed |
| 1005 * @retval CX_JSON_FORMAT_ERROR_NUMBER the JSON text contains an illegally formatted number |
902 * @retval CX_JSON_FORMAT_ERROR_NUMBER the JSON text contains an illegally formatted number |
| 1006 * @retval CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN JSON syntax error |
903 * @retval CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN JSON syntax error |
| 1007 */ |
904 */ |
| 1008 cx_attr_nonnull |
905 cx_attr_nonnull cx_attr_access_w(2) |
| 1009 cx_attr_access_w(2) |
906 CX_EXPORT CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value); |
| 1010 cx_attr_export |
|
| 1011 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value); |
|
| 1012 |
907 |
| 1013 /** |
908 /** |
| 1014 * Checks if the specified value is a JSON object. |
909 * Checks if the specified value is a JSON object. |
| 1015 * |
910 * |
| 1016 * @param value a pointer to the value |
911 * @param value a pointer to the value |
| 1017 * @retval true the value is a JSON object |
912 * @retval true the value is a JSON object |
| 1018 * @retval false otherwise |
913 * @retval false otherwise |
| 1019 */ |
914 */ |
| 1020 cx_attr_nonnull |
915 cx_attr_nonnull |
| 1021 static inline bool cxJsonIsObject(const CxJsonValue *value) { |
916 CX_INLINE bool cxJsonIsObject(const CxJsonValue *value) { |
| 1022 return value->type == CX_JSON_OBJECT; |
917 return value->type == CX_JSON_OBJECT; |
| 1023 } |
918 } |
| 1024 |
919 |
| 1025 /** |
920 /** |
| 1026 * Checks if the specified value is a JSON array. |
921 * Checks if the specified value is a JSON array. |
| 1040 * @param value a pointer to the value |
935 * @param value a pointer to the value |
| 1041 * @retval true the value is a string |
936 * @retval true the value is a string |
| 1042 * @retval false otherwise |
937 * @retval false otherwise |
| 1043 */ |
938 */ |
| 1044 cx_attr_nonnull |
939 cx_attr_nonnull |
| 1045 static inline bool cxJsonIsString(const CxJsonValue *value) { |
940 CX_INLINE bool cxJsonIsString(const CxJsonValue *value) { |
| 1046 return value->type == CX_JSON_STRING; |
941 return value->type == CX_JSON_STRING; |
| 1047 } |
942 } |
| 1048 |
943 |
| 1049 /** |
944 /** |
| 1050 * Checks if the specified value is a JSON number. |
945 * Checks if the specified value is a JSON number. |
| 1051 * |
946 * |
| 1052 * This function will return true for both floating point and |
947 * This function will return true for both floating-point and |
| 1053 * integer numbers. |
948 * integer numbers. |
| 1054 * |
949 * |
| 1055 * @param value a pointer to the value |
950 * @param value a pointer to the value |
| 1056 * @retval true the value is a JSON number |
951 * @retval true the value is a JSON number |
| 1057 * @retval false otherwise |
952 * @retval false otherwise |
| 1058 * @see cxJsonIsInteger() |
953 * @see cxJsonIsInteger() |
| 1059 */ |
954 */ |
| 1060 cx_attr_nonnull |
955 cx_attr_nonnull |
| 1061 static inline bool cxJsonIsNumber(const CxJsonValue *value) { |
956 CX_INLINE bool cxJsonIsNumber(const CxJsonValue *value) { |
| 1062 return value->type == CX_JSON_NUMBER || value->type == CX_JSON_INTEGER; |
957 return value->type == CX_JSON_NUMBER || value->type == CX_JSON_INTEGER; |
| 1063 } |
958 } |
| 1064 |
959 |
| 1065 /** |
960 /** |
| 1066 * Checks if the specified value is an integer number. |
961 * Checks if the specified value is an integer number. |
| 1100 * @retval false otherwise |
995 * @retval false otherwise |
| 1101 * @see cxJsonIsTrue() |
996 * @see cxJsonIsTrue() |
| 1102 * @see cxJsonIsFalse() |
997 * @see cxJsonIsFalse() |
| 1103 */ |
998 */ |
| 1104 cx_attr_nonnull |
999 cx_attr_nonnull |
| 1105 static inline bool cxJsonIsBool(const CxJsonValue *value) { |
1000 CX_INLINE bool cxJsonIsBool(const CxJsonValue *value) { |
| 1106 return cxJsonIsLiteral(value) && value->value.literal != CX_JSON_NULL; |
1001 return cxJsonIsLiteral(value) && value->value.literal != CX_JSON_NULL; |
| 1107 } |
1002 } |
| 1108 |
1003 |
| 1109 /** |
1004 /** |
| 1110 * Checks if the specified value is @c true. |
1005 * Checks if the specified value is @c true. |
| 1111 * |
1006 * |
| 1112 * @remark Be advised, that this is not the same as |
1007 * @remark Be advised that this is different from |
| 1113 * testing @c !cxJsonIsFalse(v). |
1008 * testing @c !cxJsonIsFalse(v). |
| 1114 * |
1009 * |
| 1115 * @param value a pointer to the value |
1010 * @param value a pointer to the value |
| 1116 * @retval true the value is @c true |
1011 * @retval true the value is @c true |
| 1117 * @retval false otherwise |
1012 * @retval false otherwise |
| 1118 * @see cxJsonIsBool() |
1013 * @see cxJsonIsBool() |
| 1119 * @see cxJsonIsFalse() |
1014 * @see cxJsonIsFalse() |
| 1120 */ |
1015 */ |
| 1121 cx_attr_nonnull |
1016 cx_attr_nonnull |
| 1122 static inline bool cxJsonIsTrue(const CxJsonValue *value) { |
1017 CX_INLINE bool cxJsonIsTrue(const CxJsonValue *value) { |
| 1123 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_TRUE; |
1018 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_TRUE; |
| 1124 } |
1019 } |
| 1125 |
1020 |
| 1126 /** |
1021 /** |
| 1127 * Checks if the specified value is @c false. |
1022 * Checks if the specified value is @c false. |
| 1128 * |
1023 * |
| 1129 * @remark Be advised, that this is not the same as |
1024 * @remark Be advised that this is different from |
| 1130 * testing @c !cxJsonIsTrue(v). |
1025 * testing @c !cxJsonIsTrue(v). |
| 1131 * |
1026 * |
| 1132 * @param value a pointer to the value |
1027 * @param value a pointer to the value |
| 1133 * @retval true the value is @c false |
1028 * @retval true the value is @c false |
| 1134 * @retval false otherwise |
1029 * @retval false otherwise |
| 1135 * @see cxJsonIsBool() |
1030 * @see cxJsonIsBool() |
| 1136 * @see cxJsonIsTrue() |
1031 * @see cxJsonIsTrue() |
| 1137 */ |
1032 */ |
| 1138 cx_attr_nonnull |
1033 cx_attr_nonnull |
| 1139 static inline bool cxJsonIsFalse(const CxJsonValue *value) { |
1034 CX_INLINE bool cxJsonIsFalse(const CxJsonValue *value) { |
| 1140 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_FALSE; |
1035 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_FALSE; |
| 1141 } |
1036 } |
| 1142 |
1037 |
| 1143 /** |
1038 /** |
| 1144 * Checks if the specified value is @c null. |
1039 * Checks if the specified value is @c null. |
| 1190 * @param value the JSON value |
1080 * @param value the JSON value |
| 1191 * @return the value represented as mutable UCX string |
1081 * @return the value represented as mutable UCX string |
| 1192 * @see cxJsonIsString() |
1082 * @see cxJsonIsString() |
| 1193 */ |
1083 */ |
| 1194 cx_attr_nonnull |
1084 cx_attr_nonnull |
| 1195 static inline cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value) { |
1085 CX_EXPORT cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value); |
| 1196 return value->value.string; |
1086 |
| 1197 } |
1087 /** |
| 1198 |
1088 * Obtains a double-precision floating-point value from the given JSON value. |
| 1199 /** |
|
| 1200 * Obtains a double-precision floating point value from the given JSON value. |
|
| 1201 * |
1089 * |
| 1202 * If the @p value is not a JSON number, the behavior is undefined. |
1090 * If the @p value is not a JSON number, the behavior is undefined. |
| 1203 * |
1091 * |
| 1204 * @param value the JSON value |
1092 * @param value the JSON value |
| 1205 * @return the value represented as double |
1093 * @return the value represented as double |
| 1206 * @see cxJsonIsNumber() |
1094 * @see cxJsonIsNumber() |
| 1207 */ |
1095 */ |
| 1208 cx_attr_nonnull |
1096 cx_attr_nonnull |
| 1209 static inline double cxJsonAsDouble(const CxJsonValue *value) { |
1097 CX_EXPORT double cxJsonAsDouble(const CxJsonValue *value); |
| 1210 if (value->type == CX_JSON_INTEGER) { |
|
| 1211 return (double) value->value.integer; |
|
| 1212 } else { |
|
| 1213 return value->value.number; |
|
| 1214 } |
|
| 1215 } |
|
| 1216 |
1098 |
| 1217 /** |
1099 /** |
| 1218 * Obtains a 64-bit signed integer from the given JSON value. |
1100 * Obtains a 64-bit signed integer from the given JSON value. |
| 1219 * |
1101 * |
| 1220 * If the @p value is not a JSON number, the behavior is undefined. |
1102 * If the @p value is not a JSON number, the behavior is undefined. |
| 1326 * |
1197 * |
| 1327 * @param value the JSON value |
1198 * @param value the JSON value |
| 1328 * @return an iterator over the object members |
1199 * @return an iterator over the object members |
| 1329 * @see cxJsonIsObject() |
1200 * @see cxJsonIsObject() |
| 1330 */ |
1201 */ |
| 1331 cx_attr_nonnull |
1202 cx_attr_nonnull cx_attr_nodiscard |
| 1332 cx_attr_nodiscard |
1203 CX_EXPORT CxIterator cxJsonObjIter(const CxJsonValue *value); |
| 1333 cx_attr_export |
1204 |
| 1334 CxIterator cxJsonObjIter(const CxJsonValue *value); |
1205 /** |
| 1335 |
1206 * Internal function, do not use. |
| 1336 /** |
1207 * @param value the JSON object |
| 1337 * @copydoc cxJsonObjGet() |
1208 * @param name the key to look up |
| 1338 */ |
1209 * @return the value corresponding to the key |
| 1339 cx_attr_nonnull |
1210 */ |
| 1340 cx_attr_returns_nonnull |
1211 cx_attr_nonnull cx_attr_returns_nonnull |
| 1341 cx_attr_export |
1212 CX_EXPORT CxJsonValue *cx_json_obj_get(const CxJsonValue *value, cxstring name); |
| 1342 CxJsonValue *cx_json_obj_get_cxstr(const CxJsonValue *value, cxstring name); |
1213 |
| 1343 |
|
| 1344 /** |
|
| 1345 * @copydoc cxJsonObjRemove() |
|
| 1346 */ |
|
| 1347 cx_attr_nonnull |
|
| 1348 cx_attr_export |
|
| 1349 CxJsonValue *cx_json_obj_remove_cxstr(CxJsonValue *value, cxstring name); |
|
| 1350 |
|
| 1351 #ifdef __cplusplus |
|
| 1352 } // extern "C" |
|
| 1353 |
|
| 1354 static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxstring name) { |
|
| 1355 return cx_json_obj_get_cxstr(value, name); |
|
| 1356 } |
|
| 1357 |
|
| 1358 static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, cxmutstr name) { |
|
| 1359 return cx_json_obj_get_cxstr(value, cx_strcast(name)); |
|
| 1360 } |
|
| 1361 |
|
| 1362 static inline CxJsonValue *cxJsonObjGet(const CxJsonValue *value, const char *name) { |
|
| 1363 return cx_json_obj_get_cxstr(value, cx_str(name)); |
|
| 1364 } |
|
| 1365 |
|
| 1366 static inline CxJsonValue *cxJsonObjRemove(CxJsonValue *value, cxstring name) { |
|
| 1367 return cx_json_obj_remove_cxstr(value, name); |
|
| 1368 } |
|
| 1369 |
|
| 1370 static inline CxJsonValue *cxJsonObjRemove(CxJsonValue *value, cxmutstr name) { |
|
| 1371 return cx_json_obj_remove_cxstr(value, cx_strcast(name)); |
|
| 1372 } |
|
| 1373 |
|
| 1374 static inline CxJsonValue *cxJsonObjRemove(CxJsonValue *value, const char *name) { |
|
| 1375 return cx_json_obj_remove_cxstr(value, cx_str(name)); |
|
| 1376 } |
|
| 1377 |
|
| 1378 extern "C" { |
|
| 1379 #else |
|
| 1380 /** |
1214 /** |
| 1381 * Returns a value corresponding to a key in a JSON object. |
1215 * Returns a value corresponding to a key in a JSON object. |
| 1382 * |
1216 * |
| 1383 * If the @p value is not a JSON object, the behavior is undefined. |
1217 * If the @p value is not a JSON object, the behavior is undefined. |
| 1384 * |
1218 * |
| 1389 * @param value the JSON object |
1223 * @param value the JSON object |
| 1390 * @param name the key to look up |
1224 * @param name the key to look up |
| 1391 * @return the value corresponding to the key |
1225 * @return the value corresponding to the key |
| 1392 * @see cxJsonIsObject() |
1226 * @see cxJsonIsObject() |
| 1393 */ |
1227 */ |
| 1394 #define cxJsonObjGet(value, name) _Generic((name), \ |
1228 #define cxJsonObjGet(value, name) cx_json_obj_get(value, cx_strcast(name)) |
| 1395 cxstring: cx_json_obj_get_cxstr, \ |
1229 |
| 1396 cxmutstr: cx_json_obj_get_mutstr, \ |
1230 /** |
| 1397 char*: cx_json_obj_get_str, \ |
1231 * Internal function, do not use. |
| 1398 const char*: cx_json_obj_get_str) \ |
1232 * @param value the JSON object |
| 1399 (value, name) |
1233 * @param name the key to look up |
| 1400 |
1234 * @return the value corresponding to the key or @c NULL when the key is not part of the object |
| 1401 /** |
1235 */ |
| 1402 * @copydoc cxJsonObjGet() |
1236 cx_attr_nonnull |
| 1403 */ |
1237 CX_EXPORT CxJsonValue *cx_json_obj_remove(CxJsonValue *value, cxstring name); |
| 1404 cx_attr_nonnull |
|
| 1405 cx_attr_returns_nonnull |
|
| 1406 static inline CxJsonValue *cx_json_obj_get_mutstr(const CxJsonValue *value, cxmutstr name) { |
|
| 1407 return cx_json_obj_get_cxstr(value, cx_strcast(name)); |
|
| 1408 } |
|
| 1409 |
|
| 1410 /** |
|
| 1411 * @copydoc cxJsonObjGet() |
|
| 1412 */ |
|
| 1413 cx_attr_nonnull |
|
| 1414 cx_attr_returns_nonnull |
|
| 1415 cx_attr_cstr_arg(2) |
|
| 1416 static inline CxJsonValue *cx_json_obj_get_str(const CxJsonValue *value, const char *name) { |
|
| 1417 return cx_json_obj_get_cxstr(value, cx_str(name)); |
|
| 1418 } |
|
| 1419 |
1238 |
| 1420 /** |
1239 /** |
| 1421 * Removes and returns a value corresponding to a key in a JSON object. |
1240 * Removes and returns a value corresponding to a key in a JSON object. |
| 1422 * |
1241 * |
| 1423 * If the @p value is not a JSON object, the behavior is undefined. |
1242 * If the @p value is not a JSON object, the behavior is undefined. |
| 1428 * @param value the JSON object |
1247 * @param value the JSON object |
| 1429 * @param name the key to look up |
1248 * @param name the key to look up |
| 1430 * @return the value corresponding to the key or @c NULL when the key is not part of the object |
1249 * @return the value corresponding to the key or @c NULL when the key is not part of the object |
| 1431 * @see cxJsonIsObject() |
1250 * @see cxJsonIsObject() |
| 1432 */ |
1251 */ |
| 1433 #define cxJsonObjRemove(value, name) _Generic((name), \ |
1252 #define cxJsonObjRemove(value, name) cx_json_obj_remove(value, cx_strcast(name)) |
| 1434 cxstring: cx_json_obj_remove_cxstr, \ |
1253 |
| 1435 cxmutstr: cx_json_obj_remove_mutstr, \ |
1254 #ifdef __cplusplus |
| 1436 char*: cx_json_obj_remove_str, \ |
|
| 1437 const char*: cx_json_obj_remove_str) \ |
|
| 1438 (value, name) |
|
| 1439 |
|
| 1440 /** |
|
| 1441 * @copydoc cxJsonObjRemove() |
|
| 1442 */ |
|
| 1443 cx_attr_nonnull |
|
| 1444 static inline CxJsonValue *cx_json_obj_remove_mutstr(CxJsonValue *value, cxmutstr name) { |
|
| 1445 return cx_json_obj_remove_cxstr(value, cx_strcast(name)); |
|
| 1446 } |
|
| 1447 |
|
| 1448 /** |
|
| 1449 * @copydoc cxJsonObjRemove() |
|
| 1450 */ |
|
| 1451 cx_attr_nonnull |
|
| 1452 cx_attr_cstr_arg(2) |
|
| 1453 static inline CxJsonValue *cx_json_obj_remove_str(CxJsonValue *value, const char *name) { |
|
| 1454 return cx_json_obj_remove_cxstr(value, cx_str(name)); |
|
| 1455 } |
1255 } |
| 1456 #endif |
1256 #endif |
| 1457 |
1257 |
| 1458 #ifdef __cplusplus |
|
| 1459 } |
|
| 1460 #endif |
|
| 1461 |
|
| 1462 #endif /* UCX_JSON_H */ |
1258 #endif /* UCX_JSON_H */ |
| 1463 |
1259 |