spa: add spa_json_object_next

This gets the next key and value from an object. This function is better
because it will skip key/value pairs that don't fit in the array to hold
the key.

The previous code patter would stop parsing the object as soon as a key
larger than the available space was found.
This commit is contained in:
Wim Taymans 2024-09-13 16:26:36 +02:00
parent cd81b5f39a
commit ce390d5b22
24 changed files with 171 additions and 269 deletions

View file

@ -1023,20 +1023,15 @@ static int json_object_find(const char *obj, const char *key, char *value, size_
{ {
struct spa_json it[1]; struct spa_json it[1];
const char *v; const char *v;
char k[128]; int l, kl = strlen(key) + 3;
char k[kl];
if (spa_json_begin_object(&it[0], obj, strlen(obj)) <= 0) if (spa_json_begin_object(&it[0], obj, strlen(obj)) <= 0)
return -EINVAL; return -EINVAL;
while (spa_json_get_string(&it[0], k, sizeof(k)) > 0) { while ((l = spa_json_object_next(&it[0], k, kl, &v)) > 0) {
if (spa_streq(k, key)) { if (spa_streq(k, key))
if (spa_json_get_string(&it[1], value, len) <= 0) return spa_json_parse_stringn(v, l, value, len);
continue;
return 0;
} else {
if (spa_json_next(&it[1], &v) <= 0)
break;
}
} }
return -ENOENT; return -ENOENT;
} }

View file

@ -1140,9 +1140,7 @@ static int parse_value(const char *str, struct param_info *info)
info->type = TYPE_MIN_MAX; info->type = TYPE_MIN_MAX;
info->n_vals = 2; info->n_vals = 2;
spa_json_enter(&it[0], &it[1]); spa_json_enter(&it[0], &it[1]);
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
if ((len = spa_json_next(&it[1], &val)) <= 0)
break;
if (info->collect(val, len, &v) < 0) if (info->collect(val, len, &v) < 0)
continue; continue;
if (spa_streq(key, "min")) if (spa_streq(key, "min"))

View file

@ -3460,20 +3460,15 @@ static int json_object_find(const char *obj, const char *key, char *value, size_
{ {
struct spa_json it[1]; struct spa_json it[1];
const char *v; const char *v;
char k[128]; int l, kl = strlen(key) + 3;
char k[kl];
if (spa_json_begin_object(&it[0], obj, strlen(obj)) <= 0) if (spa_json_begin_object(&it[0], obj, strlen(obj)) <= 0)
return -EINVAL; return -EINVAL;
while (spa_json_get_string(&it[0], k, sizeof(k)) > 0) { while ((l = spa_json_object_next(&it[0], k, kl, &v)) > 0) {
if (spa_streq(k, key)) { if (spa_streq(k, key))
if (spa_json_get_string(&it[0], value, len) <= 0) return spa_json_parse_stringn(v, l, value, len);
continue;
return 0;
} else {
if (spa_json_next(&it[0], &v) <= 0)
break;
}
} }
return -ENOENT; return -ENOENT;
} }

View file

@ -42,10 +42,8 @@ static inline int spa_json_to_pod_part(struct spa_pod_builder *b, uint32_t flags
spa_pod_builder_push_object(b, &f[0], info->parent, id); spa_pod_builder_push_object(b, &f[0], info->parent, id);
spa_json_enter(iter, &it[0]); spa_json_enter(iter, &it[0]);
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((l = spa_json_object_next(&it[0], key, sizeof(key), &v)) > 0) {
const struct spa_type_info *pi; const struct spa_type_info *pi;
if ((l = spa_json_next(&it[0], &v)) <= 0)
break;
if ((pi = spa_debug_type_find_short(ti->values, key)) != NULL) if ((pi = spa_debug_type_find_short(ti->values, key)) != NULL)
type = pi->type; type = pi->type;
else if (!spa_atou32(key, &type, 0)) else if (!spa_atou32(key, &type, 0))

View file

@ -39,7 +39,7 @@ struct spa_json {
uint32_t depth; uint32_t depth;
}; };
#define SPA_JSON_INIT(data,size) ((struct spa_json) { (data), (data)+(size), 0, 0, 0 }) #define SPA_JSON_INIT(data,size) ((struct spa_json) { (data), (data)+(size), NULL, 0, 0 })
static inline void spa_json_init(struct spa_json * iter, const char *data, size_t size) static inline void spa_json_init(struct spa_json * iter, const char *data, size_t size)
{ {
@ -54,6 +54,8 @@ static inline void spa_json_enter(struct spa_json * iter, struct spa_json * sub)
#define SPA_JSON_SAVE(iter) ((struct spa_json) { (iter)->cur, (iter)->end, NULL, (iter)->state, 0 }) #define SPA_JSON_SAVE(iter) ((struct spa_json) { (iter)->cur, (iter)->end, NULL, (iter)->state, 0 })
#define SPA_JSON_START(iter,p) ((struct spa_json) { (p), (iter)->end, NULL, 0, 0 })
/** Get the next token. \a value points to the token and the return value /** Get the next token. \a value points to the token and the return value
* is the length. Returns -1 on parse error, 0 on end of input. */ * is the length. Returns -1 on parse error, 0 on end of input. */
static inline int spa_json_next(struct spa_json * iter, const char **value) static inline int spa_json_next(struct spa_json * iter, const char **value)
@ -594,7 +596,7 @@ static inline int spa_json_parse_stringn(const char *val, int len, char *result,
{ {
const char *p; const char *p;
if (maxlen <= len) if (maxlen <= len)
return -1; return -ENOSPC;
if (!spa_json_is_string(val, len)) { if (!spa_json_is_string(val, len)) {
if (result != val) if (result != val)
memmove(result, val, len); memmove(result, val, len);
@ -712,6 +714,19 @@ static inline int spa_json_encode_string(char *str, int size, const char *val)
return len-1; return len-1;
} }
static inline int spa_json_object_next(struct spa_json *iter, char *key, int maxkeylen, const char **value)
{
int res1, res2;
while (true) {
res1 = spa_json_get_string(iter, key, maxkeylen);
if (res1 <= 0 && res1 != -ENOSPC)
return res1;
res2 = spa_json_next(iter, value);
if (res2 <= 0 || res1 != -ENOSPC)
return res2;
}
}
/** /**
* \} * \}
*/ */

View file

@ -1825,20 +1825,21 @@ static int do_auto_port_config(struct impl *this, const char *str)
#define POSITION_PRESERVE 0 #define POSITION_PRESERVE 0
#define POSITION_AUX 1 #define POSITION_AUX 1
#define POSITION_UNKNOWN 2 #define POSITION_UNKNOWN 2
int res, position = POSITION_PRESERVE; int l, res, position = POSITION_PRESERVE;
struct spa_pod *param; struct spa_pod *param;
bool have_format = false, monitor = false, control = false; bool have_format = false, monitor = false, control = false;
struct spa_audio_info format = { 0, }; struct spa_audio_info format = { 0, };
enum spa_param_port_config_mode mode = SPA_PARAM_PORT_CONFIG_MODE_none; enum spa_param_port_config_mode mode = SPA_PARAM_PORT_CONFIG_MODE_none;
struct spa_json it[1]; struct spa_json it[1];
char key[1024], val[256]; char key[1024], val[256];
const char *v;
if (spa_json_begin_object(&it[0], str, strlen(str)) <= 0) if (spa_json_begin_object(&it[0], str, strlen(str)) <= 0)
return -EINVAL; return -EINVAL;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((l = spa_json_object_next(&it[0], key, sizeof(key), &v)) > 0) {
if (spa_json_get_string(&it[0], val, sizeof(val)) <= 0) if (spa_json_parse_stringn(v, l, val, sizeof(val)) <= 0)
break; continue;
if (spa_streq(key, "mode")) { if (spa_streq(key, "mode")) {
mode = spa_debug_type_find_type_short(spa_type_param_port_config_mode, val); mode = spa_debug_type_find_type_short(spa_type_param_port_config_mode, val);

View file

@ -87,26 +87,24 @@ static int do_match(const char *rules, struct spa_dict *dict, uint32_t *no_featu
while (spa_json_enter_object(&rules_arr, &it[0]) > 0) { while (spa_json_enter_object(&rules_arr, &it[0]) > 0) {
char key[256]; char key[256];
int match = true; int match = true, len;
uint32_t no_features_cur = 0; uint32_t no_features_cur = 0;
const char *value;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) {
char val[4096]; char val[4096];
const char *str, *value; const char *str;
int len;
bool success = false; bool success = false;
if (spa_streq(key, "no-features")) { if (spa_streq(key, "no-features")) {
if (spa_json_enter_array(&it[0], &it[1]) > 0) { if (spa_json_is_array(value, len) > 0) {
spa_json_enter(&it[0], &it[1]);
while (spa_json_get_string(&it[1], val, sizeof(val)) > 0) while (spa_json_get_string(&it[1], val, sizeof(val)) > 0)
no_features_cur |= parse_feature(val); no_features_cur |= parse_feature(val);
} }
continue; continue;
} }
if ((len = spa_json_next(&it[0], &value)) <= 0)
break;
if (spa_json_is_null(value, len)) { if (spa_json_is_null(value, len)) {
value = NULL; value = NULL;
} else { } else {
@ -161,17 +159,13 @@ static void load_quirks(struct spa_bt_quirks *this, const char *str, size_t len)
struct spa_json rules; struct spa_json rules;
char key[1024]; char key[1024];
struct spa_error_location loc; struct spa_error_location loc;
int sz;
const char *value;
if (spa_json_enter_object(&data, &rules) <= 0) if (spa_json_enter_object(&data, &rules) <= 0)
spa_json_init(&rules, str, len); spa_json_init(&rules, str, len);
while (spa_json_get_string(&rules, key, sizeof(key)) > 0) { while ((sz = spa_json_object_next(&rules, key, sizeof(key), &value)) > 0) {
int sz;
const char *value;
if ((sz = spa_json_next(&rules, &value)) <= 0)
break;
if (!spa_json_is_container(value, sz)) if (!spa_json_is_container(value, sz))
continue; continue;

View file

@ -82,14 +82,12 @@ static int dump(FILE *file, int indent, struct spa_json *it, const char *value,
spa_json_enter(it, &sub); spa_json_enter(it, &sub);
else else
sub = *it; sub = *it;
while (spa_json_get_string(&sub, key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&sub, key, sizeof(key), &value)) > 0) {
fprintf(file, "%s\n%*s", fprintf(file, "%s\n%*s",
count++ > 0 ? "," : "", count++ > 0 ? "," : "",
indent+2, ""); indent+2, "");
encode_string(file, key, strlen(key)); encode_string(file, key, strlen(key));
fprintf(file, ": "); fprintf(file, ": ");
if ((len = spa_json_next(&sub, &value)) <= 0)
break;
res = dump(file, indent+2, &sub, value, len); res = dump(file, indent+2, &sub, value, len);
if (res < 0) { if (res < 0) {
if (toplevel) if (toplevel)

View file

@ -276,17 +276,14 @@ static int parse_socket_args(struct impl *impl, const char *str)
{ {
struct spa_json it[1]; struct spa_json it[1];
char socket[PATH_MAX]; char socket[PATH_MAX];
const char *val;
int len;
if (spa_json_begin_object(&it[0], str, strlen(str)) <= 0) if (spa_json_begin_object(&it[0], str, strlen(str)) <= 0)
return -EINVAL; return -EINVAL;
while (spa_json_get_string(&it[0], socket, sizeof(socket)) > 0) { while ((len = spa_json_object_next(&it[0], socket, sizeof(socket), &val)) > 0) {
char value[256]; char value[256];
const char *val;
int len;
if ((len = spa_json_next(&it[0], &val)) <= 0)
return -EINVAL;
if (spa_json_parse_stringn(val, len, value, sizeof(value)) <= 0) if (spa_json_parse_stringn(val, len, value, sizeof(value)) <= 0)
return -EINVAL; return -EINVAL;

View file

@ -286,18 +286,15 @@ static int do_discover(struct adp *adp, const char *args, FILE *out)
struct spa_json it[1]; struct spa_json it[1];
char key[128]; char key[128];
uint64_t entity_id = 0ULL; uint64_t entity_id = 0ULL;
int len;
const char *value;
if (spa_json_begin_object(&it[0], args, strlen(args)) <= 0) if (spa_json_begin_object(&it[0], args, strlen(args)) <= 0)
return -EINVAL; return -EINVAL;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) {
int len;
const char *value;
uint64_t id_val; uint64_t id_val;
if ((len = spa_json_next(&it[0], &value)) <= 0)
break;
if (spa_json_is_null(value, len)) if (spa_json_is_null(value, len))
continue; continue;

View file

@ -255,7 +255,8 @@ static int load_state(struct maap *maap)
char key[512]; char key[512];
struct spa_json it[2]; struct spa_json it[2];
bool have_offset = false; bool have_offset = false;
int count = 0, offset = 0; int count = 0, offset = 0, len;
const char *val;
snprintf(key, sizeof(key), "maap.%s", maap->server->ifname); snprintf(key, sizeof(key), "maap.%s", maap->server->ifname);
pw_conf_load_state("module-avb", key, maap->props); pw_conf_load_state("module-avb", key, maap->props);
@ -269,13 +270,7 @@ static int load_state(struct maap *maap)
if (spa_json_enter_object(&it[0], &it[1]) <= 0) if (spa_json_enter_object(&it[0], &it[1]) <= 0)
return 0; return 0;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
const char *val;
int len;
if ((len = spa_json_next(&it[1], &val)) <= 0)
break;
if (spa_streq(key, "start")) { if (spa_streq(key, "start")) {
uint8_t addr[6]; uint8_t addr[6];
if (avb_utils_parse_addr(val, len, addr) >= 0 && if (avb_utils_parse_addr(val, len, addr) >= 0 &&

View file

@ -1913,14 +1913,12 @@ done:
static int parse_control(struct node *node, struct spa_json *control) static int parse_control(struct node *node, struct spa_json *control)
{ {
char key[256]; char key[256];
const char *val;
int len;
while (spa_json_get_string(control, key, sizeof(key)) > 0) { while ((len = spa_json_object_next(control, key, sizeof(key), &val)) > 0) {
float fl; float fl;
const char *val; int res;
int res, len;
if ((len = spa_json_next(control, &val)) < 0)
break;
if (spa_json_parse_float(val, len, &fl) <= 0) { if (spa_json_parse_float(val, len, &fl) <= 0) {
pw_log_warn("control '%s' expects a number, ignoring", key); pw_log_warn("control '%s' expects a number, ignoring", key);
@ -1946,29 +1944,28 @@ static int parse_link(struct graph *graph, struct spa_json *json)
struct node *def_in_node, *def_out_node; struct node *def_in_node, *def_out_node;
struct port *in_port, *out_port; struct port *in_port, *out_port;
struct link *link; struct link *link;
int len;
if (spa_list_is_empty(&graph->node_list)) { if (spa_list_is_empty(&graph->node_list)) {
pw_log_error("can't make links in graph without nodes"); pw_log_error("can't make links in graph without nodes");
return -EINVAL; return -EINVAL;
} }
while (spa_json_get_string(json, key, sizeof(key)) > 0) { while ((len = spa_json_object_next(json, key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "output")) { if (spa_streq(key, "output")) {
if (spa_json_get_string(json, output, sizeof(output)) <= 0) { if (spa_json_parse_stringn(val, len, output, sizeof(output)) <= 0) {
pw_log_error("output expects a string"); pw_log_error("output expects a string");
return -EINVAL; return -EINVAL;
} }
} }
else if (spa_streq(key, "input")) { else if (spa_streq(key, "input")) {
if (spa_json_get_string(json, input, sizeof(input)) <= 0) { if (spa_json_parse_stringn(val, len, input, sizeof(input)) <= 0) {
pw_log_error("input expects a string"); pw_log_error("input expects a string");
return -EINVAL; return -EINVAL;
} }
} }
else { else {
pw_log_error("unexpected link key '%s'", key); pw_log_error("unexpected link key '%s'", key);
if (spa_json_next(json, &val) < 0)
break;
} }
} }
def_out_node = spa_list_first(&graph->node_list, struct node, link); def_out_node = spa_list_first(&graph->node_list, struct node, link);
@ -2049,40 +2046,39 @@ static int parse_volume(struct graph *graph, struct spa_json *json, bool capture
struct port *port; struct port *port;
struct volume *vol = capture ? &graph->capture_volume : struct volume *vol = capture ? &graph->capture_volume :
&graph->playback_volume; &graph->playback_volume;
int len;
if (spa_list_is_empty(&graph->node_list)) { if (spa_list_is_empty(&graph->node_list)) {
pw_log_error("can't set volume in graph without nodes"); pw_log_error("can't set volume in graph without nodes");
return -EINVAL; return -EINVAL;
} }
while (spa_json_get_string(json, key, sizeof(key)) > 0) { while ((len = spa_json_object_next(json, key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "control")) { if (spa_streq(key, "control")) {
if (spa_json_get_string(json, control, sizeof(control)) <= 0) { if (spa_json_parse_stringn(val, len, control, sizeof(control)) <= 0) {
pw_log_error("control expects a string"); pw_log_error("control expects a string");
return -EINVAL; return -EINVAL;
} }
} }
else if (spa_streq(key, "min")) { else if (spa_streq(key, "min")) {
if (spa_json_get_float(json, &min) <= 0) { if (spa_json_parse_float(val, len, &min) <= 0) {
pw_log_error("min expects a float"); pw_log_error("min expects a float");
return -EINVAL; return -EINVAL;
} }
} }
else if (spa_streq(key, "max")) { else if (spa_streq(key, "max")) {
if (spa_json_get_float(json, &max) <= 0) { if (spa_json_parse_float(val, len, &max) <= 0) {
pw_log_error("max expects a float"); pw_log_error("max expects a float");
return -EINVAL; return -EINVAL;
} }
} }
else if (spa_streq(key, "scale")) { else if (spa_streq(key, "scale")) {
if (spa_json_get_string(json, scale, sizeof(scale)) <= 0) { if (spa_json_parse_stringn(val, len, scale, sizeof(scale)) <= 0) {
pw_log_error("scale expects a string"); pw_log_error("scale expects a string");
return -EINVAL; return -EINVAL;
} }
} }
else { else {
pw_log_error("unexpected volume key '%s'", key); pw_log_error("unexpected volume key '%s'", key);
if (spa_json_next(json, &val) < 0)
break;
} }
} }
if (capture) if (capture)
@ -2144,44 +2140,41 @@ static int load_node(struct graph *graph, struct spa_json *json)
bool have_control = false; bool have_control = false;
bool have_config = false; bool have_config = false;
uint32_t i; uint32_t i;
int res; int res, len;
while (spa_json_get_string(json, key, sizeof(key)) > 0) { while ((len = spa_json_object_next(json, key, sizeof(key), &val)) > 0) {
if (spa_streq("type", key)) { if (spa_streq("type", key)) {
if (spa_json_get_string(json, type, sizeof(type)) <= 0) { if (spa_json_parse_stringn(val, len, type, sizeof(type)) <= 0) {
pw_log_error("type expects a string"); pw_log_error("type expects a string");
return -EINVAL; return -EINVAL;
} }
} else if (spa_streq("name", key)) { } else if (spa_streq("name", key)) {
if (spa_json_get_string(json, name, sizeof(name)) <= 0) { if (spa_json_parse_stringn(val, len, name, sizeof(name)) <= 0) {
pw_log_error("name expects a string"); pw_log_error("name expects a string");
return -EINVAL; return -EINVAL;
} }
} else if (spa_streq("plugin", key)) { } else if (spa_streq("plugin", key)) {
if (spa_json_get_string(json, plugin, sizeof(plugin)) <= 0) { if (spa_json_parse_stringn(val, len, plugin, sizeof(plugin)) <= 0) {
pw_log_error("plugin expects a string"); pw_log_error("plugin expects a string");
return -EINVAL; return -EINVAL;
} }
} else if (spa_streq("label", key)) { } else if (spa_streq("label", key)) {
if (spa_json_get_string(json, label, sizeof(label)) <= 0) { if (spa_json_parse_stringn(val, len, label, sizeof(label)) <= 0) {
pw_log_error("label expects a string"); pw_log_error("label expects a string");
return -EINVAL; return -EINVAL;
} }
} else if (spa_streq("control", key)) { } else if (spa_streq("control", key)) {
if (spa_json_enter_object(json, &control) <= 0) { if (!spa_json_is_object(val, len)) {
pw_log_error("control expects an object"); pw_log_error("control expects an object");
return -EINVAL; return -EINVAL;
} }
spa_json_enter(json, &control);
have_control = true; have_control = true;
} else if (spa_streq("config", key)) { } else if (spa_streq("config", key)) {
config = SPA_JSON_SAVE(json); config = SPA_JSON_START(json, val);
have_config = true; have_config = true;
if (spa_json_next(json, &val) < 0)
break;
} else { } else {
pw_log_warn("unexpected node key '%s'", key); pw_log_warn("unexpected node key '%s'", key);
if (spa_json_next(json, &val) < 0)
break;
} }
} }
if (spa_streq(type, "builtin")) if (spa_streq(type, "builtin"))
@ -2720,7 +2713,7 @@ static int load_graph(struct graph *graph, struct pw_properties *props)
struct spa_json nodes, *pnodes = NULL, links, *plinks = NULL; struct spa_json nodes, *pnodes = NULL, links, *plinks = NULL;
const char *json, *val; const char *json, *val;
char key[256]; char key[256];
int res; int res, len;
spa_list_init(&graph->node_list); spa_list_init(&graph->node_list);
spa_list_init(&graph->link_list); spa_list_init(&graph->link_list);
@ -2735,52 +2728,56 @@ static int load_graph(struct graph *graph, struct pw_properties *props)
return -EINVAL; return -EINVAL;
} }
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
if (spa_streq("nodes", key)) { if (spa_streq("nodes", key)) {
if (spa_json_enter_array(&it[0], &nodes) <= 0) { if (!spa_json_is_array(val, len)) {
pw_log_error("nodes expects an array"); pw_log_error("nodes expects an array");
return -EINVAL; return -EINVAL;
} }
spa_json_enter(&it[0], &nodes);
pnodes = &nodes; pnodes = &nodes;
} }
else if (spa_streq("links", key)) { else if (spa_streq("links", key)) {
if (spa_json_enter_array(&it[0], &links) <= 0) { if (!spa_json_is_array(val, len)) {
pw_log_error("links expects an array"); pw_log_error("links expects an array");
return -EINVAL; return -EINVAL;
} }
spa_json_enter(&it[0], &links);
plinks = &links; plinks = &links;
} }
else if (spa_streq("inputs", key)) { else if (spa_streq("inputs", key)) {
if (spa_json_enter_array(&it[0], &inputs) <= 0) { if (!spa_json_is_array(val, len)) {
pw_log_error("inputs expects an array"); pw_log_error("inputs expects an array");
return -EINVAL; return -EINVAL;
} }
spa_json_enter(&it[0], &inputs);
pinputs = &inputs; pinputs = &inputs;
} }
else if (spa_streq("outputs", key)) { else if (spa_streq("outputs", key)) {
if (spa_json_enter_array(&it[0], &outputs) <= 0) { if (!spa_json_is_array(val, len)) {
pw_log_error("outputs expects an array"); pw_log_error("outputs expects an array");
return -EINVAL; return -EINVAL;
} }
spa_json_enter(&it[0], &outputs);
poutputs = &outputs; poutputs = &outputs;
} }
else if (spa_streq("capture.volumes", key)) { else if (spa_streq("capture.volumes", key)) {
if (spa_json_enter_array(&it[0], &cvolumes) <= 0) { if (!spa_json_is_array(val, len)) {
pw_log_error("capture.volumes expects an array"); pw_log_error("capture.volumes expects an array");
return -EINVAL; return -EINVAL;
} }
spa_json_enter(&it[0], &cvolumes);
pcvolumes = &cvolumes; pcvolumes = &cvolumes;
} }
else if (spa_streq("playback.volumes", key)) { else if (spa_streq("playback.volumes", key)) {
if (spa_json_enter_array(&it[0], &pvolumes) <= 0) { if (!spa_json_is_array(val, len)) {
pw_log_error("playback.volumes expects an array"); pw_log_error("playback.volumes expects an array");
return -EINVAL; return -EINVAL;
} }
spa_json_enter(&it[0], &pvolumes);
ppvolumes = &pvolumes; ppvolumes = &pvolumes;
} else { } else {
pw_log_warn("unexpected graph key '%s'", key); pw_log_warn("unexpected graph key '%s'", key);
if (spa_json_next(&it[0], &val) < 0)
break;
} }
} }
if (pnodes == NULL) { if (pnodes == NULL) {

View file

@ -282,6 +282,7 @@ static void *bq_instantiate(const struct fc_descriptor * Descriptor,
const char *val; const char *val;
char key[256]; char key[256];
uint32_t best_rate = 0; uint32_t best_rate = 0;
int len;
impl = calloc(1, sizeof(*impl)); impl = calloc(1, sizeof(*impl));
if (impl == NULL) if (impl == NULL)
@ -303,64 +304,63 @@ static void *bq_instantiate(const struct fc_descriptor * Descriptor,
goto error; goto error;
} }
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "coefficients")) { if (spa_streq(key, "coefficients")) {
if (spa_json_enter_array(&it[0], &it[1]) <= 0) { if (!spa_json_is_array(val, len)) {
pw_log_error("biquads:coefficients require an array"); pw_log_error("biquads:coefficients require an array");
goto error; goto error;
} }
spa_json_enter(&it[0], &it[1]);
while (spa_json_enter_object(&it[1], &it[2]) > 0) { while (spa_json_enter_object(&it[1], &it[2]) > 0) {
int32_t rate = 0; int32_t rate = 0;
float b0 = 1.0f, b1 = 0.0f, b2 = 0.0f; float b0 = 1.0f, b1 = 0.0f, b2 = 0.0f;
float a0 = 1.0f, a1 = 0.0f, a2 = 0.0f; float a0 = 1.0f, a1 = 0.0f, a2 = 0.0f;
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[2], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "rate")) { if (spa_streq(key, "rate")) {
if (spa_json_get_int(&it[2], &rate) <= 0) { if (spa_json_parse_int(val, len, &rate) <= 0) {
pw_log_error("biquads:rate requires a number"); pw_log_error("biquads:rate requires a number");
goto error; goto error;
} }
} }
else if (spa_streq(key, "b0")) { else if (spa_streq(key, "b0")) {
if (spa_json_get_float(&it[2], &b0) <= 0) { if (spa_json_parse_float(val, len, &b0) <= 0) {
pw_log_error("biquads:b0 requires a float"); pw_log_error("biquads:b0 requires a float");
goto error; goto error;
} }
} }
else if (spa_streq(key, "b1")) { else if (spa_streq(key, "b1")) {
if (spa_json_get_float(&it[2], &b1) <= 0) { if (spa_json_parse_float(val, len, &b1) <= 0) {
pw_log_error("biquads:b1 requires a float"); pw_log_error("biquads:b1 requires a float");
goto error; goto error;
} }
} }
else if (spa_streq(key, "b2")) { else if (spa_streq(key, "b2")) {
if (spa_json_get_float(&it[2], &b2) <= 0) { if (spa_json_parse_float(val, len, &b2) <= 0) {
pw_log_error("biquads:b2 requires a float"); pw_log_error("biquads:b2 requires a float");
goto error; goto error;
} }
} }
else if (spa_streq(key, "a0")) { else if (spa_streq(key, "a0")) {
if (spa_json_get_float(&it[2], &a0) <= 0) { if (spa_json_parse_float(val, len, &a0) <= 0) {
pw_log_error("biquads:a0 requires a float"); pw_log_error("biquads:a0 requires a float");
goto error; goto error;
} }
} }
else if (spa_streq(key, "a1")) { else if (spa_streq(key, "a1")) {
if (spa_json_get_float(&it[2], &a1) <= 0) { if (spa_json_parse_float(val, len, &a1) <= 0) {
pw_log_error("biquads:a1 requires a float"); pw_log_error("biquads:a1 requires a float");
goto error; goto error;
} }
} }
else if (spa_streq(key, "a2")) { else if (spa_streq(key, "a2")) {
if (spa_json_get_float(&it[2], &a2) <= 0) { if (spa_json_parse_float(val, len, &a2) <= 0) {
pw_log_error("biquads:a0 requires a float"); pw_log_error("biquads:a0 requires a float");
goto error; goto error;
} }
} }
else { else {
pw_log_warn("biquads: ignoring coefficients key: '%s'", key); pw_log_warn("biquads: ignoring coefficients key: '%s'", key);
if (spa_json_next(&it[2], &val) < 0)
break;
} }
} }
if (labs((long)rate - (long)SampleRate) < if (labs((long)rate - (long)SampleRate) <
@ -372,8 +372,6 @@ static void *bq_instantiate(const struct fc_descriptor * Descriptor,
} }
else { else {
pw_log_warn("biquads: ignoring config key: '%s'", key); pw_log_warn("biquads: ignoring config key: '%s'", key);
if (spa_json_next(&it[0], &val) < 0)
break;
} }
} }
@ -885,36 +883,32 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
return NULL; return NULL;
} }
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "blocksize")) { if (spa_streq(key, "blocksize")) {
if (spa_json_get_int(&it[0], &blocksize) <= 0) { if (spa_json_parse_int(val, len, &blocksize) <= 0) {
pw_log_error("convolver:blocksize requires a number"); pw_log_error("convolver:blocksize requires a number");
return NULL; return NULL;
} }
} }
else if (spa_streq(key, "tailsize")) { else if (spa_streq(key, "tailsize")) {
if (spa_json_get_int(&it[0], &tailsize) <= 0) { if (spa_json_parse_int(val, len, &tailsize) <= 0) {
pw_log_error("convolver:tailsize requires a number"); pw_log_error("convolver:tailsize requires a number");
return NULL; return NULL;
} }
} }
else if (spa_streq(key, "gain")) { else if (spa_streq(key, "gain")) {
if (spa_json_get_float(&it[0], &gain) <= 0) { if (spa_json_parse_float(val, len, &gain) <= 0) {
pw_log_error("convolver:gain requires a number"); pw_log_error("convolver:gain requires a number");
return NULL; return NULL;
} }
} }
else if (spa_streq(key, "delay")) { else if (spa_streq(key, "delay")) {
if (spa_json_get_int(&it[0], &delay) <= 0) { if (spa_json_parse_int(val, len, &delay) <= 0) {
pw_log_error("convolver:delay requires a number"); pw_log_error("convolver:delay requires a number");
return NULL; return NULL;
} }
} }
else if (spa_streq(key, "filename")) { else if (spa_streq(key, "filename")) {
if ((len = spa_json_next(&it[0], &val)) <= 0) {
pw_log_error("convolver:filename requires a string or an array");
return NULL;
}
if (spa_json_is_array(val, len)) { if (spa_json_is_array(val, len)) {
spa_json_enter(&it[0], &it[1]); spa_json_enter(&it[0], &it[1]);
while (spa_json_get_string(&it[1], v, sizeof(v)) > 0 && while (spa_json_get_string(&it[1], v, sizeof(v)) > 0 &&
@ -931,33 +925,31 @@ static void * convolver_instantiate(const struct fc_descriptor * Descriptor,
} }
} }
else if (spa_streq(key, "offset")) { else if (spa_streq(key, "offset")) {
if (spa_json_get_int(&it[0], &offset) <= 0) { if (spa_json_parse_int(val, len, &offset) <= 0) {
pw_log_error("convolver:offset requires a number"); pw_log_error("convolver:offset requires a number");
return NULL; return NULL;
} }
} }
else if (spa_streq(key, "length")) { else if (spa_streq(key, "length")) {
if (spa_json_get_int(&it[0], &length) <= 0) { if (spa_json_parse_int(val, len, &length) <= 0) {
pw_log_error("convolver:length requires a number"); pw_log_error("convolver:length requires a number");
return NULL; return NULL;
} }
} }
else if (spa_streq(key, "channel")) { else if (spa_streq(key, "channel")) {
if (spa_json_get_int(&it[0], &channel) <= 0) { if (spa_json_parse_int(val, len, &channel) <= 0) {
pw_log_error("convolver:channel requires a number"); pw_log_error("convolver:channel requires a number");
return NULL; return NULL;
} }
} }
else if (spa_streq(key, "resample_quality")) { else if (spa_streq(key, "resample_quality")) {
if (spa_json_get_int(&it[0], &resample_quality) <= 0) { if (spa_json_parse_int(val, len, &resample_quality) <= 0) {
pw_log_error("convolver:resample_quality requires a number"); pw_log_error("convolver:resample_quality requires a number");
return NULL; return NULL;
} }
} }
else { else {
pw_log_warn("convolver: ignoring config key: '%s'", key); pw_log_warn("convolver: ignoring config key: '%s'", key);
if (spa_json_next(&it[0], &val) < 0)
break;
} }
} }
if (filenames[0] == NULL) { if (filenames[0] == NULL) {
@ -1099,6 +1091,7 @@ static void *delay_instantiate(const struct fc_descriptor * Descriptor,
const char *val; const char *val;
char key[256]; char key[256];
float max_delay = 1.0f; float max_delay = 1.0f;
int len;
if (config == NULL) { if (config == NULL) {
pw_log_error("delay: requires a config section"); pw_log_error("delay: requires a config section");
@ -1111,16 +1104,14 @@ static void *delay_instantiate(const struct fc_descriptor * Descriptor,
return NULL; return NULL;
} }
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "max-delay")) { if (spa_streq(key, "max-delay")) {
if (spa_json_get_float(&it[0], &max_delay) <= 0) { if (spa_json_parse_float(val, len, &max_delay) <= 0) {
pw_log_error("delay:max-delay requires a number"); pw_log_error("delay:max-delay requires a number");
return NULL; return NULL;
} }
} else { } else {
pw_log_warn("delay: ignoring config key: '%s'", key); pw_log_warn("delay: ignoring config key: '%s'", key);
if (spa_json_next(&it[0], &val) < 0)
break;
} }
} }
if (max_delay <= 0.0f) if (max_delay <= 0.0f)

View file

@ -40,6 +40,7 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
const char *val; const char *val;
char key[256]; char key[256];
char filename[PATH_MAX] = ""; char filename[PATH_MAX] = "";
int len;
errno = EINVAL; errno = EINVAL;
if (config == NULL) { if (config == NULL) {
@ -58,30 +59,28 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor,
return NULL; return NULL;
} }
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "blocksize")) { if (spa_streq(key, "blocksize")) {
if (spa_json_get_int(&it[0], &impl->blocksize) <= 0) { if (spa_json_parse_int(val, len, &impl->blocksize) <= 0) {
pw_log_error("spatializer:blocksize requires a number"); pw_log_error("spatializer:blocksize requires a number");
errno = EINVAL; errno = EINVAL;
goto error; goto error;
} }
} }
else if (spa_streq(key, "tailsize")) { else if (spa_streq(key, "tailsize")) {
if (spa_json_get_int(&it[0], &impl->tailsize) <= 0) { if (spa_json_parse_int(val, len, &impl->tailsize) <= 0) {
pw_log_error("spatializer:tailsize requires a number"); pw_log_error("spatializer:tailsize requires a number");
errno = EINVAL; errno = EINVAL;
goto error; goto error;
} }
} }
else if (spa_streq(key, "filename")) { else if (spa_streq(key, "filename")) {
if (spa_json_get_string(&it[0], filename, sizeof(filename)) <= 0) { if (spa_json_parse_stringn(val, len, filename, sizeof(filename)) <= 0) {
pw_log_error("spatializer:filename requires a string"); pw_log_error("spatializer:filename requires a string");
errno = EINVAL; errno = EINVAL;
goto error; goto error;
} }
} }
else if (spa_json_next(&it[0], &val) < 0)
break;
} }
if (!filename[0]) { if (!filename[0]) {
pw_log_error("spatializer:filename was not given"); pw_log_error("spatializer:filename was not given");

View file

@ -73,15 +73,10 @@ static int fill_metadata(struct pw_metadata *metadata, const char *str)
while (spa_json_enter_object(&it[0], &it[1]) > 0) { while (spa_json_enter_object(&it[0], &it[1]) > 0) {
char key[256], *k = NULL, *v = NULL, *t = NULL; char key[256], *k = NULL, *v = NULL, *t = NULL;
int id = 0; int id = 0, len;
const char *val;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
int len;
const char *val;
if ((len = spa_json_next(&it[1], &val)) <= 0)
return -EINVAL;
while ((len = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "id")) { if (spa_streq(key, "id")) {
if (spa_json_parse_int(val, len, &id) <= 0) if (spa_json_parse_int(val, len, &id) <= 0)
return -EINVAL; return -EINVAL;

View file

@ -1689,6 +1689,8 @@ static int create_servers(struct pw_protocol *this, struct pw_impl_core *core,
char key[256]; char key[256];
char name[PATH_MAX]; char name[PATH_MAX];
char selinux_context[PATH_MAX]; char selinux_context[PATH_MAX];
const char *value;
int len;
info.uid = getuid(); info.uid = getuid();
info.gid = getgid(); info.gid = getgid();
@ -1696,13 +1698,7 @@ static int create_servers(struct pw_protocol *this, struct pw_impl_core *core,
pw_properties_clear(p); pw_properties_clear(p);
pw_properties_update(p, &props->dict); pw_properties_update(p, &props->dict);
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[1], key, sizeof(key), &value)) > 0) {
const char *value;
int len;
if ((len = spa_json_next(&it[1], &value)) <= 0)
goto error_invalid;
if (spa_streq(key, "name")) { if (spa_streq(key, "name")) {
if (spa_json_parse_stringn(value, len, name, sizeof(name)) < 0) if (spa_json_parse_stringn(value, len, name, sizeof(name)) < 0)
goto error_invalid; goto error_invalid;

View file

@ -80,14 +80,10 @@ static int parse_cmd(void *user_data, const char *location,
while (spa_json_enter_object(&it[0], &it[1]) > 0) { while (spa_json_enter_object(&it[0], &it[1]) > 0) {
char *cmd = NULL, *args = NULL, *flags = NULL; char *cmd = NULL, *args = NULL, *flags = NULL;
const char *val;
int len;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
const char *val;
int len;
if ((len = spa_json_next(&it[1], &val)) <= 0)
break;
if (spa_streq(key, "cmd")) { if (spa_streq(key, "cmd")) {
cmd = (char*)val; cmd = (char*)val;
spa_json_parse_stringn(val, len, cmd, len+1); spa_json_parse_stringn(val, len, cmd, len+1);
@ -99,6 +95,8 @@ static int parse_cmd(void *user_data, const char *location,
len = spa_json_container_len(&it[1], val, len); len = spa_json_container_len(&it[1], val, len);
flags = (char*)val; flags = (char*)val;
spa_json_parse_stringn(val, len, flags, len+1); spa_json_parse_stringn(val, len, flags, len+1);
} else {
pw_log_warn("unknown pulse.cmd key %s", key);
} }
} }
if (cmd != NULL) if (cmd != NULL)
@ -106,7 +104,6 @@ static int parse_cmd(void *user_data, const char *location,
if (res < 0) if (res < 0)
break; break;
} }
return res; return res;
} }

View file

@ -185,6 +185,7 @@ static int do_extension_stream_restore_read(struct module *module, struct client
struct volume vol = VOLUME_INIT; struct volume vol = VOLUME_INIT;
struct channel_map map = CHANNEL_MAP_INIT; struct channel_map map = CHANNEL_MAP_INIT;
float volume = 0.0f; float volume = 0.0f;
int len;
if (key_to_name(item->key, name, sizeof(name)) < 0) if (key_to_name(item->key, name, sizeof(name)) < 0)
continue; continue;
@ -194,29 +195,31 @@ static int do_extension_stream_restore_read(struct module *module, struct client
if (spa_json_begin_object(&it[0], item->value, strlen(item->value)) <= 0) if (spa_json_begin_object(&it[0], item->value, strlen(item->value)) <= 0)
continue; continue;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) {
if (spa_streq(key, "volume")) { if (spa_streq(key, "volume")) {
if (spa_json_get_float(&it[0], &volume) <= 0) if (spa_json_parse_float(value, len, &volume) <= 0)
continue; continue;
} }
else if (spa_streq(key, "mute")) { else if (spa_streq(key, "mute")) {
if (spa_json_get_bool(&it[0], &mute) <= 0) if (spa_json_parse_bool(value, len, &mute) <= 0)
continue; continue;
} }
else if (spa_streq(key, "volumes")) { else if (spa_streq(key, "volumes")) {
vol = VOLUME_INIT; vol = VOLUME_INIT;
if (spa_json_enter_array(&it[0], &it[1]) <= 0) if (!spa_json_is_array(value, len))
continue; continue;
spa_json_enter(&it[0], &it[1]);
for (vol.channels = 0; vol.channels < CHANNELS_MAX; vol.channels++) { for (vol.channels = 0; vol.channels < CHANNELS_MAX; vol.channels++) {
if (spa_json_get_float(&it[1], &vol.values[vol.channels]) <= 0) if (spa_json_get_float(&it[1], &vol.values[vol.channels]) <= 0)
break; break;
} }
} }
else if (spa_streq(key, "channels")) { else if (spa_streq(key, "channels")) {
if (spa_json_enter_array(&it[0], &it[1]) <= 0) if (!spa_json_is_array(value, len))
continue; continue;
spa_json_enter(&it[0], &it[1]);
for (map.channels = 0; map.channels < CHANNELS_MAX; map.channels++) { for (map.channels = 0; map.channels < CHANNELS_MAX; map.channels++) {
char chname[16]; char chname[16];
if (spa_json_get_string(&it[1], chname, sizeof(chname)) <= 0) if (spa_json_get_string(&it[1], chname, sizeof(chname)) <= 0)
@ -225,11 +228,9 @@ static int do_extension_stream_restore_read(struct module *module, struct client
} }
} }
else if (spa_streq(key, "target-node")) { else if (spa_streq(key, "target-node")) {
if (spa_json_get_string(&it[0], device_name, sizeof(device_name)) <= 0) if (spa_json_parse_stringn(value, len, device_name, sizeof(device_name)) <= 0)
continue; continue;
} }
else if (spa_json_next(&it[0], &value) <= 0)
break;
} }
message_put(reply, message_put(reply,
TAG_STRING, name, TAG_STRING, name,

View file

@ -933,18 +933,16 @@ static int json_object_find(const char *obj, const char *key, char *value, size_
struct spa_json it[1]; struct spa_json it[1];
const char *v; const char *v;
char k[128]; char k[128];
int l;
if (spa_json_begin_object(&it[0], obj, strlen(obj)) <= 0) if (spa_json_begin_object(&it[0], obj, strlen(obj)) <= 0)
return -EINVAL; return -EINVAL;
while (spa_json_get_string(&it[0], k, sizeof(k)) > 0) { while ((l = spa_json_object_next(&it[0], k, sizeof(k), &v)) > 0) {
if (spa_streq(k, key)) { if (spa_streq(k, key)) {
if (spa_json_get_string(&it[0], value, len) <= 0) if (spa_json_parse_stringn(v, l, value, len) <= 0)
continue; continue;
return 0; return 0;
} else {
if (spa_json_next(&it[0], &v) <= 0)
break;
} }
} }
return -ENOENT; return -ENOENT;

View file

@ -997,10 +997,7 @@ int servers_create_and_start(struct impl *impl, const char *addresses, struct pw
if (spa_json_is_object(v, len)) { if (spa_json_is_object(v, len)) {
spa_json_enter(&it[0], &it[1]); spa_json_enter(&it[0], &it[1]);
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[1], key, sizeof(key), &v)) > 0) {
if ((len = spa_json_next(&it[1], &v)) <= 0)
break;
if (spa_streq(key, "address")) { if (spa_streq(key, "address")) {
spa_json_parse_stringn(v, len, addr_str, sizeof(addr_str)); spa_json_parse_stringn(v, len, addr_str, sizeof(addr_str));
} else if (spa_streq(key, "max-clients")) { } else if (spa_streq(key, "max-clients")) {

View file

@ -640,16 +640,10 @@ static bool find_match(struct spa_json *arr, const struct spa_dict *props, bool
int match = 0, fail = 0; int match = 0, fail = 0;
int len; int len;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) {
bool success = false, is_null, reg = false, parse_string = true; bool success = false, is_null, reg = false, parse_string = true;
int skip = 0; int skip = 0;
if ((len = spa_json_next(&it[0], &value)) <= 0) {
pw_log_warn("malformed match rule: key '%s' has "
"no value in '%.*s'", key, az, as);
break;
}
/* first decode a string, when there was a string, we assume it /* first decode a string, when there was a string, we assume it
* can not be null but the "null" string, unless there is a modifier, * can not be null but the "null" string, unless there is a modifier,
* see below. */ * see below. */
@ -765,17 +759,10 @@ static int parse_modules(void *user_data, const char *location,
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) { while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
char *name = NULL, *args = NULL, *flags = NULL; char *name = NULL, *args = NULL, *flags = NULL;
bool have_match = true; bool have_match = true;
const char *val;
int l;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
const char *val;
int l;
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;
}
if (spa_streq(key, "name")) { if (spa_streq(key, "name")) {
name = (char*)val; name = (char*)val;
spa_json_parse_stringn(val, l, name, l+1); spa_json_parse_stringn(val, l, name, l+1);
@ -873,17 +860,10 @@ static int parse_objects(void *user_data, const char *location,
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) { while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
char *factory = NULL, *args = NULL, *flags = NULL; char *factory = NULL, *args = NULL, *flags = NULL;
bool have_match = true; bool have_match = true;
const char *val;
int l;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
const char *val;
int l;
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;
}
if (spa_streq(key, "factory")) { if (spa_streq(key, "factory")) {
factory = (char*)val; factory = (char*)val;
spa_json_parse_stringn(val, l, factory, l+1); spa_json_parse_stringn(val, l, factory, l+1);
@ -1056,20 +1036,11 @@ static int parse_exec(void *user_data, const char *location,
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) { while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
char *path = NULL; char *path = NULL;
const char *args_val = "[]"; const char *args_val = "[]", *val;
int args_len = 2; int args_len = 2, l;
bool have_match = true; bool have_match = true;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
const char *val;
int l;
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;
}
if (spa_streq(key, "path")) { if (spa_streq(key, "path")) {
path = (char*)val; path = (char*)val;
spa_json_parse_stringn(val, l, path, l+1); spa_json_parse_stringn(val, l, path, l+1);
@ -1314,31 +1285,30 @@ int pw_conf_match_rules(const char *str, size_t len, const char *location,
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) { while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
char key[64]; char key[64];
bool have_match = false, have_actions = false; bool have_match = false, have_actions = false;
int res, l;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "matches")) { if (spa_streq(key, "matches")) {
if (spa_json_enter_array(&it[1], &it[2]) < 0) { if (!spa_json_is_array(val, l)) {
pw_log_warn("expected array as matches in '%.*s'", pw_log_warn("expected array as matches in '%.*s'",
(int)len, str); (int)len, str);
break; break;
} }
spa_json_enter(&it[1], &it[2]);
have_match = find_match(&it[2], props, false); have_match = find_match(&it[2], props, false);
} }
else if (spa_streq(key, "actions")) { else if (spa_streq(key, "actions")) {
if (spa_json_enter_object(&it[1], &actions) > 0) if (!spa_json_is_object(val, l)) {
have_actions = true;
else
pw_log_warn("expected object as match actions in '%.*s'", pw_log_warn("expected object as match actions in '%.*s'",
(int)len, str); (int)len, str);
} else {
have_actions = true;
spa_json_enter(&it[1], &actions);
}
} }
else { else {
pw_log_warn("unknown match key '%s'", key); pw_log_warn("unknown match key '%s'", key);
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;
}
} }
} }
if (!have_match) if (!have_match)
@ -1348,16 +1318,9 @@ int pw_conf_match_rules(const char *str, size_t len, const char *location,
continue; continue;
} }
while (spa_json_get_string(&actions, key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&actions, key, sizeof(key), &val)) > 0) {
int res, len;
pw_log_debug("action %s", key); pw_log_debug("action %s", key);
if ((len = spa_json_next(&actions, &val)) <= 0) {
pw_log_warn("malformed action: key '%s' has no value in '%.*s'",
key, (int)len, str);
break;
}
if (spa_json_is_container(val, len)) if (spa_json_is_container(val, len))
len = spa_json_container_len(&actions, val, len); len = spa_json_container_len(&actions, val, len);

View file

@ -217,6 +217,8 @@ static int setup_data_loops(struct impl *impl)
} }
while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) { while ((r = spa_json_enter_object(&it[0], &it[1])) > 0) {
char *props = NULL; char *props = NULL;
const char *val;
int l;
if (i >= MAX_LOOPS) { if (i >= MAX_LOOPS) {
pw_log_warn("too many context.data-loops, using first %d", pw_log_warn("too many context.data-loops, using first %d",
@ -228,15 +230,7 @@ static int setup_data_loops(struct impl *impl)
pw_properties_update(pr, &this->properties->dict); pw_properties_update(pr, &this->properties->dict);
pw_properties_set(pr, PW_KEY_LIBRARY_NAME_SYSTEM, lib_name); pw_properties_set(pr, PW_KEY_LIBRARY_NAME_SYSTEM, lib_name);
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
const char *val;
int l;
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)) if (spa_json_is_container(val, l))
l = spa_json_container_len(&it[1], val, l); l = spa_json_container_len(&it[1], val, l);

View file

@ -214,8 +214,9 @@ static int update_string(struct pw_properties *props, const char *str, size_t si
char key[1024]; char key[1024];
struct spa_error_location el; struct spa_error_location el;
bool err; bool err;
int res, cnt = 0; int len, res, cnt = 0;
struct properties changes; struct properties changes;
const char *value;
if (props) if (props)
properties_init(&changes, 16); properties_init(&changes, 16);
@ -223,14 +224,9 @@ static int update_string(struct pw_properties *props, const char *str, size_t si
if ((res = spa_json_begin_object_relax(&it[0], str, size)) <= 0) if ((res = spa_json_begin_object_relax(&it[0], str, size)) <= 0)
return res; return res;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) {
int len;
const char *value;
char *val = NULL; char *val = NULL;
if ((len = spa_json_next(&it[0], &value)) <= 0)
break;
if (spa_json_is_null(value, len)) if (spa_json_is_null(value, len))
val = NULL; val = NULL;
else { else {
@ -887,14 +883,12 @@ static int dump(struct dump_config *c, int indent, struct spa_json *it, const ch
fprintf(file, "{"); fprintf(file, "{");
spa_json_enter(it, &sub); spa_json_enter(it, &sub);
indent += c->indent; indent += c->indent;
while (spa_json_get_string(&sub, key, sizeof(key)) > 0) { while ((len = spa_json_object_next(&sub, key, sizeof(key), &value)) > 0) {
fprintf(file, "%s%s%*s", fprintf(file, "%s%s%*s",
count++ > 0 ? "," : "", count++ > 0 ? "," : "",
c->sep, indent, ""); c->sep, indent, "");
encode_string(c, KEY(c), key, strlen(key), NORMAL(c)); encode_string(c, KEY(c), key, strlen(key), NORMAL(c));
fprintf(file, ": "); fprintf(file, ": ");
if ((len = spa_json_next(&sub, &value)) <= 0)
break;
dump(c, indent, &sub, value, len); dump(c, indent, &sub, value, len);
} }
indent -= c->indent; indent -= c->indent;

View file

@ -1126,11 +1126,8 @@ static void json_dump_val(struct data *d, const char *key, struct spa_json *it,
char val[1024]; char val[1024];
put_begin(d, key, "{", STATE_SIMPLE); put_begin(d, key, "{", STATE_SIMPLE);
spa_json_enter(it, &sub); spa_json_enter(it, &sub);
while (spa_json_get_string(&sub, val, sizeof(val)) > 0) { while ((len = spa_json_object_next(&sub, val, sizeof(val), &value)) > 0)
if ((len = spa_json_next(&sub, &value)) <= 0)
break;
json_dump_val(d, val, &sub, value, len); json_dump_val(d, val, &sub, value, len);
}
put_end(d, "}", STATE_SIMPLE); put_end(d, "}", STATE_SIMPLE);
} else if (spa_json_is_string(value, len)) { } else if (spa_json_is_string(value, len)) {
put_encoded_string(d, key, strndupa(value, len)); put_encoded_string(d, key, strndupa(value, len));