diff --git a/src/pipewire/properties.c b/src/pipewire/properties.c index 74b5aa92a..eb0fe06e9 100644 --- a/src/pipewire/properties.c +++ b/src/pipewire/properties.c @@ -718,3 +718,61 @@ int pw_properties_move(struct pw_properties *dst, const char *dst_key, return do_replace(dst, dst_key, (char *) fallback_value, true); } } + +/** Extract a value from a property list + * + * \param properties a \ref pw_properties object + * \param key key in \a properties + * \return a pointer to the value corresponding to \a key + * or NULL if \a key cannot be found + * + * This function tries to find \a key in \a properties. If it cannot be found, + * then NULL is returned. Otherwise, the key-value pair is removed from the + * property list and the value is returned. It is the caller's responsibility + * to free the returned string with `free()`, et al. + * + * \since 0.3.31 + */ +SPA_EXPORT +char *pw_properties_steal(struct pw_properties *properties, const char *key) +{ + spa_assert(properties); + spa_assert(key); + + struct spa_dict_item *item = find_item(properties, key); + char *value; + + if (item == NULL) + return NULL; + + value = (char *) item->value; + free((char *) item->key); + + remove_item(properties, item); + + return value; +} + +/** Insert a value into a property list + * + * \param properties a \ref pw_properties object + * \param key key in \a properties + * \return 1 if \a properties were changed, + * 0 if nothing was changed because the property already existed with the same value + * + * This function is similar to \ref pw_properties_set except that it takes + * ownership of \a value. \a value must be a pointer appropriate for passing to `free()`. + * If \a key is already present in \a properties with \a value value, then + * \a value is freed. + * + * \since 0.3.31 + */ +SPA_EXPORT +int pw_properties_gift(struct pw_properties *properties, const char *key, char *value) +{ + spa_assert(properties); + spa_assert(key); + spa_assert(value); + + return do_replace(properties, key, value, false); +} diff --git a/src/pipewire/properties.h b/src/pipewire/properties.h index 925bb57ab..30f627e9c 100644 --- a/src/pipewire/properties.h +++ b/src/pipewire/properties.h @@ -108,6 +108,12 @@ pw_properties_move(struct pw_properties *dst, const char *dst_key, struct pw_properties *src, const char *src_key, const char *fallback_value); +char * +pw_properties_steal(struct pw_properties *properties, const char *key); + +int +pw_properties_gift(struct pw_properties *properties, const char *key, char *value); + static inline bool pw_properties_parse_bool(const char *value) { return spa_atob(value); } diff --git a/test/test-properties.c b/test/test-properties.c index 682693b23..1c5bf9e74 100644 --- a/test/test-properties.c +++ b/test/test-properties.c @@ -683,6 +683,41 @@ PWTEST(properties_move) return PWTEST_PASS; } +PWTEST(properties_steal_gift) +{ + struct pw_properties *a = pw_properties_new(NULL, NULL), + *b = pw_properties_new(NULL, NULL); + char *v1, *v2; + + pwtest_ptr_notnull(a); + pwtest_ptr_notnull(b); + + pwtest_int_eq(pw_properties_set(a, "a1", "value1"), 1); + pwtest_int_eq(pw_properties_set(a, "a2", "value2"), 1); + pwtest_int_eq(pw_properties_set(a, "a3", "value3"), 1); + pwtest_int_eq(pw_properties_set(a, "a4", "value4"), 1); + + pwtest_str_eq(pw_properties_steal(a, "a5"), NULL); + + v1 = pw_properties_steal(a, "a2"); + pwtest_str_eq(v1, "value2"); + pwtest_ptr_null(pw_properties_get(a, "a2")); + + v2 = strdup(v1); + pwtest_ptr_notnull(v2); + + pwtest_int_eq(pw_properties_gift(b, "b3", v1), 1); + pwtest_str_eq(pw_properties_get(b, "b3"), "value2"); + + pwtest_int_eq(pw_properties_gift(b, "b3", v2), 0); + pwtest_str_eq(pw_properties_get(b, "b3"), "value2"); + + pw_properties_free(a); + pw_properties_free(b); + + return PWTEST_PASS; +} + PWTEST_SUITE(properties) { pwtest_add(properties_abi, PWTEST_NOARG); @@ -703,6 +738,7 @@ PWTEST_SUITE(properties) pwtest_add(properties_new_json, PWTEST_NOARG); pwtest_add(properties_update, PWTEST_NOARG); pwtest_add(properties_move, PWTEST_NOARG); + pwtest_add(properties_steal_gift, PWTEST_NOARG); return PWTEST_PASS; }