]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
json: add sd_json_dispatch_double() helper
authorLennart Poettering <lennart@poettering.net>
Wed, 8 May 2024 07:11:13 +0000 (09:11 +0200)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 14 Jun 2024 23:43:56 +0000 (00:43 +0100)
src/libsystemd/libsystemd.sym
src/libsystemd/sd-json/sd-json.c
src/systemd/sd-json.h
src/test/test-json.c

index 1799706c3cd498afd82790f15f831542cab77e9d..ccd902df3d6dfd6821755e034f2dd678f77688b2 100644 (file)
@@ -851,6 +851,7 @@ global:
         sd_json_buildv;
         sd_json_dispatch;
         sd_json_dispatch_const_string;
+        sd_json_dispatch_double;
         sd_json_dispatch_full;
         sd_json_dispatch_id128;
         sd_json_dispatch_int16;
index d7b3ffdbc606907c37f60bd20a1de823b7b00f69..13164986209f2a5019d82906ce3abc53218efa17 100644 (file)
@@ -4954,6 +4954,20 @@ _public_ int sd_json_dispatch_uint8(const char *name, sd_json_variant *variant,
         return 0;
 }
 
+_public_ int sd_json_dispatch_double(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
+        double *d = ASSERT_PTR(userdata);
+
+        /* Note, this will take care of parsing NaN, -Infinity, Infinity for us */
+        if (sd_json_variant_is_string(variant) && safe_atod(sd_json_variant_string(variant), d) >= 0)
+                return 0;
+
+        if (!sd_json_variant_is_real(variant))
+                return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a floating point value, nor one formatted as string.", strna(name));
+
+        *d = sd_json_variant_real(variant);
+        return 0;
+}
+
 _public_ int sd_json_dispatch_string(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata) {
         char **s = ASSERT_PTR(userdata);
         int r;
index 097f47a0ab64f772ff178494b7aa372d76ab4bbd..434a6ffff30f30791821af60480f9a1459af71da 100644 (file)
@@ -315,6 +315,7 @@ int sd_json_dispatch_uint16(const char *name, sd_json_variant *variant, sd_json_
 int sd_json_dispatch_int16(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
 int sd_json_dispatch_int8(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
 int sd_json_dispatch_uint8(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
+int sd_json_dispatch_double(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
 int sd_json_dispatch_uid_gid(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
 int sd_json_dispatch_id128(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
 int sd_json_dispatch_unsupported(const char *name, sd_json_variant *variant, sd_json_dispatch_flags_t flags, void *userdata);
index 724a3fa4fda2c9c5a4fff261440ac9a2ecaa6eb7..4323bd5c97bcc48bead9cec9f0e12736ce67e920 100644 (file)
@@ -947,6 +947,50 @@ TEST(json_dispatch_enum_define) {
         assert(data.d < 0);
 }
 
+TEST(json_dispatch_double) {
+
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *j = NULL;
+
+        assert_se(sd_json_build(&j, SD_JSON_BUILD_OBJECT(
+                                             SD_JSON_BUILD_PAIR("x1", SD_JSON_BUILD_REAL(0.5)),
+                                             SD_JSON_BUILD_PAIR("x2", SD_JSON_BUILD_REAL(-0.5)),
+                                             SD_JSON_BUILD_PAIR("x3", JSON_BUILD_CONST_STRING("infinity")),
+                                             SD_JSON_BUILD_PAIR("x4", JSON_BUILD_CONST_STRING("-infinity")),
+                                             SD_JSON_BUILD_PAIR("x5", JSON_BUILD_CONST_STRING("nan")),
+                                             SD_JSON_BUILD_PAIR("x6", JSON_BUILD_CONST_STRING("inf")),
+                                             SD_JSON_BUILD_PAIR("x7", JSON_BUILD_CONST_STRING("-inf")))) >= 0);
+
+        struct data {
+                double x1, x2, x3, x4, x5, x6, x7;
+        } data = {};
+
+        assert_se(sd_json_dispatch(j,
+                                (const sd_json_dispatch_field[]) {
+                                        { "x1", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_double, offsetof(struct data, x1), 0 },
+                                        { "x2", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_double, offsetof(struct data, x2), 0 },
+                                        { "x3", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_double, offsetof(struct data, x3), 0 },
+                                        { "x4", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_double, offsetof(struct data, x4), 0 },
+                                        { "x5", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_double, offsetof(struct data, x5), 0 },
+                                        { "x6", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_double, offsetof(struct data, x6), 0 },
+                                        { "x7", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_double, offsetof(struct data, x7), 0 },
+                                        {},
+                                },
+                                /* flags= */ 0,
+                                &data) >= 0);
+
+        assert_se(fabs(data.x1 - 0.5) < 0.01);
+        assert_se(fabs(data.x2 + 0.5) < 0.01);
+        assert_se(isinf(data.x3));
+        assert_se(data.x3 > 0);
+        assert_se(isinf(data.x4));
+        assert_se(data.x4 < 0);
+        assert_se(isnan(data.x5));
+        assert_se(isinf(data.x6));
+        assert_se(data.x6 > 0);
+        assert_se(isinf(data.x7));
+        assert_se(data.x7 < 0);
+}
+
 TEST(json_sensitive) {
         _cleanup_(sd_json_variant_unrefp) sd_json_variant *a = NULL, *b = NULL, *v = NULL;
         _cleanup_free_ char *s = NULL;