pipewire: properties: introduce pw_properties_{steal,gift}

Add functions

  pw_properties_steal(properties, key);
  pw_properties_gift(properties, key, value);

which can be used to retrieve/insert key-value pairs from/into
a property list without creating unnecessary copies of the value.

Add tests as well.
This commit is contained in:
Barnabás Pőcze 2021-06-16 19:03:43 +02:00
parent be18d052ad
commit a6151e96cd
3 changed files with 100 additions and 0 deletions

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}