JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
json.h
Go to the documentation of this file.
1 /*
2 The latest version of this library is available on GitHub;
3 https://github.com/sheredom/json.h.
4*/
5
6/*
7 This is free and unencumbered software released into the public domain.
8
9 Anyone is free to copy, modify, publish, use, compile, sell, or
10 distribute this software, either in source code form or as a compiled
11 binary, for any purpose, commercial or non-commercial, and by any
12 means.
13
14 In jurisdictions that recognize copyright laws, the author or authors
15 of this software dedicate any and all copyright interest in the
16 software to the public domain. We make this dedication for the benefit
17 of the public at large and to the detriment of our heirs and
18 successors. We intend this dedication to be an overt act of
19 relinquishment in perpetuity of all present and future rights to this
20 software under copyright law.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
29
30 For more information, please refer to <http://unlicense.org/>.
31*/
32
33#ifndef SHEREDOM_JSON_H_INCLUDED
34#define SHEREDOM_JSON_H_INCLUDED
35
36#if defined(_MSC_VER)
37#pragma warning(push)
38
39/* disable warning: no function prototype given: converting '()' to '(void)' */
40#pragma warning(disable : 4255)
41
42/* disable warning: '__cplusplus' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
43#pragma warning(disable : 4668)
44
45/* disable warning: 'bytes padding added after construct' */
46#pragma warning(disable : 4820)
47#endif
48
49#include <stddef.h>
50#include <string.h>
51
52#if defined(_MSC_VER) || defined(__MINGW32__)
53#define json_weak __inline
54#elif defined(__clang__) || defined(__GNUC__)
55#define json_weak __attribute__((weak))
56#else
57#error Non clang, non gcc, non MSVC compiler found!
58#endif
59
60#ifdef __cplusplus
61extern "C" {
62#endif
63
64struct json_value_s;
66
67enum json_parse_flags_e {
68 json_parse_flags_default = 0,
69
70 /* allow trailing commas in objects and arrays. For example, both [true,] and
71 {"a" : null,} would be allowed with this option on. */
72 json_parse_flags_allow_trailing_comma = 0x1,
73
74 /* allow unquoted keys for objects. For example, {a : null} would be allowed
75 with this option on. */
76 json_parse_flags_allow_unquoted_keys = 0x2,
77
78 /* allow a global unbracketed object. For example, a : null, b : true, c : {}
79 would be allowed with this option on. */
80 json_parse_flags_allow_global_object = 0x4,
81
82 /* allow objects to use '=' instead of ':' between key/value pairs. For
83 example, a = null, b : true would be allowed with this option on. */
84 json_parse_flags_allow_equals_in_object = 0x8,
85
86 /* allow that objects don't have to have comma separators between key/value
87 pairs. */
88 json_parse_flags_allow_no_commas = 0x10,
89
90 /* allow c-style comments (either variants) to be ignored in the input JSON
91 file. */
92 json_parse_flags_allow_c_style_comments = 0x20,
93
94 /* deprecated flag, unused. */
95 json_parse_flags_deprecated = 0x40,
96
97 /* record location information for each value. */
98 json_parse_flags_allow_location_information = 0x80,
99
100 /* allow strings to be 'single quoted'. */
101 json_parse_flags_allow_single_quoted_strings = 0x100,
102
103 /* allow numbers to be hexadecimal. */
104 json_parse_flags_allow_hexadecimal_numbers = 0x200,
105
106 /* allow numbers like +123 to be parsed. */
107 json_parse_flags_allow_leading_plus_sign = 0x400,
108
109 /* allow numbers like .0123 or 123. to be parsed. */
110 json_parse_flags_allow_leading_or_trailing_decimal_point = 0x800,
111
112 /* allow Infinity, -Infinity, NaN, -NaN. */
113 json_parse_flags_allow_inf_and_nan = 0x1000,
114
115 /* allow multi line string values. */
116 json_parse_flags_allow_multi_line_strings = 0x2000,
117
118 /* allow simplified JSON to be parsed. Simplified JSON is an enabling of a set
119 of other parsing options. */
120 json_parse_flags_allow_simplified_json =
121 (json_parse_flags_allow_trailing_comma |
122 json_parse_flags_allow_unquoted_keys |
123 json_parse_flags_allow_global_object |
124 json_parse_flags_allow_equals_in_object |
125 json_parse_flags_allow_no_commas),
126
127 /* allow JSON5 to be parsed. JSON5 is an enabling of a set of other parsing
128 options. */
129 json_parse_flags_allow_json5 =
130 (json_parse_flags_allow_trailing_comma |
131 json_parse_flags_allow_unquoted_keys |
132 json_parse_flags_allow_c_style_comments |
133 json_parse_flags_allow_single_quoted_strings |
134 json_parse_flags_allow_hexadecimal_numbers |
135 json_parse_flags_allow_leading_plus_sign |
136 json_parse_flags_allow_leading_or_trailing_decimal_point |
137 json_parse_flags_allow_inf_and_nan |
138 json_parse_flags_allow_multi_line_strings)
139};
140
141/* Parse a JSON text file, returning a pointer to the root of the JSON
142 * structure. json_parse performs 1 call to malloc for the entire encoding.
143 * Returns 0 if an error occurred (malformed JSON input, or malloc failed). */
144json_weak struct json_value_s *json_parse(const void *src, size_t src_size);
145
146/* Parse a JSON text file, returning a pointer to the root of the JSON
147 * structure. json_parse performs 1 call to alloc_func_ptr for the entire
148 * encoding. Returns 0 if an error occurred (malformed JSON input, or malloc
149 * failed). If an error occurred, the result struct (if not NULL) will explain
150 * the type of error, and the location in the input it occurred. If
151 * alloc_func_ptr is null then malloc is used. */
152json_weak struct json_value_s *
153json_parse_ex(const void *src, size_t src_size, size_t flags_bitset,
154 void *(*alloc_func_ptr)(void *, size_t), void *user_data,
155 struct json_parse_result_s *result);
156
157/* Extracts a value and all the data that makes it up into a newly created
158 * value. json_extract_value performs 1 call to malloc for the entire encoding.
159 */
160json_weak struct json_value_s *
161json_extract_value(const struct json_value_s *value);
162
163/* Extracts a value and all the data that makes it up into a newly created
164 * value. json_extract_value performs 1 call to alloc_func_ptr for the entire
165 * encoding. If alloc_func_ptr is null then malloc is used. */
166json_weak struct json_value_s *
167json_extract_value_ex(const struct json_value_s *value,
168 void *(*alloc_func_ptr)(void *, size_t), void *user_data);
169
170/* Write out a minified JSON utf-8 string. This string is an encoding of the
171 * minimal string characters required to still encode the same data.
172 * json_write_minified performs 1 call to malloc for the entire encoding. Return
173 * 0 if an error occurred (malformed JSON input, or malloc failed). The out_size
174 * parameter is optional as the utf-8 string is null terminated. */
175json_weak void *json_write_minified(const struct json_value_s *value,
176 size_t *out_size);
177
178/* Write out a pretty JSON utf-8 string. This string is encoded such that the
179 * resultant JSON is pretty in that it is easily human readable. The indent and
180 * newline parameters allow a user to specify what kind of indentation and
181 * newline they want (two spaces / three spaces / tabs? \r, \n, \r\n ?). Both
182 * indent and newline can be NULL, indent defaults to two spaces (" "), and
183 * newline defaults to linux newlines ('\n' as the newline character).
184 * json_write_pretty performs 1 call to malloc for the entire encoding. Return 0
185 * if an error occurred (malformed JSON input, or malloc failed). The out_size
186 * parameter is optional as the utf-8 string is null terminated. */
187json_weak void *json_write_pretty(const struct json_value_s *value,
188 const char *indent, const char *newline,
189 size_t *out_size);
190
191/* Reinterpret a JSON value as a string. Returns null is the value was not a
192 * string. */
193json_weak struct json_string_s *
194json_value_as_string(struct json_value_s *const value);
195
196/* Reinterpret a JSON value as a number. Returns null is the value was not a
197 * number. */
198json_weak struct json_number_s *
199json_value_as_number(struct json_value_s *const value);
200
201/* Reinterpret a JSON value as an object. Returns null is the value was not an
202 * object. */
203json_weak struct json_object_s *
204json_value_as_object(struct json_value_s *const value);
205
206/* Reinterpret a JSON value as an array. Returns null is the value was not an
207 * array. */
208json_weak struct json_array_s *
209json_value_as_array(struct json_value_s *const value);
210
211/* Whether the value is true. */
212json_weak int json_value_is_true(const struct json_value_s *const value);
213
214/* Whether the value is false. */
215json_weak int json_value_is_false(const struct json_value_s *const value);
216
217/* Whether the value is null. */
218json_weak int json_value_is_null(const struct json_value_s *const value);
219
220/* The various types JSON values can be. Used to identify what a value is. */
221enum json_type_e {
222 json_type_string,
223 json_type_number,
224 json_type_object,
225 json_type_array,
226 json_type_true,
227 json_type_false,
228 json_type_null
229};
230
231/* A JSON string value. */
233 /* utf-8 string */
234 const char *string;
235 /* The size (in bytes) of the string */
236 size_t string_size;
237};
238
239/* A JSON string value (extended). */
241 /* The JSON string this extends. */
242 struct json_string_s string;
243
244 /* The character offset for the value in the JSON input. */
245 size_t offset;
246
247 /* The line number for the value in the JSON input. */
248 size_t line_no;
249
250 /* The row number for the value in the JSON input, in bytes. */
251 size_t row_no;
252};
253
254/* A JSON number value. */
256 /* ASCII string containing representation of the number. */
257 const char *number;
258 /* the size (in bytes) of the number. */
259 size_t number_size;
260};
261
262/* an element of a JSON object. */
264 /* the name of this element. */
265 struct json_string_s *name;
266 /* the value of this element. */
267 struct json_value_s *value;
268 /* the next object element (can be NULL if the last element in the object). */
269 struct json_object_element_s *next;
270};
271
272/* a JSON object value. */
274 /* a linked list of the elements in the object. */
275 struct json_object_element_s *start;
276 /* the number of elements in the object. */
277 size_t length;
278};
279
280/* an element of a JSON array. */
282 /* the value of this element. */
283 struct json_value_s *value;
284 /* the next array element (can be NULL if the last element in the array). */
285 struct json_array_element_s *next;
286};
287
288/* a JSON array value. */
290 /* a linked list of the elements in the array. */
291 struct json_array_element_s *start;
292 /* the number of elements in the array. */
293 size_t length;
294};
295
296/* a JSON value. */
298 /* a pointer to either a json_string_s, json_number_s, json_object_s, or. */
299 /* json_array_s. Should be cast to the appropriate struct type based on what.
300 */
301 /* the type of this value is. */
302 void *payload;
303 /* must be one of json_type_e. If type is json_type_true, json_type_false, or.
304 */
305 /* json_type_null, payload will be NULL. */
306 size_t type;
307};
308
309/* a JSON value (extended). */
311 /* the JSON value this extends. */
312 struct json_value_s value;
313
314 /* the character offset for the value in the JSON input. */
315 size_t offset;
316
317 /* the line number for the value in the JSON input. */
318 size_t line_no;
319
320 /* the row number for the value in the JSON input, in bytes. */
321 size_t row_no;
322};
323
324/* a parsing error code. */
325enum json_parse_error_e {
326 /* no error occurred (huzzah!). */
327 json_parse_error_none = 0,
328
329 /* expected either a comma or a closing '}' or ']' to close an object or. */
330 /* array! */
331 json_parse_error_expected_comma_or_closing_bracket,
332
333 /* colon separating name/value pair was missing! */
334 json_parse_error_expected_colon,
335
336 /* expected string to begin with '"'! */
337 json_parse_error_expected_opening_quote,
338
339 /* invalid escaped sequence in string! */
340 json_parse_error_invalid_string_escape_sequence,
341
342 /* invalid number format! */
343 json_parse_error_invalid_number_format,
344
345 /* invalid value! */
346 json_parse_error_invalid_value,
347
348 /* reached end of buffer before object/array was complete! */
349 json_parse_error_premature_end_of_buffer,
350
351 /* string was malformed! */
352 json_parse_error_invalid_string,
353
354 /* a call to malloc, or a user provider allocator, failed. */
355 json_parse_error_allocator_failed,
356
357 /* the JSON input had unexpected trailing characters that weren't part of the.
358 */
359 /* JSON value. */
360 json_parse_error_unexpected_trailing_characters,
361
362 /* catch-all error for everything else that exploded (real bad chi!). */
363 json_parse_error_unknown
364};
365
366/* error report from json_parse_ex(). */
368 /* the error code (one of json_parse_error_e). */
369 size_t error;
370
371 /* the character offset for the error in the JSON input. */
372 size_t error_offset;
373
374 /* the line number for the error in the JSON input. */
375 size_t error_line_no;
376
377 /* the row number for the error, in bytes. */
378 size_t error_row_no;
379};
380
381#ifdef __cplusplus
382} /* extern "C". */
383#endif
384
385#include <stdlib.h>
386
387#if defined(_MSC_VER)
388#pragma warning(pop)
389#endif
390
391#if defined(_MSC_VER) && (_MSC_VER < 1920)
392#define json_uintmax_t unsigned __int64
393#else
394#include <inttypes.h>
395#define json_uintmax_t uintmax_t
396#endif
397
398#if defined(_MSC_VER)
399#define json_strtoumax _strtoui64
400#else
401#define json_strtoumax strtoumax
402#endif
403
404#if defined(__cplusplus) && (__cplusplus >= 201103L)
405#define json_null nullptr
406#else
407#define json_null 0
408#endif
409
410#if defined(__clang__)
411#pragma clang diagnostic push
412
413/* we do one big allocation via malloc, then cast aligned slices of this for. */
414/* our structures - we don't have a way to tell the compiler we know what we. */
415/* are doing, so disable the warning instead! */
416#pragma clang diagnostic ignored "-Wcast-align"
417
418/* We use C style casts everywhere. */
419#pragma clang diagnostic ignored "-Wold-style-cast"
420
421/* We need long long for strtoull. */
422#pragma clang diagnostic ignored "-Wc++11-long-long"
423
424/* Who cares if nullptr doesn't work with C++98, we don't use it there! */
425#pragma clang diagnostic ignored "-Wc++98-compat"
426#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
427#elif defined(_MSC_VER)
428#pragma warning(push)
429
430/* disable 'function selected for inline expansion' warning. */
431#pragma warning(disable : 4711)
432
433/* disable '#pragma warning: there is no warning number' warning. */
434#pragma warning(disable : 4619)
435
436/* disable 'warning number not a valid compiler warning' warning. */
437#pragma warning(disable : 4616)
438
439/* disable 'Compiler will insert Spectre mitigation for memory load if
440 * /Qspectre. */
441/* switch specified' warning. */
442#pragma warning(disable : 5045)
443#endif
444
446 const char *src;
447 size_t size;
448 size_t offset;
449 size_t flags_bitset;
450 char *data;
451 char *dom;
452 size_t dom_size;
453 size_t data_size;
454 size_t line_no; /* line counter for error reporting. */
455 size_t line_offset; /* (offset-line_offset) is the character number (in
456 bytes). */
457 size_t error;
458};
459
460json_weak int json_hexadecimal_digit(const char c);
461int json_hexadecimal_digit(const char c) {
462 if ('0' <= c && c <= '9') {
463 return c - '0';
464 }
465 if ('a' <= c && c <= 'f') {
466 return c - 'a' + 10;
467 }
468 if ('A' <= c && c <= 'F') {
469 return c - 'A' + 10;
470 }
471 return -1;
472}
473
474json_weak int json_hexadecimal_value(const char *c, const unsigned long size,
475 unsigned long *result);
476int json_hexadecimal_value(const char *c, const unsigned long size,
477 unsigned long *result) {
478 const char *p;
479 int digit;
480
481 if (size > sizeof(unsigned long) * 2) {
482 return 0;
483 }
484
485 *result = 0;
486 for (p = c; (unsigned long)(p - c) < size; ++p) {
487 *result <<= 4;
488 digit = json_hexadecimal_digit(*p);
489 if (digit < 0 || digit > 15) {
490 return 0;
491 }
492 *result |= (unsigned char)digit;
493 }
494 return 1;
495}
496
497json_weak int json_skip_whitespace(struct json_parse_state_s *state);
498int json_skip_whitespace(struct json_parse_state_s *state) {
499 size_t offset = state->offset;
500 const size_t size = state->size;
501 const char *const src = state->src;
502
503 /* the only valid whitespace according to ECMA-404 is ' ', '\n', '\r' and
504 * '\t'. */
505 switch (src[offset]) {
506 default:
507 return 0;
508 case ' ':
509 case '\r':
510 case '\t':
511 case '\n':
512 break;
513 }
514
515 do {
516 switch (src[offset]) {
517 default:
518 /* Update offset. */
519 state->offset = offset;
520 return 1;
521 case ' ':
522 case '\r':
523 case '\t':
524 break;
525 case '\n':
526 state->line_no++;
527 state->line_offset = offset;
528 break;
529 }
530
531 offset++;
532 } while (offset < size);
533
534 /* Update offset. */
535 state->offset = offset;
536 return 1;
537}
538
539json_weak int json_skip_c_style_comments(struct json_parse_state_s *state);
540int json_skip_c_style_comments(struct json_parse_state_s *state) {
541 /* do we have a comment?. */
542 if ('/' == state->src[state->offset]) {
543 /* skip '/'. */
544 state->offset++;
545
546 if ('/' == state->src[state->offset]) {
547 /* we had a comment of the form //. */
548
549 /* skip second '/'. */
550 state->offset++;
551
552 while (state->offset < state->size) {
553 switch (state->src[state->offset]) {
554 default:
555 /* skip the character in the comment. */
556 state->offset++;
557 break;
558 case '\n':
559 /* if we have a newline, our comment has ended! Skip the newline. */
560 state->offset++;
561
562 /* we entered a newline, so move our line info forward. */
563 state->line_no++;
564 state->line_offset = state->offset;
565 return 1;
566 }
567 }
568
569 /* we reached the end of the JSON file! */
570 return 1;
571 } else if ('*' == state->src[state->offset]) {
572 /* we had a comment in the C-style long form. */
573
574 /* skip '*'. */
575 state->offset++;
576
577 while (state->offset + 1 < state->size) {
578 if (('*' == state->src[state->offset]) &&
579 ('/' == state->src[state->offset + 1])) {
580 /* we reached the end of our comment! */
581 state->offset += 2;
582 return 1;
583 } else if ('\n' == state->src[state->offset]) {
584 /* we entered a newline, so move our line info forward. */
585 state->line_no++;
586 state->line_offset = state->offset;
587 }
588
589 /* skip character within comment. */
590 state->offset++;
591 }
592
593 /* Comment wasn't ended correctly which is a failure. */
594 return 1;
595 }
596 }
597
598 /* we didn't have any comment, which is ok too! */
599 return 0;
600}
601
602json_weak int json_skip_all_skippables(struct json_parse_state_s *state);
603int json_skip_all_skippables(struct json_parse_state_s *state) {
604 /* skip all whitespace and other skippables until there are none left. note
605 * that the previous version suffered from read past errors should. the
606 * stream end on json_skip_c_style_comments eg. '{"a" ' with comments flag.
607 */
608
609 int did_consume = 0;
610 const size_t size = state->size;
611
612 if (json_parse_flags_allow_c_style_comments & state->flags_bitset) {
613 do {
614 if (state->offset == size) {
615 state->error = json_parse_error_premature_end_of_buffer;
616 return 1;
617 }
618
619 did_consume = json_skip_whitespace(state);
620
621 /* This should really be checked on access, not in front of every call.
622 */
623 if (state->offset == size) {
624 state->error = json_parse_error_premature_end_of_buffer;
625 return 1;
626 }
627
628 did_consume |= json_skip_c_style_comments(state);
629 } while (0 != did_consume);
630 } else {
631 do {
632 if (state->offset == size) {
633 state->error = json_parse_error_premature_end_of_buffer;
634 return 1;
635 }
636
637 did_consume = json_skip_whitespace(state);
638 } while (0 != did_consume);
639 }
640
641 if (state->offset == size) {
642 state->error = json_parse_error_premature_end_of_buffer;
643 return 1;
644 }
645
646 return 0;
647}
648
649json_weak int json_get_value_size(struct json_parse_state_s *state,
650 int is_global_object);
651
652json_weak int json_get_string_size(struct json_parse_state_s *state,
653 size_t is_key);
654int json_get_string_size(struct json_parse_state_s *state, size_t is_key) {
655 size_t offset = state->offset;
656 const size_t size = state->size;
657 size_t data_size = 0;
658 const char *const src = state->src;
659 const int is_single_quote = '\'' == src[offset];
660 const char quote_to_use = is_single_quote ? '\'' : '"';
661 const size_t flags_bitset = state->flags_bitset;
662 unsigned long codepoint;
663 unsigned long high_surrogate = 0;
664
665 if ((json_parse_flags_allow_location_information & flags_bitset) != 0 &&
666 is_key != 0) {
667 state->dom_size += sizeof(struct json_string_ex_s);
668 } else {
669 state->dom_size += sizeof(struct json_string_s);
670 }
671
672 if ('"' != src[offset]) {
673 /* if we are allowed single quoted strings check for that too. */
674 if (!((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&
675 is_single_quote)) {
676 state->error = json_parse_error_expected_opening_quote;
677 state->offset = offset;
678 return 1;
679 }
680 }
681
682 /* skip leading '"' or '\''. */
683 offset++;
684
685 while ((offset < size) && (quote_to_use != src[offset])) {
686 /* add space for the character. */
687 data_size++;
688
689 switch (src[offset]) {
690 default:
691 break;
692 case '\0':
693 case '\t':
694 state->error = json_parse_error_invalid_string;
695 state->offset = offset;
696 return 1;
697 }
698
699 if ('\\' == src[offset]) {
700 /* skip reverse solidus character. */
701 offset++;
702
703 if (offset == size) {
704 state->error = json_parse_error_premature_end_of_buffer;
705 state->offset = offset;
706 return 1;
707 }
708
709 switch (src[offset]) {
710 default:
711 state->error = json_parse_error_invalid_string_escape_sequence;
712 state->offset = offset;
713 return 1;
714 case '"':
715 case '\\':
716 case '/':
717 case 'b':
718 case 'f':
719 case 'n':
720 case 'r':
721 case 't':
722 /* all valid characters! */
723 offset++;
724 break;
725 case 'u':
726 if (!(offset + 5 < size)) {
727 /* invalid escaped unicode sequence! */
728 state->error = json_parse_error_invalid_string_escape_sequence;
729 state->offset = offset;
730 return 1;
731 }
732
733 codepoint = 0;
734 if (!json_hexadecimal_value(&src[offset + 1], 4, &codepoint)) {
735 /* escaped unicode sequences must contain 4 hexadecimal digits! */
736 state->error = json_parse_error_invalid_string_escape_sequence;
737 state->offset = offset;
738 return 1;
739 }
740
741 /* Valid sequence!
742 * see: https://en.wikipedia.org/wiki/UTF-8#Invalid_code_points.
743 * 1 7 U + 0000 U + 007F 0xxxxxxx.
744 * 2 11 U + 0080 U + 07FF 110xxxxx
745 * 10xxxxxx.
746 * 3 16 U + 0800 U + FFFF 1110xxxx
747 * 10xxxxxx 10xxxxxx.
748 * 4 21 U + 10000 U + 10FFFF 11110xxx
749 * 10xxxxxx 10xxxxxx 10xxxxxx.
750 * Note: the high and low surrogate halves used by UTF-16 (U+D800
751 * through U+DFFF) and code points not encodable by UTF-16 (those after
752 * U+10FFFF) are not legal Unicode values, and their UTF-8 encoding must
753 * be treated as an invalid byte sequence. */
754
755 if (high_surrogate != 0) {
756 /* we previously read the high half of the \uxxxx\uxxxx pair, so now
757 * we expect the low half. */
758 if (codepoint >= 0xdc00 &&
759 codepoint <= 0xdfff) { /* low surrogate range. */
760 data_size += 3;
761 high_surrogate = 0;
762 } else {
763 state->error = json_parse_error_invalid_string_escape_sequence;
764 state->offset = offset;
765 return 1;
766 }
767 } else if (codepoint <= 0x7f) {
768 data_size += 0;
769 } else if (codepoint <= 0x7ff) {
770 data_size += 1;
771 } else if (codepoint >= 0xd800 &&
772 codepoint <= 0xdbff) { /* high surrogate range. */
773 /* The codepoint is the first half of a "utf-16 surrogate pair". so we
774 * need the other half for it to be valid: \uHHHH\uLLLL. */
775 if (offset + 11 > size || '\\' != src[offset + 5] ||
776 'u' != src[offset + 6]) {
777 state->error = json_parse_error_invalid_string_escape_sequence;
778 state->offset = offset;
779 return 1;
780 }
781 high_surrogate = codepoint;
782 } else if (codepoint >= 0xd800 &&
783 codepoint <= 0xdfff) { /* low surrogate range. */
784 /* we did not read the other half before. */
785 state->error = json_parse_error_invalid_string_escape_sequence;
786 state->offset = offset;
787 return 1;
788 } else {
789 data_size += 2;
790 }
791 /* escaped codepoints after 0xffff are supported in json through utf-16
792 * surrogate pairs: \uD83D\uDD25 for U+1F525. */
793
794 offset += 5;
795 break;
796 }
797 } else if (('\r' == src[offset]) || ('\n' == src[offset])) {
798 if (!(json_parse_flags_allow_multi_line_strings & flags_bitset)) {
799 /* invalid escaped unicode sequence! */
800 state->error = json_parse_error_invalid_string_escape_sequence;
801 state->offset = offset;
802 return 1;
803 }
804
805 offset++;
806 } else {
807 /* skip character (valid part of sequence). */
808 offset++;
809 }
810 }
811
812 /* If the offset is equal to the size, we had a non-terminated string! */
813 if (offset == size) {
814 state->error = json_parse_error_premature_end_of_buffer;
815 state->offset = offset - 1;
816 return 1;
817 }
818
819 /* skip trailing '"' or '\''. */
820 offset++;
821
822 /* add enough space to store the string. */
823 state->data_size += data_size;
824
825 /* one more byte for null terminator ending the string! */
826 state->data_size++;
827
828 /* update offset. */
829 state->offset = offset;
830
831 return 0;
832}
833
834json_weak int is_valid_unquoted_key_char(const char c);
835int is_valid_unquoted_key_char(const char c) {
836 return (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') ||
837 ('A' <= c && c <= 'Z') || ('_' == c));
838}
839
840json_weak int json_get_key_size(struct json_parse_state_s *state);
841int json_get_key_size(struct json_parse_state_s *state) {
842 const size_t flags_bitset = state->flags_bitset;
843
844 if (json_parse_flags_allow_unquoted_keys & flags_bitset) {
845 size_t offset = state->offset;
846 const size_t size = state->size;
847 const char *const src = state->src;
848 size_t data_size = state->data_size;
849
850 /* if we are allowing unquoted keys, first grok for a quote... */
851 if ('"' == src[offset]) {
852 /* ... if we got a comma, just parse the key as a string as normal. */
853 return json_get_string_size(state, 1);
854 } else if ((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&
855 ('\'' == src[offset])) {
856 /* ... if we got a comma, just parse the key as a string as normal. */
857 return json_get_string_size(state, 1);
858 } else {
859 while ((offset < size) && is_valid_unquoted_key_char(src[offset])) {
860 offset++;
861 data_size++;
862 }
863
864 /* one more byte for null terminator ending the string! */
865 data_size++;
866
867 if (json_parse_flags_allow_location_information & flags_bitset) {
868 state->dom_size += sizeof(struct json_string_ex_s);
869 } else {
870 state->dom_size += sizeof(struct json_string_s);
871 }
872
873 /* update offset. */
874 state->offset = offset;
875
876 /* update data_size. */
877 state->data_size = data_size;
878
879 return 0;
880 }
881 } else {
882 /* we are only allowed to have quoted keys, so just parse a string! */
883 return json_get_string_size(state, 1);
884 }
885}
886
887json_weak int json_get_object_size(struct json_parse_state_s *state,
888 int is_global_object);
889int json_get_object_size(struct json_parse_state_s *state,
890 int is_global_object) {
891 const size_t flags_bitset = state->flags_bitset;
892 const char *const src = state->src;
893 const size_t size = state->size;
894 size_t elements = 0;
895 int allow_comma = 0;
896 int found_closing_brace = 0;
897
898 if (is_global_object) {
899 /* if we found an opening '{' of an object, we actually have a normal JSON
900 * object at the root of the DOM... */
901 if (!json_skip_all_skippables(state) && '{' == state->src[state->offset]) {
902 /* . and we don't actually have a global object after all! */
903 is_global_object = 0;
904 }
905 }
906
907 if (!is_global_object) {
908 if ('{' != src[state->offset]) {
909 state->error = json_parse_error_unknown;
910 return 1;
911 }
912
913 /* skip leading '{'. */
914 state->offset++;
915 }
916
917 state->dom_size += sizeof(struct json_object_s);
918
919 if ((state->offset == size) && !is_global_object) {
920 state->error = json_parse_error_premature_end_of_buffer;
921 return 1;
922 }
923
924 do {
925 if (!is_global_object) {
926 if (json_skip_all_skippables(state)) {
927 state->error = json_parse_error_premature_end_of_buffer;
928 return 1;
929 }
930
931 if ('}' == src[state->offset]) {
932 /* skip trailing '}'. */
933 state->offset++;
934
935 found_closing_brace = 1;
936
937 /* finished the object! */
938 break;
939 }
940 } else {
941 /* we don't require brackets, so that means the object ends when the input
942 * stream ends! */
943 if (json_skip_all_skippables(state)) {
944 break;
945 }
946 }
947
948 /* if we parsed at least once element previously, grok for a comma. */
949 if (allow_comma) {
950 if (',' == src[state->offset]) {
951 /* skip comma. */
952 state->offset++;
953 allow_comma = 0;
954 } else if (json_parse_flags_allow_no_commas & flags_bitset) {
955 /* we don't require a comma, and we didn't find one, which is ok! */
956 allow_comma = 0;
957 } else {
958 /* otherwise we are required to have a comma, and we found none. */
959 state->error = json_parse_error_expected_comma_or_closing_bracket;
960 return 1;
961 }
962
963 if (json_parse_flags_allow_trailing_comma & flags_bitset) {
964 continue;
965 } else {
966 if (json_skip_all_skippables(state)) {
967 state->error = json_parse_error_premature_end_of_buffer;
968 return 1;
969 }
970 }
971 }
972
973 if (json_get_key_size(state)) {
974 /* key parsing failed! */
975 state->error = json_parse_error_invalid_string;
976 return 1;
977 }
978
979 if (json_skip_all_skippables(state)) {
980 state->error = json_parse_error_premature_end_of_buffer;
981 return 1;
982 }
983
984 if (json_parse_flags_allow_equals_in_object & flags_bitset) {
985 const char current = src[state->offset];
986 if ((':' != current) && ('=' != current)) {
987 state->error = json_parse_error_expected_colon;
988 return 1;
989 }
990 } else {
991 if (':' != src[state->offset]) {
992 state->error = json_parse_error_expected_colon;
993 return 1;
994 }
995 }
996
997 /* skip colon. */
998 state->offset++;
999
1000 if (json_skip_all_skippables(state)) {
1001 state->error = json_parse_error_premature_end_of_buffer;
1002 return 1;
1003 }
1004
1005 if (json_get_value_size(state, /* is_global_object = */ 0)) {
1006 /* value parsing failed! */
1007 return 1;
1008 }
1009
1010 /* successfully parsed a name/value pair! */
1011 elements++;
1012 allow_comma = 1;
1013 } while (state->offset < size);
1014
1015 if ((state->offset == size) && !is_global_object && !found_closing_brace) {
1016 state->error = json_parse_error_premature_end_of_buffer;
1017 return 1;
1018 }
1019
1020 state->dom_size += sizeof(struct json_object_element_s) * elements;
1021
1022 return 0;
1023}
1024
1025json_weak int json_get_array_size(struct json_parse_state_s *state);
1026int json_get_array_size(struct json_parse_state_s *state) {
1027 const size_t flags_bitset = state->flags_bitset;
1028 size_t elements = 0;
1029 int allow_comma = 0;
1030 const char *const src = state->src;
1031 const size_t size = state->size;
1032
1033 if ('[' != src[state->offset]) {
1034 /* expected array to begin with leading '['. */
1035 state->error = json_parse_error_unknown;
1036 return 1;
1037 }
1038
1039 /* skip leading '['. */
1040 state->offset++;
1041
1042 state->dom_size += sizeof(struct json_array_s);
1043
1044 while (state->offset < size) {
1045 if (json_skip_all_skippables(state)) {
1046 state->error = json_parse_error_premature_end_of_buffer;
1047 return 1;
1048 }
1049
1050 if (']' == src[state->offset]) {
1051 /* skip trailing ']'. */
1052 state->offset++;
1053
1054 state->dom_size += sizeof(struct json_array_element_s) * elements;
1055
1056 /* finished the object! */
1057 return 0;
1058 }
1059
1060 /* if we parsed at least once element previously, grok for a comma. */
1061 if (allow_comma) {
1062 if (',' == src[state->offset]) {
1063 /* skip comma. */
1064 state->offset++;
1065 allow_comma = 0;
1066 } else if (!(json_parse_flags_allow_no_commas & flags_bitset)) {
1067 state->error = json_parse_error_expected_comma_or_closing_bracket;
1068 return 1;
1069 }
1070
1071 if (json_parse_flags_allow_trailing_comma & flags_bitset) {
1072 allow_comma = 0;
1073 continue;
1074 } else {
1075 if (json_skip_all_skippables(state)) {
1076 state->error = json_parse_error_premature_end_of_buffer;
1077 return 1;
1078 }
1079 }
1080 }
1081
1082 if (json_get_value_size(state, /* is_global_object = */ 0)) {
1083 /* value parsing failed! */
1084 return 1;
1085 }
1086
1087 /* successfully parsed an array element! */
1088 elements++;
1089 allow_comma = 1;
1090 }
1091
1092 /* we consumed the entire input before finding the closing ']' of the array!
1093 */
1094 state->error = json_parse_error_premature_end_of_buffer;
1095 return 1;
1096}
1097
1098json_weak int json_get_number_size(struct json_parse_state_s *state);
1099int json_get_number_size(struct json_parse_state_s *state) {
1100 const size_t flags_bitset = state->flags_bitset;
1101 size_t offset = state->offset;
1102 const size_t size = state->size;
1103 int had_leading_digits = 0;
1104 const char *const src = state->src;
1105
1106 state->dom_size += sizeof(struct json_number_s);
1107
1108 if ((json_parse_flags_allow_hexadecimal_numbers & flags_bitset) &&
1109 (offset + 1 < size) && ('0' == src[offset]) &&
1110 (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {
1111 /* skip the leading 0x that identifies a hexadecimal number. */
1112 offset += 2;
1113
1114 /* consume hexadecimal digits. */
1115 while ((offset < size) && (('0' <= src[offset] && src[offset] <= '9') ||
1116 ('a' <= src[offset] && src[offset] <= 'f') ||
1117 ('A' <= src[offset] && src[offset] <= 'F'))) {
1118 offset++;
1119 }
1120 } else {
1121 int found_sign = 0;
1122 int inf_or_nan = 0;
1123
1124 if ((offset < size) &&
1125 (('-' == src[offset]) ||
1126 ((json_parse_flags_allow_leading_plus_sign & flags_bitset) &&
1127 ('+' == src[offset])))) {
1128 /* skip valid leading '-' or '+'. */
1129 offset++;
1130
1131 found_sign = 1;
1132 }
1133
1134 if (json_parse_flags_allow_inf_and_nan & flags_bitset) {
1135 const char inf[9] = "Infinity";
1136 const size_t inf_strlen = sizeof(inf) - 1;
1137 const char nan[4] = "NaN";
1138 const size_t nan_strlen = sizeof(nan) - 1;
1139
1140 if (offset + inf_strlen < size) {
1141 int found = 1;
1142 size_t i;
1143 for (i = 0; i < inf_strlen; i++) {
1144 if (inf[i] != src[offset + i]) {
1145 found = 0;
1146 break;
1147 }
1148 }
1149
1150 if (found) {
1151 /* We found our special 'Infinity' keyword! */
1152 offset += inf_strlen;
1153
1154 inf_or_nan = 1;
1155 }
1156 }
1157
1158 if (offset + nan_strlen < size) {
1159 int found = 1;
1160 size_t i;
1161 for (i = 0; i < nan_strlen; i++) {
1162 if (nan[i] != src[offset + i]) {
1163 found = 0;
1164 break;
1165 }
1166 }
1167
1168 if (found) {
1169 /* We found our special 'NaN' keyword! */
1170 offset += nan_strlen;
1171
1172 inf_or_nan = 1;
1173 }
1174 }
1175 }
1176
1177 if (found_sign && !inf_or_nan && (offset < size) &&
1178 !('0' <= src[offset] && src[offset] <= '9')) {
1179 /* check if we are allowing leading '.'. */
1180 if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &
1181 flags_bitset) ||
1182 ('.' != src[offset])) {
1183 /* a leading '-' must be immediately followed by any digit! */
1184 state->error = json_parse_error_invalid_number_format;
1185 state->offset = offset;
1186 return 1;
1187 }
1188 }
1189
1190 if ((offset < size) && ('0' == src[offset])) {
1191 /* skip valid '0'. */
1192 offset++;
1193
1194 /* we need to record whether we had any leading digits for checks later.
1195 */
1196 had_leading_digits = 1;
1197
1198 if ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
1199 /* a leading '0' must not be immediately followed by any digit! */
1200 state->error = json_parse_error_invalid_number_format;
1201 state->offset = offset;
1202 return 1;
1203 }
1204 }
1205
1206 /* the main digits of our number next. */
1207 while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
1208 offset++;
1209
1210 /* we need to record whether we had any leading digits for checks later.
1211 */
1212 had_leading_digits = 1;
1213 }
1214
1215 if ((offset < size) && ('.' == src[offset])) {
1216 offset++;
1217
1218 if (!('0' <= src[offset] && src[offset] <= '9')) {
1219 if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &
1220 flags_bitset) ||
1221 !had_leading_digits) {
1222 /* a decimal point must be followed by at least one digit. */
1223 state->error = json_parse_error_invalid_number_format;
1224 state->offset = offset;
1225 return 1;
1226 }
1227 }
1228
1229 /* a decimal point can be followed by more digits of course! */
1230 while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
1231 offset++;
1232 }
1233 }
1234
1235 if ((offset < size) && ('e' == src[offset] || 'E' == src[offset])) {
1236 /* our number has an exponent! Skip 'e' or 'E'. */
1237 offset++;
1238
1239 if ((offset < size) && ('-' == src[offset] || '+' == src[offset])) {
1240 /* skip optional '-' or '+'. */
1241 offset++;
1242 }
1243
1244 if ((offset < size) && !('0' <= src[offset] && src[offset] <= '9')) {
1245 /* an exponent must have at least one digit! */
1246 state->error = json_parse_error_invalid_number_format;
1247 state->offset = offset;
1248 return 1;
1249 }
1250
1251 /* consume exponent digits. */
1252 do {
1253 offset++;
1254 } while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9'));
1255 }
1256 }
1257
1258 if (offset < size) {
1259 switch (src[offset]) {
1260 case ' ':
1261 case '\t':
1262 case '\r':
1263 case '\n':
1264 case '}':
1265 case ',':
1266 case ']':
1267 /* all of the above are ok. */
1268 break;
1269 case '=':
1270 if (json_parse_flags_allow_equals_in_object & flags_bitset) {
1271 break;
1272 }
1273
1274 state->error = json_parse_error_invalid_number_format;
1275 state->offset = offset;
1276 return 1;
1277 default:
1278 state->error = json_parse_error_invalid_number_format;
1279 state->offset = offset;
1280 return 1;
1281 }
1282 }
1283
1284 state->data_size += offset - state->offset;
1285
1286 /* one more byte for null terminator ending the number string! */
1287 state->data_size++;
1288
1289 /* update offset. */
1290 state->offset = offset;
1291
1292 return 0;
1293}
1294
1295json_weak int json_get_value_size(struct json_parse_state_s *state,
1296 int is_global_object);
1297int json_get_value_size(struct json_parse_state_s *state,
1298 int is_global_object) {
1299 const size_t flags_bitset = state->flags_bitset;
1300 const char *const src = state->src;
1301 size_t offset;
1302 const size_t size = state->size;
1303
1304 if (json_parse_flags_allow_location_information & flags_bitset) {
1305 state->dom_size += sizeof(struct json_value_ex_s);
1306 } else {
1307 state->dom_size += sizeof(struct json_value_s);
1308 }
1309
1310 if (is_global_object) {
1311 return json_get_object_size(state, /* is_global_object = */ 1);
1312 } else {
1313 if (json_skip_all_skippables(state)) {
1314 state->error = json_parse_error_premature_end_of_buffer;
1315 return 1;
1316 }
1317
1318 /* can cache offset now. */
1319 offset = state->offset;
1320
1321 switch (src[offset]) {
1322 case '"':
1323 return json_get_string_size(state, 0);
1324 case '\'':
1325 if (json_parse_flags_allow_single_quoted_strings & flags_bitset) {
1326 return json_get_string_size(state, 0);
1327 } else {
1328 /* invalid value! */
1329 state->error = json_parse_error_invalid_value;
1330 return 1;
1331 }
1332 case '{':
1333 return json_get_object_size(state, /* is_global_object = */ 0);
1334 case '[':
1335 return json_get_array_size(state);
1336 case '-':
1337 case '0':
1338 case '1':
1339 case '2':
1340 case '3':
1341 case '4':
1342 case '5':
1343 case '6':
1344 case '7':
1345 case '8':
1346 case '9':
1347 return json_get_number_size(state);
1348 case '+':
1349 if (json_parse_flags_allow_leading_plus_sign & flags_bitset) {
1350 return json_get_number_size(state);
1351 } else {
1352 /* invalid value! */
1353 state->error = json_parse_error_invalid_number_format;
1354 return 1;
1355 }
1356 case '.':
1357 if (json_parse_flags_allow_leading_or_trailing_decimal_point &
1358 flags_bitset) {
1359 return json_get_number_size(state);
1360 } else {
1361 /* invalid value! */
1362 state->error = json_parse_error_invalid_number_format;
1363 return 1;
1364 }
1365 default:
1366 if ((offset + 4) <= size && 't' == src[offset + 0] &&
1367 'r' == src[offset + 1] && 'u' == src[offset + 2] &&
1368 'e' == src[offset + 3]) {
1369 state->offset += 4;
1370 return 0;
1371 } else if ((offset + 5) <= size && 'f' == src[offset + 0] &&
1372 'a' == src[offset + 1] && 'l' == src[offset + 2] &&
1373 's' == src[offset + 3] && 'e' == src[offset + 4]) {
1374 state->offset += 5;
1375 return 0;
1376 } else if ((offset + 4) <= size && 'n' == state->src[offset + 0] &&
1377 'u' == state->src[offset + 1] &&
1378 'l' == state->src[offset + 2] &&
1379 'l' == state->src[offset + 3]) {
1380 state->offset += 4;
1381 return 0;
1382 } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1383 (offset + 3) <= size && 'N' == src[offset + 0] &&
1384 'a' == src[offset + 1] && 'N' == src[offset + 2]) {
1385 return json_get_number_size(state);
1386 } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1387 (offset + 8) <= size && 'I' == src[offset + 0] &&
1388 'n' == src[offset + 1] && 'f' == src[offset + 2] &&
1389 'i' == src[offset + 3] && 'n' == src[offset + 4] &&
1390 'i' == src[offset + 5] && 't' == src[offset + 6] &&
1391 'y' == src[offset + 7]) {
1392 return json_get_number_size(state);
1393 }
1394
1395 /* invalid value! */
1396 state->error = json_parse_error_invalid_value;
1397 return 1;
1398 }
1399 }
1400}
1401
1402json_weak void json_parse_value(struct json_parse_state_s *state,
1403 int is_global_object,
1404 struct json_value_s *value);
1405
1406json_weak void json_parse_string(struct json_parse_state_s *state,
1407 struct json_string_s *string);
1408void json_parse_string(struct json_parse_state_s *state,
1409 struct json_string_s *string) {
1410 size_t offset = state->offset;
1411 size_t bytes_written = 0;
1412 const char *const src = state->src;
1413 const char quote_to_use = '\'' == src[offset] ? '\'' : '"';
1414 char *data = state->data;
1415 unsigned long high_surrogate = 0;
1416 unsigned long codepoint;
1417
1418 string->string = data;
1419
1420 /* skip leading '"' or '\''. */
1421 offset++;
1422
1423 while (quote_to_use != src[offset]) {
1424 if ('\\' == src[offset]) {
1425 /* skip the reverse solidus. */
1426 offset++;
1427
1428 switch (src[offset++]) {
1429 default:
1430 return; /* we cannot ever reach here. */
1431 case 'u': {
1432 codepoint = 0;
1433 if (!json_hexadecimal_value(&src[offset], 4, &codepoint)) {
1434 return; /* this shouldn't happen as the value was already validated.
1435 */
1436 }
1437
1438 offset += 4;
1439
1440 if (codepoint <= 0x7fu) {
1441 data[bytes_written++] = (char)codepoint; /* 0xxxxxxx. */
1442 } else if (codepoint <= 0x7ffu) {
1443 data[bytes_written++] =
1444 (char)(0xc0u | (codepoint >> 6)); /* 110xxxxx. */
1445 data[bytes_written++] =
1446 (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
1447 } else if (codepoint >= 0xd800 &&
1448 codepoint <= 0xdbff) { /* high surrogate. */
1449 high_surrogate = codepoint;
1450 continue; /* we need the low half to form a complete codepoint. */
1451 } else if (codepoint >= 0xdc00 &&
1452 codepoint <= 0xdfff) { /* low surrogate. */
1453 /* combine with the previously read half to obtain the complete
1454 * codepoint. */
1455 const unsigned long surrogate_offset =
1456 0x10000u - (0xD800u << 10) - 0xDC00u;
1457 codepoint = (high_surrogate << 10) + codepoint + surrogate_offset;
1458 high_surrogate = 0;
1459 data[bytes_written++] =
1460 (char)(0xF0u | (codepoint >> 18)); /* 11110xxx. */
1461 data[bytes_written++] =
1462 (char)(0x80u | ((codepoint >> 12) & 0x3fu)); /* 10xxxxxx. */
1463 data[bytes_written++] =
1464 (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */
1465 data[bytes_written++] =
1466 (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
1467 } else {
1468 /* we assume the value was validated and thus is within the valid
1469 * range. */
1470 data[bytes_written++] =
1471 (char)(0xe0u | (codepoint >> 12)); /* 1110xxxx. */
1472 data[bytes_written++] =
1473 (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */
1474 data[bytes_written++] =
1475 (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
1476 }
1477 } break;
1478 case '"':
1479 data[bytes_written++] = '"';
1480 break;
1481 case '\\':
1482 data[bytes_written++] = '\\';
1483 break;
1484 case '/':
1485 data[bytes_written++] = '/';
1486 break;
1487 case 'b':
1488 data[bytes_written++] = '\b';
1489 break;
1490 case 'f':
1491 data[bytes_written++] = '\f';
1492 break;
1493 case 'n':
1494 data[bytes_written++] = '\n';
1495 break;
1496 case 'r':
1497 data[bytes_written++] = '\r';
1498 break;
1499 case 't':
1500 data[bytes_written++] = '\t';
1501 break;
1502 case '\r':
1503 data[bytes_written++] = '\r';
1504
1505 /* check if we have a "\r\n" sequence. */
1506 if ('\n' == src[offset]) {
1507 data[bytes_written++] = '\n';
1508 offset++;
1509 }
1510
1511 break;
1512 case '\n':
1513 data[bytes_written++] = '\n';
1514 break;
1515 }
1516 } else {
1517 /* copy the character. */
1518 data[bytes_written++] = src[offset++];
1519 }
1520 }
1521
1522 /* skip trailing '"' or '\''. */
1523 offset++;
1524
1525 /* record the size of the string. */
1526 string->string_size = bytes_written;
1527
1528 /* add null terminator to string. */
1529 data[bytes_written++] = '\0';
1530
1531 /* move data along. */
1532 state->data += bytes_written;
1533
1534 /* update offset. */
1535 state->offset = offset;
1536}
1537
1538json_weak void json_parse_key(struct json_parse_state_s *state,
1539 struct json_string_s *string);
1540void json_parse_key(struct json_parse_state_s *state,
1541 struct json_string_s *string) {
1542 if (json_parse_flags_allow_unquoted_keys & state->flags_bitset) {
1543 const char *const src = state->src;
1544 char *const data = state->data;
1545 size_t offset = state->offset;
1546
1547 /* if we are allowing unquoted keys, check for quoted anyway... */
1548 if (('"' == src[offset]) || ('\'' == src[offset])) {
1549 /* ... if we got a quote, just parse the key as a string as normal. */
1550 json_parse_string(state, string);
1551 } else {
1552 size_t size = 0;
1553
1554 string->string = state->data;
1555
1556 while (is_valid_unquoted_key_char(src[offset])) {
1557 data[size++] = src[offset++];
1558 }
1559
1560 /* add null terminator to string. */
1561 data[size] = '\0';
1562
1563 /* record the size of the string. */
1564 string->string_size = size++;
1565
1566 /* move data along. */
1567 state->data += size;
1568
1569 /* update offset. */
1570 state->offset = offset;
1571 }
1572 } else {
1573 /* we are only allowed to have quoted keys, so just parse a string! */
1574 json_parse_string(state, string);
1575 }
1576}
1577
1578json_weak void json_parse_object(struct json_parse_state_s *state,
1579 int is_global_object,
1580 struct json_object_s *object);
1581void json_parse_object(struct json_parse_state_s *state, int is_global_object,
1582 struct json_object_s *object) {
1583 const size_t flags_bitset = state->flags_bitset;
1584 const size_t size = state->size;
1585 const char *const src = state->src;
1586 size_t elements = 0;
1587 int allow_comma = 0;
1588 struct json_object_element_s *previous = json_null;
1589
1590 if (is_global_object) {
1591 /* if we skipped some whitespace, and then found an opening '{' of an. */
1592 /* object, we actually have a normal JSON object at the root of the DOM...
1593 */
1594 if ('{' == src[state->offset]) {
1595 /* . and we don't actually have a global object after all! */
1596 is_global_object = 0;
1597 }
1598 }
1599
1600 if (!is_global_object) {
1601 /* skip leading '{'. */
1602 state->offset++;
1603 }
1604
1605 (void)json_skip_all_skippables(state);
1606
1607 /* reset elements. */
1608 elements = 0;
1609
1610 while (state->offset < size) {
1611 struct json_object_element_s *element = json_null;
1612 struct json_string_s *string = json_null;
1613 struct json_value_s *value = json_null;
1614
1615 if (!is_global_object) {
1616 (void)json_skip_all_skippables(state);
1617
1618 if ('}' == src[state->offset]) {
1619 /* skip trailing '}'. */
1620 state->offset++;
1621
1622 /* finished the object! */
1623 break;
1624 }
1625 } else {
1626 if (json_skip_all_skippables(state)) {
1627 /* global object ends when the file ends! */
1628 break;
1629 }
1630 }
1631
1632 /* if we parsed at least one element previously, grok for a comma. */
1633 if (allow_comma) {
1634 if (',' == src[state->offset]) {
1635 /* skip comma. */
1636 state->offset++;
1637 allow_comma = 0;
1638 continue;
1639 }
1640 }
1641
1642 element = (struct json_object_element_s *)state->dom;
1643
1644 state->dom += sizeof(struct json_object_element_s);
1645
1646 if (json_null == previous) {
1647 /* this is our first element, so record it in our object. */
1648 object->start = element;
1649 } else {
1650 previous->next = element;
1651 }
1652
1653 previous = element;
1654
1655 if (json_parse_flags_allow_location_information & flags_bitset) {
1656 struct json_string_ex_s *string_ex =
1657 (struct json_string_ex_s *)state->dom;
1658 state->dom += sizeof(struct json_string_ex_s);
1659
1660 string_ex->offset = state->offset;
1661 string_ex->line_no = state->line_no;
1662 string_ex->row_no = state->offset - state->line_offset;
1663
1664 string = &(string_ex->string);
1665 } else {
1666 string = (struct json_string_s *)state->dom;
1667 state->dom += sizeof(struct json_string_s);
1668 }
1669
1670 element->name = string;
1671
1672 (void)json_parse_key(state, string);
1673
1674 (void)json_skip_all_skippables(state);
1675
1676 /* skip colon or equals. */
1677 state->offset++;
1678
1679 (void)json_skip_all_skippables(state);
1680
1681 if (json_parse_flags_allow_location_information & flags_bitset) {
1682 struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;
1683 state->dom += sizeof(struct json_value_ex_s);
1684
1685 value_ex->offset = state->offset;
1686 value_ex->line_no = state->line_no;
1687 value_ex->row_no = state->offset - state->line_offset;
1688
1689 value = &(value_ex->value);
1690 } else {
1691 value = (struct json_value_s *)state->dom;
1692 state->dom += sizeof(struct json_value_s);
1693 }
1694
1695 element->value = value;
1696
1697 json_parse_value(state, /* is_global_object = */ 0, value);
1698
1699 /* successfully parsed a name/value pair! */
1700 elements++;
1701 allow_comma = 1;
1702 }
1703
1704 /* if we had at least one element, end the linked list. */
1705 if (previous) {
1706 previous->next = json_null;
1707 }
1708
1709 if (0 == elements) {
1710 object->start = json_null;
1711 }
1712
1713 object->length = elements;
1714}
1715
1716json_weak void json_parse_array(struct json_parse_state_s *state,
1717 struct json_array_s *array);
1718void json_parse_array(struct json_parse_state_s *state,
1719 struct json_array_s *array) {
1720 const char *const src = state->src;
1721 const size_t size = state->size;
1722 size_t elements = 0;
1723 int allow_comma = 0;
1724 struct json_array_element_s *previous = json_null;
1725
1726 /* skip leading '['. */
1727 state->offset++;
1728
1729 (void)json_skip_all_skippables(state);
1730
1731 /* reset elements. */
1732 elements = 0;
1733
1734 do {
1735 struct json_array_element_s *element = json_null;
1736 struct json_value_s *value = json_null;
1737
1738 (void)json_skip_all_skippables(state);
1739
1740 if (']' == src[state->offset]) {
1741 /* skip trailing ']'. */
1742 state->offset++;
1743
1744 /* finished the array! */
1745 break;
1746 }
1747
1748 /* if we parsed at least one element previously, grok for a comma. */
1749 if (allow_comma) {
1750 if (',' == src[state->offset]) {
1751 /* skip comma. */
1752 state->offset++;
1753 allow_comma = 0;
1754 continue;
1755 }
1756 }
1757
1758 element = (struct json_array_element_s *)state->dom;
1759
1760 state->dom += sizeof(struct json_array_element_s);
1761
1762 if (json_null == previous) {
1763 /* this is our first element, so record it in our array. */
1764 array->start = element;
1765 } else {
1766 previous->next = element;
1767 }
1768
1769 previous = element;
1770
1771 if (json_parse_flags_allow_location_information & state->flags_bitset) {
1772 struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;
1773 state->dom += sizeof(struct json_value_ex_s);
1774
1775 value_ex->offset = state->offset;
1776 value_ex->line_no = state->line_no;
1777 value_ex->row_no = state->offset - state->line_offset;
1778
1779 value = &(value_ex->value);
1780 } else {
1781 value = (struct json_value_s *)state->dom;
1782 state->dom += sizeof(struct json_value_s);
1783 }
1784
1785 element->value = value;
1786
1787 json_parse_value(state, /* is_global_object = */ 0, value);
1788
1789 /* successfully parsed an array element! */
1790 elements++;
1791 allow_comma = 1;
1792 } while (state->offset < size);
1793
1794 /* end the linked list. */
1795 if (previous) {
1796 previous->next = json_null;
1797 }
1798
1799 if (0 == elements) {
1800 array->start = json_null;
1801 }
1802
1803 array->length = elements;
1804}
1805
1806json_weak void json_parse_number(struct json_parse_state_s *state,
1807 struct json_number_s *number);
1808void json_parse_number(struct json_parse_state_s *state,
1809 struct json_number_s *number) {
1810 const size_t flags_bitset = state->flags_bitset;
1811 size_t offset = state->offset;
1812 const size_t size = state->size;
1813 size_t bytes_written = 0;
1814 const char *const src = state->src;
1815 char *data = state->data;
1816
1817 number->number = data;
1818
1819 if (json_parse_flags_allow_hexadecimal_numbers & flags_bitset) {
1820 if (('0' == src[offset]) &&
1821 (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {
1822 /* consume hexadecimal digits. */
1823 while ((offset < size) &&
1824 (('0' <= src[offset] && src[offset] <= '9') ||
1825 ('a' <= src[offset] && src[offset] <= 'f') ||
1826 ('A' <= src[offset] && src[offset] <= 'F') ||
1827 ('x' == src[offset]) || ('X' == src[offset]))) {
1828 data[bytes_written++] = src[offset++];
1829 }
1830 }
1831 }
1832
1833 while (offset < size) {
1834 int end = 0;
1835
1836 switch (src[offset]) {
1837 case '0':
1838 case '1':
1839 case '2':
1840 case '3':
1841 case '4':
1842 case '5':
1843 case '6':
1844 case '7':
1845 case '8':
1846 case '9':
1847 case '.':
1848 case 'e':
1849 case 'E':
1850 case '+':
1851 case '-':
1852 data[bytes_written++] = src[offset++];
1853 break;
1854 default:
1855 end = 1;
1856 break;
1857 }
1858
1859 if (0 != end) {
1860 break;
1861 }
1862 }
1863
1864 if (json_parse_flags_allow_inf_and_nan & flags_bitset) {
1865 const size_t inf_strlen = 8; /* = strlen("Infinity");. */
1866 const size_t nan_strlen = 3; /* = strlen("NaN");. */
1867
1868 if (offset + inf_strlen < size) {
1869 if ('I' == src[offset]) {
1870 size_t i;
1871 /* We found our special 'Infinity' keyword! */
1872 for (i = 0; i < inf_strlen; i++) {
1873 data[bytes_written++] = src[offset++];
1874 }
1875 }
1876 }
1877
1878 if (offset + nan_strlen < size) {
1879 if ('N' == src[offset]) {
1880 size_t i;
1881 /* We found our special 'NaN' keyword! */
1882 for (i = 0; i < nan_strlen; i++) {
1883 data[bytes_written++] = src[offset++];
1884 }
1885 }
1886 }
1887 }
1888
1889 /* record the size of the number. */
1890 number->number_size = bytes_written;
1891 /* add null terminator to number string. */
1892 data[bytes_written++] = '\0';
1893 /* move data along. */
1894 state->data += bytes_written;
1895 /* update offset. */
1896 state->offset = offset;
1897}
1898
1899json_weak void json_parse_value(struct json_parse_state_s *state,
1900 int is_global_object,
1901 struct json_value_s *value);
1902void json_parse_value(struct json_parse_state_s *state, int is_global_object,
1903 struct json_value_s *value) {
1904 const size_t flags_bitset = state->flags_bitset;
1905 const char *const src = state->src;
1906 const size_t size = state->size;
1907 size_t offset;
1908
1909 (void)json_skip_all_skippables(state);
1910
1911 /* cache offset now. */
1912 offset = state->offset;
1913
1914 if (is_global_object) {
1915 value->type = json_type_object;
1916 value->payload = state->dom;
1917 state->dom += sizeof(struct json_object_s);
1918 json_parse_object(state, /* is_global_object = */ 1,
1919 (struct json_object_s *)value->payload);
1920 } else {
1921 switch (src[offset]) {
1922 case '"':
1923 case '\'':
1924 value->type = json_type_string;
1925 value->payload = state->dom;
1926 state->dom += sizeof(struct json_string_s);
1927 json_parse_string(state, (struct json_string_s *)value->payload);
1928 break;
1929 case '{':
1930 value->type = json_type_object;
1931 value->payload = state->dom;
1932 state->dom += sizeof(struct json_object_s);
1933 json_parse_object(state, /* is_global_object = */ 0,
1934 (struct json_object_s *)value->payload);
1935 break;
1936 case '[':
1937 value->type = json_type_array;
1938 value->payload = state->dom;
1939 state->dom += sizeof(struct json_array_s);
1940 json_parse_array(state, (struct json_array_s *)value->payload);
1941 break;
1942 case '-':
1943 case '+':
1944 case '0':
1945 case '1':
1946 case '2':
1947 case '3':
1948 case '4':
1949 case '5':
1950 case '6':
1951 case '7':
1952 case '8':
1953 case '9':
1954 case '.':
1955 value->type = json_type_number;
1956 value->payload = state->dom;
1957 state->dom += sizeof(struct json_number_s);
1958 json_parse_number(state, (struct json_number_s *)value->payload);
1959 break;
1960 default:
1961 if ((offset + 4) <= size && 't' == src[offset + 0] &&
1962 'r' == src[offset + 1] && 'u' == src[offset + 2] &&
1963 'e' == src[offset + 3]) {
1964 value->type = json_type_true;
1965 value->payload = json_null;
1966 state->offset += 4;
1967 } else if ((offset + 5) <= size && 'f' == src[offset + 0] &&
1968 'a' == src[offset + 1] && 'l' == src[offset + 2] &&
1969 's' == src[offset + 3] && 'e' == src[offset + 4]) {
1970 value->type = json_type_false;
1971 value->payload = json_null;
1972 state->offset += 5;
1973 } else if ((offset + 4) <= size && 'n' == src[offset + 0] &&
1974 'u' == src[offset + 1] && 'l' == src[offset + 2] &&
1975 'l' == src[offset + 3]) {
1976 value->type = json_type_null;
1977 value->payload = json_null;
1978 state->offset += 4;
1979 } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1980 (offset + 3) <= size && 'N' == src[offset + 0] &&
1981 'a' == src[offset + 1] && 'N' == src[offset + 2]) {
1982 value->type = json_type_number;
1983 value->payload = state->dom;
1984 state->dom += sizeof(struct json_number_s);
1985 json_parse_number(state, (struct json_number_s *)value->payload);
1986 } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1987 (offset + 8) <= size && 'I' == src[offset + 0] &&
1988 'n' == src[offset + 1] && 'f' == src[offset + 2] &&
1989 'i' == src[offset + 3] && 'n' == src[offset + 4] &&
1990 'i' == src[offset + 5] && 't' == src[offset + 6] &&
1991 'y' == src[offset + 7]) {
1992 value->type = json_type_number;
1993 value->payload = state->dom;
1994 state->dom += sizeof(struct json_number_s);
1995 json_parse_number(state, (struct json_number_s *)value->payload);
1996 }
1997 break;
1998 }
1999 }
2000}
2001
2002struct json_value_s *
2003json_parse_ex(const void *src, size_t src_size, size_t flags_bitset,
2004 void *(*alloc_func_ptr)(void *user_data, size_t size),
2005 void *user_data, struct json_parse_result_s *result) {
2006 struct json_parse_state_s state;
2007 void *allocation;
2008 struct json_value_s *value;
2009 size_t total_size;
2010 int input_error;
2011
2012 if (result) {
2013 result->error = json_parse_error_none;
2014 result->error_offset = 0;
2015 result->error_line_no = 0;
2016 result->error_row_no = 0;
2017 }
2018
2019 if (json_null == src) {
2020 /* invalid src pointer was null! */
2021 return json_null;
2022 }
2023
2024 state.src = (const char *)src;
2025 state.size = src_size;
2026 state.offset = 0;
2027 state.line_no = 1;
2028 state.line_offset = 0;
2029 state.error = json_parse_error_none;
2030 state.dom_size = 0;
2031 state.data_size = 0;
2032 state.flags_bitset = flags_bitset;
2033
2034 input_error = json_get_value_size(
2035 &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset));
2036
2037 if (0 == input_error) {
2038 json_skip_all_skippables(&state);
2039
2040 if (state.offset != state.size) {
2041 /* our parsing didn't have an error, but there are characters remaining in
2042 * the input that weren't part of the JSON! */
2043
2044 state.error = json_parse_error_unexpected_trailing_characters;
2045 input_error = 1;
2046 }
2047 }
2048
2049 if (input_error) {
2050 /* parsing value's size failed (most likely an invalid JSON DOM!). */
2051 if (result) {
2052 result->error = state.error;
2053 result->error_offset = state.offset;
2054 result->error_line_no = state.line_no;
2055 result->error_row_no = state.offset - state.line_offset;
2056 }
2057 return json_null;
2058 }
2059
2060 /* our total allocation is the combination of the dom and data sizes (we. */
2061 /* first encode the structure of the JSON, and then the data referenced by. */
2062 /* the JSON values). */
2063 total_size = state.dom_size + state.data_size;
2064
2065 if (json_null == alloc_func_ptr) {
2066 allocation = malloc(total_size);
2067 } else {
2068 allocation = alloc_func_ptr(user_data, total_size);
2069 }
2070
2071 if (json_null == allocation) {
2072 /* malloc failed! */
2073 if (result) {
2074 result->error = json_parse_error_allocator_failed;
2075 result->error_offset = 0;
2076 result->error_line_no = 0;
2077 result->error_row_no = 0;
2078 }
2079
2080 return json_null;
2081 }
2082
2083 /* reset offset so we can reuse it. */
2084 state.offset = 0;
2085
2086 /* reset the line information so we can reuse it. */
2087 state.line_no = 1;
2088 state.line_offset = 0;
2089
2090 state.dom = (char *)allocation;
2091 state.data = state.dom + state.dom_size;
2092
2093 if (json_parse_flags_allow_location_information & state.flags_bitset) {
2094 struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state.dom;
2095 state.dom += sizeof(struct json_value_ex_s);
2096
2097 value_ex->offset = state.offset;
2098 value_ex->line_no = state.line_no;
2099 value_ex->row_no = state.offset - state.line_offset;
2100
2101 value = &(value_ex->value);
2102 } else {
2103 value = (struct json_value_s *)state.dom;
2104 state.dom += sizeof(struct json_value_s);
2105 }
2106
2107 json_parse_value(
2108 &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset),
2109 value);
2110
2111 return (struct json_value_s *)allocation;
2112}
2113
2114struct json_value_s *json_parse(const void *src, size_t src_size) {
2115 return json_parse_ex(src, src_size, json_parse_flags_default, json_null,
2116 json_null, json_null);
2117}
2118
2120 size_t dom_size;
2121 size_t data_size;
2122};
2123
2124struct json_value_s *json_extract_value(const struct json_value_s *value) {
2125 return json_extract_value_ex(value, json_null, json_null);
2126}
2127
2128json_weak struct json_extract_result_s
2129json_extract_get_number_size(const struct json_number_s *const number);
2130json_weak struct json_extract_result_s
2131json_extract_get_string_size(const struct json_string_s *const string);
2132json_weak struct json_extract_result_s
2133json_extract_get_object_size(const struct json_object_s *const object);
2134json_weak struct json_extract_result_s
2135json_extract_get_array_size(const struct json_array_s *const array);
2136json_weak struct json_extract_result_s
2137json_extract_get_value_size(const struct json_value_s *const value);
2138
2140json_extract_get_number_size(const struct json_number_s *const number) {
2141 struct json_extract_result_s result;
2142 result.dom_size = sizeof(struct json_number_s);
2143 result.data_size = number->number_size;
2144 return result;
2145}
2146
2148json_extract_get_string_size(const struct json_string_s *const string) {
2149 struct json_extract_result_s result;
2150 result.dom_size = sizeof(struct json_string_s);
2151 result.data_size = string->string_size + 1;
2152 return result;
2153}
2154
2156json_extract_get_object_size(const struct json_object_s *const object) {
2157 struct json_extract_result_s result;
2158 size_t i;
2159 const struct json_object_element_s *element = object->start;
2160
2161 result.dom_size = sizeof(struct json_object_s) +
2162 (sizeof(struct json_object_element_s) * object->length);
2163 result.data_size = 0;
2164
2165 for (i = 0; i < object->length; i++) {
2166 const struct json_extract_result_s string_result =
2167 json_extract_get_string_size(element->name);
2168 const struct json_extract_result_s value_result =
2169 json_extract_get_value_size(element->value);
2170
2171 result.dom_size += string_result.dom_size;
2172 result.data_size += string_result.data_size;
2173
2174 result.dom_size += value_result.dom_size;
2175 result.data_size += value_result.data_size;
2176
2177 element = element->next;
2178 }
2179
2180 return result;
2181}
2182
2184json_extract_get_array_size(const struct json_array_s *const array) {
2185 struct json_extract_result_s result;
2186 size_t i;
2187 const struct json_array_element_s *element = array->start;
2188
2189 result.dom_size = sizeof(struct json_array_s) +
2190 (sizeof(struct json_array_element_s) * array->length);
2191 result.data_size = 0;
2192
2193 for (i = 0; i < array->length; i++) {
2194 const struct json_extract_result_s value_result =
2195 json_extract_get_value_size(element->value);
2196
2197 result.dom_size += value_result.dom_size;
2198 result.data_size += value_result.data_size;
2199
2200 element = element->next;
2201 }
2202
2203 return result;
2204}
2205
2207json_extract_get_value_size(const struct json_value_s *const value) {
2208 struct json_extract_result_s result = {0, 0};
2209
2210 switch (value->type) {
2211 default:
2212 break;
2213 case json_type_object:
2214 result = json_extract_get_object_size(
2215 (const struct json_object_s *)value->payload);
2216 break;
2217 case json_type_array:
2218 result = json_extract_get_array_size(
2219 (const struct json_array_s *)value->payload);
2220 break;
2221 case json_type_number:
2222 result = json_extract_get_number_size(
2223 (const struct json_number_s *)value->payload);
2224 break;
2225 case json_type_string:
2226 result = json_extract_get_string_size(
2227 (const struct json_string_s *)value->payload);
2228 break;
2229 }
2230
2231 result.dom_size += sizeof(struct json_value_s);
2232
2233 return result;
2234}
2235
2237 char *dom;
2238 char *data;
2239};
2240
2241json_weak void json_extract_copy_value(struct json_extract_state_s *const state,
2242 const struct json_value_s *const value);
2243void json_extract_copy_value(struct json_extract_state_s *const state,
2244 const struct json_value_s *const value) {
2245 struct json_string_s *string;
2246 struct json_number_s *number;
2247 struct json_object_s *object;
2248 struct json_array_s *array;
2249 struct json_value_s *new_value;
2250
2251 memcpy(state->dom, value, sizeof(struct json_value_s));
2252 new_value = (struct json_value_s *)state->dom;
2253 state->dom += sizeof(struct json_value_s);
2254 new_value->payload = state->dom;
2255
2256 if (json_type_string == value->type) {
2257 memcpy(state->dom, value->payload, sizeof(struct json_string_s));
2258 string = (struct json_string_s *)state->dom;
2259 state->dom += sizeof(struct json_string_s);
2260
2261 memcpy(state->data, string->string, string->string_size + 1);
2262 string->string = state->data;
2263 state->data += string->string_size + 1;
2264 } else if (json_type_number == value->type) {
2265 memcpy(state->dom, value->payload, sizeof(struct json_number_s));
2266 number = (struct json_number_s *)state->dom;
2267 state->dom += sizeof(struct json_number_s);
2268
2269 memcpy(state->data, number->number, number->number_size);
2270 number->number = state->data;
2271 state->data += number->number_size;
2272 } else if (json_type_object == value->type) {
2273 struct json_object_element_s *element;
2274 size_t i;
2275
2276 memcpy(state->dom, value->payload, sizeof(struct json_object_s));
2277 object = (struct json_object_s *)state->dom;
2278 state->dom += sizeof(struct json_object_s);
2279
2280 element = object->start;
2281 object->start = (struct json_object_element_s *)state->dom;
2282
2283 for (i = 0; i < object->length; i++) {
2284 struct json_value_s *previous_value;
2285 struct json_object_element_s *previous_element;
2286
2287 memcpy(state->dom, element, sizeof(struct json_object_element_s));
2288 element = (struct json_object_element_s *)state->dom;
2289 state->dom += sizeof(struct json_object_element_s);
2290
2291 string = element->name;
2292 memcpy(state->dom, string, sizeof(struct json_string_s));
2293 string = (struct json_string_s *)state->dom;
2294 state->dom += sizeof(struct json_string_s);
2295 element->name = string;
2296
2297 memcpy(state->data, string->string, string->string_size + 1);
2298 string->string = state->data;
2299 state->data += string->string_size + 1;
2300
2301 previous_value = element->value;
2302 element->value = (struct json_value_s *)state->dom;
2303 json_extract_copy_value(state, previous_value);
2304
2305 previous_element = element;
2306 element = element->next;
2307
2308 if (element) {
2309 previous_element->next = (struct json_object_element_s *)state->dom;
2310 }
2311 }
2312 } else if (json_type_array == value->type) {
2313 struct json_array_element_s *element;
2314 size_t i;
2315
2316 memcpy(state->dom, value->payload, sizeof(struct json_array_s));
2317 array = (struct json_array_s *)state->dom;
2318 state->dom += sizeof(struct json_array_s);
2319
2320 element = array->start;
2321 array->start = (struct json_array_element_s *)state->dom;
2322
2323 for (i = 0; i < array->length; i++) {
2324 struct json_value_s *previous_value;
2325 struct json_array_element_s *previous_element;
2326
2327 memcpy(state->dom, element, sizeof(struct json_array_element_s));
2328 element = (struct json_array_element_s *)state->dom;
2329 state->dom += sizeof(struct json_array_element_s);
2330
2331 previous_value = element->value;
2332 element->value = (struct json_value_s *)state->dom;
2333 json_extract_copy_value(state, previous_value);
2334
2335 previous_element = element;
2336 element = element->next;
2337
2338 if (element) {
2339 previous_element->next = (struct json_array_element_s *)state->dom;
2340 }
2341 }
2342 }
2343}
2344
2345struct json_value_s *json_extract_value_ex(const struct json_value_s *value,
2346 void *(*alloc_func_ptr)(void *,
2347 size_t),
2348 void *user_data) {
2349 void *allocation;
2350 struct json_extract_result_s result;
2351 struct json_extract_state_s state;
2352 size_t total_size;
2353
2354 if (json_null == value) {
2355 /* invalid value was null! */
2356 return json_null;
2357 }
2358
2359 result = json_extract_get_value_size(value);
2360 total_size = result.dom_size + result.data_size;
2361
2362 if (json_null == alloc_func_ptr) {
2363 allocation = malloc(total_size);
2364 } else {
2365 allocation = alloc_func_ptr(user_data, total_size);
2366 }
2367
2368 state.dom = (char *)allocation;
2369 state.data = state.dom + result.dom_size;
2370
2371 json_extract_copy_value(&state, value);
2372
2373 return (struct json_value_s *)allocation;
2374}
2375
2376struct json_string_s *json_value_as_string(struct json_value_s *const value) {
2377 if (value->type != json_type_string) {
2378 return json_null;
2379 }
2380
2381 return (struct json_string_s *)value->payload;
2382}
2383
2384struct json_number_s *json_value_as_number(struct json_value_s *const value) {
2385 if (value->type != json_type_number) {
2386 return json_null;
2387 }
2388
2389 return (struct json_number_s *)value->payload;
2390}
2391
2392struct json_object_s *json_value_as_object(struct json_value_s *const value) {
2393 if (value->type != json_type_object) {
2394 return json_null;
2395 }
2396
2397 return (struct json_object_s *)value->payload;
2398}
2399
2400struct json_array_s *json_value_as_array(struct json_value_s *const value) {
2401 if (value->type != json_type_array) {
2402 return json_null;
2403 }
2404
2405 return (struct json_array_s *)value->payload;
2406}
2407
2408int json_value_is_true(const struct json_value_s *const value) {
2409 return value->type == json_type_true;
2410}
2411
2412int json_value_is_false(const struct json_value_s *const value) {
2413 return value->type == json_type_false;
2414}
2415
2416int json_value_is_null(const struct json_value_s *const value) {
2417 return value->type == json_type_null;
2418}
2419
2420json_weak int
2421json_write_minified_get_value_size(const struct json_value_s *value,
2422 size_t *size);
2423
2424json_weak int json_write_get_number_size(const struct json_number_s *number,
2425 size_t *size);
2426int json_write_get_number_size(const struct json_number_s *number,
2427 size_t *size) {
2428 json_uintmax_t parsed_number;
2429 size_t i;
2430
2431 if (number->number_size >= 2) {
2432 switch (number->number[1]) {
2433 default:
2434 break;
2435 case 'x':
2436 case 'X':
2437 /* the number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal
2438 * so we have to do extra work to convert it to a non-hexadecimal for JSON
2439 * output. */
2440 parsed_number = json_strtoumax(number->number, json_null, 0);
2441
2442 i = 0;
2443
2444 while (0 != parsed_number) {
2445 parsed_number /= 10;
2446 i++;
2447 }
2448
2449 *size += i;
2450 return 0;
2451 }
2452 }
2453
2454 /* check to see if the number has leading/trailing decimal point. */
2455 i = 0;
2456
2457 /* skip any leading '+' or '-'. */
2458 if ((i < number->number_size) &&
2459 (('+' == number->number[i]) || ('-' == number->number[i]))) {
2460 i++;
2461 }
2462
2463 /* check if we have infinity. */
2464 if ((i < number->number_size) && ('I' == number->number[i])) {
2465 const char *inf = "Infinity";
2466 size_t k;
2467
2468 for (k = i; k < number->number_size; k++) {
2469 const char c = *inf++;
2470
2471 /* Check if we found the Infinity string! */
2472 if ('\0' == c) {
2473 break;
2474 } else if (c != number->number[k]) {
2475 break;
2476 }
2477 }
2478
2479 if ('\0' == *inf) {
2480 /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */
2481 *size += 22;
2482
2483 /* if we had a leading '-' we need to record it in the JSON output. */
2484 if ('-' == number->number[0]) {
2485 *size += 1;
2486 }
2487 }
2488
2489 return 0;
2490 }
2491
2492 /* check if we have nan. */
2493 if ((i < number->number_size) && ('N' == number->number[i])) {
2494 const char *nan = "NaN";
2495 size_t k;
2496
2497 for (k = i; k < number->number_size; k++) {
2498 const char c = *nan++;
2499
2500 /* Check if we found the NaN string! */
2501 if ('\0' == c) {
2502 break;
2503 } else if (c != number->number[k]) {
2504 break;
2505 }
2506 }
2507
2508 if ('\0' == *nan) {
2509 /* NaN becomes 1 because JSON can't support it. */
2510 *size += 1;
2511
2512 return 0;
2513 }
2514 }
2515
2516 /* if we had a leading decimal point. */
2517 if ((i < number->number_size) && ('.' == number->number[i])) {
2518 /* 1 + because we had a leading decimal point. */
2519 *size += 1;
2520 goto cleanup;
2521 }
2522
2523 for (; i < number->number_size; i++) {
2524 const char c = number->number[i];
2525 if (!('0' <= c && c <= '9')) {
2526 break;
2527 }
2528 }
2529
2530 /* if we had a trailing decimal point. */
2531 if ((i + 1 == number->number_size) && ('.' == number->number[i])) {
2532 /* 1 + because we had a trailing decimal point. */
2533 *size += 1;
2534 goto cleanup;
2535 }
2536
2537cleanup:
2538 *size += number->number_size; /* the actual string of the number. */
2539
2540 /* if we had a leading '+' we don't record it in the JSON output. */
2541 if ('+' == number->number[0]) {
2542 *size -= 1;
2543 }
2544
2545 return 0;
2546}
2547
2548json_weak int json_write_get_string_size(const struct json_string_s *string,
2549 size_t *size);
2550int json_write_get_string_size(const struct json_string_s *string,
2551 size_t *size) {
2552 size_t i;
2553 for (i = 0; i < string->string_size; i++) {
2554 switch (string->string[i]) {
2555 case '"':
2556 case '\\':
2557 case '\b':
2558 case '\f':
2559 case '\n':
2560 case '\r':
2561 case '\t':
2562 *size += 2;
2563 break;
2564 default:
2565 *size += 1;
2566 break;
2567 }
2568 }
2569
2570 *size += 2; /* need to encode the surrounding '"' characters. */
2571
2572 return 0;
2573}
2574
2575json_weak int
2576json_write_minified_get_array_size(const struct json_array_s *array,
2577 size_t *size);
2578int json_write_minified_get_array_size(const struct json_array_s *array,
2579 size_t *size) {
2580 struct json_array_element_s *element;
2581
2582 *size += 2; /* '[' and ']'. */
2583
2584 if (1 < array->length) {
2585 *size += array->length - 1; /* ','s seperate each element. */
2586 }
2587
2588 for (element = array->start; json_null != element; element = element->next) {
2589 if (json_write_minified_get_value_size(element->value, size)) {
2590 /* value was malformed! */
2591 return 1;
2592 }
2593 }
2594
2595 return 0;
2596}
2597
2598json_weak int
2599json_write_minified_get_object_size(const struct json_object_s *object,
2600 size_t *size);
2601int json_write_minified_get_object_size(const struct json_object_s *object,
2602 size_t *size) {
2603 struct json_object_element_s *element;
2604
2605 *size += 2; /* '{' and '}'. */
2606
2607 *size += object->length; /* ':'s seperate each name/value pair. */
2608
2609 if (1 < object->length) {
2610 *size += object->length - 1; /* ','s seperate each element. */
2611 }
2612
2613 for (element = object->start; json_null != element; element = element->next) {
2614 if (json_write_get_string_size(element->name, size)) {
2615 /* string was malformed! */
2616 return 1;
2617 }
2618
2619 if (json_write_minified_get_value_size(element->value, size)) {
2620 /* value was malformed! */
2621 return 1;
2622 }
2623 }
2624
2625 return 0;
2626}
2627
2628json_weak int
2629json_write_minified_get_value_size(const struct json_value_s *value,
2630 size_t *size);
2631int json_write_minified_get_value_size(const struct json_value_s *value,
2632 size_t *size) {
2633 switch (value->type) {
2634 default:
2635 /* unknown value type found! */
2636 return 1;
2637 case json_type_number:
2638 return json_write_get_number_size((struct json_number_s *)value->payload,
2639 size);
2640 case json_type_string:
2641 return json_write_get_string_size((struct json_string_s *)value->payload,
2642 size);
2643 case json_type_array:
2644 return json_write_minified_get_array_size(
2645 (struct json_array_s *)value->payload, size);
2646 case json_type_object:
2647 return json_write_minified_get_object_size(
2648 (struct json_object_s *)value->payload, size);
2649 case json_type_true:
2650 *size += 4; /* the string "true". */
2651 return 0;
2652 case json_type_false:
2653 *size += 5; /* the string "false". */
2654 return 0;
2655 case json_type_null:
2656 *size += 4; /* the string "null". */
2657 return 0;
2658 }
2659}
2660
2661json_weak char *json_write_minified_value(const struct json_value_s *value,
2662 char *data);
2663
2664json_weak char *json_write_number(const struct json_number_s *number,
2665 char *data);
2666char *json_write_number(const struct json_number_s *number, char *data) {
2667 json_uintmax_t parsed_number, backup;
2668 size_t i;
2669
2670 if (number->number_size >= 2) {
2671 switch (number->number[1]) {
2672 default:
2673 break;
2674 case 'x':
2675 case 'X':
2676 /* The number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal
2677 * so we have to do extra work to convert it to a non-hexadecimal for JSON
2678 * output. */
2679 parsed_number = json_strtoumax(number->number, json_null, 0);
2680
2681 /* We need a copy of parsed number twice, so take a backup of it. */
2682 backup = parsed_number;
2683
2684 i = 0;
2685
2686 while (0 != parsed_number) {
2687 parsed_number /= 10;
2688 i++;
2689 }
2690
2691 /* Restore parsed_number to its original value stored in the backup. */
2692 parsed_number = backup;
2693
2694 /* Now use backup to take a copy of i, or the length of the string. */
2695 backup = i;
2696
2697 do {
2698 *(data + i - 1) = '0' + (char)(parsed_number % 10);
2699 parsed_number /= 10;
2700 i--;
2701 } while (0 != parsed_number);
2702
2703 data += backup;
2704
2705 return data;
2706 }
2707 }
2708
2709 /* check to see if the number has leading/trailing decimal point. */
2710 i = 0;
2711
2712 /* skip any leading '-'. */
2713 if ((i < number->number_size) &&
2714 (('+' == number->number[i]) || ('-' == number->number[i]))) {
2715 i++;
2716 }
2717
2718 /* check if we have infinity. */
2719 if ((i < number->number_size) && ('I' == number->number[i])) {
2720 const char *inf = "Infinity";
2721 size_t k;
2722
2723 for (k = i; k < number->number_size; k++) {
2724 const char c = *inf++;
2725
2726 /* Check if we found the Infinity string! */
2727 if ('\0' == c) {
2728 break;
2729 } else if (c != number->number[k]) {
2730 break;
2731 }
2732 }
2733
2734 if ('\0' == *inf++) {
2735 const char *dbl_max;
2736
2737 /* if we had a leading '-' we need to record it in the JSON output. */
2738 if ('-' == number->number[0]) {
2739 *data++ = '-';
2740 }
2741
2742 /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */
2743 for (dbl_max = "1.7976931348623158e308"; '\0' != *dbl_max; dbl_max++) {
2744 *data++ = *dbl_max;
2745 }
2746
2747 return data;
2748 }
2749 }
2750
2751 /* check if we have nan. */
2752 if ((i < number->number_size) && ('N' == number->number[i])) {
2753 const char *nan = "NaN";
2754 size_t k;
2755
2756 for (k = i; k < number->number_size; k++) {
2757 const char c = *nan++;
2758
2759 /* Check if we found the NaN string! */
2760 if ('\0' == c) {
2761 break;
2762 } else if (c != number->number[k]) {
2763 break;
2764 }
2765 }
2766
2767 if ('\0' == *nan++) {
2768 /* NaN becomes 0 because JSON can't support it. */
2769 *data++ = '0';
2770 return data;
2771 }
2772 }
2773
2774 /* if we had a leading decimal point. */
2775 if ((i < number->number_size) && ('.' == number->number[i])) {
2776 i = 0;
2777
2778 /* skip any leading '+'. */
2779 if ('+' == number->number[i]) {
2780 i++;
2781 }
2782
2783 /* output the leading '-' if we had one. */
2784 if ('-' == number->number[i]) {
2785 *data++ = '-';
2786 i++;
2787 }
2788
2789 /* insert a '0' to fix the leading decimal point for JSON output. */
2790 *data++ = '0';
2791
2792 /* and output the rest of the number as normal. */
2793 for (; i < number->number_size; i++) {
2794 *data++ = number->number[i];
2795 }
2796
2797 return data;
2798 }
2799
2800 for (; i < number->number_size; i++) {
2801 const char c = number->number[i];
2802 if (!('0' <= c && c <= '9')) {
2803 break;
2804 }
2805 }
2806
2807 /* if we had a trailing decimal point. */
2808 if ((i + 1 == number->number_size) && ('.' == number->number[i])) {
2809 i = 0;
2810
2811 /* skip any leading '+'. */
2812 if ('+' == number->number[i]) {
2813 i++;
2814 }
2815
2816 /* output the leading '-' if we had one. */
2817 if ('-' == number->number[i]) {
2818 *data++ = '-';
2819 i++;
2820 }
2821
2822 /* and output the rest of the number as normal. */
2823 for (; i < number->number_size; i++) {
2824 *data++ = number->number[i];
2825 }
2826
2827 /* insert a '0' to fix the trailing decimal point for JSON output. */
2828 *data++ = '0';
2829
2830 return data;
2831 }
2832
2833 i = 0;
2834
2835 /* skip any leading '+'. */
2836 if ('+' == number->number[i]) {
2837 i++;
2838 }
2839
2840 for (; i < number->number_size; i++) {
2841 *data++ = number->number[i];
2842 }
2843
2844 return data;
2845}
2846
2847json_weak char *json_write_string(const struct json_string_s *string,
2848 char *data);
2849char *json_write_string(const struct json_string_s *string, char *data) {
2850 size_t i;
2851
2852 *data++ = '"'; /* open the string. */
2853
2854 for (i = 0; i < string->string_size; i++) {
2855 switch (string->string[i]) {
2856 case '"':
2857 *data++ = '\\'; /* escape the control character. */
2858 *data++ = '"';
2859 break;
2860 case '\\':
2861 *data++ = '\\'; /* escape the control character. */
2862 *data++ = '\\';
2863 break;
2864 case '\b':
2865 *data++ = '\\'; /* escape the control character. */
2866 *data++ = 'b';
2867 break;
2868 case '\f':
2869 *data++ = '\\'; /* escape the control character. */
2870 *data++ = 'f';
2871 break;
2872 case '\n':
2873 *data++ = '\\'; /* escape the control character. */
2874 *data++ = 'n';
2875 break;
2876 case '\r':
2877 *data++ = '\\'; /* escape the control character. */
2878 *data++ = 'r';
2879 break;
2880 case '\t':
2881 *data++ = '\\'; /* escape the control character. */
2882 *data++ = 't';
2883 break;
2884 default:
2885 *data++ = string->string[i];
2886 break;
2887 }
2888 }
2889
2890 *data++ = '"'; /* close the string. */
2891
2892 return data;
2893}
2894
2895json_weak char *json_write_minified_array(const struct json_array_s *array,
2896 char *data);
2897char *json_write_minified_array(const struct json_array_s *array, char *data) {
2898 struct json_array_element_s *element = json_null;
2899
2900 *data++ = '['; /* open the array. */
2901
2902 for (element = array->start; json_null != element; element = element->next) {
2903 if (element != array->start) {
2904 *data++ = ','; /* ','s seperate each element. */
2905 }
2906
2907 data = json_write_minified_value(element->value, data);
2908
2909 if (json_null == data) {
2910 /* value was malformed! */
2911 return json_null;
2912 }
2913 }
2914
2915 *data++ = ']'; /* close the array. */
2916
2917 return data;
2918}
2919
2920json_weak char *json_write_minified_object(const struct json_object_s *object,
2921 char *data);
2922char *json_write_minified_object(const struct json_object_s *object,
2923 char *data) {
2924 struct json_object_element_s *element = json_null;
2925
2926 *data++ = '{'; /* open the object. */
2927
2928 for (element = object->start; json_null != element; element = element->next) {
2929 if (element != object->start) {
2930 *data++ = ','; /* ','s seperate each element. */
2931 }
2932
2933 data = json_write_string(element->name, data);
2934
2935 if (json_null == data) {
2936 /* string was malformed! */
2937 return json_null;
2938 }
2939
2940 *data++ = ':'; /* ':'s seperate each name/value pair. */
2941
2942 data = json_write_minified_value(element->value, data);
2943
2944 if (json_null == data) {
2945 /* value was malformed! */
2946 return json_null;
2947 }
2948 }
2949
2950 *data++ = '}'; /* close the object. */
2951
2952 return data;
2953}
2954
2955json_weak char *json_write_minified_value(const struct json_value_s *value,
2956 char *data);
2957char *json_write_minified_value(const struct json_value_s *value, char *data) {
2958 switch (value->type) {
2959 default:
2960 /* unknown value type found! */
2961 return json_null;
2962 case json_type_number:
2963 return json_write_number((struct json_number_s *)value->payload, data);
2964 case json_type_string:
2965 return json_write_string((struct json_string_s *)value->payload, data);
2966 case json_type_array:
2967 return json_write_minified_array((struct json_array_s *)value->payload,
2968 data);
2969 case json_type_object:
2970 return json_write_minified_object((struct json_object_s *)value->payload,
2971 data);
2972 case json_type_true:
2973 data[0] = 't';
2974 data[1] = 'r';
2975 data[2] = 'u';
2976 data[3] = 'e';
2977 return data + 4;
2978 case json_type_false:
2979 data[0] = 'f';
2980 data[1] = 'a';
2981 data[2] = 'l';
2982 data[3] = 's';
2983 data[4] = 'e';
2984 return data + 5;
2985 case json_type_null:
2986 data[0] = 'n';
2987 data[1] = 'u';
2988 data[2] = 'l';
2989 data[3] = 'l';
2990 return data + 4;
2991 }
2992}
2993
2994void *json_write_minified(const struct json_value_s *value, size_t *out_size) {
2995 size_t size = 0;
2996 char *data = json_null;
2997 char *data_end = json_null;
2998
2999 if (json_null == value) {
3000 return json_null;
3001 }
3002
3003 if (json_write_minified_get_value_size(value, &size)) {
3004 /* value was malformed! */
3005 return json_null;
3006 }
3007
3008 size += 1; /* for the '\0' null terminating character. */
3009
3010 data = (char *)malloc(size);
3011
3012 if (json_null == data) {
3013 /* malloc failed! */
3014 return json_null;
3015 }
3016
3017 data_end = json_write_minified_value(value, data);
3018
3019 if (json_null == data_end) {
3020 /* bad chi occurred! */
3021 free(data);
3022 return json_null;
3023 }
3024
3025 /* null terminated the string. */
3026 *data_end = '\0';
3027
3028 if (json_null != out_size) {
3029 *out_size = size;
3030 }
3031
3032 return data;
3033}
3034
3035json_weak int json_write_pretty_get_value_size(const struct json_value_s *value,
3036 size_t depth, size_t indent_size,
3037 size_t newline_size,
3038 size_t *size);
3039
3040json_weak int json_write_pretty_get_array_size(const struct json_array_s *array,
3041 size_t depth, size_t indent_size,
3042 size_t newline_size,
3043 size_t *size);
3044int json_write_pretty_get_array_size(const struct json_array_s *array,
3045 size_t depth, size_t indent_size,
3046 size_t newline_size, size_t *size) {
3047 struct json_array_element_s *element;
3048
3049 *size += 1; /* '['. */
3050
3051 if (0 < array->length) {
3052 /* if we have any elements we need to add a newline after our '['. */
3053 *size += newline_size;
3054
3055 *size += array->length - 1; /* ','s seperate each element. */
3056
3057 for (element = array->start; json_null != element;
3058 element = element->next) {
3059 /* each element gets an indent. */
3060 *size += (depth + 1) * indent_size;
3061
3062 if (json_write_pretty_get_value_size(element->value, depth + 1,
3063 indent_size, newline_size, size)) {
3064 /* value was malformed! */
3065 return 1;
3066 }
3067
3068 /* each element gets a newline too. */
3069 *size += newline_size;
3070 }
3071
3072 /* since we wrote out some elements, need to add a newline and indentation.
3073 */
3074 /* to the trailing ']'. */
3075 *size += depth * indent_size;
3076 }
3077
3078 *size += 1; /* ']'. */
3079
3080 return 0;
3081}
3082
3083json_weak int
3084json_write_pretty_get_object_size(const struct json_object_s *object,
3085 size_t depth, size_t indent_size,
3086 size_t newline_size, size_t *size);
3087int json_write_pretty_get_object_size(const struct json_object_s *object,
3088 size_t depth, size_t indent_size,
3089 size_t newline_size, size_t *size) {
3090 struct json_object_element_s *element;
3091
3092 *size += 1; /* '{'. */
3093
3094 if (0 < object->length) {
3095 *size += newline_size; /* need a newline next. */
3096
3097 *size += object->length - 1; /* ','s seperate each element. */
3098
3099 for (element = object->start; json_null != element;
3100 element = element->next) {
3101 /* each element gets an indent and newline. */
3102 *size += (depth + 1) * indent_size;
3103 *size += newline_size;
3104
3105 if (json_write_get_string_size(element->name, size)) {
3106 /* string was malformed! */
3107 return 1;
3108 }
3109
3110 *size += 3; /* seperate each name/value pair with " : ". */
3111
3112 if (json_write_pretty_get_value_size(element->value, depth + 1,
3113 indent_size, newline_size, size)) {
3114 /* value was malformed! */
3115 return 1;
3116 }
3117 }
3118
3119 *size += depth * indent_size;
3120 }
3121
3122 *size += 1; /* '}'. */
3123
3124 return 0;
3125}
3126
3127json_weak int json_write_pretty_get_value_size(const struct json_value_s *value,
3128 size_t depth, size_t indent_size,
3129 size_t newline_size,
3130 size_t *size);
3131int json_write_pretty_get_value_size(const struct json_value_s *value,
3132 size_t depth, size_t indent_size,
3133 size_t newline_size, size_t *size) {
3134 switch (value->type) {
3135 default:
3136 /* unknown value type found! */
3137 return 1;
3138 case json_type_number:
3139 return json_write_get_number_size((struct json_number_s *)value->payload,
3140 size);
3141 case json_type_string:
3142 return json_write_get_string_size((struct json_string_s *)value->payload,
3143 size);
3144 case json_type_array:
3145 return json_write_pretty_get_array_size(
3146 (struct json_array_s *)value->payload, depth, indent_size, newline_size,
3147 size);
3148 case json_type_object:
3149 return json_write_pretty_get_object_size(
3150 (struct json_object_s *)value->payload, depth, indent_size,
3151 newline_size, size);
3152 case json_type_true:
3153 *size += 4; /* the string "true". */
3154 return 0;
3155 case json_type_false:
3156 *size += 5; /* the string "false". */
3157 return 0;
3158 case json_type_null:
3159 *size += 4; /* the string "null". */
3160 return 0;
3161 }
3162}
3163
3164json_weak char *json_write_pretty_value(const struct json_value_s *value,
3165 size_t depth, const char *indent,
3166 const char *newline, char *data);
3167
3168json_weak char *json_write_pretty_array(const struct json_array_s *array,
3169 size_t depth, const char *indent,
3170 const char *newline, char *data);
3171char *json_write_pretty_array(const struct json_array_s *array, size_t depth,
3172 const char *indent, const char *newline,
3173 char *data) {
3174 size_t k, m;
3175 struct json_array_element_s *element;
3176
3177 *data++ = '['; /* open the array. */
3178
3179 if (0 < array->length) {
3180 for (k = 0; '\0' != newline[k]; k++) {
3181 *data++ = newline[k];
3182 }
3183
3184 for (element = array->start; json_null != element;
3185 element = element->next) {
3186 if (element != array->start) {
3187 *data++ = ','; /* ','s seperate each element. */
3188
3189 for (k = 0; '\0' != newline[k]; k++) {
3190 *data++ = newline[k];
3191 }
3192 }
3193
3194 for (k = 0; k < depth + 1; k++) {
3195 for (m = 0; '\0' != indent[m]; m++) {
3196 *data++ = indent[m];
3197 }
3198 }
3199
3200 data = json_write_pretty_value(element->value, depth + 1, indent, newline,
3201 data);
3202
3203 if (json_null == data) {
3204 /* value was malformed! */
3205 return json_null;
3206 }
3207 }
3208
3209 for (k = 0; '\0' != newline[k]; k++) {
3210 *data++ = newline[k];
3211 }
3212
3213 for (k = 0; k < depth; k++) {
3214 for (m = 0; '\0' != indent[m]; m++) {
3215 *data++ = indent[m];
3216 }
3217 }
3218 }
3219
3220 *data++ = ']'; /* close the array. */
3221
3222 return data;
3223}
3224
3225json_weak char *json_write_pretty_object(const struct json_object_s *object,
3226 size_t depth, const char *indent,
3227 const char *newline, char *data);
3228char *json_write_pretty_object(const struct json_object_s *object, size_t depth,
3229 const char *indent, const char *newline,
3230 char *data) {
3231 size_t k, m;
3232 struct json_object_element_s *element;
3233
3234 *data++ = '{'; /* open the object. */
3235
3236 if (0 < object->length) {
3237 for (k = 0; '\0' != newline[k]; k++) {
3238 *data++ = newline[k];
3239 }
3240
3241 for (element = object->start; json_null != element;
3242 element = element->next) {
3243 if (element != object->start) {
3244 *data++ = ','; /* ','s seperate each element. */
3245
3246 for (k = 0; '\0' != newline[k]; k++) {
3247 *data++ = newline[k];
3248 }
3249 }
3250
3251 for (k = 0; k < depth + 1; k++) {
3252 for (m = 0; '\0' != indent[m]; m++) {
3253 *data++ = indent[m];
3254 }
3255 }
3256
3257 data = json_write_string(element->name, data);
3258
3259 if (json_null == data) {
3260 /* string was malformed! */
3261 return json_null;
3262 }
3263
3264 /* " : "s seperate each name/value pair. */
3265 *data++ = ' ';
3266 *data++ = ':';
3267 *data++ = ' ';
3268
3269 data = json_write_pretty_value(element->value, depth + 1, indent, newline,
3270 data);
3271
3272 if (json_null == data) {
3273 /* value was malformed! */
3274 return json_null;
3275 }
3276 }
3277
3278 for (k = 0; '\0' != newline[k]; k++) {
3279 *data++ = newline[k];
3280 }
3281
3282 for (k = 0; k < depth; k++) {
3283 for (m = 0; '\0' != indent[m]; m++) {
3284 *data++ = indent[m];
3285 }
3286 }
3287 }
3288
3289 *data++ = '}'; /* close the object. */
3290
3291 return data;
3292}
3293
3294json_weak char *json_write_pretty_value(const struct json_value_s *value,
3295 size_t depth, const char *indent,
3296 const char *newline, char *data);
3297char *json_write_pretty_value(const struct json_value_s *value, size_t depth,
3298 const char *indent, const char *newline,
3299 char *data) {
3300 switch (value->type) {
3301 default:
3302 /* unknown value type found! */
3303 return json_null;
3304 case json_type_number:
3305 return json_write_number((struct json_number_s *)value->payload, data);
3306 case json_type_string:
3307 return json_write_string((struct json_string_s *)value->payload, data);
3308 case json_type_array:
3309 return json_write_pretty_array((struct json_array_s *)value->payload, depth,
3310 indent, newline, data);
3311 case json_type_object:
3312 return json_write_pretty_object((struct json_object_s *)value->payload,
3313 depth, indent, newline, data);
3314 case json_type_true:
3315 data[0] = 't';
3316 data[1] = 'r';
3317 data[2] = 'u';
3318 data[3] = 'e';
3319 return data + 4;
3320 case json_type_false:
3321 data[0] = 'f';
3322 data[1] = 'a';
3323 data[2] = 'l';
3324 data[3] = 's';
3325 data[4] = 'e';
3326 return data + 5;
3327 case json_type_null:
3328 data[0] = 'n';
3329 data[1] = 'u';
3330 data[2] = 'l';
3331 data[3] = 'l';
3332 return data + 4;
3333 }
3334}
3335
3336void *json_write_pretty(const struct json_value_s *value, const char *indent,
3337 const char *newline, size_t *out_size) {
3338 size_t size = 0;
3339 size_t indent_size = 0;
3340 size_t newline_size = 0;
3341 char *data = json_null;
3342 char *data_end = json_null;
3343
3344 if (json_null == value) {
3345 return json_null;
3346 }
3347
3348 if (json_null == indent) {
3349 indent = " "; /* default to two spaces. */
3350 }
3351
3352 if (json_null == newline) {
3353 newline = "\n"; /* default to linux newlines. */
3354 }
3355
3356 while ('\0' != indent[indent_size]) {
3357 ++indent_size; /* skip non-null terminating characters. */
3358 }
3359
3360 while ('\0' != newline[newline_size]) {
3361 ++newline_size; /* skip non-null terminating characters. */
3362 }
3363
3364 if (json_write_pretty_get_value_size(value, 0, indent_size, newline_size,
3365 &size)) {
3366 /* value was malformed! */
3367 return json_null;
3368 }
3369
3370 size += 1; /* for the '\0' null terminating character. */
3371
3372 data = (char *)malloc(size);
3373
3374 if (json_null == data) {
3375 /* malloc failed! */
3376 return json_null;
3377 }
3378
3379 data_end = json_write_pretty_value(value, 0, indent, newline, data);
3380
3381 if (json_null == data_end) {
3382 /* bad chi occurred! */
3383 free(data);
3384 return json_null;
3385 }
3386
3387 /* null terminated the string. */
3388 *data_end = '\0';
3389
3390 if (json_null != out_size) {
3391 *out_size = size;
3392 }
3393
3394 return data;
3395}
3396
3397#if defined(__clang__)
3398#pragma clang diagnostic pop
3399#elif defined(_MSC_VER)
3400#pragma warning(pop)
3401#endif
3402
3403#endif /* SHEREDOM_JSON_H_INCLUDED. */
T data(T... args)
T end(T... args)
free
typedef char
malloc
memcpy
nan
T size(T... args)
typedef long