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) {
30 v = new0(JsonVariant, 1);
38 static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) {
42 ret->type = variant->type;
43 ret->size = variant->size;
45 if (variant->type == JSON_VARIANT_STRING) {
46 ret->string = memdup(variant->string, variant->size+1);
49 } else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) {
50 ret->objects = new0(JsonVariant, variant->size);
54 for (unsigned i = 0; i < variant->size; ++i) {
56 r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]);
62 ret->value = variant->value;
67 static JsonVariant *json_object_unref(JsonVariant *variant);
69 static JsonVariant *json_variant_unref_inner(JsonVariant *variant) {
73 if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
74 return json_object_unref(variant);
76 else if (variant->type == JSON_VARIANT_STRING)
77 free(variant->string);
82 static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) {
86 for (size_t i = 0; i < size; ++i)
87 json_variant_unref_inner(&variant[i]);
93 static JsonVariant *json_object_unref(JsonVariant *variant) {
95 if (!variant->objects)
98 for (unsigned i = 0; i < variant->size; ++i)
99 json_variant_unref_inner(&variant->objects[i]);
101 free(variant->objects);
105 static JsonVariant **json_variant_array_unref(JsonVariant **variant) {
107 JsonVariant *p = NULL;
112 while((p = (variant[i++])) != NULL) {
113 if (p->type == JSON_VARIANT_STRING)
122 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref);
124 JsonVariant *json_variant_unref(JsonVariant *variant) {
128 if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
129 json_object_unref(variant);
131 else if (variant->type == JSON_VARIANT_STRING)
132 free(variant->string);
139 char *json_variant_string(JsonVariant *variant){
141 assert(variant->type == JSON_VARIANT_STRING);
143 return variant->string;
146 bool json_variant_bool(JsonVariant *variant) {
148 assert(variant->type == JSON_VARIANT_BOOLEAN);
150 return variant->value.boolean;
153 intmax_t json_variant_integer(JsonVariant *variant) {
155 assert(variant->type == JSON_VARIANT_INTEGER);
157 return variant->value.integer;
160 double json_variant_real(JsonVariant *variant) {
162 assert(variant->type == JSON_VARIANT_REAL);
164 return variant->value.real;
167 JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) {
169 assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT);
170 assert(index < variant->size);
171 assert(variant->objects);
173 return &variant->objects[index];
176 JsonVariant *json_variant_value(JsonVariant *variant, const char *key) {
178 assert(variant->type == JSON_VARIANT_OBJECT);
179 assert(variant->objects);
181 for (unsigned i = 0; i < variant->size; i += 2) {
182 JsonVariant *p = &variant->objects[i];
183 if (p->type == JSON_VARIANT_STRING && streq(key, p->string))
184 return &variant->objects[i + 1];
190 static void inc_lines(unsigned *line, const char *s, size_t n) {
199 f = memchr(p, '\n', n);
209 static int unhex_ucs2(const char *c, uint16_t *ret) {
216 aa = unhexchar(c[0]);
220 bb = unhexchar(c[1]);
224 cc = unhexchar(c[2]);
228 dd = unhexchar(c[3]);
232 x = ((uint16_t) aa << 12) |
233 ((uint16_t) bb << 8) |
234 ((uint16_t) cc << 4) |
245 static int json_parse_string(const char **p, char **ret) {
246 _cleanup_free_ char *s = NULL;
247 size_t n = 0, allocated = 0;
268 /* Check for control characters 0x00..0x1f */
269 if (*c > 0 && *c < ' ')
272 /* Check for control character 0x7f */
298 if (IN_SET(*c, '"', '\\', '/'))
310 else if (*c == 'u') {
314 r = unhex_ucs2(c + 1, &x);
320 if (!GREEDY_REALLOC(s, allocated, n + 4))
323 if (!utf16_is_surrogate(x))
324 n += utf8_encode_unichar(s + n, x);
325 else if (utf16_is_trailing_surrogate(x))
330 if (c[0] != '\\' || c[1] != 'u')
333 r = unhex_ucs2(c + 2, &y);
339 if (!utf16_is_trailing_surrogate(y))
342 n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
349 if (!GREEDY_REALLOC(s, allocated, n + 2))
357 len = utf8_encoded_valid_unichar(c);
361 if (!GREEDY_REALLOC(s, allocated, n + len + 1))
364 memcpy(s + n, c, len);
370 static int json_parse_number(const char **p, union json_value *ret) {
371 bool negative = false, exponent_negative = false, is_double = false;
372 double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
390 if (!strchr("123456789", *c) || *c == 0)
397 t = 10 * i + (*c - '0');
398 if (t < i) /* overflow */
404 x = 10.0 * x + (*c - '0');
406 } while (strchr("0123456789", *c) && *c != 0);
413 if (!strchr("0123456789", *c) || *c == 0)
417 y = 10.0 * y + (*c - '0');
418 shift = 10.0 * shift;
420 } while (strchr("0123456789", *c) && *c != 0);
423 if (*c == 'e' || *c == 'E') {
428 exponent_negative = true;
430 } else if (*c == '+')
433 if (!strchr("0123456789", *c) || *c == 0)
437 exponent = 10.0 * exponent + (*c - '0');
439 } while (strchr("0123456789", *c) && *c != 0);
445 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent);
448 ret->integer = negative ? -i : i;
456 union json_value *ret_value,
476 t = PTR_TO_INT(*state);
479 if (t == STATE_NULL) {
488 b = c + strspn(c, WHITESPACE);
492 inc_lines(line, c, b - c);
501 *ret_value = JSON_VALUE_NULL;
503 *state = INT_TO_PTR(STATE_VALUE);
504 return JSON_OBJECT_OPEN;
506 } else if (*c == '}') {
508 *ret_value = JSON_VALUE_NULL;
510 *state = INT_TO_PTR(STATE_VALUE_POST);
511 return JSON_OBJECT_CLOSE;
513 } else if (*c == '[') {
515 *ret_value = JSON_VALUE_NULL;
517 *state = INT_TO_PTR(STATE_VALUE);
518 return JSON_ARRAY_OPEN;
520 } else if (*c == ']') {
522 *ret_value = JSON_VALUE_NULL;
524 *state = INT_TO_PTR(STATE_VALUE_POST);
525 return JSON_ARRAY_CLOSE;
527 } else if (*c == '"') {
528 r = json_parse_string(&c, ret_string);
532 *ret_value = JSON_VALUE_NULL;
534 *state = INT_TO_PTR(STATE_VALUE_POST);
537 } else if (strchr("-0123456789", *c)) {
538 r = json_parse_number(&c, ret_value);
544 *state = INT_TO_PTR(STATE_VALUE_POST);
547 } else if (startswith(c, "true")) {
549 ret_value->boolean = true;
551 *state = INT_TO_PTR(STATE_VALUE_POST);
554 } else if (startswith(c, "false")) {
556 ret_value->boolean = false;
558 *state = INT_TO_PTR(STATE_VALUE_POST);
561 } else if (startswith(c, "null")) {
563 *ret_value = JSON_VALUE_NULL;
565 *state = INT_TO_PTR(STATE_VALUE_POST);
571 case STATE_VALUE_POST:
575 *ret_value = JSON_VALUE_NULL;
577 *state = INT_TO_PTR(STATE_VALUE);
579 } else if (*c == ',') {
581 *ret_value = JSON_VALUE_NULL;
583 *state = INT_TO_PTR(STATE_VALUE);
585 } else if (*c == '}') {
587 *ret_value = JSON_VALUE_NULL;
589 *state = INT_TO_PTR(STATE_VALUE_POST);
590 return JSON_OBJECT_CLOSE;
591 } else if (*c == ']') {
593 *ret_value = JSON_VALUE_NULL;
595 *state = INT_TO_PTR(STATE_VALUE_POST);
596 return JSON_ARRAY_CLOSE;
604 static bool json_is_value(JsonVariant *var) {
607 return var->type != JSON_VARIANT_CONTROL;
610 static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) {
611 bool arr = scope->type == JSON_VARIANT_ARRAY;
612 int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE;
613 size_t allocated = 0, size = 0;
614 JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL;
620 } state = arr ? STATE_VALUE : STATE_KEY;
626 while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) {
627 bool stopper = !json_is_value(var) && var->value.integer == terminator;
631 if (state != STATE_COMMA && size > 0)
637 if (state == STATE_KEY) {
638 if (var->type != JSON_VARIANT_STRING)
645 else if (state == STATE_COLON) {
649 if (json_is_value(var))
652 if (var->value.integer != JSON_COLON)
657 else if (state == STATE_VALUE) {
658 _cleanup_jsonunref_ JsonVariant *v = NULL;
659 size_t toadd = arr ? 1 : 2;
661 if (!json_is_value(var)) {
662 int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT;
664 r = json_variant_new(&v, type);
668 r = json_scoped_parse(tokens, i, n, v);
677 if(!GREEDY_REALLOC(items, allocated, size + toadd))
681 r = json_variant_deep_copy(&items[size], value);
685 r = json_variant_deep_copy(&items[size], key);
689 r = json_variant_deep_copy(&items[size+1], value);
697 else if (state == STATE_COMMA) {
698 if (json_is_value(var))
701 if (var->value.integer != JSON_COMMA)
707 state = arr ? STATE_VALUE : STATE_KEY;
712 json_raw_unref(items, size);
717 scope->objects = items;
722 static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) {
726 _cleanup_jsonunref_ JsonVariant *p;
732 r = json_variant_new(&p, JSON_VARIANT_OBJECT);
736 if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN)
739 r = json_scoped_parse(tokens, &it, ntokens, p);
749 static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) {
750 _cleanup_free_ char *buf = NULL;
751 _cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL;
752 union json_value v = {};
753 void *json_state = NULL;
756 size_t allocated = 0, s = 0;
764 buf = strndup(string, size);
770 _cleanup_free_ char *rstr = NULL;
771 _cleanup_jsonunref_ JsonVariant *var = NULL;
773 t = json_tokenize(&p, &rstr, &v, &json_state, NULL);
777 else if (t == JSON_END)
780 if (t <= JSON_ARRAY_CLOSE) {
781 r = json_variant_new(&var, JSON_VARIANT_CONTROL);
784 var->value.integer = t;
788 r = json_variant_new(&var, JSON_VARIANT_STRING);
791 var->size = strlen(rstr);
792 var->string = strdup(rstr);
798 r = json_variant_new(&var, JSON_VARIANT_INTEGER);
804 r = json_variant_new(&var, JSON_VARIANT_REAL);
810 r = json_variant_new(&var, JSON_VARIANT_BOOLEAN);
816 r = json_variant_new(&var, JSON_VARIANT_NULL);
823 if (!GREEDY_REALLOC(items, allocated, s+2))
838 int json_parse(const char *string, JsonVariant **rv) {
839 _cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL;
840 JsonVariant *v = NULL;
847 r = json_tokens(string, strlen(string), &s, &n);
851 r = json_parse_tokens(s, n, &v);