return r;
}
-int json_parse(const char *input, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
- return json_parse_internal(&input, NULL, flags, ret, ret_line, ret_column, false);
+int json_parse_with_source(
+ const char *input,
+ const char *source,
+ JsonParseFlags flags,
+ JsonVariant **ret,
+ unsigned *ret_line,
+ unsigned *ret_column) {
+
+ _cleanup_(json_source_unrefp) JsonSource *s = NULL;
+
+ if (source) {
+ s = json_source_new(source);
+ if (!s)
+ return -ENOMEM;
+ }
+
+ return json_parse_internal(&input, s, flags, ret, ret_line, ret_column, false);
}
-int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
- return json_parse_internal(p, NULL, flags, ret, ret_line, ret_column, true);
+int json_parse_with_source_continue(
+ const char **p,
+ const char *source,
+ JsonParseFlags flags,
+ JsonVariant **ret,
+ unsigned *ret_line,
+ unsigned *ret_column) {
+
+ _cleanup_(json_source_unrefp) JsonSource *s = NULL;
+
+ if (source) {
+ s = json_source_new(source);
+ if (!s)
+ return -ENOMEM;
+ }
+
+ return json_parse_internal(p, s, flags, ret, ret_line, ret_column, true);
}
-int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
- _cleanup_(json_source_unrefp) JsonSource *source = NULL;
+int json_parse_file_at(
+ FILE *f,
+ int dir_fd,
+ const char *path,
+ JsonParseFlags flags,
+ JsonVariant **ret,
+ unsigned *ret_line,
+ unsigned *ret_column) {
+
_cleanup_free_ char *text = NULL;
int r;
if (isempty(text))
return -ENODATA;
- if (path) {
- source = json_source_new(path);
- if (!source)
- return -ENOMEM;
- }
-
- const char *p = text;
- return json_parse_internal(&p, source, flags, ret, ret_line, ret_column, false);
+ return json_parse_with_source(text, path, flags, ret, ret_line, ret_column);
}
int json_buildv(JsonVariant **ret, va_list ap) {
JSON_PARSE_SENSITIVE = 1 << 0, /* mark variant as "sensitive", i.e. something containing secret key material or such */
} JsonParseFlags;
-int json_parse(const char *string, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
-int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
+int json_parse_with_source(const char *string, const char *source, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
+int json_parse_with_source_continue(const char **p, const char *source, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
+
+static inline int json_parse(const char *string, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
+ return json_parse_with_source(string, NULL, flags, ret, ret_line, ret_column);
+}
+static inline int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
+ return json_parse_with_source_continue(p, NULL, flags, ret, ret_line, ret_column);
+}
+
int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
static inline int json_parse_file(FILE *f, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
assert_se(json_variant_equal(v, w));
}
+static inline void json_array_append_with_source_one(bool source) {
+ _cleanup_(json_variant_unrefp) JsonVariant *a, *b;
+
+ /* Parse two sources, each with a different name and line/column numbers */
+
+ assert_se(json_parse_with_source(" [41]", source ? "string 1" : NULL, 0,
+ &a, NULL, NULL) >= 0);
+ assert_se(json_parse_with_source("\n\n [42]", source ? "string 2" : NULL, 0,
+ &b, NULL, NULL) >= 0);
+
+ assert_se(json_variant_is_array(a));
+ assert_se(json_variant_elements(a) == 1);
+ assert_se(json_variant_is_array(b));
+ assert_se(json_variant_elements(b) == 1);
+
+ /* Verify source information */
+
+ const char *s1, *s2;
+ unsigned line1, col1, line2, col2;
+ assert_se(json_variant_get_source(a, &s1, &line1, &col1) >= 0);
+ assert_se(json_variant_get_source(b, &s2, &line2, &col2) >= 0);
+
+ assert_se(streq_ptr(s1, source ? "string 1" : NULL));
+ assert_se(streq_ptr(s2, source ? "string 2" : NULL));
+ assert_se(line1 == 1);
+ assert_se(col1 == 2);
+ assert_se(line2 == 3);
+ assert_se(col2 == 4);
+
+ /* Append one elem from the second array (and source) to the first. */
+
+ JsonVariant *elem;
+ assert_se(elem = json_variant_by_index(b, 0));
+ assert_se(json_variant_is_integer(elem));
+ assert_se(json_variant_elements(elem) == 0);
+
+ assert_se(json_variant_append_array(&a, elem) >= 0);
+
+ assert_se(json_variant_is_array(a));
+ assert_se(json_variant_elements(a) == 2);
+
+ /* Verify that source information was propagated correctly */
+
+ assert_se(json_variant_get_source(elem, &s1, &line1, &col1) >= 0);
+ assert_se(elem = json_variant_by_index(a, 1));
+ assert_se(json_variant_get_source(elem, &s2, &line2, &col2) >= 0);
+
+ assert_se(streq_ptr(s1, source ? "string 2" : NULL));
+ assert_se(streq_ptr(s2, source ? "string 2" : NULL));
+ assert_se(line1 == 3);
+ assert_se(col1 == 5);
+ assert_se(line2 == 3);
+ assert_se(col2 == 5);
+}
+
+TEST(json_array_append_with_source) {
+ json_array_append_with_source_one(true);
+}
+
+TEST(json_array_append_without_source) {
+ json_array_append_with_source_one(false);
+}
+
DEFINE_TEST_MAIN(LOG_DEBUG);