From: Daan De Meyer Date: Fri, 9 Aug 2024 11:40:43 +0000 (+0200) Subject: json-util: Add JSON_BUILD_PAIR_CALLBACK_NON_NULL() X-Git-Tag: v257-rc1~567^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ba489c7f6d6da48772ed3f7862c781340aecda7;p=thirdparty%2Fsystemd.git json-util: Add JSON_BUILD_PAIR_CALLBACK_NON_NULL() Like JSON_BUILD_PAIR_CALLBACK(), but doesn't add anything to the variant if the callback doesn't put anything in the return argument. --- diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h index 3be5f75878c..2d8322ab387 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -156,6 +156,7 @@ enum { _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, _JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL, _JSON_BUILD_PAIR_RATELIMIT_ENABLED, + _JSON_BUILD_PAIR_CALLBACK_NON_NULL, _SD_JSON_BUILD_REALLYMAX, }; @@ -187,6 +188,7 @@ enum { #define JSON_BUILD_PAIR_HW_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, (const char*) { name }, (const struct hw_addr_data*) { v } #define JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL(name, t) _JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL, (const char*) { name }, (dual_timestamp*) { t } #define JSON_BUILD_PAIR_RATELIMIT_ENABLED(name, rl) _JSON_BUILD_PAIR_RATELIMIT_ENABLED, (const char*) { name }, (const RateLimit*) { rl } +#define JSON_BUILD_PAIR_CALLBACK_NON_NULL(name, c, u) _JSON_BUILD_PAIR_CALLBACK_NON_NULL, (const char*) { name }, (sd_json_build_callback_t) { c }, (void*) { u } #define JSON_BUILD_PAIR_IOVEC_BASE64(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_BASE64(iov)) #define JSON_BUILD_PAIR_IOVEC_HEX(name, iov) SD_JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_HEX(iov)) diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index 62f0f3dcb1c..17d24f4844b 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -4668,6 +4668,40 @@ _public_ int sd_json_buildv(sd_json_variant **ret, va_list ap) { current->expect = EXPECT_OBJECT_KEY; break; } + + case _JSON_BUILD_PAIR_CALLBACK_NON_NULL: { + sd_json_build_callback_t cb; + void *userdata; + const char *n; + + if (current->expect != EXPECT_OBJECT_KEY) { + r = -EINVAL; + goto finish; + } + + n = va_arg(ap, const char*); + cb = va_arg(ap, sd_json_build_callback_t); + userdata = va_arg(ap, void*); + + if (current->n_suppress == 0) { + if (cb) { + r = cb(&add_more, n, userdata); + if (r < 0) + goto finish; + } + + if (add_more) { + r = sd_json_variant_new_string(&add, n); + if (r < 0) + goto finish; + } + } + + n_subtract = 2; /* we generated two item */ + + current->expect = EXPECT_OBJECT_KEY; + break; + } } /* If variants were generated, add them to our current variant, but only if we are not supposed to suppress additions */ diff --git a/src/test/test-json.c b/src/test/test-json.c index f9dc9e74c7b..378a3d0d8de 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -281,6 +281,8 @@ static int test_callback(sd_json_variant **ret, const char *name, void *userdata assert_se(PTR_TO_INT(userdata) == 4711); else if (streq_ptr(name, "mypid2")) assert_se(PTR_TO_INT(userdata) == 4712); + else if (streq_ptr(name, "mypid3")) + return 0; else assert_not_reached(); @@ -402,6 +404,16 @@ TEST(build) { assert_se(sd_json_variant_format(y, /* flags= */ 0, &f2)); ASSERT_STREQ(f1, f2); + _cleanup_(sd_json_variant_unrefp) sd_json_variant *z = NULL; + ASSERT_OK(sd_json_build(&z, SD_JSON_BUILD_OBJECT(JSON_BUILD_PAIR_CALLBACK_NON_NULL("mypid3", test_callback, INT_TO_PTR(4713))))); + ASSERT_TRUE(sd_json_variant_is_blank_object(z)); + z = sd_json_variant_unref(z); + f2 = mfree(f2); + ASSERT_OK(sd_json_build(&z, SD_JSON_BUILD_OBJECT(JSON_BUILD_PAIR_CALLBACK_NON_NULL("mypid1", test_callback, INT_TO_PTR(4711)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("mypid2", test_callback, INT_TO_PTR(4712))))); + ASSERT_OK(sd_json_variant_format(z, /* flags= */ 0, &f2)); + ASSERT_STREQ(f1, f2); + _cleanup_set_free_ Set *ss = NULL; assert_se(set_ensure_put(&ss, &string_hash_ops_free, ASSERT_PTR(strdup("pief"))) >= 0); assert_se(set_ensure_put(&ss, &string_hash_ops_free, ASSERT_PTR(strdup("xxxx"))) >= 0);