2 The latest version of this library is available on GitHub;
3 https://github.com/sheredom/json.h.
7 This is free and unencumbered software released into the public domain.
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
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.
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.
30 For more information, please refer to <http://unlicense.org/>.
33 #ifndef SHEREDOM_JSON_H_INCLUDED
34 #define SHEREDOM_JSON_H_INCLUDED
39 /* disable 'bytes padding added after construct' warning */
40 #pragma warning(disable : 4820)
45 #if defined(__clang__) || defined(__GNUC__)
46 #define json_weak __attribute__((weak))
47 #elif defined(_MSC_VER)
48 #define json_weak __inline
50 #error Non clang, non gcc, non MSVC compiler found!
58 struct json_parse_result_s;
60 enum json_parse_flags_e {
61 json_parse_flags_default = 0,
63 /* allow trailing commas in objects and arrays. For example, both [true,] and
64 {"a" : null,} would be allowed with this option on. */
65 json_parse_flags_allow_trailing_comma = 0x1,
67 /* allow unquoted keys for objects. For example, {a : null} would be allowed
68 with this option on. */
69 json_parse_flags_allow_unquoted_keys = 0x2,
71 /* allow a global unbracketed object. For example, a : null, b : true, c : {}
72 would be allowed with this option on. */
73 json_parse_flags_allow_global_object = 0x4,
75 /* allow objects to use '=' instead of ':' between key/value pairs. For
76 example, a = null, b : true would be allowed with this option on. */
77 json_parse_flags_allow_equals_in_object = 0x8,
79 /* allow that objects don't have to have comma separators between key/value
81 json_parse_flags_allow_no_commas = 0x10,
83 /* allow c-style comments (either variants) to be ignored in the input JSON
85 json_parse_flags_allow_c_style_comments = 0x20,
87 /* deprecated flag, unused. */
88 json_parse_flags_deprecated = 0x40,
90 /* record location information for each value. */
91 json_parse_flags_allow_location_information = 0x80,
93 /* allow strings to be 'single quoted'. */
94 json_parse_flags_allow_single_quoted_strings = 0x100,
96 /* allow numbers to be hexadecimal. */
97 json_parse_flags_allow_hexadecimal_numbers = 0x200,
99 /* allow numbers like +123 to be parsed. */
100 json_parse_flags_allow_leading_plus_sign = 0x400,
102 /* allow numbers like .0123 or 123. to be parsed. */
103 json_parse_flags_allow_leading_or_trailing_decimal_point = 0x800,
105 /* allow Infinity, -Infinity, NaN, -NaN. */
106 json_parse_flags_allow_inf_and_nan = 0x1000,
108 /* allow multi line string values. */
109 json_parse_flags_allow_multi_line_strings = 0x2000,
111 /* allow simplified JSON to be parsed. Simplified JSON is an enabling of a set
112 of other parsing options. */
113 json_parse_flags_allow_simplified_json =
114 (json_parse_flags_allow_trailing_comma |
115 json_parse_flags_allow_unquoted_keys |
116 json_parse_flags_allow_global_object |
117 json_parse_flags_allow_equals_in_object |
118 json_parse_flags_allow_no_commas),
120 /* allow JSON5 to be parsed. JSON5 is an enabling of a set of other parsing
122 json_parse_flags_allow_json5 =
123 (json_parse_flags_allow_trailing_comma |
124 json_parse_flags_allow_unquoted_keys |
125 json_parse_flags_allow_c_style_comments |
126 json_parse_flags_allow_single_quoted_strings |
127 json_parse_flags_allow_hexadecimal_numbers |
128 json_parse_flags_allow_leading_plus_sign |
129 json_parse_flags_allow_leading_or_trailing_decimal_point |
130 json_parse_flags_allow_inf_and_nan |
131 json_parse_flags_allow_multi_line_strings)
134 /* Parse a JSON text file, returning a pointer to the root of the JSON
135 * structure. json_parse performs 1 call to malloc for the entire encoding.
136 * Returns 0 if an error occurred (malformed JSON input, or malloc failed). */
137 json_weak struct json_value_s *json_parse(const void *src, size_t src_size);
139 /* Parse a JSON text file, returning a pointer to the root of the JSON
140 * structure. json_parse performs 1 call to malloc for the entire encoding.
141 * Returns 0 if an error occurred (malformed JSON input, or malloc failed). If
142 * an error occurred, the result struct (if not NULL) will explain the type of
143 * error, and the location in the input it occurred. */
144 json_weak struct json_value_s *
145 json_parse_ex(const void *src, size_t src_size, size_t flags_bitset,
146 void *(*alloc_func_ptr)(void *, size_t), void *user_data,
147 struct json_parse_result_s *result);
149 /* Write out a minified JSON utf-8 string. This string is an encoding of the
150 * minimal string characters required to still encode the same data.
151 * json_write_minified performs 1 call to malloc for the entire encoding. Return
152 * 0 if an error occurred (malformed JSON input, or malloc failed). The out_size
153 * parameter is optional as the utf-8 string is null terminated. */
154 json_weak void *json_write_minified(const struct json_value_s *value,
157 /* Write out a pretty JSON utf-8 string. This string is encoded such that the
158 * resultant JSON is pretty in that it is easily human readable. The indent and
159 * newline parameters allow a user to specify what kind of indentation and
160 * newline they want (two spaces / three spaces / tabs? \r, \n, \r\n ?). Both
161 * indent and newline can be NULL, indent defaults to two spaces (" "), and
162 * newline defaults to linux newlines ('\n' as the newline character).
163 * json_write_pretty performs 1 call to malloc for the entire encoding. Return 0
164 * if an error occurred (malformed JSON input, or malloc failed). The out_size
165 * parameter is optional as the utf-8 string is null terminated. */
166 json_weak void *json_write_pretty(const struct json_value_s *value,
167 const char *indent, const char *newline,
170 /* Reinterpret a JSON value as a string. Returns null is the value was not a
172 json_weak struct json_string_s *
173 json_value_as_string(struct json_value_s *const value);
175 /* Reinterpret a JSON value as a number. Returns null is the value was not a
177 json_weak struct json_number_s *
178 json_value_as_number(struct json_value_s *const value);
180 /* Reinterpret a JSON value as an object. Returns null is the value was not an
182 json_weak struct json_object_s *
183 json_value_as_object(struct json_value_s *const value);
185 /* Reinterpret a JSON value as an array. Returns null is the value was not an
187 json_weak struct json_array_s *
188 json_value_as_array(struct json_value_s *const value);
190 /* Whether the value is true. */
191 json_weak int json_value_is_true(const struct json_value_s *const value);
193 /* Whether the value is false. */
194 json_weak int json_value_is_false(const struct json_value_s *const value);
196 /* Whether the value is null. */
197 json_weak int json_value_is_null(const struct json_value_s *const value);
199 /* The various types JSON values can be. Used to identify what a value is. */
210 /* A JSON string value. */
211 struct json_string_s {
214 /* The size (in bytes) of the string */
218 /* A JSON string value (extended). */
219 struct json_string_ex_s {
220 /* The JSON string this extends. */
221 struct json_string_s string;
223 /* The character offset for the value in the JSON input. */
226 /* The line number for the value in the JSON input. */
229 /* The row number for the value in the JSON input, in bytes. */
233 /* A JSON number value. */
234 struct json_number_s {
235 /* ASCII string containing representation of the number. */
237 /* the size (in bytes) of the number. */
241 /* an element of a JSON object. */
242 struct json_object_element_s {
243 /* the name of this element. */
244 struct json_string_s *name;
245 /* the value of this element. */
246 struct json_value_s *value;
247 /* the next object element (can be NULL if the last element in the object). */
248 struct json_object_element_s *next;
251 /* a JSON object value. */
252 struct json_object_s {
253 /* a linked list of the elements in the object. */
254 struct json_object_element_s *start;
255 /* the number of elements in the object. */
259 /* an element of a JSON array. */
260 struct json_array_element_s {
261 /* the value of this element. */
262 struct json_value_s *value;
263 /* the next array element (can be NULL if the last element in the array). */
264 struct json_array_element_s *next;
267 /* a JSON array value. */
268 struct json_array_s {
269 /* a linked list of the elements in the array. */
270 struct json_array_element_s *start;
271 /* the number of elements in the array. */
276 struct json_value_s {
277 /* a pointer to either a json_string_s, json_number_s, json_object_s, or. */
278 /* json_array_s. Should be cast to the appropriate struct type based on what.
280 /* the type of this value is. */
282 /* must be one of json_type_e. If type is json_type_true, json_type_false, or.
284 /* json_type_null, payload will be NULL. */
288 /* a JSON value (extended). */
289 struct json_value_ex_s {
290 /* the JSON value this extends. */
291 struct json_value_s value;
293 /* the character offset for the value in the JSON input. */
296 /* the line number for the value in the JSON input. */
299 /* the row number for the value in the JSON input, in bytes. */
303 /* a parsing error code. */
304 enum json_parse_error_e {
305 /* no error occurred (huzzah!). */
306 json_parse_error_none = 0,
308 /* expected either a comma or a closing '}' or ']' to close an object or. */
310 json_parse_error_expected_comma_or_closing_bracket,
312 /* colon separating name/value pair was missing! */
313 json_parse_error_expected_colon,
315 /* expected string to begin with '"'! */
316 json_parse_error_expected_opening_quote,
318 /* invalid escaped sequence in string! */
319 json_parse_error_invalid_string_escape_sequence,
321 /* invalid number format! */
322 json_parse_error_invalid_number_format,
325 json_parse_error_invalid_value,
327 /* reached end of buffer before object/array was complete! */
328 json_parse_error_premature_end_of_buffer,
330 /* string was malformed! */
331 json_parse_error_invalid_string,
333 /* a call to malloc, or a user provider allocator, failed. */
334 json_parse_error_allocator_failed,
336 /* the JSON input had unexpected trailing characters that weren't part of the.
339 json_parse_error_unexpected_trailing_characters,
341 /* catch-all error for everything else that exploded (real bad chi!). */
342 json_parse_error_unknown
345 /* error report from json_parse_ex(). */
346 struct json_parse_result_s {
347 /* the error code (one of json_parse_error_e). */
350 /* the character offset for the error in the JSON input. */
353 /* the line number for the error in the JSON input. */
354 size_t error_line_no;
356 /* the row number for the error, in bytes. */
364 #if defined(_MSC_VER)
370 #if defined(_MSC_VER)
371 #define json_strtoumax _strtoui64
372 #define json_uintmax_t unsigned __int64
374 #include <inttypes.h>
375 #define json_strtoumax strtoumax
376 #define json_uintmax_t uintmax_t
379 #if defined(__cplusplus) && (__cplusplus >= 201103L)
380 #define json_null nullptr
385 #if defined(__clang__)
386 #pragma clang diagnostic push
388 /* we do one big allocation via malloc, then cast aligned slices of this for. */
389 /* our structures - we don't have a way to tell the compiler we know what we. */
390 /* are doing, so disable the warning instead! */
391 #pragma clang diagnostic ignored "-Wcast-align"
393 /* We use C style casts everywhere. */
394 #pragma clang diagnostic ignored "-Wold-style-cast"
396 /* We need long long for strtoull. */
397 #pragma clang diagnostic ignored "-Wc++11-long-long"
399 /* Who cares if nullptr doesn't work with C++98, we don't use it there! */
400 #pragma clang diagnostic ignored "-Wc++98-compat"
401 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
402 #elif defined(_MSC_VER)
403 #pragma warning(push)
405 /* disable 'function selected for inline expansion' warning. */
406 #pragma warning(disable : 4711)
408 /* disable '#pragma warning: there is no warning number' warning. */
409 #pragma warning(disable : 4619)
411 /* disable 'warning number not a valid compiler warning' warning. */
412 #pragma warning(disable : 4616)
414 /* disable 'Compiler will insert Spectre mitigation for memory load if
416 /* switch specified' warning. */
417 #pragma warning(disable : 5045)
420 struct json_parse_state_s {
429 size_t line_no; /* line counter for error reporting. */
430 size_t line_offset; /* (offset-line_offset) is the character number (in
435 json_weak int json_hexadecimal_digit(const char c);
436 int json_hexadecimal_digit(const char c) {
437 if ('0' <= c && c <= '9') {
440 if ('a' <= c && c <= 'f') {
443 if ('A' <= c && c <= 'F') {
449 json_weak int json_hexadecimal_value(const char * c, const unsigned long size, unsigned long * result);
450 int json_hexadecimal_value(const char * c, const unsigned long size, unsigned long * result) {
454 if (size > sizeof(unsigned long) * 2) {
459 for (p = c; (unsigned long)(p - c) < size; ++p) {
461 digit = json_hexadecimal_digit(*p);
462 if (digit < 0 || digit > 15) {
465 *result |= (unsigned char)digit;
470 json_weak int json_skip_whitespace(struct json_parse_state_s *state);
471 int json_skip_whitespace(struct json_parse_state_s *state) {
472 size_t offset = state->offset;
473 const size_t size = state->size;
474 const char *const src = state->src;
476 /* the only valid whitespace according to ECMA-404 is ' ', '\n', '\r' and
478 switch (src[offset]) {
489 switch (src[offset]) {
492 state->offset = offset;
500 state->line_offset = offset;
505 } while (offset < size);
508 state->offset = offset;
512 json_weak int json_skip_c_style_comments(struct json_parse_state_s *state);
513 int json_skip_c_style_comments(struct json_parse_state_s *state) {
514 /* do we have a comment?. */
515 if ('/' == state->src[state->offset]) {
519 if ('/' == state->src[state->offset]) {
520 /* we had a comment of the form //. */
522 /* skip second '/'. */
525 while (state->offset < state->size) {
526 switch (state->src[state->offset]) {
528 /* skip the character in the comment. */
532 /* if we have a newline, our comment has ended! Skip the newline. */
535 /* we entered a newline, so move our line info forward. */
537 state->line_offset = state->offset;
542 /* we reached the end of the JSON file! */
545 else if ('*' == state->src[state->offset]) {
546 /* we had a comment in the C-style long form. */
551 while (state->offset + 1 < state->size) {
552 if (('*' == state->src[state->offset]) &&
553 ('/' == state->src[state->offset + 1])) {
554 /* we reached the end of our comment! */
558 else if ('\n' == state->src[state->offset]) {
559 /* we entered a newline, so move our line info forward. */
561 state->line_offset = state->offset;
564 /* skip character within comment. */
568 /* Comment wasn't ended correctly which is a failure. */
573 /* we didn't have any comment, which is ok too! */
577 json_weak int json_skip_all_skippables(struct json_parse_state_s *state);
578 int json_skip_all_skippables(struct json_parse_state_s *state) {
579 /* skip all whitespace and other skippables until there are none left. note
580 * that the previous version suffered from read past errors should. the
581 * stream end on json_skip_c_style_comments eg. '{"a" ' with comments flag.
585 const size_t size = state->size;
587 if (json_parse_flags_allow_c_style_comments & state->flags_bitset) {
589 if (state->offset == size) {
590 state->error = json_parse_error_premature_end_of_buffer;
594 did_consume = json_skip_whitespace(state);
596 /* This should really be checked on access, not in front of every call.
598 if (state->offset == size) {
599 state->error = json_parse_error_premature_end_of_buffer;
603 did_consume |= json_skip_c_style_comments(state);
604 } while (0 != did_consume);
608 if (state->offset == size) {
609 state->error = json_parse_error_premature_end_of_buffer;
613 did_consume = json_skip_whitespace(state);
614 } while (0 != did_consume);
617 if (state->offset == size) {
618 state->error = json_parse_error_premature_end_of_buffer;
625 json_weak int json_get_value_size(struct json_parse_state_s *state,
626 int is_global_object);
628 json_weak int json_get_string_size(struct json_parse_state_s *state,
630 int json_get_string_size(struct json_parse_state_s *state,
632 size_t offset = state->offset;
633 const size_t size = state->size;
634 size_t data_size = 0;
635 const char *const src = state->src;
636 const int is_single_quote = '\'' == src[offset];
637 const char quote_to_use = is_single_quote ? '\'' : '"';
638 const size_t flags_bitset = state->flags_bitset;
639 unsigned long codepoint;
640 unsigned long high_surrogate = 0;
642 if ((json_parse_flags_allow_location_information & flags_bitset) != 0 &&
644 state->dom_size += sizeof(struct json_string_ex_s);
647 state->dom_size += sizeof(struct json_string_s);
650 if ('"' != src[offset]) {
651 /* if we are allowed single quoted strings check for that too. */
652 if (!((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&
654 state->error = json_parse_error_expected_opening_quote;
655 state->offset = offset;
660 /* skip leading '"' or '\''. */
663 while ((offset < size) && (quote_to_use != src[offset])) {
664 /* add space for the character. */
667 if ('\\' == src[offset]) {
668 /* skip reverse solidus character. */
671 if (offset == size) {
672 state->error = json_parse_error_premature_end_of_buffer;
673 state->offset = offset;
677 switch (src[offset]) {
679 state->error = json_parse_error_invalid_string_escape_sequence;
680 state->offset = offset;
690 /* all valid characters! */
694 if (!(offset + 5 < size)) {
695 /* invalid escaped unicode sequence! */
696 state->error = json_parse_error_invalid_string_escape_sequence;
697 state->offset = offset;
702 if (!json_hexadecimal_value(&src[offset + 1], 4, &codepoint)) {
703 /* escaped unicode sequences must contain 4 hexadecimal digits! */
704 state->error = json_parse_error_invalid_string_escape_sequence;
705 state->offset = offset;
710 * see: https://en.wikipedia.org/wiki/UTF-8#Invalid_code_points.
711 * 1 7 U + 0000 U + 007F 0xxxxxxx.
712 * 2 11 U + 0080 U + 07FF 110xxxxx
714 * 3 16 U + 0800 U + FFFF 1110xxxx
716 * 4 21 U + 10000 U + 10FFFF 11110xxx
717 * 10xxxxxx 10xxxxxx 10xxxxxx.
718 * Note: the high and low surrogate halves used by UTF-16 (U+D800
719 * through U+DFFF) and code points not encodable by UTF-16 (those after
720 * U+10FFFF) are not legal Unicode values, and their UTF-8 encoding must
721 * be treated as an invalid byte sequence. */
723 if (high_surrogate != 0) {
724 /* we previously read the high half of the \uxxxx\uxxxx pair, so now
725 * we expect the low half. */
726 if (codepoint >= 0xdc00 &&
727 codepoint <= 0xdfff) { /* low surrogate range. */
732 state->error = json_parse_error_invalid_string_escape_sequence;
733 state->offset = offset;
737 else if (codepoint <= 0x7f) {
740 else if (codepoint <= 0x7ff) {
743 else if (codepoint >= 0xd800 &&
744 codepoint <= 0xdbff) { /* high surrogate range. */
745 /* The codepoint is the first half of a "utf-16 surrogate pair". so we
746 * need the other half for it to be valid: \uHHHH\uLLLL. */
747 if (offset + 11 > size || '\\' != src[offset + 5] ||
748 'u' != src[offset + 6]) {
749 state->error = json_parse_error_invalid_string_escape_sequence;
750 state->offset = offset;
753 high_surrogate = codepoint;
755 else if (codepoint >= 0xd800 &&
756 codepoint <= 0xdfff) { /* low surrogate range. */
757 /* we did not read the other half before. */
758 state->error = json_parse_error_invalid_string_escape_sequence;
759 state->offset = offset;
765 /* escaped codepoints after 0xffff are supported in json through utf-16
766 * surrogate pairs: \uD83D\uDD25 for U+1F525. */
772 else if (('\r' == src[offset]) || ('\n' == src[offset])) {
773 if (!(json_parse_flags_allow_multi_line_strings & flags_bitset)) {
774 /* invalid escaped unicode sequence! */
775 state->error = json_parse_error_invalid_string_escape_sequence;
776 state->offset = offset;
783 /* skip character (valid part of sequence). */
788 /* skip trailing '"' or '\''. */
791 /* add enough space to store the string. */
792 state->data_size += data_size;
794 /* one more byte for null terminator ending the string! */
798 state->offset = offset;
803 json_weak int is_valid_unquoted_key_char(const char c);
804 int is_valid_unquoted_key_char(const char c) {
805 return (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') ||
806 ('A' <= c && c <= 'Z') || ('_' == c));
809 json_weak int json_get_key_size(struct json_parse_state_s *state);
810 int json_get_key_size(struct json_parse_state_s *state) {
811 const size_t flags_bitset = state->flags_bitset;
813 if (json_parse_flags_allow_unquoted_keys & flags_bitset) {
814 size_t offset = state->offset;
815 const size_t size = state->size;
816 const char *const src = state->src;
817 size_t data_size = state->data_size;
819 /* if we are allowing unquoted keys, first grok for a quote... */
820 if ('"' == src[offset]) {
821 /* ... if we got a comma, just parse the key as a string as normal. */
822 return json_get_string_size(state, 1);
824 else if ((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&
825 ('\'' == src[offset])) {
826 /* ... if we got a comma, just parse the key as a string as normal. */
827 return json_get_string_size(state, 1);
830 while ((offset < size) && is_valid_unquoted_key_char(src[offset])) {
835 /* one more byte for null terminator ending the string! */
838 if (json_parse_flags_allow_location_information & flags_bitset) {
839 state->dom_size += sizeof(struct json_string_ex_s);
842 state->dom_size += sizeof(struct json_string_s);
846 state->offset = offset;
848 /* update data_size. */
849 state->data_size = data_size;
855 /* we are only allowed to have quoted keys, so just parse a string! */
856 return json_get_string_size(state, 1);
860 json_weak int json_get_object_size(struct json_parse_state_s *state,
861 int is_global_object);
862 int json_get_object_size(struct json_parse_state_s *state,
863 int is_global_object) {
864 const size_t flags_bitset = state->flags_bitset;
865 const char *const src = state->src;
866 const size_t size = state->size;
870 if (is_global_object) {
871 /* if we found an opening '{' of an object, we actually have a normal JSON
872 * object at the root of the DOM... */
873 if (!json_skip_all_skippables(state) && '{' == state->src[state->offset]) {
874 /* . and we don't actually have a global object after all! */
875 is_global_object = 0;
879 if (!is_global_object) {
880 if ('{' != src[state->offset]) {
881 state->error = json_parse_error_unknown;
885 /* skip leading '{'. */
889 state->dom_size += sizeof(struct json_object_s);
891 while (state->offset < size) {
892 if (!is_global_object) {
893 if (json_skip_all_skippables(state)) {
894 state->error = json_parse_error_premature_end_of_buffer;
897 if ('}' == src[state->offset]) {
898 /* skip trailing '}'. */
901 /* finished the object! */
906 /* we don't require brackets, so that means the object ends when the input
908 if (json_skip_all_skippables(state)) {
913 /* if we parsed at least once element previously, grok for a comma. */
915 if (',' == src[state->offset]) {
920 else if (json_parse_flags_allow_no_commas & flags_bitset) {
921 /* we don't require a comma, and we didn't find one, which is ok! */
925 /* otherwise we are required to have a comma, and we found none. */
926 state->error = json_parse_error_expected_comma_or_closing_bracket;
930 if (json_parse_flags_allow_trailing_comma & flags_bitset) {
934 if (json_skip_all_skippables(state)) {
935 state->error = json_parse_error_premature_end_of_buffer;
941 if (json_get_key_size(state)) {
942 /* key parsing failed! */
943 state->error = json_parse_error_invalid_string;
947 if (json_skip_all_skippables(state)) {
948 state->error = json_parse_error_premature_end_of_buffer;
952 if (json_parse_flags_allow_equals_in_object & flags_bitset) {
953 const char current = src[state->offset];
954 if ((':' != current) && ('=' != current)) {
955 state->error = json_parse_error_expected_colon;
960 if (':' != src[state->offset]) {
961 state->error = json_parse_error_expected_colon;
969 if (json_skip_all_skippables(state)) {
970 state->error = json_parse_error_premature_end_of_buffer;
974 if (json_get_value_size(state, /* is_global_object = */ 0)) {
975 /* value parsing failed! */
979 /* successfully parsed a name/value pair! */
984 state->dom_size += sizeof(struct json_object_element_s) * elements;
989 json_weak int json_get_array_size(struct json_parse_state_s *state);
990 int json_get_array_size(struct json_parse_state_s *state) {
991 const size_t flags_bitset = state->flags_bitset;
994 const char *const src = state->src;
995 const size_t size = state->size;
997 if ('[' != src[state->offset]) {
998 /* expected array to begin with leading '['. */
999 state->error = json_parse_error_unknown;
1003 /* skip leading '['. */
1006 state->dom_size += sizeof(struct json_array_s);
1008 while (state->offset < size) {
1009 if (json_skip_all_skippables(state)) {
1010 state->error = json_parse_error_premature_end_of_buffer;
1014 if (']' == src[state->offset]) {
1015 /* skip trailing ']'. */
1018 state->dom_size += sizeof(struct json_array_element_s) * elements;
1020 /* finished the object! */
1024 /* if we parsed at least once element previously, grok for a comma. */
1026 if (',' == src[state->offset]) {
1031 else if (!(json_parse_flags_allow_no_commas & flags_bitset)) {
1032 state->error = json_parse_error_expected_comma_or_closing_bracket;
1036 if (json_parse_flags_allow_trailing_comma & flags_bitset) {
1041 if (json_skip_all_skippables(state)) {
1042 state->error = json_parse_error_premature_end_of_buffer;
1048 if (json_get_value_size(state, /* is_global_object = */ 0)) {
1049 /* value parsing failed! */
1053 /* successfully parsed an array element! */
1058 /* we consumed the entire input before finding the closing ']' of the array!
1060 state->error = json_parse_error_premature_end_of_buffer;
1064 json_weak int json_get_number_size(struct json_parse_state_s *state);
1065 int json_get_number_size(struct json_parse_state_s *state) {
1066 const size_t flags_bitset = state->flags_bitset;
1067 size_t offset = state->offset;
1068 const size_t size = state->size;
1069 int had_leading_digits = 0;
1070 const char *const src = state->src;
1072 state->dom_size += sizeof(struct json_number_s);
1074 if ((json_parse_flags_allow_hexadecimal_numbers & flags_bitset) &&
1075 (offset + 1 < size) && ('0' == src[offset]) &&
1076 (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {
1077 /* skip the leading 0x that identifies a hexadecimal number. */
1080 /* consume hexadecimal digits. */
1081 while ((offset < size) && (('0' <= src[offset] && src[offset] <= '9') ||
1082 ('a' <= src[offset] && src[offset] <= 'f') ||
1083 ('A' <= src[offset] && src[offset] <= 'F'))) {
1091 if ((offset < size) &&
1092 (('-' == src[offset]) ||
1093 ((json_parse_flags_allow_leading_plus_sign & flags_bitset) &&
1094 ('+' == src[offset])))) {
1095 /* skip valid leading '-' or '+'. */
1101 if (json_parse_flags_allow_inf_and_nan & flags_bitset) {
1102 const char inf[9] = "Infinity";
1103 const size_t inf_strlen = sizeof(inf) - 1;
1104 const char nan[4] = "NaN";
1105 const size_t nan_strlen = sizeof(nan) - 1;
1107 if (offset + inf_strlen < size) {
1110 for (i = 0; i < inf_strlen; i++) {
1111 if (inf[i] != src[offset + i]) {
1118 /* We found our special 'Infinity' keyword! */
1119 offset += inf_strlen;
1125 if (offset + nan_strlen < size) {
1128 for (i = 0; i < nan_strlen; i++) {
1129 if (nan[i] != src[offset + i]) {
1136 /* We found our special 'NaN' keyword! */
1137 offset += nan_strlen;
1144 if (found_sign && !inf_or_nan && (offset < size) &&
1145 !('0' <= src[offset] && src[offset] <= '9')) {
1146 /* check if we are allowing leading '.'. */
1147 if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &
1149 ('.' != src[offset])) {
1150 /* a leading '-' must be immediately followed by any digit! */
1151 state->error = json_parse_error_invalid_number_format;
1152 state->offset = offset;
1157 if ((offset < size) && ('0' == src[offset])) {
1158 /* skip valid '0'. */
1161 /* we need to record whether we had any leading digits for checks later.
1163 had_leading_digits = 1;
1165 if ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
1166 /* a leading '0' must not be immediately followed by any digit! */
1167 state->error = json_parse_error_invalid_number_format;
1168 state->offset = offset;
1173 /* the main digits of our number next. */
1174 while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
1177 /* we need to record whether we had any leading digits for checks later.
1179 had_leading_digits = 1;
1182 if ((offset < size) && ('.' == src[offset])) {
1185 if (!('0' <= src[offset] && src[offset] <= '9')) {
1186 if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &
1188 !had_leading_digits) {
1189 /* a decimal point must be followed by at least one digit. */
1190 state->error = json_parse_error_invalid_number_format;
1191 state->offset = offset;
1196 /* a decimal point can be followed by more digits of course! */
1197 while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
1202 if ((offset < size) && ('e' == src[offset] || 'E' == src[offset])) {
1203 /* our number has an exponent! Wkip 'e' or 'E'. */
1206 if ((offset < size) && ('-' == src[offset] || '+' == src[offset])) {
1207 /* skip optional '-' or '+'. */
1211 /* consume exponent digits. */
1212 while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {
1218 if (offset < size) {
1219 switch (src[offset]) {
1227 /* all of the above are ok. */
1230 if (json_parse_flags_allow_equals_in_object & flags_bitset) {
1234 state->error = json_parse_error_invalid_number_format;
1235 state->offset = offset;
1238 state->error = json_parse_error_invalid_number_format;
1239 state->offset = offset;
1244 state->data_size += offset - state->offset;
1246 /* one more byte for null terminator ending the number string! */
1249 /* update offset. */
1250 state->offset = offset;
1255 json_weak int json_get_value_size(struct json_parse_state_s *state,
1256 int is_global_object);
1257 int json_get_value_size(struct json_parse_state_s *state,
1258 int is_global_object) {
1259 const size_t flags_bitset = state->flags_bitset;
1260 const char *const src = state->src;
1262 const size_t size = state->size;
1264 if (json_parse_flags_allow_location_information & flags_bitset) {
1265 state->dom_size += sizeof(struct json_value_ex_s);
1268 state->dom_size += sizeof(struct json_value_s);
1271 if (is_global_object) {
1272 return json_get_object_size(state, /* is_global_object = */ 1);
1275 if (json_skip_all_skippables(state)) {
1276 state->error = json_parse_error_premature_end_of_buffer;
1280 /* can cache offset now. */
1281 offset = state->offset;
1283 switch (src[offset]) {
1285 return json_get_string_size(state, 0);
1287 if (json_parse_flags_allow_single_quoted_strings & flags_bitset) {
1288 return json_get_string_size(state, 0);
1291 /* invalid value! */
1292 state->error = json_parse_error_invalid_value;
1296 return json_get_object_size(state, /* is_global_object = */ 0);
1298 return json_get_array_size(state);
1310 return json_get_number_size(state);
1312 if (json_parse_flags_allow_leading_plus_sign & flags_bitset) {
1313 return json_get_number_size(state);
1316 /* invalid value! */
1317 state->error = json_parse_error_invalid_number_format;
1321 if (json_parse_flags_allow_leading_or_trailing_decimal_point &
1323 return json_get_number_size(state);
1326 /* invalid value! */
1327 state->error = json_parse_error_invalid_number_format;
1331 if ((offset + 4) <= size && 't' == src[offset + 0] &&
1332 'r' == src[offset + 1] && 'u' == src[offset + 2] &&
1333 'e' == src[offset + 3]) {
1337 else if ((offset + 5) <= size && 'f' == src[offset + 0] &&
1338 'a' == src[offset + 1] && 'l' == src[offset + 2] &&
1339 's' == src[offset + 3] && 'e' == src[offset + 4]) {
1343 else if ((offset + 4) <= size && 'n' == state->src[offset + 0] &&
1344 'u' == state->src[offset + 1] &&
1345 'l' == state->src[offset + 2] &&
1346 'l' == state->src[offset + 3]) {
1350 else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1351 (offset + 3) <= size && 'N' == src[offset + 0] &&
1352 'a' == src[offset + 1] && 'N' == src[offset + 2]) {
1353 return json_get_number_size(state);
1355 else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1356 (offset + 8) <= size && 'I' == src[offset + 0] &&
1357 'n' == src[offset + 1] && 'f' == src[offset + 2] &&
1358 'i' == src[offset + 3] && 'n' == src[offset + 4] &&
1359 'i' == src[offset + 5] && 't' == src[offset + 6] &&
1360 'y' == src[offset + 7]) {
1361 return json_get_number_size(state);
1364 /* invalid value! */
1365 state->error = json_parse_error_invalid_value;
1371 json_weak void json_parse_value(struct json_parse_state_s *state,
1372 int is_global_object, struct json_value_s *value);
1374 json_weak void json_parse_string(struct json_parse_state_s *state,
1375 struct json_string_s *string);
1376 void json_parse_string(struct json_parse_state_s *state,
1377 struct json_string_s *string) {
1378 size_t offset = state->offset;
1379 size_t bytes_written = 0;
1380 const char *const src = state->src;
1381 const char quote_to_use = '\'' == src[offset] ? '\'' : '"';
1382 char *data = state->data;
1383 unsigned long high_surrogate = 0;
1384 unsigned long codepoint;
1386 string->string = data;
1388 /* skip leading '"' or '\''. */
1391 while (quote_to_use != src[offset]) {
1392 if ('\\' == src[offset]) {
1393 /* skip the reverse solidus. */
1396 switch (src[offset++]) {
1398 return; /* we cannot ever reach here. */
1401 if (!json_hexadecimal_value(&src[offset], 4, &codepoint)) {
1402 return; /* this shouldn't happen as the value was already validated.
1408 if (codepoint <= 0x7fu) {
1409 data[bytes_written++] = (char)codepoint; /* 0xxxxxxx. */
1411 else if (codepoint <= 0x7ffu) {
1412 data[bytes_written++] =
1413 (char)(0xc0u | (codepoint >> 6)); /* 110xxxxx. */
1414 data[bytes_written++] =
1415 (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
1417 else if (codepoint >= 0xd800 &&
1418 codepoint <= 0xdbff) { /* high surrogate. */
1419 high_surrogate = codepoint;
1420 continue; /* we need the low half to form a complete codepoint. */
1422 else if (codepoint >= 0xdc00 &&
1423 codepoint <= 0xdfff) { /* low surrogate. */
1424 /* combine with the previously read half to obtain the complete
1426 const unsigned long surrogate_offset = 0x10000u - (0xD800u << 10) - 0xDC00u;
1427 codepoint = (high_surrogate << 10) + codepoint + surrogate_offset;
1429 data[bytes_written++] =
1430 (char)(0xF0u | (codepoint >> 18)); /* 11110xxx. */
1431 data[bytes_written++] =
1432 (char)(0x80u | ((codepoint >> 12) & 0x3fu)); /* 10xxxxxx. */
1433 data[bytes_written++] =
1434 (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */
1435 data[bytes_written++] =
1436 (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
1439 /* we assume the value was validated and thus is within the valid
1441 data[bytes_written++] =
1442 (char)(0xe0u | (codepoint >> 12)); /* 1110xxxx. */
1443 data[bytes_written++] =
1444 (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */
1445 data[bytes_written++] =
1446 (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */
1450 data[bytes_written++] = '"';
1453 data[bytes_written++] = '\\';
1456 data[bytes_written++] = '/';
1459 data[bytes_written++] = '\b';
1462 data[bytes_written++] = '\f';
1465 data[bytes_written++] = '\n';
1468 data[bytes_written++] = '\r';
1471 data[bytes_written++] = '\t';
1474 data[bytes_written++] = '\r';
1476 /* check if we have a "\r\n" sequence. */
1477 if ('\n' == src[offset]) {
1478 data[bytes_written++] = '\n';
1484 data[bytes_written++] = '\n';
1489 /* copy the character. */
1490 data[bytes_written++] = src[offset++];
1494 /* skip trailing '"' or '\''. */
1497 /* record the size of the string. */
1498 string->string_size = bytes_written;
1500 /* add null terminator to string. */
1501 data[bytes_written++] = '\0';
1503 /* move data along. */
1504 state->data += bytes_written;
1506 /* update offset. */
1507 state->offset = offset;
1510 json_weak void json_parse_key(struct json_parse_state_s *state,
1511 struct json_string_s *string);
1512 void json_parse_key(struct json_parse_state_s *state,
1513 struct json_string_s *string) {
1514 if (json_parse_flags_allow_unquoted_keys & state->flags_bitset) {
1515 const char *const src = state->src;
1516 char *const data = state->data;
1517 size_t offset = state->offset;
1519 /* if we are allowing unquoted keys, check for quoted anyway... */
1520 if (('"' == src[offset]) || ('\'' == src[offset])) {
1521 /* ... if we got a quote, just parse the key as a string as normal. */
1522 json_parse_string(state, string);
1527 string->string = state->data;
1529 while (is_valid_unquoted_key_char(src[offset])) {
1530 data[size++] = src[offset++];
1533 /* add null terminator to string. */
1536 /* record the size of the string. */
1537 string->string_size = size++;
1539 /* move data along. */
1540 state->data += size;
1542 /* update offset. */
1543 state->offset = offset;
1547 /* we are only allowed to have quoted keys, so just parse a string! */
1548 json_parse_string(state, string);
1552 json_weak void json_parse_object(struct json_parse_state_s *state,
1553 int is_global_object,
1554 struct json_object_s *object);
1555 void json_parse_object(struct json_parse_state_s *state,
1556 int is_global_object,
1557 struct json_object_s *object) {
1558 const size_t flags_bitset = state->flags_bitset;
1559 const size_t size = state->size;
1560 const char *const src = state->src;
1561 size_t elements = 0;
1562 int allow_comma = 0;
1563 struct json_object_element_s *previous = json_null;
1565 if (is_global_object) {
1566 /* if we skipped some whitespace, and then found an opening '{' of an. */
1567 /* object, we actually have a normal JSON object at the root of the DOM...
1569 if ('{' == src[state->offset]) {
1570 /* . and we don't actually have a global object after all! */
1571 is_global_object = 0;
1575 if (!is_global_object) {
1576 /* skip leading '{'. */
1580 (void)json_skip_all_skippables(state);
1582 /* reset elements. */
1585 while (state->offset < size) {
1586 struct json_object_element_s *element = json_null;
1587 struct json_string_s *string = json_null;
1588 struct json_value_s *value = json_null;
1590 if (!is_global_object) {
1591 (void)json_skip_all_skippables(state);
1593 if ('}' == src[state->offset]) {
1594 /* skip trailing '}'. */
1597 /* finished the object! */
1602 if (json_skip_all_skippables(state)) {
1603 /* global object ends when the file ends! */
1608 /* if we parsed at least one element previously, grok for a comma. */
1610 if (',' == src[state->offset]) {
1618 element = (struct json_object_element_s *)state->dom;
1620 state->dom += sizeof(struct json_object_element_s);
1622 if (json_null == previous) {
1623 /* this is our first element, so record it in our object. */
1624 object->start = element;
1627 previous->next = element;
1632 if (json_parse_flags_allow_location_information & flags_bitset) {
1633 struct json_string_ex_s *string_ex =
1634 (struct json_string_ex_s *)state->dom;
1635 state->dom += sizeof(struct json_string_ex_s);
1637 string_ex->offset = state->offset;
1638 string_ex->line_no = state->line_no;
1639 string_ex->row_no = state->offset - state->line_offset;
1641 string = &(string_ex->string);
1644 string = (struct json_string_s *)state->dom;
1645 state->dom += sizeof(struct json_string_s);
1648 element->name = string;
1650 (void)json_parse_key(state, string);
1652 (void)json_skip_all_skippables(state);
1654 /* skip colon or equals. */
1657 (void)json_skip_all_skippables(state);
1659 if (json_parse_flags_allow_location_information & flags_bitset) {
1660 struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;
1661 state->dom += sizeof(struct json_value_ex_s);
1663 value_ex->offset = state->offset;
1664 value_ex->line_no = state->line_no;
1665 value_ex->row_no = state->offset - state->line_offset;
1667 value = &(value_ex->value);
1670 value = (struct json_value_s *)state->dom;
1671 state->dom += sizeof(struct json_value_s);
1674 element->value = value;
1676 json_parse_value(state, /* is_global_object = */ 0, value);
1678 /* successfully parsed a name/value pair! */
1683 /* if we had at least one element, end the linked list. */
1685 previous->next = json_null;
1688 if (0 == elements) {
1689 object->start = json_null;
1692 object->length = elements;
1695 json_weak void json_parse_array(struct json_parse_state_s *state,
1696 struct json_array_s *array);
1697 void json_parse_array(struct json_parse_state_s *state,
1698 struct json_array_s *array) {
1699 const char *const src = state->src;
1700 const size_t size = state->size;
1701 size_t elements = 0;
1702 int allow_comma = 0;
1703 struct json_array_element_s *previous = json_null;
1705 /* skip leading '['. */
1708 (void)json_skip_all_skippables(state);
1710 /* reset elements. */
1714 struct json_array_element_s *element = json_null;
1715 struct json_value_s *value = json_null;
1717 (void)json_skip_all_skippables(state);
1719 if (']' == src[state->offset]) {
1720 /* skip trailing ']'. */
1723 /* finished the array! */
1727 /* if we parsed at least one element previously, grok for a comma. */
1729 if (',' == src[state->offset]) {
1737 element = (struct json_array_element_s *)state->dom;
1739 state->dom += sizeof(struct json_array_element_s);
1741 if (json_null == previous) {
1742 /* this is our first element, so record it in our array. */
1743 array->start = element;
1746 previous->next = element;
1751 if (json_parse_flags_allow_location_information & state->flags_bitset) {
1752 struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;
1753 state->dom += sizeof(struct json_value_ex_s);
1755 value_ex->offset = state->offset;
1756 value_ex->line_no = state->line_no;
1757 value_ex->row_no = state->offset - state->line_offset;
1759 value = &(value_ex->value);
1762 value = (struct json_value_s *)state->dom;
1763 state->dom += sizeof(struct json_value_s);
1766 element->value = value;
1768 json_parse_value(state, /* is_global_object = */ 0, value);
1770 /* successfully parsed an array element! */
1773 } while (state->offset < size);
1775 /* end the linked list. */
1777 previous->next = json_null;
1780 if (0 == elements) {
1781 array->start = json_null;
1784 array->length = elements;
1787 json_weak void json_parse_number(struct json_parse_state_s *state,
1788 struct json_number_s *number);
1789 void json_parse_number(struct json_parse_state_s *state,
1790 struct json_number_s *number) {
1791 const size_t flags_bitset = state->flags_bitset;
1792 size_t offset = state->offset;
1793 const size_t size = state->size;
1794 size_t bytes_written = 0;
1795 const char *const src = state->src;
1796 char *data = state->data;
1798 number->number = data;
1800 if (json_parse_flags_allow_hexadecimal_numbers & flags_bitset) {
1801 if (('0' == src[offset]) &&
1802 (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {
1803 /* consume hexadecimal digits. */
1804 while ((offset < size) &&
1805 (('0' <= src[offset] && src[offset] <= '9') ||
1806 ('a' <= src[offset] && src[offset] <= 'f') ||
1807 ('A' <= src[offset] && src[offset] <= 'F') ||
1808 ('x' == src[offset]) || ('X' == src[offset]))) {
1809 data[bytes_written++] = src[offset++];
1814 while (offset < size) {
1817 switch (src[offset]) {
1833 data[bytes_written++] = src[offset++];
1845 if (json_parse_flags_allow_inf_and_nan & flags_bitset) {
1846 const size_t inf_strlen = 8; /* = strlen("Infinity");. */
1847 const size_t nan_strlen = 3; /* = strlen("NaN");. */
1849 if (offset + inf_strlen < size) {
1850 if ('I' == src[offset]) {
1852 /* We found our special 'Infinity' keyword! */
1853 for (i = 0; i < inf_strlen; i++) {
1854 data[bytes_written++] = src[offset++];
1859 if (offset + nan_strlen < size) {
1860 if ('N' == src[offset]) {
1862 /* We found our special 'NaN' keyword! */
1863 for (i = 0; i < nan_strlen; i++) {
1864 data[bytes_written++] = src[offset++];
1870 /* record the size of the number. */
1871 number->number_size = bytes_written;
1872 /* add null terminator to number string. */
1873 data[bytes_written++] = '\0';
1874 /* move data along. */
1875 state->data += bytes_written;
1876 /* update offset. */
1877 state->offset = offset;
1880 json_weak void json_parse_value(struct json_parse_state_s *state,
1881 int is_global_object, struct json_value_s *value);
1882 void json_parse_value(struct json_parse_state_s *state,
1883 int is_global_object, struct json_value_s *value) {
1884 const size_t flags_bitset = state->flags_bitset;
1885 const char *const src = state->src;
1886 const size_t size = state->size;
1889 (void)json_skip_all_skippables(state);
1891 /* cache offset now. */
1892 offset = state->offset;
1894 if (is_global_object) {
1895 value->type = json_type_object;
1896 value->payload = state->dom;
1897 state->dom += sizeof(struct json_object_s);
1898 json_parse_object(state, /* is_global_object = */ 1,
1899 (struct json_object_s *)value->payload);
1902 switch (src[offset]) {
1905 value->type = json_type_string;
1906 value->payload = state->dom;
1907 state->dom += sizeof(struct json_string_s);
1908 json_parse_string(state, (struct json_string_s *)value->payload);
1911 value->type = json_type_object;
1912 value->payload = state->dom;
1913 state->dom += sizeof(struct json_object_s);
1914 json_parse_object(state, /* is_global_object = */ 0,
1915 (struct json_object_s *)value->payload);
1918 value->type = json_type_array;
1919 value->payload = state->dom;
1920 state->dom += sizeof(struct json_array_s);
1921 json_parse_array(state, (struct json_array_s *)value->payload);
1936 value->type = json_type_number;
1937 value->payload = state->dom;
1938 state->dom += sizeof(struct json_number_s);
1939 json_parse_number(state, (struct json_number_s *)value->payload);
1942 if ((offset + 4) <= size && 't' == src[offset + 0] &&
1943 'r' == src[offset + 1] && 'u' == src[offset + 2] &&
1944 'e' == src[offset + 3]) {
1945 value->type = json_type_true;
1946 value->payload = json_null;
1949 else if ((offset + 5) <= size && 'f' == src[offset + 0] &&
1950 'a' == src[offset + 1] && 'l' == src[offset + 2] &&
1951 's' == src[offset + 3] && 'e' == src[offset + 4]) {
1952 value->type = json_type_false;
1953 value->payload = json_null;
1956 else if ((offset + 4) <= size && 'n' == src[offset + 0] &&
1957 'u' == src[offset + 1] && 'l' == src[offset + 2] &&
1958 'l' == src[offset + 3]) {
1959 value->type = json_type_null;
1960 value->payload = json_null;
1963 else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1964 (offset + 3) <= size && 'N' == src[offset + 0] &&
1965 'a' == src[offset + 1] && 'N' == src[offset + 2]) {
1966 value->type = json_type_number;
1967 value->payload = state->dom;
1968 state->dom += sizeof(struct json_number_s);
1969 json_parse_number(state, (struct json_number_s *)value->payload);
1971 else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&
1972 (offset + 8) <= size && 'I' == src[offset + 0] &&
1973 'n' == src[offset + 1] && 'f' == src[offset + 2] &&
1974 'i' == src[offset + 3] && 'n' == src[offset + 4] &&
1975 'i' == src[offset + 5] && 't' == src[offset + 6] &&
1976 'y' == src[offset + 7]) {
1977 value->type = json_type_number;
1978 value->payload = state->dom;
1979 state->dom += sizeof(struct json_number_s);
1980 json_parse_number(state, (struct json_number_s *)value->payload);
1987 struct json_value_s *
1988 json_parse_ex(const void *src, size_t src_size, size_t flags_bitset,
1989 void *(*alloc_func_ptr)(void *user_data, size_t size),
1990 void *user_data, struct json_parse_result_s *result) {
1991 struct json_parse_state_s state;
1993 struct json_value_s *value;
1998 result->error = json_parse_error_none;
1999 result->error_offset = 0;
2000 result->error_line_no = 0;
2001 result->error_row_no = 0;
2004 if (json_null == src) {
2005 /* invalid src pointer was null! */
2009 state.src = (const char *)src;
2010 state.size = src_size;
2013 state.line_offset = 0;
2014 state.error = json_parse_error_none;
2016 state.data_size = 0;
2017 state.flags_bitset = flags_bitset;
2019 input_error = json_get_value_size(
2020 &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset));
2022 if (0 == input_error) {
2023 json_skip_all_skippables(&state);
2025 if (state.offset != state.size) {
2026 /* our parsing didn't have an error, but there are characters remaining in
2027 * the input that weren't part of the JSON! */
2029 state.error = json_parse_error_unexpected_trailing_characters;
2035 /* parsing value's size failed (most likely an invalid JSON DOM!). */
2037 result->error = state.error;
2038 result->error_offset = state.offset;
2039 result->error_line_no = state.line_no;
2040 result->error_row_no = state.offset - state.line_offset;
2045 /* our total allocation is the combination of the dom and data sizes (we. */
2046 /* first encode the structure of the JSON, and then the data referenced by. */
2047 /* the JSON values). */
2048 total_size = state.dom_size + state.data_size;
2050 if (json_null == alloc_func_ptr) {
2051 allocation = malloc(total_size);
2054 allocation = alloc_func_ptr(user_data, total_size);
2057 if (json_null == allocation) {
2058 /* malloc failed! */
2060 result->error = json_parse_error_allocator_failed;
2061 result->error_offset = 0;
2062 result->error_line_no = 0;
2063 result->error_row_no = 0;
2069 /* reset offset so we can reuse it. */
2072 /* reset the line information so we can reuse it. */
2074 state.line_offset = 0;
2076 state.dom = (char *)allocation;
2077 state.data = state.dom + state.dom_size;
2079 if (json_parse_flags_allow_location_information & state.flags_bitset) {
2080 struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state.dom;
2081 state.dom += sizeof(struct json_value_ex_s);
2083 value_ex->offset = state.offset;
2084 value_ex->line_no = state.line_no;
2085 value_ex->row_no = state.offset - state.line_offset;
2087 value = &(value_ex->value);
2090 value = (struct json_value_s *)state.dom;
2091 state.dom += sizeof(struct json_value_s);
2095 &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset),
2098 return (struct json_value_s *)allocation;
2101 struct json_value_s *json_parse(const void *src, size_t src_size) {
2102 return json_parse_ex(src, src_size, json_parse_flags_default, json_null,
2103 json_null, json_null);
2106 struct json_string_s *json_value_as_string(struct json_value_s *const value) {
2107 if (value->type != json_type_string) {
2111 return (struct json_string_s *)value->payload;
2114 struct json_number_s *json_value_as_number(struct json_value_s *const value) {
2115 if (value->type != json_type_number) {
2119 return (struct json_number_s *)value->payload;
2122 struct json_object_s *json_value_as_object(struct json_value_s *const value) {
2123 if (value->type != json_type_object) {
2127 return (struct json_object_s *)value->payload;
2130 struct json_array_s *json_value_as_array(struct json_value_s *const value) {
2131 if (value->type != json_type_array) {
2135 return (struct json_array_s *)value->payload;
2138 int json_value_is_true(const struct json_value_s *const value) {
2139 return value->type == json_type_true;
2142 int json_value_is_false(const struct json_value_s *const value) {
2143 return value->type == json_type_false;
2146 int json_value_is_null(const struct json_value_s *const value) {
2147 return value->type == json_type_null;
2150 json_weak int json_write_minified_get_value_size(const struct json_value_s *value,
2153 json_weak int json_write_get_number_size(const struct json_number_s *number,
2155 int json_write_get_number_size(const struct json_number_s *number,
2157 json_uintmax_t parsed_number;
2160 if (number->number_size >= 2) {
2161 switch (number->number[1]) {
2166 /* the number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal
2167 * so we have to do extra work to convert it to a non-hexadecimal for JSON
2169 parsed_number = json_strtoumax(number->number, json_null, 0);
2173 while (0 != parsed_number) {
2174 parsed_number /= 10;
2183 /* check to see if the number has leading/trailing decimal point. */
2186 /* skip any leading '+' or '-'. */
2187 if ((i < number->number_size) &&
2188 (('+' == number->number[i]) || ('-' == number->number[i]))) {
2192 /* check if we have infinity. */
2193 if ((i < number->number_size) && ('I' == number->number[i])) {
2194 const char *inf = "Infinity";
2197 for (k = i; k < number->number_size; k++) {
2198 const char c = *inf++;
2200 /* Check if we found the Infinity string! */
2204 else if (c != number->number[k]) {
2210 /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */
2213 /* if we had a leading '-' we need to record it in the JSON output. */
2214 if ('-' == number->number[0]) {
2222 /* check if we have nan. */
2223 if ((i < number->number_size) && ('N' == number->number[i])) {
2224 const char *nan = "NaN";
2227 for (k = i; k < number->number_size; k++) {
2228 const char c = *nan++;
2230 /* Check if we found the NaN string! */
2234 else if (c != number->number[k]) {
2240 /* NaN becomes 1 because JSON can't support it. */
2247 /* if we had a leading decimal point. */
2248 if ((i < number->number_size) && ('.' == number->number[i])) {
2249 /* 1 + because we had a leading decimal point. */
2254 for (; i < number->number_size; i++) {
2255 const char c = number->number[i];
2256 if (!('0' <= c && c <= '9')) {
2261 /* if we had a trailing decimal point. */
2262 if ((i + 1 == number->number_size) && ('.' == number->number[i])) {
2263 /* 1 + because we had a trailing decimal point. */
2269 *size += number->number_size; /* the actual string of the number. */
2271 /* if we had a leading '+' we don't record it in the JSON output. */
2272 if ('+' == number->number[0]) {
2279 json_weak int json_write_get_string_size(const struct json_string_s *string,
2281 int json_write_get_string_size(const struct json_string_s *string,
2284 for (i = 0; i < string->string_size; i++) {
2285 switch (string->string[i]) {
2301 *size += 2; /* need to encode the surrounding '"' characters. */
2306 json_weak int json_write_minified_get_array_size(const struct json_array_s *array,
2308 int json_write_minified_get_array_size(const struct json_array_s *array,
2310 struct json_array_element_s *element;
2312 *size += 2; /* '[' and ']'. */
2314 if (1 < array->length) {
2315 *size += array->length - 1; /* ','s seperate each element. */
2318 for (element = array->start; json_null != element; element = element->next) {
2319 if (json_write_minified_get_value_size(element->value, size)) {
2320 /* value was malformed! */
2329 json_write_minified_get_object_size(const struct json_object_s *object,
2332 json_write_minified_get_object_size(const struct json_object_s *object,
2334 struct json_object_element_s *element;
2336 *size += 2; /* '{' and '}'. */
2338 *size += object->length; /* ':'s seperate each name/value pair. */
2340 if (1 < object->length) {
2341 *size += object->length - 1; /* ','s seperate each element. */
2344 for (element = object->start; json_null != element; element = element->next) {
2345 if (json_write_get_string_size(element->name, size)) {
2346 /* string was malformed! */
2350 if (json_write_minified_get_value_size(element->value, size)) {
2351 /* value was malformed! */
2359 json_weak int json_write_minified_get_value_size(const struct json_value_s *value,
2361 int json_write_minified_get_value_size(const struct json_value_s *value,
2363 switch (value->type) {
2365 /* unknown value type found! */
2367 case json_type_number:
2368 return json_write_get_number_size((struct json_number_s *)value->payload,
2370 case json_type_string:
2371 return json_write_get_string_size((struct json_string_s *)value->payload,
2373 case json_type_array:
2374 return json_write_minified_get_array_size(
2375 (struct json_array_s *)value->payload, size);
2376 case json_type_object:
2377 return json_write_minified_get_object_size(
2378 (struct json_object_s *)value->payload, size);
2379 case json_type_true:
2380 *size += 4; /* the string "true". */
2382 case json_type_false:
2383 *size += 5; /* the string "false". */
2385 case json_type_null:
2386 *size += 4; /* the string "null". */
2391 json_weak char *json_write_minified_value(const struct json_value_s *value,
2394 json_weak char *json_write_number(const struct json_number_s *number, char *data);
2395 char *json_write_number(const struct json_number_s *number, char *data) {
2396 json_uintmax_t parsed_number, backup;
2399 if (number->number_size >= 2) {
2400 switch (number->number[1]) {
2405 /* The number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal
2406 * so we have to do extra work to convert it to a non-hexadecimal for JSON
2408 parsed_number = json_strtoumax(number->number, json_null, 0);
2410 /* We need a copy of parsed number twice, so take a backup of it. */
2411 backup = parsed_number;
2415 while (0 != parsed_number) {
2416 parsed_number /= 10;
2420 /* Restore parsed_number to its original value stored in the backup. */
2421 parsed_number = backup;
2423 /* Now use backup to take a copy of i, or the length of the string. */
2427 *(data + i - 1) = '0' + (char)(parsed_number % 10);
2428 parsed_number /= 10;
2430 } while (0 != parsed_number);
2438 /* check to see if the number has leading/trailing decimal point. */
2441 /* skip any leading '-'. */
2442 if ((i < number->number_size) &&
2443 (('+' == number->number[i]) || ('-' == number->number[i]))) {
2447 /* check if we have infinity. */
2448 if ((i < number->number_size) && ('I' == number->number[i])) {
2449 const char *inf = "Infinity";
2452 for (k = i; k < number->number_size; k++) {
2453 const char c = *inf++;
2455 /* Check if we found the Infinity string! */
2459 else if (c != number->number[k]) {
2464 if ('\0' == *inf++) {
2465 const char *dbl_max;
2467 /* if we had a leading '-' we need to record it in the JSON output. */
2468 if ('-' == number->number[0]) {
2472 /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */
2473 for (dbl_max = "1.7976931348623158e308"; '\0' != *dbl_max; dbl_max++) {
2481 /* check if we have nan. */
2482 if ((i < number->number_size) && ('N' == number->number[i])) {
2483 const char *nan = "NaN";
2486 for (k = i; k < number->number_size; k++) {
2487 const char c = *nan++;
2489 /* Check if we found the NaN string! */
2493 else if (c != number->number[k]) {
2498 if ('\0' == *nan++) {
2499 /* NaN becomes 0 because JSON can't support it. */
2505 /* if we had a leading decimal point. */
2506 if ((i < number->number_size) && ('.' == number->number[i])) {
2509 /* skip any leading '+'. */
2510 if ('+' == number->number[i]) {
2514 /* output the leading '-' if we had one. */
2515 if ('-' == number->number[i]) {
2520 /* insert a '0' to fix the leading decimal point for JSON output. */
2523 /* and output the rest of the number as normal. */
2524 for (; i < number->number_size; i++) {
2525 *data++ = number->number[i];
2531 for (; i < number->number_size; i++) {
2532 const char c = number->number[i];
2533 if (!('0' <= c && c <= '9')) {
2538 /* if we had a trailing decimal point. */
2539 if ((i + 1 == number->number_size) && ('.' == number->number[i])) {
2542 /* skip any leading '+'. */
2543 if ('+' == number->number[i]) {
2547 /* output the leading '-' if we had one. */
2548 if ('-' == number->number[i]) {
2553 /* and output the rest of the number as normal. */
2554 for (; i < number->number_size; i++) {
2555 *data++ = number->number[i];
2558 /* insert a '0' to fix the trailing decimal point for JSON output. */
2566 /* skip any leading '+'. */
2567 if ('+' == number->number[i]) {
2571 for (; i < number->number_size; i++) {
2572 *data++ = number->number[i];
2578 json_weak char *json_write_string(const struct json_string_s *string, char *data);
2579 char *json_write_string(const struct json_string_s *string, char *data) {
2582 *data++ = '"'; /* open the string. */
2584 for (i = 0; i < string->string_size; i++) {
2585 switch (string->string[i]) {
2587 *data++ = '\\'; /* escape the control character. */
2591 *data++ = '\\'; /* escape the control character. */
2595 *data++ = '\\'; /* escape the control character. */
2599 *data++ = '\\'; /* escape the control character. */
2603 *data++ = '\\'; /* escape the control character. */
2607 *data++ = '\\'; /* escape the control character. */
2611 *data++ = '\\'; /* escape the control character. */
2615 *data++ = string->string[i];
2620 *data++ = '"'; /* close the string. */
2625 json_weak char *json_write_minified_array(const struct json_array_s *array,
2627 char *json_write_minified_array(const struct json_array_s *array,
2629 struct json_array_element_s *element = json_null;
2631 *data++ = '['; /* open the array. */
2633 for (element = array->start; json_null != element; element = element->next) {
2634 if (element != array->start) {
2635 *data++ = ','; /* ','s seperate each element. */
2638 data = json_write_minified_value(element->value, data);
2640 if (json_null == data) {
2641 /* value was malformed! */
2646 *data++ = ']'; /* close the array. */
2651 json_weak char *json_write_minified_object(const struct json_object_s *object,
2653 char *json_write_minified_object(const struct json_object_s *object,
2655 struct json_object_element_s *element = json_null;
2657 *data++ = '{'; /* open the object. */
2659 for (element = object->start; json_null != element;
2660 element = element->next) {
2661 if (element != object->start) {
2662 *data++ = ','; /* ','s seperate each element. */
2665 data = json_write_string(element->name, data);
2667 if (json_null == data) {
2668 /* string was malformed! */
2672 *data++ = ':'; /* ':'s seperate each name/value pair. */
2674 data = json_write_minified_value(element->value, data);
2676 if (json_null == data) {
2677 /* value was malformed! */
2682 *data++ = '}'; /* close the object. */
2687 json_weak char *json_write_minified_value(const struct json_value_s *value,
2689 char *json_write_minified_value(const struct json_value_s *value,
2691 switch (value->type) {
2693 /* unknown value type found! */
2695 case json_type_number:
2696 return json_write_number((struct json_number_s *)value->payload, data);
2697 case json_type_string:
2698 return json_write_string((struct json_string_s *)value->payload, data);
2699 case json_type_array:
2700 return json_write_minified_array((struct json_array_s *)value->payload,
2702 case json_type_object:
2703 return json_write_minified_object((struct json_object_s *)value->payload,
2705 case json_type_true:
2711 case json_type_false:
2718 case json_type_null:
2727 void *json_write_minified(const struct json_value_s *value, size_t *out_size) {
2729 char *data = json_null;
2730 char *data_end = json_null;
2732 if (json_null == value) {
2736 if (json_write_minified_get_value_size(value, &size)) {
2737 /* value was malformed! */
2741 size += 1; /* for the '\0' null terminating character. */
2743 data = (char *)malloc(size);
2745 if (json_null == data) {
2746 /* malloc failed! */
2750 data_end = json_write_minified_value(value, data);
2752 if (json_null == data_end) {
2753 /* bad chi occurred! */
2758 /* null terminated the string. */
2761 if (json_null != out_size) {
2768 json_weak int json_write_pretty_get_value_size(const struct json_value_s *value,
2769 size_t depth, size_t indent_size,
2770 size_t newline_size, size_t *size);
2772 json_weak int json_write_pretty_get_array_size(const struct json_array_s *array,
2773 size_t depth, size_t indent_size,
2774 size_t newline_size, size_t *size);
2775 int json_write_pretty_get_array_size(const struct json_array_s *array,
2776 size_t depth, size_t indent_size,
2777 size_t newline_size, size_t *size) {
2778 struct json_array_element_s *element;
2780 *size += 1; /* '['. */
2782 if (0 < array->length) {
2783 /* if we have any elements we need to add a newline after our '['. */
2784 *size += newline_size;
2786 *size += array->length - 1; /* ','s seperate each element. */
2788 for (element = array->start; json_null != element;
2789 element = element->next) {
2790 /* each element gets an indent. */
2791 *size += (depth + 1) * indent_size;
2793 if (json_write_pretty_get_value_size(element->value, depth + 1,
2794 indent_size, newline_size, size)) {
2795 /* value was malformed! */
2799 /* each element gets a newline too. */
2800 *size += newline_size;
2803 /* since we wrote out some elements, need to add a newline and indentation.
2805 /* to the trailing ']'. */
2806 *size += depth * indent_size;
2809 *size += 1; /* ']'. */
2814 json_weak int json_write_pretty_get_object_size(const struct json_object_s *object,
2815 size_t depth, size_t indent_size,
2816 size_t newline_size,
2818 int json_write_pretty_get_object_size(const struct json_object_s *object,
2819 size_t depth, size_t indent_size,
2820 size_t newline_size,
2822 struct json_object_element_s *element;
2824 *size += 1; /* '{'. */
2826 if (0 < object->length) {
2827 *size += newline_size; /* need a newline next. */
2829 *size += object->length - 1; /* ','s seperate each element. */
2831 for (element = object->start; json_null != element;
2832 element = element->next) {
2833 /* each element gets an indent and newline. */
2834 *size += (depth + 1) * indent_size;
2835 *size += newline_size;
2837 if (json_write_get_string_size(element->name, size)) {
2838 /* string was malformed! */
2842 *size += 3; /* seperate each name/value pair with " : ". */
2844 if (json_write_pretty_get_value_size(element->value, depth + 1,
2845 indent_size, newline_size, size)) {
2846 /* value was malformed! */
2851 *size += depth * indent_size;
2854 *size += 1; /* '}'. */
2859 json_weak int json_write_pretty_get_value_size(const struct json_value_s *value,
2860 size_t depth, size_t indent_size,
2861 size_t newline_size, size_t *size);
2862 int json_write_pretty_get_value_size(const struct json_value_s *value,
2863 size_t depth, size_t indent_size,
2864 size_t newline_size, size_t *size) {
2865 switch (value->type) {
2867 /* unknown value type found! */
2869 case json_type_number:
2870 return json_write_get_number_size((struct json_number_s *)value->payload,
2872 case json_type_string:
2873 return json_write_get_string_size((struct json_string_s *)value->payload,
2875 case json_type_array:
2876 return json_write_pretty_get_array_size(
2877 (struct json_array_s *)value->payload, depth, indent_size, newline_size,
2879 case json_type_object:
2880 return json_write_pretty_get_object_size(
2881 (struct json_object_s *)value->payload, depth, indent_size,
2882 newline_size, size);
2883 case json_type_true:
2884 *size += 4; /* the string "true". */
2886 case json_type_false:
2887 *size += 5; /* the string "false". */
2889 case json_type_null:
2890 *size += 4; /* the string "null". */
2895 json_weak char *json_write_pretty_value(const struct json_value_s *value,
2896 size_t depth, const char *indent,
2897 const char *newline, char *data);
2899 json_weak char *json_write_pretty_array(const struct json_array_s *array,
2900 size_t depth, const char *indent,
2901 const char *newline, char *data);
2902 char *json_write_pretty_array(const struct json_array_s *array,
2903 size_t depth, const char *indent,
2904 const char *newline, char *data) {
2906 struct json_array_element_s *element;
2908 *data++ = '['; /* open the array. */
2910 if (0 < array->length) {
2911 for (k = 0; '\0' != newline[k]; k++) {
2912 *data++ = newline[k];
2915 for (element = array->start; json_null != element;
2916 element = element->next) {
2917 if (element != array->start) {
2918 *data++ = ','; /* ','s seperate each element. */
2920 for (k = 0; '\0' != newline[k]; k++) {
2921 *data++ = newline[k];
2925 for (k = 0; k < depth + 1; k++) {
2926 for (m = 0; '\0' != indent[m]; m++) {
2927 *data++ = indent[m];
2931 data = json_write_pretty_value(element->value, depth + 1, indent, newline,
2934 if (json_null == data) {
2935 /* value was malformed! */
2940 for (k = 0; '\0' != newline[k]; k++) {
2941 *data++ = newline[k];
2944 for (k = 0; k < depth; k++) {
2945 for (m = 0; '\0' != indent[m]; m++) {
2946 *data++ = indent[m];
2951 *data++ = ']'; /* close the array. */
2956 json_weak char *json_write_pretty_object(const struct json_object_s *object,
2957 size_t depth, const char *indent,
2958 const char *newline, char *data);
2959 char *json_write_pretty_object(const struct json_object_s *object,
2960 size_t depth, const char *indent,
2961 const char *newline, char *data) {
2963 struct json_object_element_s *element;
2965 *data++ = '{'; /* open the object. */
2967 if (0 < object->length) {
2968 for (k = 0; '\0' != newline[k]; k++) {
2969 *data++ = newline[k];
2972 for (element = object->start; json_null != element;
2973 element = element->next) {
2974 if (element != object->start) {
2975 *data++ = ','; /* ','s seperate each element. */
2977 for (k = 0; '\0' != newline[k]; k++) {
2978 *data++ = newline[k];
2982 for (k = 0; k < depth + 1; k++) {
2983 for (m = 0; '\0' != indent[m]; m++) {
2984 *data++ = indent[m];
2988 data = json_write_string(element->name, data);
2990 if (json_null == data) {
2991 /* string was malformed! */
2995 /* " : "s seperate each name/value pair. */
3000 data = json_write_pretty_value(element->value, depth + 1, indent, newline,
3003 if (json_null == data) {
3004 /* value was malformed! */
3009 for (k = 0; '\0' != newline[k]; k++) {
3010 *data++ = newline[k];
3013 for (k = 0; k < depth; k++) {
3014 for (m = 0; '\0' != indent[m]; m++) {
3015 *data++ = indent[m];
3020 *data++ = '}'; /* close the object. */
3025 json_weak char *json_write_pretty_value(const struct json_value_s *value,
3026 size_t depth, const char *indent,
3027 const char *newline, char *data);
3028 char *json_write_pretty_value(const struct json_value_s *value,
3029 size_t depth, const char *indent,
3030 const char *newline, char *data) {
3031 switch (value->type) {
3033 /* unknown value type found! */
3035 case json_type_number:
3036 return json_write_number((struct json_number_s *)value->payload, data);
3037 case json_type_string:
3038 return json_write_string((struct json_string_s *)value->payload, data);
3039 case json_type_array:
3040 return json_write_pretty_array((struct json_array_s *)value->payload, depth,
3041 indent, newline, data);
3042 case json_type_object:
3043 return json_write_pretty_object((struct json_object_s *)value->payload,
3044 depth, indent, newline, data);
3045 case json_type_true:
3051 case json_type_false:
3058 case json_type_null:
3067 void *json_write_pretty(const struct json_value_s *value, const char *indent,
3068 const char *newline, size_t *out_size) {
3070 size_t indent_size = 0;
3071 size_t newline_size = 0;
3072 char *data = json_null;
3073 char *data_end = json_null;
3075 if (json_null == value) {
3079 if (json_null == indent) {
3080 indent = " "; /* default to two spaces. */
3083 if (json_null == newline) {
3084 newline = "\n"; /* default to linux newlines. */
3087 while ('\0' != indent[indent_size]) {
3088 ++indent_size; /* skip non-null terminating characters. */
3091 while ('\0' != newline[newline_size]) {
3092 ++newline_size; /* skip non-null terminating characters. */
3095 if (json_write_pretty_get_value_size(value, 0, indent_size, newline_size,
3097 /* value was malformed! */
3101 size += 1; /* for the '\0' null terminating character. */
3103 data = (char *)malloc(size);
3105 if (json_null == data) {
3106 /* malloc failed! */
3110 data_end = json_write_pretty_value(value, 0, indent, newline, data);
3112 if (json_null == data_end) {
3113 /* bad chi occurred! */
3118 /* null terminated the string. */
3121 if (json_null != out_size) {
3128 #if defined(__clang__)
3129 #pragma clang diagnostic pop
3130 #elif defined(_MSC_VER)
3131 #pragma warning(pop)
3134 #endif /* SHEREDOM_JSON_H_INCLUDED. */