From: Lennart Poettering Date: Wed, 8 May 2024 07:11:13 +0000 (+0200) Subject: json: add sd_json_dispatch_double() helper X-Git-Tag: v257-rc1~1146 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4fae650ad8f29b82bf0c37b2201d3663ebb058dd;p=thirdparty%2Fsystemd.git json: add sd_json_dispatch_double() helper --- diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 1799706c3cd..ccd902df3d6 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -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; diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index d7b3ffdbc60..13164986209 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -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; diff --git a/src/systemd/sd-json.h b/src/systemd/sd-json.h index 097f47a0ab6..434a6ffff30 100644 --- a/src/systemd/sd-json.h +++ b/src/systemd/sd-json.h @@ -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); diff --git a/src/test/test-json.c b/src/test/test-json.c index 724a3fa4fda..4323bd5c97b 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -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;