]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
json-util: Add JSON_BUILD_PAIR_CALLBACK_NON_NULL()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 9 Aug 2024 11:40:43 +0000 (13:40 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 3 Sep 2024 10:08:41 +0000 (12:08 +0200)
Like JSON_BUILD_PAIR_CALLBACK(), but doesn't add anything to the variant
if the callback doesn't put anything in the return argument.

src/libsystemd/sd-json/json-util.h
src/libsystemd/sd-json/sd-json.c
src/test/test-json.c

index 3be5f75878c75b34991422886d89f3f09922265d..2d8322ab387757909a753d02f6875669bb8057f8 100644 (file)
@@ -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))
index 62f0f3dcb1cede164c6f71fb23497b7bc29cf6af..17d24f4844b5698d95547caad9fcc23591d506e4 100644 (file)
@@ -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 */
index f9dc9e74c7baddc6a7e1855815cf911332818c49..378a3d0d8de69d24fad320b5c7d65f4f73183a43 100644 (file)
@@ -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);