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