1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <sys/types.h>
28 int json_variant_new(JsonVariant **ret, JsonVariantType type) {
31 v = new0(JsonVariant, 1);
39 static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) {
45 ret->type = variant->type;
46 ret->size = variant->size;
48 if (variant->type == JSON_VARIANT_STRING) {
49 ret->string = memdup(variant->string, variant->size+1);
52 } else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) {
55 ret->objects = new0(JsonVariant, variant->size);
59 for (i = 0; i < variant->size; ++i) {
60 r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]);
65 ret->value = variant->value;
70 static JsonVariant *json_object_unref(JsonVariant *variant);
72 static JsonVariant *json_variant_unref_inner(JsonVariant *variant) {
76 if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
77 return json_object_unref(variant);
78 else if (variant->type == JSON_VARIANT_STRING)
79 free(variant->string);
84 static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) {
88 for (size_t i = 0; i < size; ++i)
89 json_variant_unref_inner(&variant[i]);
95 static JsonVariant *json_object_unref(JsonVariant *variant) {
100 if (!variant->objects)
103 for (i = 0; i < variant->size; ++i)
104 json_variant_unref_inner(&variant->objects[i]);
106 free(variant->objects);
110 static JsonVariant **json_variant_array_unref(JsonVariant **variant) {
112 JsonVariant *p = NULL;
117 while((p = (variant[i++])) != NULL) {
118 if (p->type == JSON_VARIANT_STRING)
128 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref);
130 JsonVariant *json_variant_unref(JsonVariant *variant) {
134 if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
135 json_object_unref(variant);
136 else if (variant->type == JSON_VARIANT_STRING)
137 free(variant->string);
144 char *json_variant_string(JsonVariant *variant){
146 assert(variant->type == JSON_VARIANT_STRING);
148 return variant->string;
151 bool json_variant_bool(JsonVariant *variant) {
153 assert(variant->type == JSON_VARIANT_BOOLEAN);
155 return variant->value.boolean;
158 intmax_t json_variant_integer(JsonVariant *variant) {
160 assert(variant->type == JSON_VARIANT_INTEGER);
162 return variant->value.integer;
165 double json_variant_real(JsonVariant *variant) {
167 assert(variant->type == JSON_VARIANT_REAL);
169 return variant->value.real;
172 JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) {
174 assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT);
175 assert(index < variant->size);
176 assert(variant->objects);
178 return &variant->objects[index];
181 JsonVariant *json_variant_value(JsonVariant *variant, const char *key) {
185 assert(variant->type == JSON_VARIANT_OBJECT);
186 assert(variant->objects);
188 for (i = 0; i < variant->size; i += 2) {
189 JsonVariant *p = &variant->objects[i];
190 if (p->type == JSON_VARIANT_STRING && streq(key, p->string))
191 return &variant->objects[i + 1];
197 static void inc_lines(unsigned *line, const char *s, size_t n) {
206 f = memchr(p, '\n', n);
216 static int unhex_ucs2(const char *c, uint16_t *ret) {
223 aa = unhexchar(c[0]);
227 bb = unhexchar(c[1]);
231 cc = unhexchar(c[2]);
235 dd = unhexchar(c[3]);
239 x = ((uint16_t) aa << 12) |
240 ((uint16_t) bb << 8) |
241 ((uint16_t) cc << 4) |
252 static int json_parse_string(const char **p, char **ret) {
253 _cleanup_free_ char *s = NULL;
254 size_t n = 0, allocated = 0;
275 /* Check for control characters 0x00..0x1f */
276 if (*c > 0 && *c < ' ')
279 /* Check for control character 0x7f */
305 if (IN_SET(*c, '"', '\\', '/'))
317 else if (*c == 'u') {
321 r = unhex_ucs2(c + 1, &x);
327 if (!GREEDY_REALLOC(s, allocated, n + 4))
330 if (!utf16_is_surrogate(x))
331 n += utf8_encode_unichar(s + n, x);
332 else if (utf16_is_trailing_surrogate(x))
337 if (c[0] != '\\' || c[1] != 'u')
340 r = unhex_ucs2(c + 2, &y);
346 if (!utf16_is_trailing_surrogate(y))
349 n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
356 if (!GREEDY_REALLOC(s, allocated, n + 2))
364 len = utf8_encoded_valid_unichar(c);
368 if (!GREEDY_REALLOC(s, allocated, n + len + 1))
371 memcpy(s + n, c, len);
377 static int json_parse_number(const char **p, union json_value *ret) {
378 bool negative = false, exponent_negative = false, is_double = false;
379 double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
397 if (!strchr("123456789", *c) || *c == 0)
404 t = 10 * i + (*c - '0');
405 if (t < i) /* overflow */
411 x = 10.0 * x + (*c - '0');
413 } while (strchr("0123456789", *c) && *c != 0);
420 if (!strchr("0123456789", *c) || *c == 0)
424 y = 10.0 * y + (*c - '0');
425 shift = 10.0 * shift;
427 } while (strchr("0123456789", *c) && *c != 0);
430 if (*c == 'e' || *c == 'E') {
435 exponent_negative = true;
437 } else if (*c == '+')
440 if (!strchr("0123456789", *c) || *c == 0)
444 exponent = 10.0 * exponent + (*c - '0');
446 } while (strchr("0123456789", *c) && *c != 0);
452 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent);
455 ret->integer = negative ? -i : i;
463 union json_value *ret_value,
483 t = PTR_TO_INT(*state);
486 if (t == STATE_NULL) {
495 b = c + strspn(c, WHITESPACE);
499 inc_lines(line, c, b - c);
508 *ret_value = JSON_VALUE_NULL;
510 *state = INT_TO_PTR(STATE_VALUE);
511 return JSON_OBJECT_OPEN;
513 } else if (*c == '}') {
515 *ret_value = JSON_VALUE_NULL;
517 *state = INT_TO_PTR(STATE_VALUE_POST);
518 return JSON_OBJECT_CLOSE;
520 } else if (*c == '[') {
522 *ret_value = JSON_VALUE_NULL;
524 *state = INT_TO_PTR(STATE_VALUE);
525 return JSON_ARRAY_OPEN;
527 } else if (*c == ']') {
529 *ret_value = JSON_VALUE_NULL;
531 *state = INT_TO_PTR(STATE_VALUE_POST);
532 return JSON_ARRAY_CLOSE;
534 } else if (*c == '"') {
535 r = json_parse_string(&c, ret_string);
539 *ret_value = JSON_VALUE_NULL;
541 *state = INT_TO_PTR(STATE_VALUE_POST);
544 } else if (strchr("-0123456789", *c)) {
545 r = json_parse_number(&c, ret_value);
551 *state = INT_TO_PTR(STATE_VALUE_POST);
554 } else if (startswith(c, "true")) {
556 ret_value->boolean = true;
558 *state = INT_TO_PTR(STATE_VALUE_POST);
561 } else if (startswith(c, "false")) {
563 ret_value->boolean = false;
565 *state = INT_TO_PTR(STATE_VALUE_POST);
568 } else if (startswith(c, "null")) {
570 *ret_value = JSON_VALUE_NULL;
572 *state = INT_TO_PTR(STATE_VALUE_POST);
578 case STATE_VALUE_POST:
582 *ret_value = JSON_VALUE_NULL;
584 *state = INT_TO_PTR(STATE_VALUE);
586 } else if (*c == ',') {
588 *ret_value = JSON_VALUE_NULL;
590 *state = INT_TO_PTR(STATE_VALUE);
592 } else if (*c == '}') {
594 *ret_value = JSON_VALUE_NULL;
596 *state = INT_TO_PTR(STATE_VALUE_POST);
597 return JSON_OBJECT_CLOSE;
598 } else if (*c == ']') {
600 *ret_value = JSON_VALUE_NULL;
602 *state = INT_TO_PTR(STATE_VALUE_POST);
603 return JSON_ARRAY_CLOSE;
611 static bool json_is_value(JsonVariant *var) {
614 return var->type != JSON_VARIANT_CONTROL;
617 static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) {
618 bool arr = scope->type == JSON_VARIANT_ARRAY;
619 int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE;
620 size_t allocated = 0, size = 0;
621 JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL;
627 } state = arr ? STATE_VALUE : STATE_KEY;
633 while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) {
637 stopper = !json_is_value(var) && var->value.integer == terminator;
640 if (state != STATE_COMMA && size > 0)
646 if (state == STATE_KEY) {
647 if (var->type != JSON_VARIANT_STRING)
654 else if (state == STATE_COLON) {
658 if (json_is_value(var))
661 if (var->value.integer != JSON_COLON)
666 else if (state == STATE_VALUE) {
667 _cleanup_json_variant_unref_ JsonVariant *v = NULL;
668 size_t toadd = arr ? 1 : 2;
670 if (!json_is_value(var)) {
671 int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT;
673 r = json_variant_new(&v, type);
677 r = json_scoped_parse(tokens, i, n, v);
686 if(!GREEDY_REALLOC(items, allocated, size + toadd))
690 r = json_variant_deep_copy(&items[size], value);
694 r = json_variant_deep_copy(&items[size], key);
698 r = json_variant_deep_copy(&items[size+1], value);
706 else if (state == STATE_COMMA) {
707 if (json_is_value(var))
710 if (var->value.integer != JSON_COMMA)
716 state = arr ? STATE_VALUE : STATE_KEY;
721 json_raw_unref(items, size);
726 scope->objects = items;
731 static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) {
735 _cleanup_json_variant_unref_ JsonVariant *p = NULL;
741 r = json_variant_new(&p, JSON_VARIANT_OBJECT);
745 if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN)
748 r = json_scoped_parse(tokens, &it, ntokens, p);
758 static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) {
759 _cleanup_free_ char *buf = NULL;
760 _cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL;
761 union json_value v = {};
762 void *json_state = NULL;
765 size_t allocated = 0, s = 0;
773 buf = strndup(string, size);
779 _cleanup_json_variant_unref_ JsonVariant *var = NULL;
780 _cleanup_free_ char *rstr = NULL;
782 t = json_tokenize(&p, &rstr, &v, &json_state, NULL);
786 else if (t == JSON_END)
789 if (t <= JSON_ARRAY_CLOSE) {
790 r = json_variant_new(&var, JSON_VARIANT_CONTROL);
793 var->value.integer = t;
797 r = json_variant_new(&var, JSON_VARIANT_STRING);
800 var->size = strlen(rstr);
801 var->string = strdup(rstr);
807 r = json_variant_new(&var, JSON_VARIANT_INTEGER);
813 r = json_variant_new(&var, JSON_VARIANT_REAL);
819 r = json_variant_new(&var, JSON_VARIANT_BOOLEAN);
825 r = json_variant_new(&var, JSON_VARIANT_NULL);
832 if (!GREEDY_REALLOC(items, allocated, s+2))
847 int json_parse(const char *string, JsonVariant **rv) {
848 _cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL;
849 JsonVariant *v = NULL;
856 r = json_tokens(string, strlen(string), &s, &n);
860 r = json_parse_tokens(s, n, &v);