| 890:e77ccf1c4bb3 | 891:4d58cbcc9efa |
|---|---|
| 39 #include "common.h" | 39 #include "common.h" |
| 40 #include "allocator.h" | 40 #include "allocator.h" |
| 41 #include "string.h" | 41 #include "string.h" |
| 42 #include "buffer.h" | 42 #include "buffer.h" |
| 43 #include "array_list.h" | 43 #include "array_list.h" |
| 44 | 44 #include "map.h" |
| 45 #include <string.h> | |
| 46 | 45 |
| 47 #ifdef __cplusplus | 46 #ifdef __cplusplus |
| 48 extern "C" { | 47 extern "C" { |
| 49 #endif | 48 #endif |
| 50 | 49 |
| 182 * Type alias for the JSON value struct. | 181 * Type alias for the JSON value struct. |
| 183 */ | 182 */ |
| 184 typedef struct cx_json_value_s CxJsonValue; | 183 typedef struct cx_json_value_s CxJsonValue; |
| 185 | 184 |
| 186 /** | 185 /** |
| 187 * Type alias for the JSON array struct. | 186 * Type alias for the map representing a JSON object. |
| 188 */ | 187 * The map contains pointers of type @c CxJsonValue. |
| 189 typedef struct cx_json_array_s CxJsonArray; | 188 */ |
| 190 /** | 189 typedef CxMap* CxJsonObject; |
| 191 * Type alias for the JSON object struct. | |
| 192 */ | |
| 193 typedef struct cx_json_object_s CxJsonObject; | |
| 194 /** | 190 /** |
| 195 * Type alias for a JSON string. | 191 * Type alias for a JSON string. |
| 196 */ | 192 */ |
| 197 typedef struct cx_mutstr_s CxJsonString; | 193 typedef struct cx_mutstr_s CxJsonString; |
| 198 /** | 194 /** |
| 205 typedef double CxJsonNumber; | 201 typedef double CxJsonNumber; |
| 206 /** | 202 /** |
| 207 * Type alias for a JSON literal. | 203 * Type alias for a JSON literal. |
| 208 */ | 204 */ |
| 209 typedef enum cx_json_literal CxJsonLiteral; | 205 typedef enum cx_json_literal CxJsonLiteral; |
| 210 | |
| 211 /** | |
| 212 * Type alias for a key/value pair in a JSON object. | |
| 213 */ | |
| 214 typedef struct cx_json_obj_value_s CxJsonObjValue; | |
| 215 | |
| 216 /** | |
| 217 * JSON array structure. | |
| 218 */ | |
| 219 struct cx_json_array_s { | |
| 220 /** | |
| 221 * The array data. | |
| 222 */ | |
| 223 CX_ARRAY_DECLARE(CxJsonValue*, array); | |
| 224 }; | |
| 225 | |
| 226 /** | |
| 227 * JSON object structure. | |
| 228 */ | |
| 229 struct cx_json_object_s { | |
| 230 /** | |
| 231 * The key/value entries. | |
| 232 */ | |
| 233 CX_ARRAY_DECLARE(CxJsonObjValue, values); | |
| 234 /** | |
| 235 * The original indices to reconstruct the order in which the members were added. | |
| 236 */ | |
| 237 size_t *indices; | |
| 238 }; | |
| 239 | |
| 240 /** | |
| 241 * Structure for a key/value entry in a JSON object. | |
| 242 */ | |
| 243 struct cx_json_obj_value_s { | |
| 244 /** | |
| 245 * The key (or name in JSON terminology) of the value. | |
| 246 */ | |
| 247 cxmutstr name; | |
| 248 /** | |
| 249 * The value. | |
| 250 */ | |
| 251 CxJsonValue *value; | |
| 252 }; | |
| 253 | 206 |
| 254 /** | 207 /** |
| 255 * Structure for a JSON value. | 208 * Structure for a JSON value. |
| 256 */ | 209 */ |
| 257 struct cx_json_value_s { | 210 struct cx_json_value_s { |
| 272 */ | 225 */ |
| 273 union { | 226 union { |
| 274 /** | 227 /** |
| 275 * The array data if the type is #CX_JSON_ARRAY. | 228 * The array data if the type is #CX_JSON_ARRAY. |
| 276 */ | 229 */ |
| 277 CxJsonArray array; | 230 CX_ARRAY(CxJsonValue*, array); |
| 278 /** | 231 /** |
| 279 * The object data if the type is #CX_JSON_OBJECT. | 232 * The object data if the type is #CX_JSON_OBJECT. |
| 280 */ | 233 */ |
| 281 CxJsonObject object; | 234 CxJsonObject object; |
| 282 /** | 235 /** |
| 293 CxJsonNumber number; | 246 CxJsonNumber number; |
| 294 /** | 247 /** |
| 295 * The literal type if the type is #CX_JSON_LITERAL. | 248 * The literal type if the type is #CX_JSON_LITERAL. |
| 296 */ | 249 */ |
| 297 CxJsonLiteral literal; | 250 CxJsonLiteral literal; |
| 298 } value; | 251 }; |
| 299 }; | 252 }; |
| 300 | 253 |
| 301 /** | 254 /** |
| 302 * Internally used structure for a parsed token. | 255 * Internally used structure for a parsed token. |
| 303 * | 256 * |
| 327 struct cx_json_s { | 280 struct cx_json_s { |
| 328 /** | 281 /** |
| 329 * The allocator used for produced JSON values. | 282 * The allocator used for produced JSON values. |
| 330 */ | 283 */ |
| 331 const CxAllocator *allocator; | 284 const CxAllocator *allocator; |
| 285 | |
| 332 /** | 286 /** |
| 333 * The input buffer. | 287 * The input buffer. |
| 334 */ | 288 */ |
| 335 CxBuffer buffer; | 289 CxBuffer buffer; |
| 336 | 290 |
| 347 * Never access this value manually. | 301 * Never access this value manually. |
| 348 */ | 302 */ |
| 349 CxJsonValue *parsed; | 303 CxJsonValue *parsed; |
| 350 | 304 |
| 351 /** | 305 /** |
| 352 * A pointer to an intermediate state of a currently parsed object member. | 306 * The name of a not yet completely parsed object member. |
| 353 * | 307 * |
| 354 * Never access this value manually. | 308 * Never access this value manually. |
| 355 */ | 309 */ |
| 356 CxJsonObjValue uncompleted_member; | 310 cxmutstr uncompleted_member_name; |
| 357 | 311 |
| 358 /** | 312 /** |
| 359 * State stack. | 313 * State stack. |
| 360 */ | 314 */ |
| 361 CX_ARRAY_DECLARE_SIZED(int, states, unsigned); | 315 CX_ARRAY(int, states); |
| 362 | 316 |
| 363 /** | 317 /** |
| 364 * Value buffer stack. | 318 * Value buffer stack. |
| 365 */ | 319 */ |
| 366 CX_ARRAY_DECLARE_SIZED(CxJsonValue*, vbuf, unsigned); | 320 CX_ARRAY(CxJsonValue*, vbuf); |
| 367 | 321 |
| 368 /** | 322 /** |
| 369 * Internally reserved memory for the state stack. | 323 * Internally reserved memory for the state stack. |
| 370 */ | 324 */ |
| 371 int states_internal[8]; | 325 int states_internal[8]; |
| 436 struct cx_json_writer_s { | 390 struct cx_json_writer_s { |
| 437 /** | 391 /** |
| 438 * Set true to enable pretty output. | 392 * Set true to enable pretty output. |
| 439 */ | 393 */ |
| 440 bool pretty; | 394 bool pretty; |
| 441 /** | |
| 442 * Set false to output the members in the order in which they were added. | |
| 443 */ | |
| 444 bool sort_members; | |
| 445 /** | 395 /** |
| 446 * The maximum number of fractional digits in a number value. | 396 * 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. | 397 * 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. | 398 * Note that the actual number of digits may be lower, depending on the concrete number. |
| 449 */ | 399 */ |
| 506 */ | 456 */ |
| 507 cx_attr_nonnull_arg(1, 2, 3) | 457 cx_attr_nonnull_arg(1, 2, 3) |
| 508 CX_EXPORT int cxJsonWrite(void* target, const CxJsonValue* value, | 458 CX_EXPORT int cxJsonWrite(void* target, const CxJsonValue* value, |
| 509 cx_write_func wfunc, const CxJsonWriter* settings); | 459 cx_write_func wfunc, const CxJsonWriter* settings); |
| 510 | 460 |
| 461 | |
| 462 /** | |
| 463 * Produces a compact string representation of the specified JSON value. | |
| 464 * | |
| 465 * @param allocator the allocator for the string | |
| 466 * @param value the JSON value | |
| 467 * @return the produced string | |
| 468 * @see cxJsonWrite() | |
| 469 * @see cxJsonWriterCompact() | |
| 470 * @see cxJsonToPrettyString() | |
| 471 */ | |
| 472 cx_attr_nonnull_arg(2) | |
| 473 CX_EXPORT cxmutstr cxJsonToString(const CxAllocator *allocator, CxJsonValue *value); | |
| 474 | |
| 475 /** | |
| 476 * Produces a pretty string representation of the specified JSON value. | |
| 477 * | |
| 478 * @param allocator the allocator for the string | |
| 479 * @param value the JSON value | |
| 480 * @return the produced string | |
| 481 * @see cxJsonWrite() | |
| 482 * @see cxJsonWriterPretty() | |
| 483 * @see cxJsonToString() | |
| 484 */ | |
| 485 cx_attr_nonnull_arg(2) | |
| 486 CX_EXPORT cxmutstr cxJsonToPrettyString(const CxAllocator *allocator, CxJsonValue *value); | |
| 487 | |
| 511 /** | 488 /** |
| 512 * Initializes the JSON interface. | 489 * Initializes the JSON interface. |
| 513 * | 490 * |
| 514 * @param json the JSON interface | 491 * @param json the JSON interface |
| 515 * @param allocator the allocator that shall be used for the produced values | 492 * @param allocator the allocator that shall be used for the produced values |
| 528 CX_EXPORT void cxJsonDestroy(CxJson *json); | 505 CX_EXPORT void cxJsonDestroy(CxJson *json); |
| 529 | 506 |
| 530 /** | 507 /** |
| 531 * Destroys and re-initializes the JSON interface. | 508 * Destroys and re-initializes the JSON interface. |
| 532 * | 509 * |
| 533 * You might want to use this to reset the parser after | 510 * You must use this to reset the parser after encountering a syntax error |
| 534 * encountering a syntax error. | 511 * if you want to continue using it. |
| 535 * | 512 * |
| 536 * @param json the JSON interface | 513 * @param json the JSON interface |
| 537 */ | 514 */ |
| 538 cx_attr_nonnull | 515 cx_attr_nonnull |
| 539 CX_EXPORT void cxJsonReset(CxJson *json); | 516 CX_EXPORT void cxJsonReset(CxJson *json); |
| 554 * @param len the length of the source buffer | 531 * @param len the length of the source buffer |
| 555 * @retval zero success | 532 * @retval zero success |
| 556 * @retval non-zero internal allocation error | 533 * @retval non-zero internal allocation error |
| 557 * @see cxJsonFill() | 534 * @see cxJsonFill() |
| 558 */ | 535 */ |
| 559 cx_attr_nonnull cx_attr_access_r(2, 3) | 536 cx_attr_nonnull_arg(1) cx_attr_access_r(2, 3) |
| 560 CX_EXPORT int cxJsonFilln(CxJson *json, const char *buf, size_t len); | 537 CX_EXPORT int cxJsonFilln(CxJson *json, const char *buf, size_t len); |
| 561 | 538 |
| 562 | 539 |
| 563 /** | 540 /** |
| 564 * Internal function, do not use. | 541 * Internal function, do not use. |
| 590 * @retval non-zero internal allocation error | 567 * @retval non-zero internal allocation error |
| 591 * @see cxJsonFilln() | 568 * @see cxJsonFilln() |
| 592 */ | 569 */ |
| 593 #define cxJsonFill(json, str) cx_json_fill(json, cx_strcast(str)) | 570 #define cxJsonFill(json, str) cx_json_fill(json, cx_strcast(str)) |
| 594 | 571 |
| 572 | |
| 573 /** | |
| 574 * Internal function - use cxJsonFromString() instead. | |
| 575 * | |
| 576 * @param allocator the allocator for the JSON value | |
| 577 * @param str the string to parse | |
| 578 * @param value a pointer where the JSON value shall be stored to | |
| 579 * @return status code | |
| 580 */ | |
| 581 cx_attr_nonnull_arg(3) | |
| 582 CX_EXPORT CxJsonStatus cx_json_from_string(const CxAllocator *allocator, | |
| 583 cxstring str, CxJsonValue **value); | |
| 584 | |
| 585 /** | |
| 586 * Parses a string into a JSON value. | |
| 587 * | |
| 588 * @param allocator (@c CxAllocator*) the allocator for the JSON value | |
| 589 * @param str (any string) the string to parse | |
| 590 * @param value (@c CxJsonValue**) a pointer where the JSON value shall be stored to | |
| 591 * @retval CX_JSON_NO_ERROR success | |
| 592 * @retval CX_JSON_NO_DATA the string was empty or blank | |
| 593 * @retval CX_JSON_INCOMPLETE_DATA the string unexpectedly ended | |
| 594 * @retval CX_JSON_BUFFER_ALLOC_FAILED allocating internal buffer space failed | |
| 595 * @retval CX_JSON_VALUE_ALLOC_FAILED allocating memory for the CxJsonValue failed | |
| 596 * @retval CX_JSON_FORMAT_ERROR_NUMBER the JSON text contains an illegally formatted number | |
| 597 * @retval CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN JSON syntax error | |
| 598 */ | |
| 599 #define cxJsonFromString(allocator, str, value) \ | |
| 600 cx_json_from_string(allocator, cx_strcast(str), value) | |
| 601 | |
| 595 /** | 602 /** |
| 596 * Creates a new (empty) JSON object. | 603 * Creates a new (empty) JSON object. |
| 597 * | 604 * |
| 598 * @param allocator the allocator to use | 605 * @param allocator the allocator to use |
| 599 * @return the new JSON object or @c NULL if allocation fails | 606 * @return the new JSON object or @c NULL if allocation fails |
| 604 CX_EXPORT CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator); | 611 CX_EXPORT CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator); |
| 605 | 612 |
| 606 /** | 613 /** |
| 607 * Creates a new (empty) JSON array. | 614 * Creates a new (empty) JSON array. |
| 608 * | 615 * |
| 616 * Optionally, this function already allocates memory with the given capacity. | |
| 617 * | |
| 609 * @param allocator the allocator to use | 618 * @param allocator the allocator to use |
| 619 * @param capacity optional capacity or zero if it's unknown how many elements the array will have | |
| 610 * @return the new JSON array or @c NULL if allocation fails | 620 * @return the new JSON array or @c NULL if allocation fails |
| 611 * @see cxJsonObjPutArr() | 621 * @see cxJsonObjPutArr() |
| 612 * @see cxJsonArrAddValues() | 622 * @see cxJsonArrAddValues() |
| 613 */ | 623 */ |
| 614 cx_attr_nodiscard | 624 cx_attr_nodiscard |
| 615 CX_EXPORT CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator); | 625 CX_EXPORT CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator, size_t capacity); |
| 616 | 626 |
| 617 /** | 627 /** |
| 618 * Creates a new JSON number value. | 628 * Creates a new JSON number value. |
| 619 * | 629 * |
| 620 * @param allocator the allocator to use | 630 * @param allocator the allocator to use |
| 639 CX_EXPORT CxJsonValue* cxJsonCreateInteger(const CxAllocator* allocator, int64_t num); | 649 CX_EXPORT CxJsonValue* cxJsonCreateInteger(const CxAllocator* allocator, int64_t num); |
| 640 | 650 |
| 641 /** | 651 /** |
| 642 * Creates a new JSON string. | 652 * Creates a new JSON string. |
| 643 * | 653 * |
| 654 * Internal function - use cxJsonCreateString() instead. | |
| 655 * | |
| 644 * @param allocator the allocator to use | 656 * @param allocator the allocator to use |
| 645 * @param str the string data | 657 * @param str the string data |
| 646 * @return the new JSON value or @c NULL if allocation fails | 658 * @return the new JSON value or @c NULL if allocation fails |
| 647 * @see cxJsonCreateString() | |
| 648 * @see cxJsonObjPutString() | 659 * @see cxJsonObjPutString() |
| 649 * @see cxJsonArrAddStrings() | 660 * @see cxJsonArrAddCxStrings() |
| 650 */ | 661 */ |
| 651 cx_attr_nodiscard cx_attr_nonnull_arg(2) cx_attr_cstr_arg(2) | 662 cx_attr_nodiscard |
| 652 CX_EXPORT CxJsonValue* cxJsonCreateString(const CxAllocator* allocator, const char *str); | 663 CX_EXPORT CxJsonValue* cx_json_create_string(const CxAllocator* allocator, cxstring str); |
| 653 | 664 |
| 654 /** | 665 /** |
| 655 * Creates a new JSON string. | 666 * Creates a new JSON string. |
| 656 * | 667 * |
| 657 * @param allocator the allocator to use | 668 * @param allocator (@c CxAllocator*) the allocator to use |
| 658 * @param str the string data | 669 * @param str the string |
| 659 * @return the new JSON value or @c NULL if allocation fails | 670 * @return (@c CxJsonValue*) the new JSON value or @c NULL if allocation fails |
| 660 * @see cxJsonCreateCxString() | 671 * @see cxJsonObjPutString() |
| 661 * @see cxJsonObjPutCxString() | |
| 662 * @see cxJsonArrAddCxStrings() | 672 * @see cxJsonArrAddCxStrings() |
| 663 */ | 673 */ |
| 664 cx_attr_nodiscard | 674 #define cxJsonCreateString(allocator, str) cx_json_create_string(allocator, cx_strcast(str)) |
| 665 CX_EXPORT CxJsonValue* cxJsonCreateCxString(const CxAllocator* allocator, cxstring str); | |
| 666 | 675 |
| 667 /** | 676 /** |
| 668 * Creates a new JSON literal. | 677 * Creates a new JSON literal. |
| 669 * | 678 * |
| 670 * @param allocator the allocator to use | 679 * @param allocator the allocator to use |
| 758 CX_EXPORT int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count); | 767 CX_EXPORT int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count); |
| 759 | 768 |
| 760 /** | 769 /** |
| 761 * Adds or replaces a value within a JSON object. | 770 * Adds or replaces a value within a JSON object. |
| 762 * | 771 * |
| 763 * The value will be directly added and not copied. | 772 * Internal function - use cxJsonObjPut(). |
| 764 * | |
| 765 * @note If a value with the specified @p name already exists, | |
| 766 * it will be (recursively) freed with its own allocator. | |
| 767 * | 773 * |
| 768 * @param obj the JSON object | 774 * @param obj the JSON object |
| 769 * @param name the name of the value | 775 * @param name the name of the value |
| 770 * @param child the value | 776 * @param child the value |
| 771 * @retval zero success | 777 * @retval zero success |
| 772 * @retval non-zero allocation failure | 778 * @retval non-zero allocation failure |
| 773 */ | 779 */ |
| 774 cx_attr_nonnull | 780 cx_attr_nonnull |
| 775 CX_EXPORT int cxJsonObjPut(CxJsonValue* obj, cxstring name, CxJsonValue* child); | 781 CX_EXPORT int cx_json_obj_put(CxJsonValue* obj, cxstring name, CxJsonValue* child); |
| 782 | |
| 783 /** | |
| 784 * Adds or replaces a value within a JSON object. | |
| 785 * | |
| 786 * The value will be directly added and not copied. | |
| 787 * | |
| 788 * @note If a value with the specified @p name already exists, | |
| 789 * it will be (recursively) freed with its own allocator. | |
| 790 * | |
| 791 * @param obj (@c CxJsonValue*) the JSON object | |
| 792 * @param name (any string) the name of the value | |
| 793 * @param child (@c CxJsonValue*) the value | |
| 794 * @retval zero success | |
| 795 * @retval non-zero allocation failure | |
| 796 */ | |
| 797 #define cxJsonObjPut(obj, name, child) cx_json_obj_put(obj, cx_strcast(name), child) | |
| 776 | 798 |
| 777 /** | 799 /** |
| 778 * Creates a new JSON object and adds it to an existing object. | 800 * Creates a new JSON object and adds it to an existing object. |
| 801 * | |
| 802 * Internal function - use cxJsonObjPutObj(). | |
| 779 * | 803 * |
| 780 * @param obj the target JSON object | 804 * @param obj the target JSON object |
| 781 * @param name the name of the new value | 805 * @param name the name of the new value |
| 782 * @return the new value or @c NULL if allocation fails | 806 * @return the new value or @c NULL if allocation fails |
| 783 * @see cxJsonObjPut() | 807 * @see cxJsonObjPut() |
| 784 * @see cxJsonCreateObj() | 808 * @see cxJsonCreateObj() |
| 785 */ | 809 */ |
| 786 cx_attr_nonnull | 810 cx_attr_nonnull |
| 787 CX_EXPORT CxJsonValue* cxJsonObjPutObj(CxJsonValue* obj, cxstring name); | 811 CX_EXPORT CxJsonValue* cx_json_obj_put_obj(CxJsonValue* obj, cxstring name); |
| 812 | |
| 813 /** | |
| 814 * Creates a new JSON object and adds it to an existing object. | |
| 815 * | |
| 816 * @param obj (@c CxJsonValue*) the target JSON object | |
| 817 * @param name (any string) the name of the new value | |
| 818 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails | |
| 819 * @see cxJsonObjPut() | |
| 820 * @see cxJsonCreateObj() | |
| 821 */ | |
| 822 #define cxJsonObjPutObj(obj, name) cx_json_obj_put_obj(obj, cx_strcast(name)) | |
| 788 | 823 |
| 789 /** | 824 /** |
| 790 * Creates a new JSON array and adds it to an object. | 825 * Creates a new JSON array and adds it to an object. |
| 826 * | |
| 827 * Internal function - use cxJsonObjPutArr(). | |
| 791 * | 828 * |
| 792 * @param obj the target JSON object | 829 * @param obj the target JSON object |
| 793 * @param name the name of the new value | 830 * @param name the name of the new value |
| 831 * @param capacity optional initial capacity | |
| 794 * @return the new value or @c NULL if allocation fails | 832 * @return the new value or @c NULL if allocation fails |
| 795 * @see cxJsonObjPut() | 833 * @see cxJsonObjPut() |
| 796 * @see cxJsonCreateArr() | 834 * @see cxJsonCreateArr() |
| 797 */ | 835 */ |
| 798 cx_attr_nonnull | 836 cx_attr_nonnull |
| 799 CX_EXPORT CxJsonValue* cxJsonObjPutArr(CxJsonValue* obj, cxstring name); | 837 CX_EXPORT CxJsonValue* cx_json_obj_put_arr(CxJsonValue* obj, cxstring name, size_t capacity); |
| 838 | |
| 839 /** | |
| 840 * Creates a new JSON array and adds it to an object. | |
| 841 * | |
| 842 * @param obj (@c CxJsonValue*) the target JSON object | |
| 843 * @param name (any string) the name of the new value | |
| 844 * @param capacity (@c size_t) optional initial capacity | |
| 845 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails | |
| 846 * @see cxJsonObjPut() | |
| 847 * @see cxJsonCreateArr() | |
| 848 */ | |
| 849 #define cxJsonObjPutArr(obj, name, capacity) cx_json_obj_put_arr(obj, cx_strcast(name), capacity) | |
| 800 | 850 |
| 801 /** | 851 /** |
| 802 * Creates a new JSON number and adds it to an object. | 852 * Creates a new JSON number and adds it to an object. |
| 853 * | |
| 854 * Internal function - use cxJsonObjPutNumber(). | |
| 803 * | 855 * |
| 804 * @param obj the target JSON object | 856 * @param obj the target JSON object |
| 805 * @param name the name of the new value | 857 * @param name the name of the new value |
| 806 * @param num the numeric value | 858 * @param num the numeric value |
| 807 * @return the new value or @c NULL if allocation fails | 859 * @return the new value or @c NULL if allocation fails |
| 808 * @see cxJsonObjPut() | 860 * @see cxJsonObjPut() |
| 809 * @see cxJsonCreateNumber() | 861 * @see cxJsonCreateNumber() |
| 810 */ | 862 */ |
| 811 cx_attr_nonnull | 863 cx_attr_nonnull |
| 812 CX_EXPORT CxJsonValue* cxJsonObjPutNumber(CxJsonValue* obj, cxstring name, double num); | 864 CX_EXPORT CxJsonValue* cx_json_obj_put_number(CxJsonValue* obj, cxstring name, double num); |
| 865 | |
| 866 /** | |
| 867 * Creates a new JSON number and adds it to an object. | |
| 868 * | |
| 869 * @param obj (@c CxJsonValue*) the target JSON object | |
| 870 * @param name (any string) the name of the new value | |
| 871 * @param num (@c double) the numeric value | |
| 872 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails | |
| 873 * @see cxJsonObjPut() | |
| 874 * @see cxJsonCreateNumber() | |
| 875 */ | |
| 876 #define cxJsonObjPutNumber(obj, name, num) cx_json_obj_put_number(obj, cx_strcast(name), num) | |
| 813 | 877 |
| 814 /** | 878 /** |
| 815 * Creates a new JSON number, based on an integer, and adds it to an object. | 879 * Creates a new JSON number, based on an integer, and adds it to an object. |
| 880 * | |
| 881 * Internal function - use cxJsonObjPutInteger(). | |
| 816 * | 882 * |
| 817 * @param obj the target JSON object | 883 * @param obj the target JSON object |
| 818 * @param name the name of the new value | 884 * @param name the name of the new value |
| 819 * @param num the numeric value | 885 * @param num the numeric value |
| 820 * @return the new value or @c NULL if allocation fails | 886 * @return the new value or @c NULL if allocation fails |
| 821 * @see cxJsonObjPut() | 887 * @see cxJsonObjPut() |
| 822 * @see cxJsonCreateInteger() | 888 * @see cxJsonCreateInteger() |
| 823 */ | 889 */ |
| 824 cx_attr_nonnull | 890 cx_attr_nonnull |
| 825 CX_EXPORT CxJsonValue* cxJsonObjPutInteger(CxJsonValue* obj, cxstring name, int64_t num); | 891 CX_EXPORT CxJsonValue* cx_json_obj_put_integer(CxJsonValue* obj, cxstring name, int64_t num); |
| 892 | |
| 893 /** | |
| 894 * Creates a new JSON number, based on an integer, and adds it to an object. | |
| 895 * | |
| 896 * @param obj (@c CxJsonValue*) the target JSON object | |
| 897 * @param name (any string) the name of the new value | |
| 898 * @param num (@c int64_t) the numeric value | |
| 899 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails | |
| 900 * @see cxJsonObjPut() | |
| 901 * @see cxJsonCreateInteger() | |
| 902 */ | |
| 903 #define cxJsonObjPutInteger(obj, name, num) cx_json_obj_put_integer(obj, cx_strcast(name), num) | |
| 826 | 904 |
| 827 /** | 905 /** |
| 828 * Creates a new JSON string and adds it to an object. | 906 * Creates a new JSON string and adds it to an object. |
| 829 * | 907 * |
| 830 * The string data is copied. | 908 * Internal function - use cxJsonObjPutString() |
| 831 * | 909 * |
| 832 * @param obj the target JSON object | 910 * @param obj the target JSON object |
| 833 * @param name the name of the new value | 911 * @param name the name of the new value |
| 834 * @param str the string data | 912 * @param str the string data |
| 835 * @return the new value or @c NULL if allocation fails | 913 * @return the new value or @c NULL if allocation fails |
| 836 * @see cxJsonObjPut() | 914 * @see cxJsonObjPut() |
| 837 * @see cxJsonCreateString() | 915 * @see cxJsonCreateString() |
| 838 */ | 916 */ |
| 839 cx_attr_nonnull cx_attr_cstr_arg(3) | 917 cx_attr_nonnull |
| 840 CX_EXPORT CxJsonValue* cxJsonObjPutString(CxJsonValue* obj, cxstring name, const char* str); | 918 CX_EXPORT CxJsonValue* cx_json_obj_put_string(CxJsonValue* obj, cxstring name, cxstring str); |
| 841 | 919 |
| 842 /** | 920 /** |
| 843 * Creates a new JSON string and adds it to an object. | 921 * Creates a new JSON string and adds it to an object. |
| 844 * | 922 * |
| 845 * The string data is copied. | 923 * The string data is copied. |
| 846 * | 924 * |
| 847 * @param obj the target JSON object | 925 * @param obj (@c CxJsonValue*) the target JSON object |
| 848 * @param name the name of the new value | 926 * @param name (any string) the name of the new value |
| 849 * @param str the string data | 927 * @param str (any string) the string data |
| 850 * @return the new value or @c NULL if allocation fails | 928 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails |
| 851 * @see cxJsonObjPut() | 929 * @see cxJsonObjPut() |
| 852 * @see cxJsonCreateCxString() | 930 * @see cxJsonCreateString() |
| 853 */ | 931 */ |
| 854 cx_attr_nonnull | 932 #define cxJsonObjPutString(obj, name, str) cx_json_obj_put_string(obj, cx_strcast(name), cx_strcast(str)) |
| 855 CX_EXPORT CxJsonValue* cxJsonObjPutCxString(CxJsonValue* obj, cxstring name, cxstring str); | |
| 856 | 933 |
| 857 /** | 934 /** |
| 858 * Creates a new JSON literal and adds it to an object. | 935 * Creates a new JSON literal and adds it to an object. |
| 936 * | |
| 937 * Internal function - use cxJsonObjPutLiteral(). | |
| 859 * | 938 * |
| 860 * @param obj the target JSON object | 939 * @param obj the target JSON object |
| 861 * @param name the name of the new value | 940 * @param name the name of the new value |
| 862 * @param lit the type of literal | 941 * @param lit the type of literal |
| 863 * @return the new value or @c NULL if allocation fails | 942 * @return the new value or @c NULL if allocation fails |
| 864 * @see cxJsonObjPut() | 943 * @see cxJsonObjPut() |
| 865 * @see cxJsonCreateLiteral() | 944 * @see cxJsonCreateLiteral() |
| 866 */ | 945 */ |
| 867 cx_attr_nonnull | 946 cx_attr_nonnull |
| 868 CX_EXPORT CxJsonValue* cxJsonObjPutLiteral(CxJsonValue* obj, cxstring name, CxJsonLiteral lit); | 947 CX_EXPORT CxJsonValue* cx_json_obj_put_literal(CxJsonValue* obj, cxstring name, CxJsonLiteral lit); |
| 948 | |
| 949 /** | |
| 950 * Creates a new JSON literal and adds it to an object. | |
| 951 * | |
| 952 * @param obj (@c CxJsonValue*) the target JSON object | |
| 953 * @param name (any string) the name of the new value | |
| 954 * @param lit (@c CxJsonLiteral) the type of literal | |
| 955 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails | |
| 956 * @see cxJsonObjPut() | |
| 957 * @see cxJsonCreateLiteral() | |
| 958 */ | |
| 959 #define cxJsonObjPutLiteral(obj, name, lit) cx_json_obj_put_literal(obj, cx_strcast(name), lit) | |
| 869 | 960 |
| 870 /** | 961 /** |
| 871 * Recursively deallocates the memory of a JSON value. | 962 * Recursively deallocates the memory of a JSON value. |
| 872 * | 963 * |
| 873 * @remark The type of each deallocated value will be changed | 964 * @remark The type of each deallocated value will be changed |
| 996 * @see cxJsonIsTrue() | 1087 * @see cxJsonIsTrue() |
| 997 * @see cxJsonIsFalse() | 1088 * @see cxJsonIsFalse() |
| 998 */ | 1089 */ |
| 999 cx_attr_nonnull | 1090 cx_attr_nonnull |
| 1000 CX_INLINE bool cxJsonIsBool(const CxJsonValue *value) { | 1091 CX_INLINE bool cxJsonIsBool(const CxJsonValue *value) { |
| 1001 return cxJsonIsLiteral(value) && value->value.literal != CX_JSON_NULL; | 1092 return cxJsonIsLiteral(value) && value->literal != CX_JSON_NULL; |
| 1002 } | 1093 } |
| 1003 | 1094 |
| 1004 /** | 1095 /** |
| 1005 * Checks if the specified value is @c true. | 1096 * Checks if the specified value is @c true. |
| 1006 * | 1097 * |
| 1013 * @see cxJsonIsBool() | 1104 * @see cxJsonIsBool() |
| 1014 * @see cxJsonIsFalse() | 1105 * @see cxJsonIsFalse() |
| 1015 */ | 1106 */ |
| 1016 cx_attr_nonnull | 1107 cx_attr_nonnull |
| 1017 CX_INLINE bool cxJsonIsTrue(const CxJsonValue *value) { | 1108 CX_INLINE bool cxJsonIsTrue(const CxJsonValue *value) { |
| 1018 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_TRUE; | 1109 return cxJsonIsLiteral(value) && value->literal == CX_JSON_TRUE; |
| 1019 } | 1110 } |
| 1020 | 1111 |
| 1021 /** | 1112 /** |
| 1022 * Checks if the specified value is @c false. | 1113 * Checks if the specified value is @c false. |
| 1023 * | 1114 * |
| 1030 * @see cxJsonIsBool() | 1121 * @see cxJsonIsBool() |
| 1031 * @see cxJsonIsTrue() | 1122 * @see cxJsonIsTrue() |
| 1032 */ | 1123 */ |
| 1033 cx_attr_nonnull | 1124 cx_attr_nonnull |
| 1034 CX_INLINE bool cxJsonIsFalse(const CxJsonValue *value) { | 1125 CX_INLINE bool cxJsonIsFalse(const CxJsonValue *value) { |
| 1035 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_FALSE; | 1126 return cxJsonIsLiteral(value) && value->literal == CX_JSON_FALSE; |
| 1036 } | 1127 } |
| 1037 | 1128 |
| 1038 /** | 1129 /** |
| 1039 * Checks if the specified value is @c null. | 1130 * Checks if the specified value is @c null. |
| 1040 * | 1131 * |
| 1043 * @retval false otherwise | 1134 * @retval false otherwise |
| 1044 * @see cxJsonIsLiteral() | 1135 * @see cxJsonIsLiteral() |
| 1045 */ | 1136 */ |
| 1046 cx_attr_nonnull | 1137 cx_attr_nonnull |
| 1047 CX_INLINE bool cxJsonIsNull(const CxJsonValue *value) { | 1138 CX_INLINE bool cxJsonIsNull(const CxJsonValue *value) { |
| 1048 return cxJsonIsLiteral(value) && value->value.literal == CX_JSON_NULL; | 1139 return cxJsonIsLiteral(value) && value->literal == CX_JSON_NULL; |
| 1049 } | 1140 } |
| 1050 | 1141 |
| 1051 /** | 1142 /** |
| 1052 * Obtains a C string from the given JSON value. | 1143 * Obtains a C string from the given JSON value. |
| 1053 * | 1144 * |
| 1121 * @return the value represented as double | 1212 * @return the value represented as double |
| 1122 * @see cxJsonIsLiteral() | 1213 * @see cxJsonIsLiteral() |
| 1123 */ | 1214 */ |
| 1124 cx_attr_nonnull | 1215 cx_attr_nonnull |
| 1125 CX_INLINE bool cxJsonAsBool(const CxJsonValue *value) { | 1216 CX_INLINE bool cxJsonAsBool(const CxJsonValue *value) { |
| 1126 return value->value.literal == CX_JSON_TRUE; | 1217 return value->literal == CX_JSON_TRUE; |
| 1127 } | 1218 } |
| 1128 | 1219 |
| 1129 /** | 1220 /** |
| 1130 * Returns the size of a JSON array. | 1221 * Returns the size of a JSON array. |
| 1131 * | 1222 * |
| 1135 * @return the size of the array | 1226 * @return the size of the array |
| 1136 * @see cxJsonIsArray() | 1227 * @see cxJsonIsArray() |
| 1137 */ | 1228 */ |
| 1138 cx_attr_nonnull | 1229 cx_attr_nonnull |
| 1139 CX_INLINE size_t cxJsonArrSize(const CxJsonValue *value) { | 1230 CX_INLINE size_t cxJsonArrSize(const CxJsonValue *value) { |
| 1140 return value->value.array.array_size; | 1231 return value->array.size; |
| 1141 } | 1232 } |
| 1142 | 1233 |
| 1143 /** | 1234 /** |
| 1144 * Returns an element from a JSON array. | 1235 * Returns an element from a JSON array. |
| 1145 * | 1236 * |
| 1186 */ | 1277 */ |
| 1187 cx_attr_nonnull cx_attr_nodiscard | 1278 cx_attr_nonnull cx_attr_nodiscard |
| 1188 CX_EXPORT CxIterator cxJsonArrIter(const CxJsonValue *value); | 1279 CX_EXPORT CxIterator cxJsonArrIter(const CxJsonValue *value); |
| 1189 | 1280 |
| 1190 /** | 1281 /** |
| 1191 * Returns an iterator over the JSON object members. | 1282 * Returns the size of a JSON object. |
| 1192 * | 1283 * |
| 1193 * The iterator yields values of type @c CxJsonObjValue* which | 1284 * If the @p value is not a JSON object, the behavior is undefined. |
| 1194 * contain the name and value of the member. | 1285 * |
| 1286 * @param value the JSON value | |
| 1287 * @return the size of the object, i.e., the number of key/value pairs | |
| 1288 * @see cxJsonIsObject() | |
| 1289 */ | |
| 1290 cx_attr_nonnull | |
| 1291 CX_INLINE size_t cxJsonObjSize(const CxJsonValue *value) { | |
| 1292 return cxCollectionSize(value->object); | |
| 1293 } | |
| 1294 | |
| 1295 /** | |
| 1296 * Returns a map iterator over the JSON object members. | |
| 1297 * | |
| 1298 * The iterator yields values of type @c CxMapEntry* which | |
| 1299 * contain the name and the @c CxJsonObjValue* of the member. | |
| 1195 * | 1300 * |
| 1196 * If the @p value is not a JSON object, the behavior is undefined. | 1301 * If the @p value is not a JSON object, the behavior is undefined. |
| 1197 * | 1302 * |
| 1198 * @param value the JSON value | 1303 * @param value the JSON value |
| 1199 * @return an iterator over the object members | 1304 * @return an iterator over the object members |
| 1200 * @see cxJsonIsObject() | 1305 * @see cxJsonIsObject() |
| 1201 */ | 1306 */ |
| 1202 cx_attr_nonnull cx_attr_nodiscard | 1307 cx_attr_nonnull cx_attr_nodiscard |
| 1203 CX_EXPORT CxIterator cxJsonObjIter(const CxJsonValue *value); | 1308 CX_EXPORT CxMapIterator cxJsonObjIter(const CxJsonValue *value); |
| 1204 | 1309 |
| 1205 /** | 1310 /** |
| 1206 * Internal function, do not use. | 1311 * Internal function, do not use. |
| 1207 * @param value the JSON object | 1312 * @param value the JSON object |
| 1208 * @param name the key to look up | 1313 * @param name the key to look up |
| 1249 * @return the value corresponding to the key or @c NULL when the key is not part of the object | 1354 * @return the value corresponding to the key or @c NULL when the key is not part of the object |
| 1250 * @see cxJsonIsObject() | 1355 * @see cxJsonIsObject() |
| 1251 */ | 1356 */ |
| 1252 #define cxJsonObjRemove(value, name) cx_json_obj_remove(value, cx_strcast(name)) | 1357 #define cxJsonObjRemove(value, name) cx_json_obj_remove(value, cx_strcast(name)) |
| 1253 | 1358 |
| 1359 /** | |
| 1360 * Performs a deep comparison of two JSON values. | |
| 1361 * | |
| 1362 * The order of object members is ignored during comparison. | |
| 1363 * | |
| 1364 * @param json the JSON value | |
| 1365 * @param other the other JSON value that the JSON value is compared to | |
| 1366 * @retval zero the values are equal (except for ordering of object members) | |
| 1367 * @retval non-zero the values differ | |
| 1368 */ | |
| 1369 CX_EXPORT int cxJsonCompare(const CxJsonValue *json, const CxJsonValue *other); | |
| 1370 | |
| 1371 | |
| 1372 /** | |
| 1373 * Creates a deep copy of the specified JSON value. | |
| 1374 * | |
| 1375 * If you need a @c cx_clone_func compatible version, see cxJsonCloneFunc(). | |
| 1376 * | |
| 1377 * @note when you are cloning @c NULL, you will get a pointer to a statically | |
| 1378 * allocated value which represents nothing. | |
| 1379 * | |
| 1380 * @param value the value to be cloned | |
| 1381 * @param allocator the allocator for the new value | |
| 1382 * @return the new value or @c NULL if any allocation was unsuccessful | |
| 1383 * @see cxJsonCloneFunc() | |
| 1384 */ | |
| 1385 cx_attr_nodiscard | |
| 1386 CX_EXPORT CxJsonValue* cxJsonClone(const CxJsonValue* value, | |
| 1387 const CxAllocator* allocator); | |
| 1388 | |
| 1389 | |
| 1390 /** | |
| 1391 * A @c cx_clone_func compatible version of cxJsonClone(). | |
| 1392 * | |
| 1393 * Internal function - use cxJsonCloneFunc() to get a properly casted function pointer. | |
| 1394 * | |
| 1395 * @param target the target memory or @c NULL | |
| 1396 * @param source the value to be cloned | |
| 1397 * @param allocator the allocator for the new value | |
| 1398 * @param data unused | |
| 1399 * @return the new value or @c NULL if any allocation was unsuccessful | |
| 1400 * @see cxJsonClone() | |
| 1401 */ | |
| 1402 cx_attr_nodiscard | |
| 1403 CX_EXPORT CxJsonValue* cx_json_clone_func( | |
| 1404 CxJsonValue* target, const CxJsonValue* source, | |
| 1405 const CxAllocator* allocator, void *data); | |
| 1406 | |
| 1407 /** | |
| 1408 * A @c cx_clone_func compatible version of cxJsonClone(). | |
| 1409 * | |
| 1410 * @param target (@c CxJsonValue*) the target memory or @c NULL | |
| 1411 * @param source (@c CxJsonValue*) the value to be cloned | |
| 1412 * @param allocator (@c CxAllocator*) the allocator for the new value | |
| 1413 * @param data unused | |
| 1414 * @return the new value or @c NULL if any allocation was unsuccessful | |
| 1415 * @see cxJsonClone() | |
| 1416 */ | |
| 1417 #define cxJsonCloneFunc ((cx_clone_func) cx_json_clone_func) | |
| 1418 | |
| 1254 #ifdef __cplusplus | 1419 #ifdef __cplusplus |
| 1255 } | 1420 } |
| 1256 #endif | 1421 #endif |
| 1257 | 1422 |
| 1258 #endif /* UCX_JSON_H */ | 1423 #endif /* UCX_JSON_H */ |