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);
|
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)
|
static struct properties *properties_new(int prealloc)
|
||||||
{
|
{
|
||||||
struct properties *impl;
|
struct properties *impl;
|
||||||
|
|
@ -613,3 +643,78 @@ int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t
|
||||||
}
|
}
|
||||||
return count;
|
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)
|
#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_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) {
|
static inline bool pw_properties_parse_bool(const char *value) {
|
||||||
return spa_atob(value);
|
return spa_atob(value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -605,6 +605,84 @@ PWTEST(properties_update)
|
||||||
return PWTEST_PASS;
|
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_SUITE(properties)
|
||||||
{
|
{
|
||||||
pwtest_add(properties_abi, PWTEST_NOARG);
|
pwtest_add(properties_abi, PWTEST_NOARG);
|
||||||
|
|
@ -624,6 +702,7 @@ PWTEST_SUITE(properties)
|
||||||
pwtest_add(properties_new_dict, PWTEST_NOARG);
|
pwtest_add(properties_new_dict, PWTEST_NOARG);
|
||||||
pwtest_add(properties_new_json, PWTEST_NOARG);
|
pwtest_add(properties_new_json, PWTEST_NOARG);
|
||||||
pwtest_add(properties_update, PWTEST_NOARG);
|
pwtest_add(properties_update, PWTEST_NOARG);
|
||||||
|
pwtest_add(properties_move, PWTEST_NOARG);
|
||||||
|
|
||||||
return PWTEST_PASS;
|
return PWTEST_PASS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue