mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-06-07 03:01:36 -04:00
pipewire: properties: introduce pw_properties_move
Add pw_properties_move(dst, dst_key, src, src_key, fallback_value) which can move a key-value pair from one property list into another, optionally using the fallback value as value if `src_key` cannot be found in `src`. Add tests as well. This commit also adds `pw_properties_rename()`, which can be used to change the key in a dictionary, but that is not made part of the public API yet.
This commit is contained in:
parent
5459c759ee
commit
be18d052ad
3 changed files with 189 additions and 0 deletions
|
|
@ -96,6 +96,36 @@ static struct spa_dict_item *find_item(const struct pw_properties *this, const c
|
|||
return pw_array_get_unchecked(&impl->items, index, struct spa_dict_item);
|
||||
}
|
||||
|
||||
static int rename_item(struct pw_properties *properties, struct spa_dict_item *item,
|
||||
const char *new_key)
|
||||
{
|
||||
struct spa_dict_item *item2;
|
||||
|
||||
if (SPA_UNLIKELY(spa_streq(item->key, new_key)))
|
||||
return 0;
|
||||
|
||||
item2 = find_item(properties, new_key);
|
||||
if (item2 != NULL) {
|
||||
free((char *) item2->value);
|
||||
free((char *) item->key);
|
||||
|
||||
item->key = item2->key;
|
||||
|
||||
remove_item(properties, item2);
|
||||
} else {
|
||||
new_key = strdup(new_key);
|
||||
if (new_key == NULL)
|
||||
return -errno;
|
||||
|
||||
free((char *) item->key);
|
||||
item->key = new_key;
|
||||
|
||||
SPA_FLAG_CLEAR(properties->dict.flags, SPA_DICT_FLAG_SORTED);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct properties *properties_new(int prealloc)
|
||||
{
|
||||
struct properties *impl;
|
||||
|
|
@ -613,3 +643,78 @@ int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int pw_properties_rename(struct pw_properties *properties,
|
||||
const char *old_key, const char *new_key)
|
||||
{
|
||||
spa_assert(properties);
|
||||
spa_assert(old_key);
|
||||
spa_assert(new_key);
|
||||
|
||||
struct spa_dict_item *item;
|
||||
|
||||
item = find_item(properties, old_key);
|
||||
if (item == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
return rename_item(properties, item, new_key);
|
||||
}
|
||||
|
||||
/** Move a key-value pair from one property list into another
|
||||
*
|
||||
* \param dst a \ref pw_properties into which to move
|
||||
* \param dst_key key in \a new
|
||||
* \param src a \ref pw_properties from which to move
|
||||
* \param src_key key in \a src
|
||||
* \param fallback_value the value to use if \a src_key cannot be found in \a src
|
||||
* \return 1 if \a dst has been changed, 0 if no updates were done, or
|
||||
* -ENOENT if \a src_key could not be found and \a fallback_value
|
||||
* was not specified.
|
||||
*
|
||||
* This function finds \a src_key in \a src, and moves the corresponding value
|
||||
* into \a dst under the key \a dst_key. If \a src_key is not found in \a src,
|
||||
* then \a fallback_value will be used instead. If \a src_key is not found,
|
||||
* and \a fallback_value is NULL, then -ENOENT is returned. \a src and \a dst
|
||||
* may refer to the same object. \a src_key and \a dst_key may be the same.
|
||||
*
|
||||
* \since 0.3.31
|
||||
*/
|
||||
SPA_EXPORT
|
||||
int pw_properties_move(struct pw_properties *dst, const char *dst_key,
|
||||
struct pw_properties *src, const char *src_key,
|
||||
const char *fallback_value)
|
||||
{
|
||||
spa_assert(dst);
|
||||
spa_assert(dst_key);
|
||||
spa_assert(src);
|
||||
spa_assert(src_key);
|
||||
|
||||
struct spa_dict_item *item;
|
||||
int res;
|
||||
|
||||
if (SPA_LIKELY(src != dst)) {
|
||||
item = find_item(src, src_key);
|
||||
if (item != NULL) {
|
||||
res = do_replace(dst, dst_key, (char *) item->value, false);
|
||||
|
||||
free((char *) item->key);
|
||||
remove_item(src, item);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
if (fallback_value != NULL)
|
||||
return do_replace(dst, dst_key, (char *) fallback_value, true);
|
||||
|
||||
return -ENOENT;
|
||||
} else {
|
||||
if (fallback_value == NULL)
|
||||
return pw_properties_rename(dst, src_key, dst_key);
|
||||
|
||||
item = find_item(dst, src_key);
|
||||
if (item != NULL)
|
||||
return rename_item(dst, item, dst_key);
|
||||
|
||||
return do_replace(dst, dst_key, (char *) fallback_value, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@ pw_properties_iterate(const struct pw_properties *properties, void **state);
|
|||
#define PW_PROPERTIES_FLAG_NL (1<<0)
|
||||
int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t flags);
|
||||
|
||||
int
|
||||
pw_properties_move(struct pw_properties *dst, const char *dst_key,
|
||||
struct pw_properties *src, const char *src_key,
|
||||
const char *fallback_value);
|
||||
|
||||
static inline bool pw_properties_parse_bool(const char *value) {
|
||||
return spa_atob(value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -605,6 +605,84 @@ PWTEST(properties_update)
|
|||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
PWTEST(properties_move)
|
||||
{
|
||||
struct pw_properties *a = pw_properties_new(NULL, NULL),
|
||||
*b = pw_properties_new(NULL, NULL);
|
||||
|
||||
pwtest_ptr_notnull(a);
|
||||
pwtest_ptr_notnull(b);
|
||||
|
||||
pwtest_int_eq(pw_properties_set(a, "some key", "foo"), 1);
|
||||
pwtest_int_eq(pw_properties_set(a, "some other key", "bar"), 1);
|
||||
|
||||
/*
|
||||
* a = {"some key" : "foo", "some other key" : "bar"}
|
||||
* b = {}
|
||||
*/
|
||||
|
||||
pwtest_int_eq(pw_properties_move(b, "different key", a, "some key", NULL), 1);
|
||||
pwtest_str_eq(pw_properties_get(b, "different key"), "foo");
|
||||
pwtest_str_eq(pw_properties_get(a, "some key"), NULL);
|
||||
|
||||
/*
|
||||
* a = {"some other key" : "bar"}
|
||||
* b = {"different key" : "foo"}
|
||||
*/
|
||||
|
||||
pwtest_ptr_null(pw_properties_get(a, "server_address"));
|
||||
pwtest_int_eq(pw_properties_move(b, "server.address", a, "server_address", NULL), -ENOENT);
|
||||
pwtest_str_eq(pw_properties_get(b, "server.address"), NULL);
|
||||
|
||||
/*
|
||||
* a = {"some other key" : "bar"}
|
||||
* b = {"different key" : "foo"}
|
||||
*/
|
||||
|
||||
pwtest_int_eq(pw_properties_move(b, "server.port", a, "server_port", "4444"), 1);
|
||||
pwtest_str_eq(pw_properties_get(b, "server.port"), "4444");
|
||||
pwtest_str_eq(pw_properties_get(a, "server_port"), NULL);
|
||||
|
||||
/*
|
||||
* a = {"some other key" : "bar"}
|
||||
* b = {"different key" : "foo", "server.port" : "4444"}
|
||||
*/
|
||||
|
||||
pwtest_int_eq(pw_properties_move(b, "server.port", b, "server.port", NULL), 0);
|
||||
pwtest_str_eq(pw_properties_get(b, "server.port"), "4444");
|
||||
|
||||
/*
|
||||
* a = {"some other key" : "bar"}
|
||||
* b = {"different key" : "foo", "server.port" : "4444"}
|
||||
*/
|
||||
|
||||
pwtest_int_eq(pw_properties_move(b, "server_port", b, "server.port", NULL), 1);
|
||||
pwtest_str_eq(pw_properties_get(b, "server_port"), "4444");
|
||||
pwtest_str_eq(pw_properties_get(b, "server.port"), NULL);
|
||||
|
||||
/*
|
||||
* a = {"some other key" : "bar"}
|
||||
* b = {"different key" : "foo", "server_port" : "4444"}
|
||||
*/
|
||||
|
||||
pwtest_int_eq(pw_properties_move(b, "server_port", a, "server_port", "9999"), 1);
|
||||
pwtest_str_eq(pw_properties_get(b, "server_port"), "9999");
|
||||
|
||||
/*
|
||||
* a = {"some other key" : "bar"}
|
||||
* b = {"different key" : "foo", "server_port" : "9999"}
|
||||
*/
|
||||
|
||||
pwtest_int_eq(pw_properties_move(b, "server_port", b, "server.port", "8888"), 1);
|
||||
pwtest_str_eq(pw_properties_get(b, "server_port"), "8888");
|
||||
pwtest_str_eq(pw_properties_get(b, "server.port"), NULL);
|
||||
|
||||
pw_properties_free(a);
|
||||
pw_properties_free(b);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
PWTEST_SUITE(properties)
|
||||
{
|
||||
pwtest_add(properties_abi, PWTEST_NOARG);
|
||||
|
|
@ -624,6 +702,7 @@ PWTEST_SUITE(properties)
|
|||
pwtest_add(properties_new_dict, PWTEST_NOARG);
|
||||
pwtest_add(properties_new_json, PWTEST_NOARG);
|
||||
pwtest_add(properties_update, PWTEST_NOARG);
|
||||
pwtest_add(properties_move, PWTEST_NOARG);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue