From: Lennart Poettering Date: Wed, 22 Jan 2025 15:13:27 +0000 (+0100) Subject: sd-json: add new sd_json_variant_unset_field() call X-Git-Tag: v258-rc1~1504^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b6a2df630701de0bcf77850ced213d7fc3d0c4de;p=thirdparty%2Fsystemd.git sd-json: add new sd_json_variant_unset_field() call --- diff --git a/man/rules/meson.build b/man/rules/meson.build index 4fe9ca17b83..ae6e8a1f589 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -806,6 +806,7 @@ manpages = [ 'sd_journal_seek_tail'], ''], ['sd_journal_stream_fd', '3', ['sd_journal_stream_fd_with_namespace'], ''], + ['sd_json_variant_unset_field', '3', [], ''], ['sd_listen_fds', '3', ['SD_LISTEN_FDS_START', 'sd_listen_fds_with_names'], diff --git a/man/sd_json_variant_unset_field.xml b/man/sd_json_variant_unset_field.xml new file mode 100644 index 00000000000..891d3d602f2 --- /dev/null +++ b/man/sd_json_variant_unset_field.xml @@ -0,0 +1,95 @@ + + + + + + + + sd_json_variant_unset_field + systemd + + + + sd_json_variant_unset_field + 3 + + + + sd_json_variant_unset_field + Remove a specific field from a JSON object + + + + + #include <systemd/sd-json.h> + + + int sd_json_variant_unset_field + sd_json_variant **object + const char *field + + + + + + Description + + sd_json_variant_unset_field() takes a pointer to a pointer to a JSON object + and a field name. If the object contains a field under the specified name, a new JSON object is allocated + that is a copy of the original one, however the specified field is removed. The object parameter is + updated to point to the new object, which has an initial reference counter of one. The reference counter + of the original object is decremented by one. Or in other words: the specified object is replaced by one + with the field removed. + + If the referenced object does not contain a field matching the specified name, no operation is + executed. + + Similar, if a NULL pointer is referenced, no operation is executed. + + + + Return Value + + On success, and if a field was removed sd_json_variant_unset_field() returns a + positive non-zero integer. If no matching field was found it returns zero. On failure, it returns a + negative errno-style error code. + + + Errors + + Returned errors may indicate the following problems: + + + + -EINVAL + + An argument is invalid. + + + + -ENOMEM + + Memory allocation failed. + + + + + + + + + History + sd_json_variant_unset_field() was added in version 258. + + + + See Also + + + systemd1 + sd-json3 + + + + diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index c953085ef9b..b2990a222f0 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -1065,6 +1065,7 @@ global: sd_device_enumerator_add_all_parents; sd_json_variant_type_from_string; sd_json_variant_type_to_string; + sd_json_variant_unset_field; sd_varlink_get_current_method; sd_varlink_get_input_fd; sd_varlink_get_output_fd; diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index 99d941e1efd..051ab8d69fc 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -2129,6 +2129,55 @@ _public_ int sd_json_variant_set_field_strv(sd_json_variant **v, const char *fie return sd_json_variant_set_field(v, field, m); } +_public_ int sd_json_variant_unset_field(sd_json_variant **v, const char *field) { + int r; + + assert_return(v, -EINVAL); + assert_return(field, -EINVAL); + + if (sd_json_variant_is_blank_object(*v)) + return 0; + if (!sd_json_variant_is_object(*v)) + return -EINVAL; + + _cleanup_free_ sd_json_variant **array = NULL; + size_t k = 0; + for (size_t i = 0; i < sd_json_variant_elements(*v); i += 2) { + sd_json_variant *p; + + p = sd_json_variant_by_index(*v, i); + if (!sd_json_variant_is_string(p)) + return -EINVAL; + + if (streq(sd_json_variant_string(p), field)) { + if (!array) { + array = new(sd_json_variant*, sd_json_variant_elements(*v) - 2); + if (!array) + return -ENOMEM; + + for (k = 0; k < i; k++) + array[k] = sd_json_variant_by_index(*v, k); + } + } else if (array) { + array[k++] = p; + array[k++] = sd_json_variant_by_index(*v, i + 1); + } + } + + if (!array) + return 0; + + _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL; + r = sd_json_variant_new_object(&w, array, k); + if (r < 0) + return r; + + json_variant_propagate_sensitive(*v, w); + JSON_VARIANT_REPLACE(*v, TAKE_PTR(w)); + + return 1; +} + _public_ int sd_json_variant_merge_object(sd_json_variant **v, sd_json_variant *m) { _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = NULL; _cleanup_free_ sd_json_variant **array = NULL; diff --git a/src/systemd/sd-json.h b/src/systemd/sd-json.h index 3930d82b0d0..a3a1dff94dd 100644 --- a/src/systemd/sd-json.h +++ b/src/systemd/sd-json.h @@ -168,6 +168,8 @@ int sd_json_variant_set_field_unsigned(sd_json_variant **v, const char *field, u int sd_json_variant_set_field_boolean(sd_json_variant **v, const char *field, int b); int sd_json_variant_set_field_strv(sd_json_variant **v, const char *field, char **l); +int sd_json_variant_unset_field(sd_json_variant **v, const char *field); + sd_json_variant* sd_json_variant_find(sd_json_variant *haystack, sd_json_variant *needle); int sd_json_variant_append_array(sd_json_variant **v, sd_json_variant *element); diff --git a/src/test/test-json.c b/src/test/test-json.c index 8dd5746495e..630ff8c8512 100644 --- a/src/test/test-json.c +++ b/src/test/test-json.c @@ -1419,4 +1419,42 @@ TEST(fd_info) { pidref_done(&pidref); } +TEST(json_variant_unset_field) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + + ASSERT_OK_POSITIVE(sd_json_variant_is_blank_object(v)); + ASSERT_OK_ZERO(sd_json_variant_unset_field(&v, "foo")); + ASSERT_OK_POSITIVE(sd_json_variant_is_blank_object(v)); + + ASSERT_NULL(v); + + ASSERT_OK(sd_json_buildo(&v, + SD_JSON_BUILD_PAIR_STRING("foo", "bar"), + SD_JSON_BUILD_PAIR_STRING("quux", "waldo"), + SD_JSON_BUILD_PAIR_STRING("piff", "paff"))); + + _cleanup_(sd_json_variant_unrefp) sd_json_variant *w = sd_json_variant_ref(v); + + ASSERT_OK_POSITIVE(sd_json_variant_equal(v, w)); + ASSERT_OK_ZERO(sd_json_variant_unset_field(&v, "fooxxx")); + ASSERT_OK_POSITIVE(sd_json_variant_equal(v, w)); + ASSERT_OK_POSITIVE(sd_json_variant_unset_field(&v, "foo")); + ASSERT_OK_ZERO(sd_json_variant_equal(v, w)); + + _cleanup_(sd_json_variant_unrefp) sd_json_variant *x = NULL; + ASSERT_OK(sd_json_buildo(&x, + SD_JSON_BUILD_PAIR_STRING("quux", "waldo"), + SD_JSON_BUILD_PAIR_STRING("piff", "paff"))); + ASSERT_OK_POSITIVE(sd_json_variant_equal(v, x)); + + ASSERT_OK_POSITIVE(sd_json_variant_unset_field(&v, "piff")); + x = sd_json_variant_unref(x); + ASSERT_OK(sd_json_buildo(&x, + SD_JSON_BUILD_PAIR_STRING("quux", "waldo"))); + ASSERT_OK_POSITIVE(sd_json_variant_equal(x, v)); + + ASSERT_OK_POSITIVE(sd_json_variant_unset_field(&v, "quux")); + ASSERT_OK_POSITIVE(sd_json_variant_is_blank_object(v)); +} + DEFINE_TEST_MAIN(LOG_DEBUG);