mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
properties: support properties from json object sting
Make pw_properties_new_string() work with a json object string. This makes it possible to specify property strings as more complex objects and escape characters.
This commit is contained in:
parent
62cdec8448
commit
6e4c138238
3 changed files with 96 additions and 20 deletions
|
|
@ -33,7 +33,9 @@ extern "C" {
|
|||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <spa/utils/defs.h>
|
||||
|
||||
/* a simple JSON compatible tokenizer */
|
||||
struct spa_json {
|
||||
|
|
@ -169,6 +171,20 @@ static inline int spa_json_enter_container(struct spa_json *iter, struct spa_jso
|
|||
return 1;
|
||||
}
|
||||
|
||||
static inline int spa_json_is_container(const char *val, int len)
|
||||
{
|
||||
return len > 0 && (*val == '{' || *val == '[');
|
||||
}
|
||||
|
||||
static inline int spa_json_container_len(struct spa_json *iter, const char *value, int len)
|
||||
{
|
||||
const char *val;
|
||||
struct spa_json sub;
|
||||
spa_json_enter(iter, &sub);
|
||||
while (spa_json_next(&sub, &val) > 0);
|
||||
return sub.cur + 1 - value;
|
||||
}
|
||||
|
||||
/* object */
|
||||
static inline int spa_json_is_object(const char *val, int len)
|
||||
{
|
||||
|
|
@ -321,6 +337,7 @@ static inline int spa_json_encode_string(char *str, int size, const char *val)
|
|||
}
|
||||
__PUT('"');
|
||||
__PUT('\0');
|
||||
#undef __PUT
|
||||
return len-1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <spa/utils/json.h>
|
||||
|
||||
#include "pipewire/array.h"
|
||||
#include "pipewire/utils.h"
|
||||
|
|
@ -144,23 +145,11 @@ struct pw_properties *pw_properties_new_dict(const struct spa_dict *dict)
|
|||
return &impl->this;
|
||||
}
|
||||
|
||||
/** Make a new properties object from the given str
|
||||
*
|
||||
* \a str should be a whitespace separated list of key=value
|
||||
* strings.
|
||||
*
|
||||
* \param args a property description
|
||||
* \return a new properties object
|
||||
*
|
||||
* \memberof pw_properties
|
||||
*/
|
||||
SPA_EXPORT
|
||||
struct pw_properties *
|
||||
pw_properties_new_string(const char *str)
|
||||
static struct pw_properties *
|
||||
properties_new_string(const char *str)
|
||||
{
|
||||
|
||||
struct properties *impl;
|
||||
const char *state = NULL, *s = NULL;
|
||||
const char *state = NULL, *s = NULL;
|
||||
size_t len;
|
||||
int res;
|
||||
|
||||
|
|
@ -172,10 +161,8 @@ pw_properties_new_string(const char *str)
|
|||
while (s) {
|
||||
char *val, *eq;
|
||||
|
||||
if ((val = strndup(s, len)) == NULL) {
|
||||
res = -errno;
|
||||
goto no_mem;
|
||||
}
|
||||
if ((val = strndup(s, len)) == NULL)
|
||||
goto error_errno;
|
||||
|
||||
eq = strchr(val, '=');
|
||||
if (eq && eq != val) {
|
||||
|
|
@ -188,7 +175,61 @@ pw_properties_new_string(const char *str)
|
|||
}
|
||||
return &impl->this;
|
||||
|
||||
no_mem:
|
||||
error_errno:
|
||||
res = -errno;
|
||||
pw_properties_free(&impl->this);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Make a new properties object from the given str
|
||||
*
|
||||
* \a str should be a whitespace separated list of key=value
|
||||
* strings or a json object.
|
||||
*
|
||||
* \param args a property description
|
||||
* \return a new properties object
|
||||
*
|
||||
* \memberof pw_properties
|
||||
*/
|
||||
SPA_EXPORT
|
||||
struct pw_properties *
|
||||
pw_properties_new_string(const char *object)
|
||||
{
|
||||
struct properties *impl;
|
||||
struct spa_json it[2];
|
||||
char key[256], *val;
|
||||
int res;
|
||||
|
||||
spa_json_init(&it[0], object, strlen(object));
|
||||
if (spa_json_enter_object(&it[0], &it[1]) < 0)
|
||||
return properties_new_string(object);
|
||||
|
||||
impl = properties_new(16);
|
||||
if (impl == NULL)
|
||||
return NULL;
|
||||
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)-1)) {
|
||||
int len;
|
||||
const char *value;
|
||||
|
||||
if ((len = spa_json_next(&it[1], &value)) <= 0)
|
||||
break;
|
||||
|
||||
if (spa_json_is_container(value, len))
|
||||
len = spa_json_container_len(&it[1], value, len);
|
||||
|
||||
if ((val = strndup(value, len)) == NULL)
|
||||
goto error_errno;
|
||||
|
||||
if (spa_json_is_string(value, len))
|
||||
spa_json_parse_string(value, len, val);
|
||||
|
||||
add_func(&impl->this, strdup(key), val);
|
||||
}
|
||||
return &impl->this;
|
||||
error_errno:
|
||||
res = errno;
|
||||
pw_properties_free(&impl->this);
|
||||
errno = -res;
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -310,6 +310,23 @@ static void test_parse(void)
|
|||
spa_assert(pw_properties_parse_double("1.234") == 1.234);
|
||||
}
|
||||
|
||||
static void test_new_json(void)
|
||||
{
|
||||
struct pw_properties *props;
|
||||
|
||||
props = pw_properties_new_string("{ \"foo\": \"bar\\n\\t\", \"bar\": 1.8, \"empty\": [ \"foo\", \"bar\" ], \"\": \"gg\"");
|
||||
spa_assert(props != NULL);
|
||||
spa_assert(props->flags == 0);
|
||||
spa_assert(props->dict.n_items == 4);
|
||||
|
||||
spa_assert(!strcmp(pw_properties_get(props, "foo"), "bar\n\t"));
|
||||
spa_assert(!strcmp(pw_properties_get(props, "bar"), "1.8"));
|
||||
fprintf(stderr, "'%s'\n", pw_properties_get(props, "empty"));
|
||||
spa_assert(!strcmp(pw_properties_get(props, "empty"), "[ \"foo\", \"bar\" ]"));
|
||||
|
||||
pw_properties_free(props);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
test_abi();
|
||||
|
|
@ -321,6 +338,7 @@ int main(int argc, char *argv[])
|
|||
test_new_string();
|
||||
test_update();
|
||||
test_parse();
|
||||
test_new_json();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue