summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/json.c871
-rw-r--r--src/basic/json.h90
-rw-r--r--src/test/test-json.c202
3 files changed, 0 insertions, 1163 deletions
diff --git a/src/basic/json.c b/src/basic/json.c
deleted file mode 100644
index daa98fc815..0000000000
--- a/src/basic/json.c
+++ /dev/null
@@ -1,871 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "alloc-util.h"
-#include "hexdecoct.h"
-#include "json.h"
-#include "macro.h"
-#include "string-util.h"
-#include "utf8.h"
-
-int json_variant_new(JsonVariant **ret, JsonVariantType type) {
- JsonVariant *v;
-
- v = new0(JsonVariant, 1);
- if (!v)
- return -ENOMEM;
- v->type = type;
- *ret = v;
- return 0;
-}
-
-static int json_variant_deep_copy(JsonVariant *ret, JsonVariant *variant) {
- int r;
-
- assert(ret);
- assert(variant);
-
- ret->type = variant->type;
- ret->size = variant->size;
-
- if (variant->type == JSON_VARIANT_STRING) {
- ret->string = memdup(variant->string, variant->size+1);
- if (!ret->string)
- return -ENOMEM;
- } else if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT) {
- size_t i;
-
- ret->objects = new0(JsonVariant, variant->size);
- if (!ret->objects)
- return -ENOMEM;
-
- for (i = 0; i < variant->size; ++i) {
- r = json_variant_deep_copy(&ret->objects[i], &variant->objects[i]);
- if (r < 0)
- return r;
- }
- } else
- ret->value = variant->value;
-
- return 0;
-}
-
-static JsonVariant *json_object_unref(JsonVariant *variant);
-
-static JsonVariant *json_variant_unref_inner(JsonVariant *variant) {
- if (!variant)
- return NULL;
-
- if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
- return json_object_unref(variant);
- else if (variant->type == JSON_VARIANT_STRING)
- free(variant->string);
-
- return NULL;
-}
-
-static JsonVariant *json_raw_unref(JsonVariant *variant, size_t size) {
- if (!variant)
- return NULL;
-
- for (size_t i = 0; i < size; ++i)
- json_variant_unref_inner(&variant[i]);
-
- free(variant);
- return NULL;
-}
-
-static JsonVariant *json_object_unref(JsonVariant *variant) {
- size_t i;
-
- assert(variant);
-
- if (!variant->objects)
- return NULL;
-
- for (i = 0; i < variant->size; ++i)
- json_variant_unref_inner(&variant->objects[i]);
-
- free(variant->objects);
- return NULL;
-}
-
-static JsonVariant **json_variant_array_unref(JsonVariant **variant) {
- size_t i = 0;
- JsonVariant *p = NULL;
-
- if (!variant)
- return NULL;
-
- while((p = (variant[i++])) != NULL) {
- if (p->type == JSON_VARIANT_STRING)
- free(p->string);
- free(p);
- }
-
- free(variant);
-
- return NULL;
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant **, json_variant_array_unref);
-
-JsonVariant *json_variant_unref(JsonVariant *variant) {
- if (!variant)
- return NULL;
-
- if (variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT)
- json_object_unref(variant);
- else if (variant->type == JSON_VARIANT_STRING)
- free(variant->string);
-
- free(variant);
-
- return NULL;
-}
-
-char *json_variant_string(JsonVariant *variant){
- assert(variant);
- assert(variant->type == JSON_VARIANT_STRING);
-
- return variant->string;
-}
-
-bool json_variant_bool(JsonVariant *variant) {
- assert(variant);
- assert(variant->type == JSON_VARIANT_BOOLEAN);
-
- return variant->value.boolean;
-}
-
-intmax_t json_variant_integer(JsonVariant *variant) {
- assert(variant);
- assert(variant->type == JSON_VARIANT_INTEGER);
-
- return variant->value.integer;
-}
-
-double json_variant_real(JsonVariant *variant) {
- assert(variant);
- assert(variant->type == JSON_VARIANT_REAL);
-
- return variant->value.real;
-}
-
-JsonVariant *json_variant_element(JsonVariant *variant, unsigned index) {
- assert(variant);
- assert(variant->type == JSON_VARIANT_ARRAY || variant->type == JSON_VARIANT_OBJECT);
- assert(index < variant->size);
- assert(variant->objects);
-
- return &variant->objects[index];
-}
-
-JsonVariant *json_variant_value(JsonVariant *variant, const char *key) {
- size_t i;
-
- assert(variant);
- assert(variant->type == JSON_VARIANT_OBJECT);
- assert(variant->objects);
-
- for (i = 0; i < variant->size; i += 2) {
- JsonVariant *p = &variant->objects[i];
- if (p->type == JSON_VARIANT_STRING && streq(key, p->string))
- return &variant->objects[i + 1];
- }
-
- return NULL;
-}
-
-static void inc_lines(unsigned *line, const char *s, size_t n) {
- const char *p = s;
-
- if (!line)
- return;
-
- for (;;) {
- const char *f;
-
- f = memchr(p, '\n', n);
- if (!f)
- return;
-
- n -= (f - p) + 1;
- p = f + 1;
- (*line)++;
- }
-}
-
-static int unhex_ucs2(const char *c, uint16_t *ret) {
- int aa, bb, cc, dd;
- uint16_t x;
-
- assert(c);
- assert(ret);
-
- aa = unhexchar(c[0]);
- if (aa < 0)
- return -EINVAL;
-
- bb = unhexchar(c[1]);
- if (bb < 0)
- return -EINVAL;
-
- cc = unhexchar(c[2]);
- if (cc < 0)
- return -EINVAL;
-
- dd = unhexchar(c[3]);
- if (dd < 0)
- return -EINVAL;
-
- x = ((uint16_t) aa << 12) |
- ((uint16_t) bb << 8) |
- ((uint16_t) cc << 4) |
- ((uint16_t) dd);
-
- if (x <= 0)
- return -EINVAL;
-
- *ret = x;
-
- return 0;
-}
-
-static int json_parse_string(const char **p, char **ret) {
- _cleanup_free_ char *s = NULL;
- size_t n = 0, allocated = 0;
- const char *c;
-
- assert(p);
- assert(*p);
- assert(ret);
-
- c = *p;
-
- if (*c != '"')
- return -EINVAL;
-
- c++;
-
- for (;;) {
- int len;
-
- /* Check for EOF */
- if (*c == 0)
- return -EINVAL;
-
- /* Check for control characters 0x00..0x1f */
- if (*c > 0 && *c < ' ')
- return -EINVAL;
-
- /* Check for control character 0x7f */
- if (*c == 0x7f)
- return -EINVAL;
-
- if (*c == '"') {
- if (!s) {
- s = strdup("");
- if (!s)
- return -ENOMEM;
- } else
- s[n] = 0;
-
- *p = c + 1;
-
- *ret = s;
- s = NULL;
- return JSON_STRING;
- }
-
- if (*c == '\\') {
- char ch = 0;
- c++;
-
- if (*c == 0)
- return -EINVAL;
-
- if (IN_SET(*c, '"', '\\', '/'))
- ch = *c;
- else if (*c == 'b')
- ch = '\b';
- else if (*c == 'f')
- ch = '\f';
- else if (*c == 'n')
- ch = '\n';
- else if (*c == 'r')
- ch = '\r';
- else if (*c == 't')
- ch = '\t';
- else if (*c == 'u') {
- char16_t x;
- int r;
-
- r = unhex_ucs2(c + 1, &x);
- if (r < 0)
- return r;
-
- c += 5;
-
- if (!GREEDY_REALLOC(s, allocated, n + 4))
- return -ENOMEM;
-
- if (!utf16_is_surrogate(x))
- n += utf8_encode_unichar(s + n, (char32_t) x);
- else if (utf16_is_trailing_surrogate(x))
- return -EINVAL;
- else {
- char16_t y;
-
- if (c[0] != '\\' || c[1] != 'u')
- return -EINVAL;
-
- r = unhex_ucs2(c + 2, &y);
- if (r < 0)
- return r;
-
- c += 6;
-
- if (!utf16_is_trailing_surrogate(y))
- return -EINVAL;
-
- n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
- }
-
- continue;
- } else
- return -EINVAL;
-
- if (!GREEDY_REALLOC(s, allocated, n + 2))
- return -ENOMEM;
-
- s[n++] = ch;
- c ++;
- continue;
- }
-
- len = utf8_encoded_valid_unichar(c);
- if (len < 0)
- return len;
-
- if (!GREEDY_REALLOC(s, allocated, n + len + 1))
- return -ENOMEM;
-
- memcpy(s + n, c, len);
- n += len;
- c += len;
- }
-}
-
-static int json_parse_number(const char **p, union json_value *ret) {
- bool negative = false, exponent_negative = false, is_double = false;
- double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
- intmax_t i = 0;
- const char *c;
-
- assert(p);
- assert(*p);
- assert(ret);
-
- c = *p;
-
- if (*c == '-') {
- negative = true;
- c++;
- }
-
- if (*c == '0')
- c++;
- else {
- if (!strchr("123456789", *c) || *c == 0)
- return -EINVAL;
-
- do {
- if (!is_double) {
- int64_t t;
-
- t = 10 * i + (*c - '0');
- if (t < i) /* overflow */
- is_double = false;
- else
- i = t;
- }
-
- x = 10.0 * x + (*c - '0');
- c++;
- } while (strchr("0123456789", *c) && *c != 0);
- }
-
- if (*c == '.') {
- is_double = true;
- c++;
-
- if (!strchr("0123456789", *c) || *c == 0)
- return -EINVAL;
-
- do {
- y = 10.0 * y + (*c - '0');
- shift = 10.0 * shift;
- c++;
- } while (strchr("0123456789", *c) && *c != 0);
- }
-
- if (*c == 'e' || *c == 'E') {
- is_double = true;
- c++;
-
- if (*c == '-') {
- exponent_negative = true;
- c++;
- } else if (*c == '+')
- c++;
-
- if (!strchr("0123456789", *c) || *c == 0)
- return -EINVAL;
-
- do {
- exponent = 10.0 * exponent + (*c - '0');
- c++;
- } while (strchr("0123456789", *c) && *c != 0);
- }
-
- *p = c;
-
- if (is_double) {
- ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10((exponent_negative ? -1.0 : 1.0) * exponent);
- return JSON_REAL;
- } else {
- ret->integer = negative ? -i : i;
- return JSON_INTEGER;
- }
-}
-
-int json_tokenize(
- const char **p,
- char **ret_string,
- union json_value *ret_value,
- void **state,
- unsigned *line) {
-
- const char *c;
- int t;
- int r;
-
- enum {
- STATE_NULL,
- STATE_VALUE,
- STATE_VALUE_POST,
- };
-
- assert(p);
- assert(*p);
- assert(ret_string);
- assert(ret_value);
- assert(state);
-
- t = PTR_TO_INT(*state);
- c = *p;
-
- if (t == STATE_NULL) {
- if (line)
- *line = 1;
- t = STATE_VALUE;
- }
-
- for (;;) {
- const char *b;
-
- b = c + strspn(c, WHITESPACE);
- if (*b == 0)
- return JSON_END;
-
- inc_lines(line, c, b - c);
- c = b;
-
- switch (t) {
-
- case STATE_VALUE:
-
- if (*c == '{') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE);
- return JSON_OBJECT_OPEN;
-
- } else if (*c == '}') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return JSON_OBJECT_CLOSE;
-
- } else if (*c == '[') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE);
- return JSON_ARRAY_OPEN;
-
- } else if (*c == ']') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return JSON_ARRAY_CLOSE;
-
- } else if (*c == '"') {
- r = json_parse_string(&c, ret_string);
- if (r < 0)
- return r;
-
- *ret_value = JSON_VALUE_NULL;
- *p = c;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return r;
-
- } else if (strchr("-0123456789", *c)) {
- r = json_parse_number(&c, ret_value);
- if (r < 0)
- return r;
-
- *ret_string = NULL;
- *p = c;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return r;
-
- } else if (startswith(c, "true")) {
- *ret_string = NULL;
- ret_value->boolean = true;
- *p = c + 4;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return JSON_BOOLEAN;
-
- } else if (startswith(c, "false")) {
- *ret_string = NULL;
- ret_value->boolean = false;
- *p = c + 5;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return JSON_BOOLEAN;
-
- } else if (startswith(c, "null")) {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 4;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return JSON_NULL;
-
- } else
- return -EINVAL;
-
- case STATE_VALUE_POST:
-
- if (*c == ':') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE);
- return JSON_COLON;
- } else if (*c == ',') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE);
- return JSON_COMMA;
- } else if (*c == '}') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return JSON_OBJECT_CLOSE;
- } else if (*c == ']') {
- *ret_string = NULL;
- *ret_value = JSON_VALUE_NULL;
- *p = c + 1;
- *state = INT_TO_PTR(STATE_VALUE_POST);
- return JSON_ARRAY_CLOSE;
- } else
- return -EINVAL;
- }
-
- }
-}
-
-static bool json_is_value(JsonVariant *var) {
- assert(var);
-
- return var->type != JSON_VARIANT_CONTROL;
-}
-
-static int json_scoped_parse(JsonVariant **tokens, size_t *i, size_t n, JsonVariant *scope) {
- bool arr = scope->type == JSON_VARIANT_ARRAY;
- int terminator = arr ? JSON_ARRAY_CLOSE : JSON_OBJECT_CLOSE;
- size_t allocated = 0, size = 0;
- JsonVariant *key = NULL, *value = NULL, *var = NULL, *items = NULL;
- enum {
- STATE_KEY,
- STATE_COLON,
- STATE_COMMA,
- STATE_VALUE
- } state = arr ? STATE_VALUE : STATE_KEY;
-
- assert(tokens);
- assert(i);
- assert(scope);
-
- while((var = *i < n ? tokens[(*i)++] : NULL) != NULL) {
- bool stopper;
- int r;
-
- stopper = !json_is_value(var) && var->value.integer == terminator;
-
- if (stopper) {
- if (state != STATE_COMMA && size > 0)
- goto error;
-
- goto out;
- }
-
- if (state == STATE_KEY) {
- if (var->type != JSON_VARIANT_STRING)
- goto error;
- else {
- key = var;
- state = STATE_COLON;
- }
- }
- else if (state == STATE_COLON) {
- if (key == NULL)
- goto error;
-
- if (json_is_value(var))
- goto error;
-
- if (var->value.integer != JSON_COLON)
- goto error;
-
- state = STATE_VALUE;
- }
- else if (state == STATE_VALUE) {
- _cleanup_json_variant_unref_ JsonVariant *v = NULL;
- size_t toadd = arr ? 1 : 2;
-
- if (!json_is_value(var)) {
- int type = (var->value.integer == JSON_ARRAY_OPEN) ? JSON_VARIANT_ARRAY : JSON_VARIANT_OBJECT;
-
- r = json_variant_new(&v, type);
- if (r < 0)
- goto error;
-
- r = json_scoped_parse(tokens, i, n, v);
- if (r < 0)
- goto error;
-
- value = v;
- }
- else
- value = var;
-
- if(!GREEDY_REALLOC(items, allocated, size + toadd))
- goto error;
-
- if (arr) {
- r = json_variant_deep_copy(&items[size], value);
- if (r < 0)
- goto error;
- } else {
- r = json_variant_deep_copy(&items[size], key);
- if (r < 0)
- goto error;
-
- r = json_variant_deep_copy(&items[size+1], value);
- if (r < 0)
- goto error;
- }
-
- size += toadd;
- state = STATE_COMMA;
- }
- else if (state == STATE_COMMA) {
- if (json_is_value(var))
- goto error;
-
- if (var->value.integer != JSON_COMMA)
- goto error;
-
- key = NULL;
- value = NULL;
-
- state = arr ? STATE_VALUE : STATE_KEY;
- }
- }
-
-error:
- json_raw_unref(items, size);
- return -EBADMSG;
-
-out:
- scope->size = size;
- scope->objects = items;
-
- return scope->type;
-}
-
-static int json_parse_tokens(JsonVariant **tokens, size_t ntokens, JsonVariant **rv) {
- size_t it = 0;
- int r;
- JsonVariant *e;
- _cleanup_json_variant_unref_ JsonVariant *p = NULL;
-
- assert(tokens);
- assert(ntokens);
-
- e = tokens[it++];
- r = json_variant_new(&p, JSON_VARIANT_OBJECT);
- if (r < 0)
- return r;
-
- if (e->type != JSON_VARIANT_CONTROL && e->value.integer != JSON_OBJECT_OPEN)
- return -EBADMSG;
-
- r = json_scoped_parse(tokens, &it, ntokens, p);
- if (r < 0)
- return r;
-
- *rv = p;
- p = NULL;
-
- return 0;
-}
-
-static int json_tokens(const char *string, size_t size, JsonVariant ***tokens, size_t *n) {
- _cleanup_free_ char *buf = NULL;
- _cleanup_(json_variant_array_unrefp) JsonVariant **items = NULL;
- union json_value v = {};
- void *json_state = NULL;
- const char *p;
- int t, r;
- size_t allocated = 0, s = 0;
-
- assert(string);
- assert(n);
-
- if (size <= 0)
- return -EBADMSG;
-
- buf = strndup(string, size);
- if (!buf)
- return -ENOMEM;
-
- p = buf;
- for (;;) {
- _cleanup_json_variant_unref_ JsonVariant *var = NULL;
- _cleanup_free_ char *rstr = NULL;
-
- t = json_tokenize(&p, &rstr, &v, &json_state, NULL);
-
- if (t < 0)
- return t;
- else if (t == JSON_END)
- break;
-
- if (t <= JSON_ARRAY_CLOSE) {
- r = json_variant_new(&var, JSON_VARIANT_CONTROL);
- if (r < 0)
- return r;
- var->value.integer = t;
- } else {
- switch (t) {
- case JSON_STRING:
- r = json_variant_new(&var, JSON_VARIANT_STRING);
- if (r < 0)
- return r;
- var->size = strlen(rstr);
- var->string = strdup(rstr);
- if (!var->string) {
- return -ENOMEM;
- }
- break;
- case JSON_INTEGER:
- r = json_variant_new(&var, JSON_VARIANT_INTEGER);
- if (r < 0)
- return r;
- var->value = v;
- break;
- case JSON_REAL:
- r = json_variant_new(&var, JSON_VARIANT_REAL);
- if (r < 0)
- return r;
- var->value = v;
- break;
- case JSON_BOOLEAN:
- r = json_variant_new(&var, JSON_VARIANT_BOOLEAN);
- if (r < 0)
- return r;
- var->value = v;
- break;
- case JSON_NULL:
- r = json_variant_new(&var, JSON_VARIANT_NULL);
- if (r < 0)
- return r;
- break;
- }
- }
-
- if (!GREEDY_REALLOC(items, allocated, s+2))
- return -ENOMEM;
-
- items[s++] = var;
- items[s] = NULL;
- var = NULL;
- }
-
- *n = s;
- *tokens = items;
- items = NULL;
-
- return 0;
-}
-
-int json_parse(const char *string, JsonVariant **rv) {
- _cleanup_(json_variant_array_unrefp) JsonVariant **s = NULL;
- JsonVariant *v = NULL;
- size_t n = 0;
- int r;
-
- assert(string);
- assert(rv);
-
- r = json_tokens(string, strlen(string), &s, &n);
- if (r < 0)
- return r;
-
- r = json_parse_tokens(s, n, &v);
- if (r < 0)
- return r;
-
- *rv = v;
- return 0;
-}
diff --git a/src/basic/json.h b/src/basic/json.h
deleted file mode 100644
index a4509f680f..0000000000
--- a/src/basic/json.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "macro.h"
-#include "util.h"
-
-enum {
- JSON_END,
- JSON_COLON,
- JSON_COMMA,
- JSON_OBJECT_OPEN,
- JSON_OBJECT_CLOSE,
- JSON_ARRAY_OPEN,
- JSON_ARRAY_CLOSE,
- JSON_STRING,
- JSON_REAL,
- JSON_INTEGER,
- JSON_BOOLEAN,
- JSON_NULL,
-};
-
-typedef enum {
- JSON_VARIANT_CONTROL,
- JSON_VARIANT_STRING,
- JSON_VARIANT_INTEGER,
- JSON_VARIANT_BOOLEAN,
- JSON_VARIANT_REAL,
- JSON_VARIANT_ARRAY,
- JSON_VARIANT_OBJECT,
- JSON_VARIANT_NULL
-} JsonVariantType;
-
-union json_value {
- bool boolean;
- double real;
- intmax_t integer;
-};
-
-typedef struct JsonVariant {
- JsonVariantType type;
- size_t size;
- union {
- char *string;
- struct JsonVariant *objects;
- union json_value value;
- };
-} JsonVariant;
-
-int json_variant_new(JsonVariant **ret, JsonVariantType type);
-JsonVariant *json_variant_unref(JsonVariant *v);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
-#define _cleanup_json_variant_unref_ _cleanup_(json_variant_unrefp)
-
-char *json_variant_string(JsonVariant *v);
-bool json_variant_bool(JsonVariant *v);
-intmax_t json_variant_integer(JsonVariant *v);
-double json_variant_real(JsonVariant *v);
-
-JsonVariant *json_variant_element(JsonVariant *v, unsigned index);
-JsonVariant *json_variant_value(JsonVariant *v, const char *key);
-
-#define JSON_VALUE_NULL ((union json_value) {})
-
-int json_tokenize(const char **p, char **ret_string, union json_value *ret_value, void **state, unsigned *line);
-
-int json_parse(const char *string, JsonVariant **rv);
-int json_parse_measure(const char *string, size_t *size);
diff --git a/src/test/test-json.c b/src/test/test-json.c
deleted file mode 100644
index 3fe2f58d04..0000000000
--- a/src/test/test-json.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <math.h>
-
-#include "alloc-util.h"
-#include "json.h"
-#include "string-util.h"
-#include "util.h"
-
-static void test_one(const char *data, ...) {
- void *state = NULL;
- va_list ap;
-
- va_start(ap, data);
-
- for (;;) {
- _cleanup_free_ char *str = NULL;
- union json_value v = {};
- int t, tt;
-
- t = json_tokenize(&data, &str, &v, &state, NULL);
- tt = va_arg(ap, int);
-
- assert_se(t == tt);
-
- if (t == JSON_END || t < 0)
- break;
-
- else if (t == JSON_STRING) {
- const char *nn;
-
- nn = va_arg(ap, const char *);
- assert_se(streq_ptr(nn, str));
-
- } else if (t == JSON_REAL) {
- double d;
-
- d = va_arg(ap, double);
- assert_se(fabs(d - v.real) < 0.001);
-
- } else if (t == JSON_INTEGER) {
- intmax_t i;
-
- i = va_arg(ap, intmax_t);
- assert_se(i == v.integer);
-
- } else if (t == JSON_BOOLEAN) {
- bool b;
-
- b = va_arg(ap, int);
- assert_se(b == v.boolean);
- }
- }
-
- va_end(ap);
-}
-
-typedef void (*Test)(JsonVariant *);
-
-static void test_file(const char *data, Test test) {
- _cleanup_json_variant_unref_ JsonVariant *v = NULL;
- int r;
-
- r = json_parse(data, &v);
- assert_se(r == 0);
- assert_se(v != NULL);
- assert_se(v->type == JSON_VARIANT_OBJECT);
-
- if (test)
- test(v);
-}
-
-static void test_1(JsonVariant *v) {
- JsonVariant *p, *q;
- unsigned i;
-
- /* 3 keys + 3 values */
- assert_se(v->size == 6);
-
- /* has k */
- p = json_variant_value(v, "k");
- assert_se(p && p->type == JSON_VARIANT_STRING);
-
- /* k equals v */
- assert_se(streq(json_variant_string(p), "v"));
-
- /* has foo */
- p = json_variant_value(v, "foo");
- assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 3);
-
- /* check foo[0] = 1, foo[1] = 2, foo[2] = 3 */
- for (i = 0; i < 3; ++i) {
- q = json_variant_element(p, i);
- assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == (i+1));
- }
-
- /* has bar */
- p = json_variant_value(v, "bar");
- assert_se(p && p->type == JSON_VARIANT_OBJECT && p->size == 2);
-
- /* zap is null */
- q = json_variant_value(p, "zap");
- assert_se(q && q->type == JSON_VARIANT_NULL);
-}
-
-static void test_2(JsonVariant *v) {
- JsonVariant *p, *q;
-
- /* 2 keys + 2 values */
- assert_se(v->size == 4);
-
- /* has mutant */
- p = json_variant_value(v, "mutant");
- assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 4);
-
- /* mutant[0] == 1 */
- q = json_variant_element(p, 0);
- assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1);
-
- /* mutant[1] == null */
- q = json_variant_element(p, 1);
- assert_se(q && q->type == JSON_VARIANT_NULL);
-
- /* mutant[2] == "1" */
- q = json_variant_element(p, 2);
- assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
-
- /* mutant[3] == JSON_VARIANT_OBJECT */
- q = json_variant_element(p, 3);
- assert_se(q && q->type == JSON_VARIANT_OBJECT && q->size == 2);
-
- /* has 1 */
- p = json_variant_value(q, "1");
- assert_se(p && p->type == JSON_VARIANT_ARRAY && p->size == 2);
-
- /* "1"[0] == 1 */
- q = json_variant_element(p, 0);
- assert_se(q && q->type == JSON_VARIANT_INTEGER && json_variant_integer(q) == 1);
-
- /* "1"[1] == "1" */
- q = json_variant_element(p, 1);
- assert_se(q && q->type == JSON_VARIANT_STRING && streq(json_variant_string(q), "1"));
-
- /* has blah */
- p = json_variant_value(v, "blah");
- assert_se(p && p->type == JSON_VARIANT_REAL && fabs(json_variant_real(p) - 1.27) < 0.001);
-}
-
-int main(int argc, char *argv[]) {
-
- test_one("x", -EINVAL);
- test_one("", JSON_END);
- test_one(" ", JSON_END);
- test_one("0", JSON_INTEGER, (intmax_t) 0, JSON_END);
- test_one("1234", JSON_INTEGER, (intmax_t) 1234, JSON_END);
- test_one("3.141", JSON_REAL, 3.141, JSON_END);
- test_one("0.0", JSON_REAL, 0.0, JSON_END);
- test_one("7e3", JSON_REAL, 7e3, JSON_END);
- test_one("-7e-3", JSON_REAL, -7e-3, JSON_END);
- test_one("true", JSON_BOOLEAN, true, JSON_END);
- test_one("false", JSON_BOOLEAN, false, JSON_END);
- test_one("null", JSON_NULL, JSON_END);
- test_one("{}", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END);
- test_one("\t {\n} \n", JSON_OBJECT_OPEN, JSON_OBJECT_CLOSE, JSON_END);
- test_one("[]", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END);
- test_one("\t [] \n\n", JSON_ARRAY_OPEN, JSON_ARRAY_CLOSE, JSON_END);
- test_one("\"\"", JSON_STRING, "", JSON_END);
- test_one("\"foo\"", JSON_STRING, "foo", JSON_END);
- test_one("\"foo\\nfoo\"", JSON_STRING, "foo\nfoo", JSON_END);
- test_one("{\"foo\" : \"bar\"}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_STRING, "bar", JSON_OBJECT_CLOSE, JSON_END);
- test_one("{\"foo\" : [true, false]}", JSON_OBJECT_OPEN, JSON_STRING, "foo", JSON_COLON, JSON_ARRAY_OPEN, JSON_BOOLEAN, true, JSON_COMMA, JSON_BOOLEAN, false, JSON_ARRAY_CLOSE, JSON_OBJECT_CLOSE, JSON_END);
- test_one("\"\xef\xbf\xbd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END);
- test_one("\"\\ufffd\"", JSON_STRING, "\xef\xbf\xbd", JSON_END);
- test_one("\"\\uf\"", -EINVAL);
- test_one("\"\\ud800a\"", -EINVAL);
- test_one("\"\\udc00\\udc00\"", -EINVAL);
- test_one("\"\\ud801\\udc37\"", JSON_STRING, "\xf0\x90\x90\xb7", JSON_END);
-
- test_one("[1, 2]", JSON_ARRAY_OPEN, JSON_INTEGER, (intmax_t) 1, JSON_COMMA, JSON_INTEGER, (intmax_t) 2, JSON_ARRAY_CLOSE, JSON_END);
-
- test_file("{\"k\": \"v\", \"foo\": [1, 2, 3], \"bar\": {\"zap\": null}}", test_1);
- test_file("{\"mutant\": [1, null, \"1\", {\"1\": [1, \"1\"]}], \"blah\": 1.27}", test_2);
-
- return 0;
-}