GCC Code Coverage Report


Directory: ./
File: cx/json.h
Date: 2025-12-31 16:19:05
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 0 0 -%
Branches: 8 8 100.0%

Line Branch Exec Source
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28 /**
29 * @file json.h
30 * @brief Interface for parsing data from JSON files.
31 * @author Mike Becker
32 * @author Olaf Wintermann
33 * @copyright 2-Clause BSD License
34 */
35
36 #ifndef UCX_JSON_H
37 #define UCX_JSON_H
38
39 #include "common.h"
40 #include "allocator.h"
41 #include "string.h"
42 #include "buffer.h"
43 #include "array_list.h"
44 #include "map.h"
45
46 /**
47 * The type of the parsed token.
48 */
49 enum cx_json_token_type {
50 /**
51 * No complete token parsed, yet.
52 */
53 CX_JSON_NO_TOKEN,
54 /**
55 * The presumed token contains syntactical errors.
56 */
57 CX_JSON_TOKEN_ERROR,
58 /**
59 * A "begin of array" '[' token.
60 */
61 CX_JSON_TOKEN_BEGIN_ARRAY,
62 /**
63 * A "begin of object" '{' token.
64 */
65 CX_JSON_TOKEN_BEGIN_OBJECT,
66 /**
67 * An "end of array" ']' token.
68 */
69 CX_JSON_TOKEN_END_ARRAY,
70 /**
71 * An "end of object" '}' token.
72 */
73 CX_JSON_TOKEN_END_OBJECT,
74 /**
75 * A colon ':' token separating names and values.
76 */
77 CX_JSON_TOKEN_NAME_SEPARATOR,
78 /**
79 * A comma ',' token separating object entries or array elements.
80 */
81 CX_JSON_TOKEN_VALUE_SEPARATOR,
82 /**
83 * A string token.
84 */
85 CX_JSON_TOKEN_STRING,
86 /**
87 * A number token that can be represented as an integer.
88 */
89 CX_JSON_TOKEN_INTEGER,
90 /**
91 * A number token that cannot be represented as an integer.
92 */
93 CX_JSON_TOKEN_NUMBER,
94 /**
95 * A literal token.
96 */
97 CX_JSON_TOKEN_LITERAL,
98 /**
99 * A white-space token.
100 */
101 CX_JSON_TOKEN_SPACE
102 };
103
104 /**
105 * The type of some JSON value.
106 */
107 enum cx_json_value_type {
108 /**
109 * Reserved.
110 */
111 CX_JSON_NOTHING, // this allows us to always return non-NULL values
112 /**
113 * No meaningful data.
114 */
115 CX_JSON_UNINITIALIZED,
116 /**
117 * A JSON object.
118 */
119 CX_JSON_OBJECT,
120 /**
121 * A JSON array.
122 */
123 CX_JSON_ARRAY,
124 /**
125 * A string.
126 */
127 CX_JSON_STRING,
128 /**
129 * A number that contains an integer.
130 */
131 CX_JSON_INTEGER,
132 /**
133 * A number, not necessarily an integer.
134 */
135 CX_JSON_NUMBER,
136 /**
137 * A literal (true, false, null).
138 */
139 CX_JSON_LITERAL
140 };
141
142 /**
143 * JSON literal types.
144 */
145 enum cx_json_literal {
146 /**
147 * The @c null literal.
148 */
149 CX_JSON_NULL,
150 /**
151 * The @c true literal.
152 */
153 CX_JSON_TRUE,
154 /**
155 * The @c false literal.
156 */
157 CX_JSON_FALSE
158 };
159
160 /**
161 * Type alias for the token type enum.
162 */
163 typedef enum cx_json_token_type CxJsonTokenType;
164 /**
165 * Type alias for the value type enum.
166 */
167 typedef enum cx_json_value_type CxJsonValueType;
168
169 /**
170 * Type alias for the JSON parser interface.
171 */
172 typedef struct cx_json_s CxJson;
173
174 /**
175 * Type alias for the token struct.
176 */
177 typedef struct cx_json_token_s CxJsonToken;
178
179 /**
180 * Type alias for the JSON value struct.
181 */
182 typedef struct cx_json_value_s CxJsonValue;
183
184 /**
185 * Type alias for the map representing a JSON object.
186 * The map contains pointers of type @c CxJsonValue.
187 */
188 typedef CxMap* CxJsonObject;
189 /**
190 * Type alias for a JSON string.
191 */
192 typedef struct cx_mutstr_s CxJsonString;
193 /**
194 * Type alias for a number that can be represented as a 64-bit signed integer.
195 */
196 typedef int64_t CxJsonInteger;
197 /**
198 * Type alias for a number that is not an integer.
199 */
200 typedef double CxJsonNumber;
201 /**
202 * Type alias for a JSON literal.
203 */
204 typedef enum cx_json_literal CxJsonLiteral;
205
206 /**
207 * Structure for a JSON value.
208 */
209 struct cx_json_value_s {
210 /**
211 * The allocator with which the value was allocated.
212 *
213 * Required for recursively deallocating memory of objects and arrays.
214 */
215 const CxAllocator *allocator;
216 /**
217 * The type of this value.
218 *
219 * Specifies how the @c value union shall be resolved.
220 */
221 CxJsonValueType type;
222 /**
223 * The value data.
224 */
225 union {
226 /**
227 * The array data if the type is #CX_JSON_ARRAY.
228 */
229 CX_ARRAY(CxJsonValue*, array);
230 /**
231 * The object data if the type is #CX_JSON_OBJECT.
232 */
233 CxJsonObject object;
234 /**
235 * The string data if the type is #CX_JSON_STRING.
236 */
237 CxJsonString string;
238 /**
239 * The integer if the type is #CX_JSON_INTEGER.
240 */
241 CxJsonInteger integer;
242 /**
243 * The number if the type is #CX_JSON_NUMBER.
244 */
245 CxJsonNumber number;
246 /**
247 * The literal type if the type is #CX_JSON_LITERAL.
248 */
249 CxJsonLiteral literal;
250 };
251 };
252
253 /**
254 * Internally used structure for a parsed token.
255 *
256 * You should never need to use this in your code.
257 */
258 struct cx_json_token_s {
259 /**
260 * The token type.
261 */
262 CxJsonTokenType tokentype;
263 /**
264 * True, if the @c content must be passed to cx_strfree().
265 */
266 bool allocated;
267 /**
268 * The token text, if any.
269 *
270 * This is not necessarily set when the token type already
271 * uniquely identifies the content.
272 */
273 cxmutstr content;
274 };
275
276 /**
277 * The JSON parser interface.
278 */
279 struct cx_json_s {
280 /**
281 * The allocator used for produced JSON values.
282 */
283 const CxAllocator *allocator;
284
285 /**
286 * The input buffer.
287 */
288 CxBuffer buffer;
289
290 /**
291 * A pointer to an intermediate state of the currently parsed value.
292 *
293 * Never access this value manually.
294 */
295 CxJsonValue *parsed;
296
297 /**
298 * The name of a not yet completely parsed object member.
299 *
300 * Never access this value manually.
301 */
302 cxmutstr uncompleted_member_name;
303
304 /**
305 * Internal buffer for uncompleted tokens.
306 */
307 cxmutstr uncompleted_content;
308
309 /**
310 * The expected type of the currently parsed, uncompleted token.
311 */
312 CxJsonTokenType uncompleted_tokentype;
313
314 /**
315 * State stack.
316 */
317 CX_ARRAY(int, states);
318
319 /**
320 * Value buffer stack.
321 */
322 CX_ARRAY(CxJsonValue*, vbuf);
323
324 /**
325 * Internally reserved memory for the state stack.
326 */
327 int states_internal[8];
328
329 /**
330 * Internally reserved memory for the value buffer stack.
331 */
332 CxJsonValue* vbuf_internal[8];
333 };
334
335 /**
336 * Status codes for the JSON interface.
337 */
338 enum cx_json_status {
339 /**
340 * Everything is fine.
341 */
342 CX_JSON_NO_ERROR,
343 /**
344 * The input buffer does not contain more data.
345 */
346 CX_JSON_NO_DATA,
347 /**
348 * The input ends unexpectedly.
349 *
350 * Refill the buffer with cxJsonFill() to complete the JSON data.
351 */
352 CX_JSON_INCOMPLETE_DATA,
353 /**
354 * Not used as a status and never returned by any function.
355 *
356 * You can use this enumerator to check for all "good" status results
357 * by checking if the status is less than @c CX_JSON_OK.
358 *
359 * A "good" status means that you can refill data and continue parsing.
360 */
361 CX_JSON_OK,
362 /**
363 * The input buffer has never been filled.
364 */
365 CX_JSON_NULL_DATA,
366 /**
367 * Allocating memory for the internal buffer failed.
368 */
369 CX_JSON_BUFFER_ALLOC_FAILED,
370 /**
371 * Allocating memory for a JSON value failed.
372 */
373 CX_JSON_VALUE_ALLOC_FAILED,
374 /**
375 * A number value is incorrectly formatted.
376 */
377 CX_JSON_FORMAT_ERROR_NUMBER,
378 /**
379 * The tokenizer found something unexpected.
380 */
381 CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN
382 };
383
384 /**
385 * Typedef for the JSON status enum.
386 */
387 typedef enum cx_json_status CxJsonStatus;
388
389 /**
390 * The JSON writer settings.
391 */
392 struct cx_json_writer_s {
393 /**
394 * Set true to enable pretty output.
395 */
396 bool pretty;
397 /**
398 * The maximum number of fractional digits in a number value.
399 * The default value is 6 and values larger than 15 are reduced to 15.
400 * Note that the actual number of digits may be lower, depending on the concrete number.
401 */
402 uint8_t frac_max_digits;
403 /**
404 * Set true to use spaces instead of tab characters.
405 * Indentation is only used in pretty output.
406 */
407 bool indent_space;
408 /**
409 * If @c indent_space is true, this is the number of spaces per tab.
410 * Indentation is only used in pretty output.
411 */
412 uint8_t indent;
413 /**
414 * Set true to enable escaping of the slash character (solidus).
415 */
416 bool escape_slash;
417 };
418
419 /**
420 * Typedef for the JSON writer.
421 */
422 typedef struct cx_json_writer_s CxJsonWriter;
423
424 /**
425 * Creates a default writer configuration for compact output.
426 *
427 * @return new JSON writer settings
428 */
429 CX_EXTERN CX_NODISCARD
430 CxJsonWriter cxJsonWriterCompact(void);
431
432 /**
433 * Creates a default writer configuration for pretty output.
434 *
435 * @param use_spaces false if you want tabs, true if you want four spaces instead
436 * @return new JSON writer settings
437 */
438 CX_EXTERN CX_NODISCARD
439 CxJsonWriter cxJsonWriterPretty(bool use_spaces);
440
441 /**
442 * Writes a JSON value to a buffer or stream.
443 *
444 * This function blocks until either all data is written, or an error occurs.
445 * The write operation is not atomic in the sense that it might happen
446 * that the data is only partially written when an error occurs with no
447 * way to indicate how much data was written.
448 * To avoid this problem, you can use a CxBuffer as @p target which is
449 * unlikely to fail a write operation. You can, for example, use the buffer's flush
450 * feature to relay the data.
451 *
452 * @param target the buffer or stream where to write to
453 * @param value the value that shall be written
454 * @param wfunc the write function to use
455 * @param settings formatting settings (or @c NULL to use a compact default)
456 * @retval zero success
457 * @retval non-zero when no or not all data could be written
458 */
459 CX_EXTERN CX_NONNULL_ARG(1, 2, 3)
460 int cxJsonWrite(void* target, const CxJsonValue* value,
461 cx_write_func wfunc, const CxJsonWriter* settings);
462
463
464 /**
465 * Produces a compact string representation of the specified JSON value.
466 *
467 * @param allocator the allocator for the string
468 * @param value the JSON value
469 * @return the produced string
470 * @see cxJsonWrite()
471 * @see cxJsonWriterCompact()
472 * @see cxJsonToPrettyString()
473 */
474 CX_EXTERN CX_NONNULL_ARG(2) CX_NODISCARD
475 cxmutstr cxJsonToString(const CxAllocator *allocator, CxJsonValue *value);
476
477 /**
478 * Produces a pretty string representation of the specified JSON value.
479 *
480 * @param allocator the allocator for the string
481 * @param value the JSON value
482 * @return the produced string
483 * @see cxJsonWrite()
484 * @see cxJsonWriterPretty()
485 * @see cxJsonToString()
486 */
487 CX_EXTERN CX_NONNULL_ARG(2) CX_NODISCARD
488 cxmutstr cxJsonToPrettyString(const CxAllocator *allocator, CxJsonValue *value);
489
490 /**
491 * Initializes the JSON interface.
492 *
493 * @param json the JSON interface
494 * @param allocator the allocator that shall be used for the produced values
495 * @see cxJsonDestroy()
496 */
497 CX_EXTERN CX_NONNULL_ARG(1)
498 void cxJsonInit(CxJson *json, const CxAllocator *allocator);
499
500 /**
501 * Destroys the JSON interface.
502 *
503 * @param json the JSON interface
504 * @see cxJsonInit()
505 */
506 CX_EXTERN CX_NONNULL
507 void cxJsonDestroy(CxJson *json);
508
509 /**
510 * Destroys and re-initializes the JSON interface.
511 *
512 * You must use this to reset the parser after encountering a syntax error
513 * if you want to continue using it.
514 *
515 * @param json the JSON interface
516 */
517 CX_EXTERN CX_NONNULL
518 void cxJsonReset(CxJson *json);
519
520 /**
521 * Fills the input buffer.
522 *
523 * @remark The JSON interface tries to avoid copying the input data.
524 * When you use this function and cxJsonNext() interleaving,
525 * no copies are performed. However, you must not free the
526 * pointer to the data in that case. When you invoke the fill
527 * function more than once before calling cxJsonNext(),
528 * the additional data is appended - inevitably leading to
529 * an allocation of a new buffer and copying the previous contents.
530 *
531 * @param json the JSON interface
532 * @param buf the source buffer
533 * @param len the length of the source buffer
534 * @retval zero success
535 * @retval non-zero internal allocation error
536 * @see cxJsonFill()
537 */
538 CX_EXTERN CX_NONNULL_ARG(1) CX_ACCESS_R(2, 3)
539 int cxJsonFilln(CxJson *json, const char *buf, size_t len);
540
541
542 /**
543 * Internal function, do not use.
544 *
545 * @param json the JSON interface
546 * @param str the string
547 * @retval zero success
548 * @retval non-zero internal allocation error
549 */
550 CX_NONNULL CX_INLINE
551 int cx_json_fill(CxJson *json, cxstring str) {
552 50 return cxJsonFilln(json, str.ptr, str.length);
553 }
554
555 /**
556 * Fills the input buffer.
557 *
558 * The JSON interface tries to avoid copying the input data.
559 * When you use this function and cxJsonNext() interleaving,
560 * no copies are performed. However, you must not free the
561 * pointer to the data in that case. When you invoke the fill
562 * function more than once before calling cxJsonNext(),
563 * the additional data is appended - inevitably leading to
564 * an allocation of a new buffer and copying the previous contents.
565 *
566 * @param json the JSON interface
567 * @param str the source string
568 * @retval zero success
569 * @retval non-zero internal allocation error
570 * @see cxJsonFilln()
571 */
572 #define cxJsonFill(json, str) cx_json_fill(json, cx_strcast(str))
573
574
575 /**
576 * Internal function - use cxJsonFromString() instead.
577 *
578 * @param allocator the allocator for the JSON value
579 * @param str the string to parse
580 * @param value a pointer where the JSON value shall be stored to
581 * @return status code
582 */
583 CX_EXTERN CX_NONNULL_ARG(3) CX_ACCESS_W(3)
584 CxJsonStatus cx_json_from_string(const CxAllocator *allocator,
585 cxstring str, CxJsonValue **value);
586
587 /**
588 * Parses a string into a JSON value.
589 *
590 * @param allocator (@c CxAllocator*) the allocator for the JSON value
591 * @param str (any string) the string to parse
592 * @param value (@c CxJsonValue**) a pointer where the JSON value shall be stored to
593 * @retval CX_JSON_NO_ERROR success
594 * @retval CX_JSON_NO_DATA the string was empty or blank
595 * @retval CX_JSON_INCOMPLETE_DATA the string unexpectedly ended
596 * @retval CX_JSON_BUFFER_ALLOC_FAILED allocating internal buffer space failed
597 * @retval CX_JSON_VALUE_ALLOC_FAILED allocating memory for the CxJsonValue failed
598 * @retval CX_JSON_FORMAT_ERROR_NUMBER the JSON text contains an illegally formatted number
599 * @retval CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN JSON syntax error
600 */
601 #define cxJsonFromString(allocator, str, value) \
602 cx_json_from_string(allocator, cx_strcast(str), value)
603
604 /**
605 * Recursively deallocates the memory of a JSON value.
606 *
607 * @remark The type of each deallocated value will be changed
608 * to #CX_JSON_NOTHING, and values of such a type will be skipped
609 * by the deallocation. That means this function protects
610 * you from double-frees when you are accidentally freeing
611 * a nested value and then the parent value (or vice versa).
612 *
613 * @param value the value
614 */
615 CX_EXTERN
616 void cxJsonValueFree(CxJsonValue *value);
617
618 /**
619 * Creates a new (empty) JSON object.
620 *
621 * @param allocator the allocator to use
622 * @return the new JSON object or @c NULL if allocation fails
623 * @see cxJsonObjPutObj()
624 * @see cxJsonArrAddValues()
625 */
626 CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
627 CxJsonValue* cxJsonCreateObj(const CxAllocator* allocator);
628
629 /**
630 * Creates a new (empty) JSON array.
631 *
632 * Optionally, this function already allocates memory with the given capacity.
633 *
634 * @param allocator the allocator to use
635 * @param capacity optional capacity or zero if it's unknown how many elements the array will have
636 * @return the new JSON array or @c NULL if allocation fails
637 * @see cxJsonObjPutArr()
638 * @see cxJsonArrAddValues()
639 */
640 CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
641 CxJsonValue* cxJsonCreateArr(const CxAllocator* allocator, size_t capacity);
642
643 /**
644 * Creates a new JSON number value.
645 *
646 * @param allocator the allocator to use
647 * @param num the numeric value
648 * @return the new JSON value or @c NULL if allocation fails
649 * @see cxJsonObjPutNumber()
650 * @see cxJsonArrAddNumbers()
651 */
652 CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
653 CxJsonValue* cxJsonCreateNumber(const CxAllocator* allocator, double num);
654
655 /**
656 * Creates a new JSON number value based on an integer.
657 *
658 * @param allocator the allocator to use
659 * @param num the numeric value
660 * @return the new JSON value or @c NULL if allocation fails
661 * @see cxJsonObjPutInteger()
662 * @see cxJsonArrAddIntegers()
663 */
664 CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
665 CxJsonValue* cxJsonCreateInteger(const CxAllocator* allocator, int64_t num);
666
667 /**
668 * Creates a new JSON string.
669 *
670 * Internal function - use cxJsonCreateString() instead.
671 *
672 * @param allocator the allocator to use
673 * @param str the string data
674 * @return the new JSON value or @c NULL if allocation fails
675 * @see cxJsonObjPutString()
676 * @see cxJsonArrAddCxStrings()
677 */
678 CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
679 CxJsonValue* cx_json_create_string(const CxAllocator* allocator, cxstring str);
680
681 /**
682 * Creates a new JSON string.
683 *
684 * @param allocator (@c CxAllocator*) the allocator to use
685 * @param str the string
686 * @return (@c CxJsonValue*) the new JSON value or @c NULL if allocation fails
687 * @see cxJsonObjPutString()
688 * @see cxJsonArrAddCxStrings()
689 */
690 #define cxJsonCreateString(allocator, str) cx_json_create_string(allocator, cx_strcast(str))
691
692 /**
693 * Creates a new JSON literal.
694 *
695 * @param allocator the allocator to use
696 * @param lit the type of literal
697 * @return the new JSON value or @c NULL if allocation fails
698 * @see cxJsonObjPutLiteral()
699 * @see cxJsonArrAddLiterals()
700 */
701 CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
702 CxJsonValue* cxJsonCreateLiteral(const CxAllocator* allocator, CxJsonLiteral lit);
703
704 /**
705 * Adds number values to a JSON array.
706 *
707 * @param arr the JSON array
708 * @param num the array of values
709 * @param count the number of elements
710 * @retval zero success
711 * @retval non-zero allocation failure
712 */
713 CX_EXTERN CX_NONNULL CX_ACCESS_R(2, 3)
714 int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count);
715
716 /**
717 * Adds number values, of which all are integers, to a JSON array.
718 *
719 * @param arr the JSON array
720 * @param num the array of values
721 * @param count the number of elements
722 * @retval zero success
723 * @retval non-zero allocation failure
724 */
725 CX_EXTERN CX_NONNULL CX_ACCESS_R(2, 3)
726 int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count);
727
728 /**
729 * Adds strings to a JSON array.
730 *
731 * The strings will be copied with the allocator of the array.
732 *
733 * @param arr the JSON array
734 * @param str the array of strings
735 * @param count the number of elements
736 * @retval zero success
737 * @retval non-zero allocation failure
738 * @see cxJsonArrAddCxStrings()
739 */
740 CX_EXTERN CX_NONNULL CX_ACCESS_R(2, 3)
741 int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count);
742
743 /**
744 * Adds strings to a JSON array.
745 *
746 * The strings will be copied with the allocator of the array.
747 *
748 * @param arr the JSON array
749 * @param str the array of strings
750 * @param count the number of elements
751 * @retval zero success
752 * @retval non-zero allocation failure
753 * @see cxJsonArrAddStrings()
754 */
755 CX_EXTERN CX_NONNULL CX_ACCESS_R(2, 3)
756 int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count);
757
758 /**
759 * Adds literals to a JSON array.
760 *
761 * @param arr the JSON array
762 * @param lit the array of literal types
763 * @param count the number of elements
764 * @retval zero success
765 * @retval non-zero allocation failure
766 */
767 CX_EXTERN CX_NONNULL CX_ACCESS_R(2, 3)
768 int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count);
769
770 /**
771 * Add arbitrary values to a JSON array.
772 *
773 * @attention In contrast to all other add functions, this function adds the values
774 * directly to the array instead of copying them.
775 *
776 * @param arr the JSON array
777 * @param val the values
778 * @param count the number of elements
779 * @retval zero success
780 * @retval non-zero allocation failure
781 */
782 CX_EXTERN CX_NONNULL CX_ACCESS_R(2, 3)
783 int cxJsonArrAddValues(CxJsonValue* arr, CxJsonValue* const* val, size_t count);
784
785 /**
786 * Adds or replaces a value within a JSON object.
787 *
788 * Internal function - use cxJsonObjPut().
789 *
790 * @param obj the JSON object
791 * @param name the name of the value
792 * @param child the value
793 * @retval zero success
794 * @retval non-zero allocation failure
795 */
796 CX_EXTERN CX_NONNULL
797 int cx_json_obj_put(CxJsonValue* obj, cxstring name, CxJsonValue* child);
798
799 /**
800 * Adds or replaces a value within a JSON object.
801 *
802 * The value will be directly added and not copied.
803 *
804 * @note If a value with the specified @p name already exists,
805 * it will be (recursively) freed with its own allocator.
806 *
807 * @param obj (@c CxJsonValue*) the JSON object
808 * @param name (any string) the name of the value
809 * @param child (@c CxJsonValue*) the value
810 * @retval zero success
811 * @retval non-zero allocation failure
812 */
813 #define cxJsonObjPut(obj, name, child) cx_json_obj_put(obj, cx_strcast(name), child)
814
815 /**
816 * Creates a new JSON object and adds it to an existing object.
817 *
818 * Internal function - use cxJsonObjPutObj().
819 *
820 * @param obj the target JSON object
821 * @param name the name of the new value
822 * @return the new value or @c NULL if allocation fails
823 * @see cxJsonObjPut()
824 * @see cxJsonCreateObj()
825 */
826 CX_EXTERN CX_NONNULL CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
827 CxJsonValue* cx_json_obj_put_obj(CxJsonValue* obj, cxstring name);
828
829 /**
830 * Creates a new JSON object and adds it to an existing object.
831 *
832 * @param obj (@c CxJsonValue*) the target JSON object
833 * @param name (any string) the name of the new value
834 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails
835 * @see cxJsonObjPut()
836 * @see cxJsonCreateObj()
837 */
838 #define cxJsonObjPutObj(obj, name) cx_json_obj_put_obj(obj, cx_strcast(name))
839
840 /**
841 * Creates a new JSON array and adds it to an object.
842 *
843 * Internal function - use cxJsonObjPutArr().
844 *
845 * @param obj the target JSON object
846 * @param name the name of the new value
847 * @param capacity optional initial capacity
848 * @return the new value or @c NULL if allocation fails
849 * @see cxJsonObjPut()
850 * @see cxJsonCreateArr()
851 */
852 CX_EXTERN CX_NONNULL CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
853 CxJsonValue* cx_json_obj_put_arr(CxJsonValue* obj, cxstring name, size_t capacity);
854
855 /**
856 * Creates a new JSON array and adds it to an object.
857 *
858 * @param obj (@c CxJsonValue*) the target JSON object
859 * @param name (any string) the name of the new value
860 * @param capacity (@c size_t) optional initial capacity
861 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails
862 * @see cxJsonObjPut()
863 * @see cxJsonCreateArr()
864 */
865 #define cxJsonObjPutArr(obj, name, capacity) cx_json_obj_put_arr(obj, cx_strcast(name), capacity)
866
867 /**
868 * Creates a new JSON number and adds it to an object.
869 *
870 * Internal function - use cxJsonObjPutNumber().
871 *
872 * @param obj the target JSON object
873 * @param name the name of the new value
874 * @param num the numeric value
875 * @return the new value or @c NULL if allocation fails
876 * @see cxJsonObjPut()
877 * @see cxJsonCreateNumber()
878 */
879 CX_EXTERN CX_NONNULL CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
880 CxJsonValue* cx_json_obj_put_number(CxJsonValue* obj, cxstring name, double num);
881
882 /**
883 * Creates a new JSON number and adds it to an object.
884 *
885 * @param obj (@c CxJsonValue*) the target JSON object
886 * @param name (any string) the name of the new value
887 * @param num (@c double) the numeric value
888 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails
889 * @see cxJsonObjPut()
890 * @see cxJsonCreateNumber()
891 */
892 #define cxJsonObjPutNumber(obj, name, num) cx_json_obj_put_number(obj, cx_strcast(name), num)
893
894 /**
895 * Creates a new JSON number, based on an integer, and adds it to an object.
896 *
897 * Internal function - use cxJsonObjPutInteger().
898 *
899 * @param obj the target JSON object
900 * @param name the name of the new value
901 * @param num the numeric value
902 * @return the new value or @c NULL if allocation fails
903 * @see cxJsonObjPut()
904 * @see cxJsonCreateInteger()
905 */
906 CX_EXTERN CX_NONNULL CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
907 CxJsonValue* cx_json_obj_put_integer(CxJsonValue* obj, cxstring name, int64_t num);
908
909 /**
910 * Creates a new JSON number, based on an integer, and adds it to an object.
911 *
912 * @param obj (@c CxJsonValue*) the target JSON object
913 * @param name (any string) the name of the new value
914 * @param num (@c int64_t) the numeric value
915 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails
916 * @see cxJsonObjPut()
917 * @see cxJsonCreateInteger()
918 */
919 #define cxJsonObjPutInteger(obj, name, num) cx_json_obj_put_integer(obj, cx_strcast(name), num)
920
921 /**
922 * Creates a new JSON string and adds it to an object.
923 *
924 * Internal function - use cxJsonObjPutString()
925 *
926 * @param obj the target JSON object
927 * @param name the name of the new value
928 * @param str the string data
929 * @return the new value or @c NULL if allocation fails
930 * @see cxJsonObjPut()
931 * @see cxJsonCreateString()
932 */
933 CX_EXTERN CX_NONNULL CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
934 CxJsonValue* cx_json_obj_put_string(CxJsonValue* obj, cxstring name, cxstring str);
935
936 /**
937 * Creates a new JSON string and adds it to an object.
938 *
939 * The string data is copied.
940 *
941 * @param obj (@c CxJsonValue*) the target JSON object
942 * @param name (any string) the name of the new value
943 * @param str (any string) the string data
944 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails
945 * @see cxJsonObjPut()
946 * @see cxJsonCreateString()
947 */
948 #define cxJsonObjPutString(obj, name, str) cx_json_obj_put_string(obj, cx_strcast(name), cx_strcast(str))
949
950 /**
951 * Creates a new JSON literal and adds it to an object.
952 *
953 * Internal function - use cxJsonObjPutLiteral().
954 *
955 * @param obj the target JSON object
956 * @param name the name of the new value
957 * @param lit the type of literal
958 * @return the new value or @c NULL if allocation fails
959 * @see cxJsonObjPut()
960 * @see cxJsonCreateLiteral()
961 */
962 CX_EXTERN CX_NONNULL CX_MALLOC CX_DEALLOC(cxJsonValueFree, 1)
963 CxJsonValue* cx_json_obj_put_literal(CxJsonValue* obj, cxstring name, CxJsonLiteral lit);
964
965 /**
966 * Creates a new JSON literal and adds it to an object.
967 *
968 * @param obj (@c CxJsonValue*) the target JSON object
969 * @param name (any string) the name of the new value
970 * @param lit (@c CxJsonLiteral) the type of literal
971 * @return (@c CxJsonValue*) the new value or @c NULL if allocation fails
972 * @see cxJsonObjPut()
973 * @see cxJsonCreateLiteral()
974 */
975 #define cxJsonObjPutLiteral(obj, name, lit) cx_json_obj_put_literal(obj, cx_strcast(name), lit)
976
977 /**
978 * Tries to obtain the next JSON value.
979 *
980 * Before this function can be called, the input buffer needs
981 * to be filled with cxJsonFill().
982 *
983 * When this function returns #CX_JSON_INCOMPLETE_DATA, you can
984 * add the missing data with another invocation of cxJsonFill()
985 * and then repeat the call to cxJsonNext().
986 *
987 * @param json the JSON interface
988 * @param value a pointer where the next value shall be stored
989 * @retval CX_JSON_NO_ERROR successfully retrieve the @p value
990 * @retval CX_JSON_NO_DATA there is no (more) data in the buffer to read from
991 * @retval CX_JSON_INCOMPLETE_DATA an incomplete value was read
992 * and more data needs to be filled
993 * @retval CX_JSON_NULL_DATA the buffer was never initialized
994 * @retval CX_JSON_BUFFER_ALLOC_FAILED allocating internal buffer space failed
995 * @retval CX_JSON_VALUE_ALLOC_FAILED allocating memory for a CxJsonValue failed
996 * @retval CX_JSON_FORMAT_ERROR_NUMBER the JSON text contains an illegally formatted number
997 * @retval CX_JSON_FORMAT_ERROR_UNEXPECTED_TOKEN JSON syntax error
998 */
999 CX_EXTERN CX_NONNULL CX_ACCESS_W(2)
1000 CxJsonStatus cxJsonNext(CxJson *json, CxJsonValue **value);
1001
1002 /**
1003 * Checks if the specified value is a JSON object.
1004 *
1005 * @param value a pointer to the value
1006 * @retval true the value is a JSON object
1007 * @retval false otherwise
1008 */
1009 CX_NONNULL CX_NODISCARD CX_INLINE
1010 bool cxJsonIsObject(const CxJsonValue *value) {
1011 return value->type == CX_JSON_OBJECT;
1012 }
1013
1014 /**
1015 * Checks if the specified value is a JSON array.
1016 *
1017 * @param value a pointer to the value
1018 * @retval true the value is a JSON array
1019 * @retval false otherwise
1020 */
1021 CX_NONNULL CX_NODISCARD CX_INLINE
1022 bool cxJsonIsArray(const CxJsonValue *value) {
1023 return value->type == CX_JSON_ARRAY;
1024 }
1025
1026 /**
1027 * Checks if the specified value is a string.
1028 *
1029 * @param value a pointer to the value
1030 * @retval true the value is a string
1031 * @retval false otherwise
1032 */
1033 CX_NONNULL CX_NODISCARD CX_INLINE
1034 bool cxJsonIsString(const CxJsonValue *value) {
1035 return value->type == CX_JSON_STRING;
1036 }
1037
1038 /**
1039 * Checks if the specified value is a JSON number.
1040 *
1041 * This function will return true for both floating-point and
1042 * integer numbers.
1043 *
1044 * @param value a pointer to the value
1045 * @retval true the value is a JSON number
1046 * @retval false otherwise
1047 * @see cxJsonIsInteger()
1048 */
1049 CX_NONNULL CX_NODISCARD CX_INLINE
1050 bool cxJsonIsNumber(const CxJsonValue *value) {
1051
8/8
✓ Branch 0 (8→9) taken 126 times.
✓ Branch 1 (8→10) taken 50 times.
✓ Branch 2 (9→10) taken 44 times.
✓ Branch 3 (9→11) taken 82 times.
✓ Branch 4 (16→17) taken 74 times.
✓ Branch 5 (16→18) taken 20 times.
✓ Branch 6 (17→18) taken 20 times.
✓ Branch 7 (17→19) taken 54 times.
270 return value->type == CX_JSON_NUMBER || value->type == CX_JSON_INTEGER;
1052 }
1053
1054 /**
1055 * Checks if the specified value is an integer number.
1056 *
1057 * @param value a pointer to the value
1058 * @retval true the value is an integer number
1059 * @retval false otherwise
1060 * @see cxJsonIsNumber()
1061 */
1062 CX_NONNULL CX_NODISCARD CX_INLINE
1063 bool cxJsonIsInteger(const CxJsonValue *value) {
1064 return value->type == CX_JSON_INTEGER;
1065 }
1066
1067 /**
1068 * Checks if the specified value is a JSON literal.
1069 *
1070 * JSON literals are @c true, @c false, and @c null.
1071 *
1072 * @param value a pointer to the value
1073 * @retval true the value is a JSON literal
1074 * @retval false otherwise
1075 * @see cxJsonIsTrue()
1076 * @see cxJsonIsFalse()
1077 * @see cxJsonIsNull()
1078 */
1079 CX_NONNULL CX_NODISCARD CX_INLINE
1080 bool cxJsonIsLiteral(const CxJsonValue *value) {
1081 return value->type == CX_JSON_LITERAL;
1082 }
1083
1084 /**
1085 * Checks if the specified value is a Boolean literal.
1086 *
1087 * @param value a pointer to the value
1088 * @retval true the value is either @c true or @c false
1089 * @retval false otherwise
1090 * @see cxJsonIsTrue()
1091 * @see cxJsonIsFalse()
1092 */
1093 CX_NONNULL CX_NODISCARD CX_INLINE
1094 bool cxJsonIsBool(const CxJsonValue *value) {
1095 return cxJsonIsLiteral(value) && value->literal != CX_JSON_NULL;
1096 }
1097
1098 /**
1099 * Checks if the specified value is @c true.
1100 *
1101 * @remark Be advised that this is different from
1102 * testing @c !cxJsonIsFalse(v).
1103 *
1104 * @param value a pointer to the value
1105 * @retval true the value is @c true
1106 * @retval false otherwise
1107 * @see cxJsonIsBool()
1108 * @see cxJsonIsFalse()
1109 */
1110 CX_NONNULL CX_NODISCARD CX_INLINE
1111 bool cxJsonIsTrue(const CxJsonValue *value) {
1112 return cxJsonIsLiteral(value) && value->literal == CX_JSON_TRUE;
1113 }
1114
1115 /**
1116 * Checks if the specified value is @c false.
1117 *
1118 * @remark Be advised that this is different from
1119 * testing @c !cxJsonIsTrue(v).
1120 *
1121 * @param value a pointer to the value
1122 * @retval true the value is @c false
1123 * @retval false otherwise
1124 * @see cxJsonIsBool()
1125 * @see cxJsonIsTrue()
1126 */
1127 CX_NONNULL CX_NODISCARD CX_INLINE
1128 bool cxJsonIsFalse(const CxJsonValue *value) {
1129 return cxJsonIsLiteral(value) && value->literal == CX_JSON_FALSE;
1130 }
1131
1132 /**
1133 * Checks if the specified value is @c null.
1134 *
1135 * @param value a pointer to the value
1136 * @retval true the value is @c null
1137 * @retval false otherwise
1138 * @see cxJsonIsLiteral()
1139 */
1140 CX_NONNULL CX_NODISCARD CX_INLINE
1141 bool cxJsonIsNull(const CxJsonValue *value) {
1142 return cxJsonIsLiteral(value) && value->literal == CX_JSON_NULL;
1143 }
1144
1145 /**
1146 * Obtains a C string from the given JSON value.
1147 *
1148 * If the @p value is not a string, the behavior is undefined.
1149 *
1150 * @param value the JSON value
1151 * @return the value represented as C string
1152 * @see cxJsonIsString()
1153 */
1154 CX_EXTERN CX_NONNULL CX_RETURNS_NONNULL CX_NODISCARD
1155 char *cxJsonAsString(const CxJsonValue *value);
1156
1157 /**
1158 * Obtains a UCX string from the given JSON value.
1159 *
1160 * If the @p value is not a string, the behavior is undefined.
1161 *
1162 * @param value the JSON value
1163 * @return the value represented as UCX string
1164 * @see cxJsonIsString()
1165 */
1166 CX_EXTERN CX_NONNULL CX_NODISCARD
1167 cxstring cxJsonAsCxString(const CxJsonValue *value);
1168
1169 /**
1170 * Obtains a mutable UCX string from the given JSON value.
1171 *
1172 * If the @p value is not a string, the behavior is undefined.
1173 *
1174 * @param value the JSON value
1175 * @return the value represented as mutable UCX string
1176 * @see cxJsonIsString()
1177 */
1178 CX_EXTERN CX_NONNULL CX_NODISCARD
1179 cxmutstr cxJsonAsCxMutStr(const CxJsonValue *value);
1180
1181 /**
1182 * Obtains a double-precision floating-point value from the given JSON value.
1183 *
1184 * If the @p value is not a JSON number, the behavior is undefined.
1185 *
1186 * @param value the JSON value
1187 * @return the value represented as double
1188 * @see cxJsonIsNumber()
1189 */
1190 CX_EXTERN CX_NONNULL CX_NODISCARD
1191 double cxJsonAsDouble(const CxJsonValue *value);
1192
1193 /**
1194 * Obtains a 64-bit signed integer from the given JSON value.
1195 *
1196 * If the @p value is not a JSON number, the behavior is undefined.
1197 * If it is a JSON number, but not an integer, the value will be
1198 * converted to an integer, possibly losing precision.
1199 *
1200 * @param value the JSON value
1201 * @return the value represented as double
1202 * @see cxJsonIsNumber()
1203 * @see cxJsonIsInteger()
1204 */
1205 CX_EXTERN CX_NONNULL CX_NODISCARD
1206 int64_t cxJsonAsInteger(const CxJsonValue *value);
1207
1208 /**
1209 * Obtains a Boolean value from the given JSON value.
1210 *
1211 * If the @p value is not a JSON literal, the behavior is undefined.
1212 * The @c null literal is interpreted as @c false.
1213 *
1214 * @param value the JSON value
1215 * @return the value represented as double
1216 * @see cxJsonIsLiteral()
1217 */
1218 CX_NONNULL CX_NODISCARD CX_INLINE
1219 bool cxJsonAsBool(const CxJsonValue *value) {
1220 return value->literal == CX_JSON_TRUE;
1221 }
1222
1223 /**
1224 * Returns the size of a JSON array.
1225 *
1226 * If the @p value is not a JSON array, the behavior is undefined.
1227 *
1228 * @param value the JSON value
1229 * @return the size of the array
1230 * @see cxJsonIsArray()
1231 */
1232 CX_NONNULL CX_NODISCARD CX_INLINE
1233 size_t cxJsonArrSize(const CxJsonValue *value) {
1234 return value->array.size;
1235 }
1236
1237 /**
1238 * Returns an element from a JSON array.
1239 *
1240 * If the @p value is not a JSON array, the behavior is undefined.
1241 *
1242 * This function guarantees to return a value. If the index is
1243 * out of bounds, the returned value will be of type
1244 * #CX_JSON_NOTHING, but never @c NULL.
1245 *
1246 * @param value the JSON value
1247 * @param index the index in the array
1248 * @return the value at the specified index
1249 * @see cxJsonIsArray()
1250 */
1251 CX_EXTERN CX_NONNULL CX_RETURNS_NONNULL CX_NODISCARD
1252 CxJsonValue *cxJsonArrGet(const CxJsonValue *value, size_t index);
1253
1254 /**
1255 * Removes an element from a JSON array.
1256 *
1257 * If the @p value is not a JSON array, the behavior is undefined.
1258 *
1259 * This function, in contrast to cxJsonArrayGet(), returns @c NULL
1260 * when the index is out of bounds.
1261 *
1262 * @param value the JSON value
1263 * @param index the index in the array
1264 * @return the removed value from the specified index or @c NULL when the index was out of bounds
1265 * @see cxJsonIsArray()
1266 */
1267 CX_EXTERN CX_NONNULL
1268 CxJsonValue *cxJsonArrRemove(CxJsonValue *value, size_t index);
1269
1270 /**
1271 * Returns an iterator over the JSON array elements.
1272 *
1273 * The iterator yields values of type @c CxJsonValue* .
1274 *
1275 * If the @p value is not a JSON array, the behavior is undefined.
1276 *
1277 * @param value the JSON value
1278 * @return an iterator over the array elements
1279 * @see cxJsonIsArray()
1280 */
1281 CX_EXTERN CX_NONNULL CX_NODISCARD
1282 CxIterator cxJsonArrIter(const CxJsonValue *value);
1283
1284 /**
1285 * Returns the size of a JSON object.
1286 *
1287 * If the @p value is not a JSON object, the behavior is undefined.
1288 *
1289 * @param value the JSON value
1290 * @return the size of the object, i.e., the number of key/value pairs
1291 * @see cxJsonIsObject()
1292 */
1293 CX_NONNULL CX_INLINE
1294 size_t cxJsonObjSize(const CxJsonValue *value) {
1295 return cxCollectionSize(value->object);
1296 }
1297
1298 /**
1299 * Returns a map iterator over the JSON object members.
1300 *
1301 * The iterator yields values of type @c CxMapEntry* which
1302 * contain the name and the @c CxJsonObjValue* of the member.
1303 *
1304 * If the @p value is not a JSON object, the behavior is undefined.
1305 *
1306 * @param value the JSON value
1307 * @return an iterator over the object members
1308 * @see cxJsonIsObject()
1309 */
1310 CX_EXTERN CX_NONNULL CX_NODISCARD
1311 CxMapIterator cxJsonObjIter(const CxJsonValue *value);
1312
1313 /**
1314 * Internal function, do not use.
1315 * @param value the JSON object
1316 * @param name the key to look up
1317 * @return the value corresponding to the key
1318 */
1319 CX_EXTERN CX_NONNULL CX_RETURNS_NONNULL CX_NODISCARD
1320 CxJsonValue *cx_json_obj_get(const CxJsonValue *value, cxstring name);
1321
1322 /**
1323 * Returns a value corresponding to a key in a JSON object.
1324 *
1325 * If the @p value is not a JSON object, the behavior is undefined.
1326 *
1327 * This function guarantees to return a JSON value. If the
1328 * object does not contain @p name, the returned JSON value
1329 * will be of type #CX_JSON_NOTHING, but never @c NULL.
1330 *
1331 * @param value the JSON object
1332 * @param name the key to look up
1333 * @return the value corresponding to the key
1334 * @see cxJsonIsObject()
1335 */
1336 #define cxJsonObjGet(value, name) cx_json_obj_get(value, cx_strcast(name))
1337
1338 /**
1339 * Internal function, do not use.
1340 * @param value the JSON object
1341 * @param name the key to look up
1342 * @return the value corresponding to the key or @c NULL when the key is not part of the object
1343 */
1344 CX_EXTERN CX_NONNULL
1345 CxJsonValue *cx_json_obj_remove(CxJsonValue *value, cxstring name);
1346
1347 /**
1348 * Removes and returns a value corresponding to a key in a JSON object.
1349 *
1350 * If the @p value is not a JSON object, the behavior is undefined.
1351 *
1352 * This function, in contrast to cxJsonObjGet() returns @c NULL when the
1353 * object does not contain @p name.
1354 *
1355 * @param value the JSON object
1356 * @param name the key to look up
1357 * @return the value corresponding to the key or @c NULL when the key is not part of the object
1358 * @see cxJsonIsObject()
1359 */
1360 #define cxJsonObjRemove(value, name) cx_json_obj_remove(value, cx_strcast(name))
1361
1362 /**
1363 * Performs a deep comparison of two JSON values.
1364 *
1365 * The order of object members is ignored during comparison.
1366 *
1367 * @param json the JSON value
1368 * @param other the other JSON value that the JSON value is compared to
1369 * @retval zero the values are equal (except for ordering of object members)
1370 * @retval non-zero the values differ
1371 */
1372 CX_EXTERN CX_NODISCARD
1373 int cxJsonCompare(const CxJsonValue *json, const CxJsonValue *other);
1374
1375
1376 /**
1377 * Creates a deep copy of the specified JSON value.
1378 *
1379 * If you need a @c cx_clone_func compatible version, see cxJsonCloneFunc().
1380 *
1381 * @note when you are cloning @c NULL, you will get a pointer to a statically
1382 * allocated value which represents nothing.
1383 *
1384 * @param value the value to be cloned
1385 * @param allocator the allocator for the new value
1386 * @return the new value or @c NULL if any allocation was unsuccessful
1387 * @see cxJsonCloneFunc()
1388 */
1389 CX_EXTERN CX_NODISCARD
1390 CxJsonValue* cxJsonClone(const CxJsonValue* value,
1391 const CxAllocator* allocator);
1392
1393 /**
1394 * A @c cx_clone_func compatible version of cxJsonClone().
1395 *
1396 * Internal function - use cxJsonCloneFunc() to get a properly casted function pointer.
1397 *
1398 * @param target the target memory or @c NULL
1399 * @param source the value to be cloned
1400 * @param allocator the allocator for the new value
1401 * @param data unused
1402 * @return the new value or @c NULL if any allocation was unsuccessful
1403 * @see cxJsonClone()
1404 */
1405 CX_EXTERN CX_NODISCARD
1406 CxJsonValue* cx_json_clone_func(
1407 CxJsonValue* target, const CxJsonValue* source,
1408 const CxAllocator* allocator, void *data);
1409
1410 /**
1411 * A @c cx_clone_func compatible version of cxJsonClone().
1412 *
1413 * @param target (@c CxJsonValue*) the target memory or @c NULL
1414 * @param source (@c CxJsonValue*) the value to be cloned
1415 * @param allocator (@c CxAllocator*) the allocator for the new value
1416 * @param data unused
1417 * @return the new value or @c NULL if any allocation was unsuccessful
1418 * @see cxJsonClone()
1419 */
1420 #define cxJsonCloneFunc ((cx_clone_func) cx_json_clone_func)
1421
1422 #endif /* UCX_JSON_H */
1423
1424