From: Daan De Meyer Date: Fri, 20 Oct 2023 10:31:56 +0000 (+0200) Subject: json: Introduce JSON_BUILD_CALLBACK X-Git-Tag: v255-rc1~182^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F29630%2Fhead;p=thirdparty%2Fsystemd.git json: Introduce JSON_BUILD_CALLBACK --- diff --git a/src/shared/json.c b/src/shared/json.c index db3581dfd4a..592ab356383 100644 --- a/src/shared/json.c +++ b/src/shared/json.c @@ -3351,6 +3351,7 @@ int json_parse_file_at( int json_buildv(JsonVariant **ret, va_list ap) { JsonStack *stack = NULL; size_t n_stack = 1; + const char *name = NULL; int r; assert_return(ret, -EINVAL); @@ -3912,6 +3913,43 @@ int json_buildv(JsonVariant **ret, va_list ap) { break; } + case _JSON_BUILD_CALLBACK: { + JsonBuildCallback cb; + void *userdata; + + if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { + r = -EINVAL; + goto finish; + } + + cb = va_arg(ap, JsonBuildCallback); + userdata = va_arg(ap, void *); + + if (current->n_suppress == 0) { + if (cb) { + r = cb(&add, name, userdata); + if (r < 0) + goto finish; + } + + if (!add) + add = JSON_VARIANT_MAGIC_NULL; + + name = NULL; + } + + n_subtract = 1; + + if (current->expect == EXPECT_TOPLEVEL) + current->expect = EXPECT_END; + else if (current->expect == EXPECT_OBJECT_VALUE) + current->expect = EXPECT_OBJECT_KEY; + else + assert(current->expect == EXPECT_ARRAY_ELEMENT); + + break; + } + case _JSON_BUILD_OBJECT_BEGIN: if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) { @@ -3965,17 +4003,16 @@ int json_buildv(JsonVariant **ret, va_list ap) { break; case _JSON_BUILD_PAIR: { - const char *n; if (current->expect != EXPECT_OBJECT_KEY) { r = -EINVAL; goto finish; } - n = va_arg(ap, const char *); + name = va_arg(ap, const char *); if (current->n_suppress == 0) { - r = json_variant_new_string(&add, n); + r = json_variant_new_string(&add, name); if (r < 0) goto finish; } @@ -3987,7 +4024,6 @@ int json_buildv(JsonVariant **ret, va_list ap) { } case _JSON_BUILD_PAIR_CONDITION: { - const char *n; bool b; if (current->expect != EXPECT_OBJECT_KEY) { @@ -3996,10 +4032,10 @@ int json_buildv(JsonVariant **ret, va_list ap) { } b = va_arg(ap, int); - n = va_arg(ap, const char *); + name = va_arg(ap, const char *); if (b && current->n_suppress == 0) { - r = json_variant_new_string(&add, n); + r = json_variant_new_string(&add, name); if (r < 0) goto finish; } diff --git a/src/shared/json.h b/src/shared/json.h index 4b25d36a325..f24fabfeb6a 100644 --- a/src/shared/json.h +++ b/src/shared/json.h @@ -276,6 +276,7 @@ enum { _JSON_BUILD_BYTE_ARRAY, _JSON_BUILD_HW_ADDR, _JSON_BUILD_STRING_SET, + _JSON_BUILD_CALLBACK, _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO, _JSON_BUILD_PAIR_FINITE_USEC, _JSON_BUILD_PAIR_STRING_NON_EMPTY, @@ -290,6 +291,8 @@ enum { _JSON_BUILD_MAX, }; +typedef int (*JsonBuildCallback)(JsonVariant **ret, const char *name, void *userdata); + #define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, (const char*) { s } #define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, (int64_t) { i } #define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, (uint64_t) { u } @@ -321,6 +324,7 @@ enum { #define JSON_BUILD_ETHER_ADDR(v) JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr)) #define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v } #define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s } +#define JSON_BUILD_CALLBACK(c, u) _JSON_BUILD_CALLBACK, (JsonBuildCallback) { c }, (void*) { u } #define JSON_BUILD_PAIR_STRING(name, s) JSON_BUILD_PAIR(name, JSON_BUILD_STRING(s)) #define JSON_BUILD_PAIR_INTEGER(name, i) JSON_BUILD_PAIR(name, JSON_BUILD_INTEGER(i)) @@ -347,6 +351,7 @@ enum { #define JSON_BUILD_PAIR_ETHER_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v)) #define JSON_BUILD_PAIR_HW_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_HW_ADDR(v)) #define JSON_BUILD_PAIR_STRING_SET(name, s) JSON_BUILD_PAIR(name, JSON_BUILD_STRING_SET(s)) +#define JSON_BUILD_PAIR_CALLBACK(name, c, u) JSON_BUILD_PAIR(name, JSON_BUILD_CALLBACK(c, u)) #define JSON_BUILD_PAIR_UNSIGNED_NON_ZERO(name, u) _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO, (const char*) { name }, (uint64_t) { u } #define JSON_BUILD_PAIR_FINITE_USEC(name, u) _JSON_BUILD_PAIR_FINITE_USEC, (const char*) { name }, (usec_t) { u }