mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-03-12 05:34:05 -04:00
spa: add spa_json_begin_array/object and relaxed versions
Add spa_json_begin_array/object to replace spa_json_init+spa_json_begin_array/object This function is better because it does not waste a useless spa_json structure as an iterator. The relaxed versions also error out when the container is mismatched because parsing a mismatched container is not going to give any results anyway.
This commit is contained in:
parent
feccb882b6
commit
cd81b5f39a
51 changed files with 401 additions and 452 deletions
|
|
@ -565,19 +565,18 @@ static int parse_spa_libs(void *user_data, const char *location,
|
|||
{
|
||||
struct data *d = user_data;
|
||||
struct pw_context *context = d->context;
|
||||
struct spa_json it[2];
|
||||
struct spa_json it[1];
|
||||
char key[512], value[512];
|
||||
int res;
|
||||
|
||||
spa_json_init(&it[0], str, len);
|
||||
if (spa_json_enter_object(&it[0], &it[1]) < 0) {
|
||||
if (spa_json_begin_object(&it[0], str, len) < 0) {
|
||||
pw_log_error("config file error: context.spa-libs is not an "
|
||||
"object in '%.*s'", (int)len, str);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
if (spa_json_get_string(&it[1], value, sizeof(value)) > 0) {
|
||||
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
|
||||
if (spa_json_get_string(&it[0], value, sizeof(value)) > 0) {
|
||||
if ((res = pw_context_add_spa_lib(context, key, value)) < 0) {
|
||||
pw_log_error("error adding spa-libs for '%s' in '%.*s': %s",
|
||||
key, (int)len, str, spa_strerror(res));
|
||||
|
|
@ -752,27 +751,26 @@ static int parse_modules(void *user_data, const char *location,
|
|||
{
|
||||
struct data *d = user_data;
|
||||
struct pw_context *context = d->context;
|
||||
struct spa_json it[4];
|
||||
struct spa_json it[3];
|
||||
char key[512];
|
||||
int res = 0, r;
|
||||
|
||||
spa_autofree char *s = strndup(str, len);
|
||||
spa_json_init(&it[0], s, len);
|
||||
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
|
||||
if (spa_json_begin_array(&it[0], s, len) < 0) {
|
||||
pw_log_error("context.modules is not an array in '%.*s'",
|
||||
(int)len, str);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while ((r = spa_json_enter_object(&it[1], &it[2])) > 0) {
|
||||
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
|
||||
char *name = NULL, *args = NULL, *flags = NULL;
|
||||
bool have_match = true;
|
||||
|
||||
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
const char *val;
|
||||
int l;
|
||||
|
||||
if ((l = spa_json_next(&it[2], &val)) <= 0) {
|
||||
if ((l = spa_json_next(&it[1], &val)) <= 0) {
|
||||
pw_log_warn("malformed module: key '%s' has no "
|
||||
"value in '%.*s'", key, (int)len, str);
|
||||
break;
|
||||
|
|
@ -783,13 +781,13 @@ static int parse_modules(void *user_data, const char *location,
|
|||
spa_json_parse_stringn(val, l, name, l+1);
|
||||
} else if (spa_streq(key, "args")) {
|
||||
if (spa_json_is_container(val, l))
|
||||
l = spa_json_container_len(&it[2], val, l);
|
||||
l = spa_json_container_len(&it[1], val, l);
|
||||
|
||||
args = (char*)val;
|
||||
spa_json_parse_stringn(val, l, args, l+1);
|
||||
} else if (spa_streq(key, "flags")) {
|
||||
if (spa_json_is_container(val, l))
|
||||
l = spa_json_container_len(&it[2], val, l);
|
||||
l = spa_json_container_len(&it[1], val, l);
|
||||
flags = (char*)val;
|
||||
spa_json_parse_stringn(val, l, flags, l+1);
|
||||
} else if (spa_streq(key, "condition")) {
|
||||
|
|
@ -798,8 +796,8 @@ static int parse_modules(void *user_data, const char *location,
|
|||
(int)len, str);
|
||||
break;
|
||||
}
|
||||
spa_json_enter(&it[2], &it[3]);
|
||||
have_match = find_match(&it[3], &context->properties->dict, true);
|
||||
spa_json_enter(&it[1], &it[2]);
|
||||
have_match = find_match(&it[2], &context->properties->dict, true);
|
||||
} else {
|
||||
pw_log_warn("unknown module key '%s' in '%.*s'", key,
|
||||
(int)len, str);
|
||||
|
|
@ -862,26 +860,25 @@ static int parse_objects(void *user_data, const char *location,
|
|||
{
|
||||
struct data *d = user_data;
|
||||
struct pw_context *context = d->context;
|
||||
struct spa_json it[4];
|
||||
struct spa_json it[3];
|
||||
char key[512];
|
||||
int res = 0, r;
|
||||
|
||||
spa_autofree char *s = strndup(str, len);
|
||||
spa_json_init(&it[0], s, len);
|
||||
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
|
||||
if (spa_json_begin_array(&it[0], s, len) < 0) {
|
||||
pw_log_error("config file error: context.objects is not an array");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while ((r = spa_json_enter_object(&it[1], &it[2])) > 0) {
|
||||
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
|
||||
char *factory = NULL, *args = NULL, *flags = NULL;
|
||||
bool have_match = true;
|
||||
|
||||
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
const char *val;
|
||||
int l;
|
||||
|
||||
if ((l = spa_json_next(&it[2], &val)) <= 0) {
|
||||
if ((l = spa_json_next(&it[1], &val)) <= 0) {
|
||||
pw_log_warn("malformed object: key '%s' has no "
|
||||
"value in '%.*s'", key, (int)len, str);
|
||||
break;
|
||||
|
|
@ -892,13 +889,13 @@ static int parse_objects(void *user_data, const char *location,
|
|||
spa_json_parse_stringn(val, l, factory, l+1);
|
||||
} else if (spa_streq(key, "args")) {
|
||||
if (spa_json_is_container(val, l))
|
||||
l = spa_json_container_len(&it[2], val, l);
|
||||
l = spa_json_container_len(&it[1], val, l);
|
||||
|
||||
args = (char*)val;
|
||||
spa_json_parse_stringn(val, l, args, l+1);
|
||||
} else if (spa_streq(key, "flags")) {
|
||||
if (spa_json_is_container(val, l))
|
||||
l = spa_json_container_len(&it[2], val, l);
|
||||
l = spa_json_container_len(&it[1], val, l);
|
||||
|
||||
flags = (char*)val;
|
||||
spa_json_parse_stringn(val, l, flags, l+1);
|
||||
|
|
@ -908,8 +905,8 @@ static int parse_objects(void *user_data, const char *location,
|
|||
(int)len, str);
|
||||
break;
|
||||
}
|
||||
spa_json_enter(&it[2], &it[3]);
|
||||
have_match = find_match(&it[3], &context->properties->dict, true);
|
||||
spa_json_enter(&it[1], &it[2]);
|
||||
have_match = find_match(&it[2], &context->properties->dict, true);
|
||||
} else {
|
||||
pw_log_warn("unknown object key '%s' in '%.*s'", key,
|
||||
(int)len, str);
|
||||
|
|
@ -1046,29 +1043,28 @@ static int parse_exec(void *user_data, const char *location,
|
|||
{
|
||||
struct data *d = user_data;
|
||||
struct pw_context *context = d->context;
|
||||
struct spa_json it[4];
|
||||
struct spa_json it[3];
|
||||
char key[512];
|
||||
int r, res = 0;
|
||||
|
||||
spa_autofree char *s = strndup(str, len);
|
||||
spa_json_init(&it[0], s, len);
|
||||
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
|
||||
if (spa_json_begin_array(&it[0], s, len) < 0) {
|
||||
pw_log_error("config file error: context.exec is not an array in '%.*s'",
|
||||
(int)len, str);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while ((r = spa_json_enter_object(&it[1], &it[2])) > 0) {
|
||||
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
|
||||
char *path = NULL;
|
||||
const char *args_val = "[]";
|
||||
int args_len = 2;
|
||||
bool have_match = true;
|
||||
|
||||
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
const char *val;
|
||||
int l;
|
||||
|
||||
if ((l = spa_json_next(&it[2], &val)) <= 0) {
|
||||
if ((l = spa_json_next(&it[1], &val)) <= 0) {
|
||||
pw_log_warn("malformed exec: key '%s' has no "
|
||||
"value in '%.*s'", key, (int)len, str);
|
||||
break;
|
||||
|
|
@ -1079,7 +1075,7 @@ static int parse_exec(void *user_data, const char *location,
|
|||
spa_json_parse_stringn(val, l, path, l+1);
|
||||
} else if (spa_streq(key, "args")) {
|
||||
if (spa_json_is_container(val, l))
|
||||
l = spa_json_container_len(&it[2], val, l);
|
||||
l = spa_json_container_len(&it[1], val, l);
|
||||
args_val = val;
|
||||
args_len = l;
|
||||
} else if (spa_streq(key, "condition")) {
|
||||
|
|
@ -1088,8 +1084,8 @@ static int parse_exec(void *user_data, const char *location,
|
|||
(int)len, str);
|
||||
goto next;
|
||||
}
|
||||
spa_json_enter(&it[2], &it[3]);
|
||||
have_match = find_match(&it[3], &context->properties->dict, true);
|
||||
spa_json_enter(&it[1], &it[2]);
|
||||
have_match = find_match(&it[2], &context->properties->dict, true);
|
||||
} else {
|
||||
pw_log_warn("unknown exec key '%s' in '%.*s'", key,
|
||||
(int)len, str);
|
||||
|
|
@ -1307,31 +1303,30 @@ int pw_conf_match_rules(const char *str, size_t len, const char *location,
|
|||
void *data)
|
||||
{
|
||||
const char *val;
|
||||
struct spa_json it[4], actions;
|
||||
struct spa_json it[3], actions;
|
||||
int r;
|
||||
|
||||
spa_json_init(&it[0], str, len);
|
||||
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
|
||||
if (spa_json_begin_array(&it[0], str, len) < 0) {
|
||||
pw_log_warn("expect array of match rules in: '%.*s'", (int)len, str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((r = spa_json_enter_object(&it[1], &it[2])) > 0) {
|
||||
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
|
||||
char key[64];
|
||||
bool have_match = false, have_actions = false;
|
||||
|
||||
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
if (spa_streq(key, "matches")) {
|
||||
if (spa_json_enter_array(&it[2], &it[3]) < 0) {
|
||||
if (spa_json_enter_array(&it[1], &it[2]) < 0) {
|
||||
pw_log_warn("expected array as matches in '%.*s'",
|
||||
(int)len, str);
|
||||
break;
|
||||
}
|
||||
|
||||
have_match = find_match(&it[3], props, false);
|
||||
have_match = find_match(&it[2], props, false);
|
||||
}
|
||||
else if (spa_streq(key, "actions")) {
|
||||
if (spa_json_enter_object(&it[2], &actions) > 0)
|
||||
if (spa_json_enter_object(&it[1], &actions) > 0)
|
||||
have_actions = true;
|
||||
else
|
||||
pw_log_warn("expected object as match actions in '%.*s'",
|
||||
|
|
@ -1339,7 +1334,7 @@ int pw_conf_match_rules(const char *str, size_t len, const char *location,
|
|||
}
|
||||
else {
|
||||
pw_log_warn("unknown match key '%s'", key);
|
||||
if (spa_json_next(&it[2], &val) <= 0) {
|
||||
if (spa_json_next(&it[1], &val) <= 0) {
|
||||
pw_log_warn("malformed match rule: key '%s' has "
|
||||
"no value in '%.*s'", key, (int)len, str);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -204,19 +204,18 @@ static int setup_data_loops(struct impl *impl)
|
|||
lib_name = pw_properties_get(this->properties, "context.data-loop." PW_KEY_LIBRARY_NAME_SYSTEM);
|
||||
|
||||
if ((str = pw_properties_get(this->properties, "context.data-loops")) != NULL) {
|
||||
struct spa_json it[4];
|
||||
struct spa_json it[2];
|
||||
char key[512];
|
||||
int r, len = strlen(str);
|
||||
spa_autofree char *s = strndup(str, len);
|
||||
|
||||
i = 0;
|
||||
spa_json_init(&it[0], s, len);
|
||||
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
|
||||
if (spa_json_begin_array(&it[0], s, len) < 0) {
|
||||
pw_log_error("context.data-loops is not an array in '%s'", str);
|
||||
res = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
while ((r = spa_json_enter_object(&it[1], &it[2])) > 0) {
|
||||
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
|
||||
char *props = NULL;
|
||||
|
||||
if (i >= MAX_LOOPS) {
|
||||
|
|
@ -229,17 +228,17 @@ static int setup_data_loops(struct impl *impl)
|
|||
pw_properties_update(pr, &this->properties->dict);
|
||||
pw_properties_set(pr, PW_KEY_LIBRARY_NAME_SYSTEM, lib_name);
|
||||
|
||||
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
const char *val;
|
||||
int l;
|
||||
|
||||
if ((l = spa_json_next(&it[2], &val)) <= 0) {
|
||||
if ((l = spa_json_next(&it[1], &val)) <= 0) {
|
||||
pw_log_warn("malformed data-loop: key '%s' has no "
|
||||
"value in '%.*s'", key, (int)len, str);
|
||||
break;
|
||||
}
|
||||
if (spa_json_is_container(val, l))
|
||||
l = spa_json_container_len(&it[2], val, l);
|
||||
l = spa_json_container_len(&it[1], val, l);
|
||||
|
||||
props = (char*)val;
|
||||
spa_json_parse_stringn(val, l, props, l+1);
|
||||
|
|
|
|||
|
|
@ -1282,20 +1282,18 @@ int pw_impl_port_add(struct pw_impl_port *port, struct pw_impl_node *node)
|
|||
|
||||
channel_names = pw_properties_get(nprops, PW_KEY_NODE_CHANNELNAMES);
|
||||
if (channel_names != NULL) {
|
||||
struct spa_json it[2];
|
||||
struct spa_json it[1];
|
||||
char v[256];
|
||||
uint32_t i;
|
||||
|
||||
spa_json_init(&it[0], channel_names, strlen(channel_names));
|
||||
if (spa_json_enter_array(&it[0], &it[1]) <= 0)
|
||||
spa_json_init(&it[1], channel_names, strlen(channel_names));
|
||||
if (spa_json_begin_array_relax(&it[0], channel_names, strlen(channel_names)) > 0) {
|
||||
for (i = 0; i < port->port_id + 1; i++)
|
||||
if (spa_json_get_string(&it[0], v, sizeof(v)) <= 0)
|
||||
break;
|
||||
|
||||
for (i = 0; i < port->port_id + 1; i++)
|
||||
if (spa_json_get_string(&it[1], v, sizeof(v)) <= 0)
|
||||
break;
|
||||
|
||||
if (i == port->port_id + 1 && strlen(v) > 0)
|
||||
snprintf(position, sizeof(position), "%s", v);
|
||||
if (i == port->port_id + 1 && strlen(v) > 0)
|
||||
snprintf(position, sizeof(position), "%s", v);
|
||||
}
|
||||
}
|
||||
|
||||
if (pw_properties_get(port->properties, PW_KEY_PORT_NAME) == NULL) {
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ exit_noupdate:
|
|||
static int update_string(struct pw_properties *props, const char *str, size_t size,
|
||||
int *count, struct spa_error_location *loc)
|
||||
{
|
||||
struct spa_json it[2];
|
||||
struct spa_json it[1];
|
||||
char key[1024];
|
||||
struct spa_error_location el;
|
||||
bool err;
|
||||
|
|
@ -220,29 +220,28 @@ static int update_string(struct pw_properties *props, const char *str, size_t si
|
|||
if (props)
|
||||
properties_init(&changes, 16);
|
||||
|
||||
spa_json_init(&it[0], str, size);
|
||||
if (spa_json_enter_object(&it[0], &it[1]) <= 0)
|
||||
spa_json_init(&it[1], str, size);
|
||||
if ((res = spa_json_begin_object_relax(&it[0], str, size)) <= 0)
|
||||
return res;
|
||||
|
||||
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
|
||||
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
|
||||
int len;
|
||||
const char *value;
|
||||
char *val = NULL;
|
||||
|
||||
if ((len = spa_json_next(&it[1], &value)) <= 0)
|
||||
if ((len = spa_json_next(&it[0], &value)) <= 0)
|
||||
break;
|
||||
|
||||
if (spa_json_is_null(value, len))
|
||||
val = NULL;
|
||||
else {
|
||||
if (spa_json_is_container(value, len))
|
||||
len = spa_json_container_len(&it[1], value, len);
|
||||
len = spa_json_container_len(&it[0], value, len);
|
||||
if (len <= 0)
|
||||
break;
|
||||
|
||||
if (props) {
|
||||
if ((val = malloc(len+1)) == NULL) {
|
||||
it[1].state = SPA_JSON_ERROR_FLAG;
|
||||
it[0].state = SPA_JSON_ERROR_FLAG;
|
||||
break;
|
||||
}
|
||||
spa_json_parse_stringn(value, len, val, len+1);
|
||||
|
|
@ -257,12 +256,12 @@ static int update_string(struct pw_properties *props, const char *str, size_t si
|
|||
}
|
||||
/* item changed or added, apply changes later */
|
||||
if ((errno = -add_item(&changes, key, false, val, true) < 0)) {
|
||||
it[1].state = SPA_JSON_ERROR_FLAG;
|
||||
it[0].state = SPA_JSON_ERROR_FLAG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((err = spa_json_get_error(&it[1], str, &el))) {
|
||||
if ((err = spa_json_get_error(&it[0], str, &el))) {
|
||||
if (loc == NULL)
|
||||
spa_debug_log_error_location(pw_log_get(), SPA_LOG_LEVEL_WARN,
|
||||
&el, "error parsing more than %d properties: %s",
|
||||
|
|
|
|||
|
|
@ -90,14 +90,13 @@ static bool uint32_array_contains(uint32_t *vals, uint32_t n_vals, uint32_t val)
|
|||
static uint32_t parse_uint32_array(const char *str, uint32_t *vals, uint32_t max, uint32_t def)
|
||||
{
|
||||
uint32_t count = 0, r;
|
||||
struct spa_json it[2];
|
||||
struct spa_json it[1];
|
||||
char v[256];
|
||||
|
||||
spa_json_init(&it[0], str, strlen(str));
|
||||
if (spa_json_enter_array(&it[0], &it[1]) <= 0)
|
||||
spa_json_init(&it[1], str, strlen(str));
|
||||
if (spa_json_begin_array_relax(&it[0], str, strlen(str)) <= 0)
|
||||
return 0;
|
||||
|
||||
while (spa_json_get_string(&it[1], v, sizeof(v)) > 0 &&
|
||||
while (spa_json_get_string(&it[0], v, sizeof(v)) > 0 &&
|
||||
count < max) {
|
||||
if (spa_atou32(v, &r, 0))
|
||||
vals[count++] = r;
|
||||
|
|
|
|||
|
|
@ -27,15 +27,14 @@ do { \
|
|||
|
||||
static int parse_affinity(const char *affinity, cpu_set_t *set)
|
||||
{
|
||||
struct spa_json it[2];
|
||||
struct spa_json it[1];
|
||||
int v;
|
||||
|
||||
CPU_ZERO(set);
|
||||
spa_json_init(&it[0], affinity, strlen(affinity));
|
||||
if (spa_json_enter_array(&it[0], &it[1]) <= 0)
|
||||
spa_json_init(&it[1], affinity, strlen(affinity));
|
||||
if (spa_json_begin_array_relax(&it[0], affinity, strlen(affinity)) <= 0)
|
||||
return 0;
|
||||
|
||||
while (spa_json_get_int(&it[1], &v) > 0) {
|
||||
while (spa_json_get_int(&it[0], &v) > 0) {
|
||||
if (v >= 0 && v < CPU_SETSIZE)
|
||||
CPU_SET(v, set);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ SPA_EXPORT
|
|||
char **pw_strv_parse(const char *val, size_t len, int max_tokens, int *n_tokens)
|
||||
{
|
||||
struct pw_array arr;
|
||||
struct spa_json it[2];
|
||||
struct spa_json it[1];
|
||||
int n = 0, l, res;
|
||||
const char *value;
|
||||
struct spa_error_location el;
|
||||
|
|
@ -140,11 +140,10 @@ char **pw_strv_parse(const char *val, size_t len, int max_tokens, int *n_tokens)
|
|||
|
||||
pw_array_init(&arr, sizeof(char*) * 16);
|
||||
|
||||
spa_json_init(&it[0], val, len);
|
||||
if (spa_json_enter_array(&it[0], &it[1]) <= 0)
|
||||
spa_json_init(&it[1], val, len);
|
||||
if (spa_json_begin_array_relax(&it[0], val, len) <= 0)
|
||||
return NULL;
|
||||
|
||||
while ((l = spa_json_next(&it[1], &value)) > 0 && n + 1 < max_tokens) {
|
||||
while ((l = spa_json_next(&it[0], &value)) > 0 && n + 1 < max_tokens) {
|
||||
char *s;
|
||||
|
||||
if ((s = malloc(l+1)) == NULL)
|
||||
|
|
@ -161,7 +160,7 @@ char **pw_strv_parse(const char *val, size_t len, int max_tokens, int *n_tokens)
|
|||
if ((res = pw_array_add_ptr(&arr, NULL)) < 0)
|
||||
goto error;
|
||||
done:
|
||||
if ((res = spa_json_get_error(&it[1], val, &el))) {
|
||||
if ((res = spa_json_get_error(&it[0], val, &el))) {
|
||||
spa_debug_log_error_location(pw_log_get(), SPA_LOG_LEVEL_WARN,
|
||||
&el, "error parsing strv: %s", el.reason);
|
||||
|
||||
|
|
@ -179,7 +178,7 @@ done:
|
|||
error_errno:
|
||||
res = -errno;
|
||||
error:
|
||||
it[1].state = SPA_JSON_ERROR_FLAG;
|
||||
it[0].state = SPA_JSON_ERROR_FLAG;
|
||||
errno = -res;
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue