2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/types.h>
26 #include "alloc-util.h"
27 #include "hexdecoct.h"
30 #include "string-util.h"
33 int json_variant_new(JsonVariant
**ret
, JsonVariantType type
) {
36 v
= new0(JsonVariant
, 1);
44 static int json_variant_deep_copy(JsonVariant
*ret
, JsonVariant
*variant
) {
50 ret
->type
= variant
->type
;
51 ret
->size
= variant
->size
;
53 if (variant
->type
== JSON_VARIANT_STRING
) {
54 ret
->string
= memdup(variant
->string
, variant
->size
+1);
57 } else if (variant
->type
== JSON_VARIANT_ARRAY
|| variant
->type
== JSON_VARIANT_OBJECT
) {
60 ret
->objects
= new0(JsonVariant
, variant
->size
);
64 for (i
= 0; i
< variant
->size
; ++i
) {
65 r
= json_variant_deep_copy(&ret
->objects
[i
], &variant
->objects
[i
]);
70 ret
->value
= variant
->value
;
75 static JsonVariant
*json_object_unref(JsonVariant
*variant
);
77 static JsonVariant
*json_variant_unref_inner(JsonVariant
*variant
) {
81 if (variant
->type
== JSON_VARIANT_ARRAY
|| variant
->type
== JSON_VARIANT_OBJECT
)
82 return json_object_unref(variant
);
83 else if (variant
->type
== JSON_VARIANT_STRING
)
84 free(variant
->string
);
89 static JsonVariant
*json_raw_unref(JsonVariant
*variant
, size_t size
) {
93 for (size_t i
= 0; i
< size
; ++i
)
94 json_variant_unref_inner(&variant
[i
]);
100 static JsonVariant
*json_object_unref(JsonVariant
*variant
) {
105 if (!variant
->objects
)
108 for (i
= 0; i
< variant
->size
; ++i
)
109 json_variant_unref_inner(&variant
->objects
[i
]);
111 free(variant
->objects
);
115 static JsonVariant
**json_variant_array_unref(JsonVariant
**variant
) {
117 JsonVariant
*p
= NULL
;
122 while((p
= (variant
[i
++])) != NULL
) {
123 if (p
->type
== JSON_VARIANT_STRING
)
133 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant
**, json_variant_array_unref
);
135 JsonVariant
*json_variant_unref(JsonVariant
*variant
) {
139 if (variant
->type
== JSON_VARIANT_ARRAY
|| variant
->type
== JSON_VARIANT_OBJECT
)
140 json_object_unref(variant
);
141 else if (variant
->type
== JSON_VARIANT_STRING
)
142 free(variant
->string
);
149 char *json_variant_string(JsonVariant
*variant
){
151 assert(variant
->type
== JSON_VARIANT_STRING
);
153 return variant
->string
;
156 bool json_variant_bool(JsonVariant
*variant
) {
158 assert(variant
->type
== JSON_VARIANT_BOOLEAN
);
160 return variant
->value
.boolean
;
163 intmax_t json_variant_integer(JsonVariant
*variant
) {
165 assert(variant
->type
== JSON_VARIANT_INTEGER
);
167 return variant
->value
.integer
;
170 double json_variant_real(JsonVariant
*variant
) {
172 assert(variant
->type
== JSON_VARIANT_REAL
);
174 return variant
->value
.real
;
177 JsonVariant
*json_variant_element(JsonVariant
*variant
, unsigned index
) {
179 assert(variant
->type
== JSON_VARIANT_ARRAY
|| variant
->type
== JSON_VARIANT_OBJECT
);
180 assert(index
< variant
->size
);
181 assert(variant
->objects
);
183 return &variant
->objects
[index
];
186 JsonVariant
*json_variant_value(JsonVariant
*variant
, const char *key
) {
190 assert(variant
->type
== JSON_VARIANT_OBJECT
);
191 assert(variant
->objects
);
193 for (i
= 0; i
< variant
->size
; i
+= 2) {
194 JsonVariant
*p
= &variant
->objects
[i
];
195 if (p
->type
== JSON_VARIANT_STRING
&& streq(key
, p
->string
))
196 return &variant
->objects
[i
+ 1];
202 static void inc_lines(unsigned *line
, const char *s
, size_t n
) {
211 f
= memchr(p
, '\n', n
);
221 static int unhex_ucs2(const char *c
, uint16_t *ret
) {
228 aa
= unhexchar(c
[0]);
232 bb
= unhexchar(c
[1]);
236 cc
= unhexchar(c
[2]);
240 dd
= unhexchar(c
[3]);
244 x
= ((uint16_t) aa
<< 12) |
245 ((uint16_t) bb
<< 8) |
246 ((uint16_t) cc
<< 4) |
257 static int json_parse_string(const char **p
, char **ret
) {
258 _cleanup_free_
char *s
= NULL
;
259 size_t n
= 0, allocated
= 0;
280 /* Check for control characters 0x00..0x1f */
281 if (*c
> 0 && *c
< ' ')
284 /* Check for control character 0x7f */
310 if (IN_SET(*c
, '"', '\\', '/'))
322 else if (*c
== 'u') {
326 r
= unhex_ucs2(c
+ 1, &x
);
332 if (!GREEDY_REALLOC(s
, allocated
, n
+ 4))
335 if (!utf16_is_surrogate(x
))
336 n
+= utf8_encode_unichar(s
+ n
, (char32_t
) x
);
337 else if (utf16_is_trailing_surrogate(x
))
342 if (c
[0] != '\\' || c
[1] != 'u')
345 r
= unhex_ucs2(c
+ 2, &y
);
351 if (!utf16_is_trailing_surrogate(y
))
354 n
+= utf8_encode_unichar(s
+ n
, utf16_surrogate_pair_to_unichar(x
, y
));
361 if (!GREEDY_REALLOC(s
, allocated
, n
+ 2))
369 len
= utf8_encoded_valid_unichar(c
);
373 if (!GREEDY_REALLOC(s
, allocated
, n
+ len
+ 1))
376 memcpy(s
+ n
, c
, len
);
382 static int json_parse_number(const char **p
, union json_value
*ret
) {
383 bool negative
= false, exponent_negative
= false, is_double
= false;
384 double x
= 0.0, y
= 0.0, exponent
= 0.0, shift
= 1.0;
402 if (!strchr("123456789", *c
) || *c
== 0)
409 t
= 10 * i
+ (*c
- '0');
410 if (t
< i
) /* overflow */
416 x
= 10.0 * x
+ (*c
- '0');
418 } while (strchr("0123456789", *c
) && *c
!= 0);
425 if (!strchr("0123456789", *c
) || *c
== 0)
429 y
= 10.0 * y
+ (*c
- '0');
430 shift
= 10.0 * shift
;
432 } while (strchr("0123456789", *c
) && *c
!= 0);
435 if (*c
== 'e' || *c
== 'E') {
440 exponent_negative
= true;
442 } else if (*c
== '+')
445 if (!strchr("0123456789", *c
) || *c
== 0)
449 exponent
= 10.0 * exponent
+ (*c
- '0');
451 } while (strchr("0123456789", *c
) && *c
!= 0);
457 ret
->real
= ((negative
? -1.0 : 1.0) * (x
+ (y
/ shift
))) * exp10((exponent_negative
? -1.0 : 1.0) * exponent
);
460 ret
->integer
= negative
? -i
: i
;
468 union json_value
*ret_value
,
488 t
= PTR_TO_INT(*state
);
491 if (t
== STATE_NULL
) {
500 b
= c
+ strspn(c
, WHITESPACE
);
504 inc_lines(line
, c
, b
- c
);
513 *ret_value
= JSON_VALUE_NULL
;
515 *state
= INT_TO_PTR(STATE_VALUE
);
516 return JSON_OBJECT_OPEN
;
518 } else if (*c
== '}') {
520 *ret_value
= JSON_VALUE_NULL
;
522 *state
= INT_TO_PTR(STATE_VALUE_POST
);
523 return JSON_OBJECT_CLOSE
;
525 } else if (*c
== '[') {
527 *ret_value
= JSON_VALUE_NULL
;
529 *state
= INT_TO_PTR(STATE_VALUE
);
530 return JSON_ARRAY_OPEN
;
532 } else if (*c
== ']') {
534 *ret_value
= JSON_VALUE_NULL
;
536 *state
= INT_TO_PTR(STATE_VALUE_POST
);
537 return JSON_ARRAY_CLOSE
;
539 } else if (*c
== '"') {
540 r
= json_parse_string(&c
, ret_string
);
544 *ret_value
= JSON_VALUE_NULL
;
546 *state
= INT_TO_PTR(STATE_VALUE_POST
);
549 } else if (strchr("-0123456789", *c
)) {
550 r
= json_parse_number(&c
, ret_value
);
556 *state
= INT_TO_PTR(STATE_VALUE_POST
);
559 } else if (startswith(c
, "true")) {
561 ret_value
->boolean
= true;
563 *state
= INT_TO_PTR(STATE_VALUE_POST
);
566 } else if (startswith(c
, "false")) {
568 ret_value
->boolean
= false;
570 *state
= INT_TO_PTR(STATE_VALUE_POST
);
573 } else if (startswith(c
, "null")) {
575 *ret_value
= JSON_VALUE_NULL
;
577 *state
= INT_TO_PTR(STATE_VALUE_POST
);
583 case STATE_VALUE_POST
:
587 *ret_value
= JSON_VALUE_NULL
;
589 *state
= INT_TO_PTR(STATE_VALUE
);
591 } else if (*c
== ',') {
593 *ret_value
= JSON_VALUE_NULL
;
595 *state
= INT_TO_PTR(STATE_VALUE
);
597 } else if (*c
== '}') {
599 *ret_value
= JSON_VALUE_NULL
;
601 *state
= INT_TO_PTR(STATE_VALUE_POST
);
602 return JSON_OBJECT_CLOSE
;
603 } else if (*c
== ']') {
605 *ret_value
= JSON_VALUE_NULL
;
607 *state
= INT_TO_PTR(STATE_VALUE_POST
);
608 return JSON_ARRAY_CLOSE
;
616 static bool json_is_value(JsonVariant
*var
) {
619 return var
->type
!= JSON_VARIANT_CONTROL
;
622 static int json_scoped_parse(JsonVariant
**tokens
, size_t *i
, size_t n
, JsonVariant
*scope
) {
623 bool arr
= scope
->type
== JSON_VARIANT_ARRAY
;
624 int terminator
= arr
? JSON_ARRAY_CLOSE
: JSON_OBJECT_CLOSE
;
625 size_t allocated
= 0, size
= 0;
626 JsonVariant
*key
= NULL
, *value
= NULL
, *var
= NULL
, *items
= NULL
;
632 } state
= arr
? STATE_VALUE
: STATE_KEY
;
638 while((var
= *i
< n
? tokens
[(*i
)++] : NULL
) != NULL
) {
642 stopper
= !json_is_value(var
) && var
->value
.integer
== terminator
;
645 if (state
!= STATE_COMMA
&& size
> 0)
651 if (state
== STATE_KEY
) {
652 if (var
->type
!= JSON_VARIANT_STRING
)
659 else if (state
== STATE_COLON
) {
663 if (json_is_value(var
))
666 if (var
->value
.integer
!= JSON_COLON
)
671 else if (state
== STATE_VALUE
) {
672 _cleanup_json_variant_unref_ JsonVariant
*v
= NULL
;
673 size_t toadd
= arr
? 1 : 2;
675 if (!json_is_value(var
)) {
676 int type
= (var
->value
.integer
== JSON_ARRAY_OPEN
) ? JSON_VARIANT_ARRAY
: JSON_VARIANT_OBJECT
;
678 r
= json_variant_new(&v
, type
);
682 r
= json_scoped_parse(tokens
, i
, n
, v
);
691 if(!GREEDY_REALLOC(items
, allocated
, size
+ toadd
))
695 r
= json_variant_deep_copy(&items
[size
], value
);
699 r
= json_variant_deep_copy(&items
[size
], key
);
703 r
= json_variant_deep_copy(&items
[size
+1], value
);
711 else if (state
== STATE_COMMA
) {
712 if (json_is_value(var
))
715 if (var
->value
.integer
!= JSON_COMMA
)
721 state
= arr
? STATE_VALUE
: STATE_KEY
;
726 json_raw_unref(items
, size
);
731 scope
->objects
= items
;
736 static int json_parse_tokens(JsonVariant
**tokens
, size_t ntokens
, JsonVariant
**rv
) {
740 _cleanup_json_variant_unref_ JsonVariant
*p
= NULL
;
746 r
= json_variant_new(&p
, JSON_VARIANT_OBJECT
);
750 if (e
->type
!= JSON_VARIANT_CONTROL
&& e
->value
.integer
!= JSON_OBJECT_OPEN
)
753 r
= json_scoped_parse(tokens
, &it
, ntokens
, p
);
763 static int json_tokens(const char *string
, size_t size
, JsonVariant
***tokens
, size_t *n
) {
764 _cleanup_free_
char *buf
= NULL
;
765 _cleanup_(json_variant_array_unrefp
) JsonVariant
**items
= NULL
;
766 union json_value v
= {};
767 void *json_state
= NULL
;
770 size_t allocated
= 0, s
= 0;
778 buf
= strndup(string
, size
);
784 _cleanup_json_variant_unref_ JsonVariant
*var
= NULL
;
785 _cleanup_free_
char *rstr
= NULL
;
787 t
= json_tokenize(&p
, &rstr
, &v
, &json_state
, NULL
);
791 else if (t
== JSON_END
)
794 if (t
<= JSON_ARRAY_CLOSE
) {
795 r
= json_variant_new(&var
, JSON_VARIANT_CONTROL
);
798 var
->value
.integer
= t
;
802 r
= json_variant_new(&var
, JSON_VARIANT_STRING
);
805 var
->size
= strlen(rstr
);
806 var
->string
= strdup(rstr
);
812 r
= json_variant_new(&var
, JSON_VARIANT_INTEGER
);
818 r
= json_variant_new(&var
, JSON_VARIANT_REAL
);
824 r
= json_variant_new(&var
, JSON_VARIANT_BOOLEAN
);
830 r
= json_variant_new(&var
, JSON_VARIANT_NULL
);
837 if (!GREEDY_REALLOC(items
, allocated
, s
+2))
852 int json_parse(const char *string
, JsonVariant
**rv
) {
853 _cleanup_(json_variant_array_unrefp
) JsonVariant
**s
= NULL
;
854 JsonVariant
*v
= NULL
;
861 r
= json_tokens(string
, strlen(string
), &s
, &n
);
865 r
= json_parse_tokens(s
, n
, &v
);