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

@ -640,16 +640,10 @@ static bool find_match(struct spa_json *arr, const struct spa_dict *props, bool
int match = 0, fail = 0;
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;
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
* can not be null but the "null" string, unless there is a modifier,
* 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) {
char *name = NULL, *args = NULL, *flags = NULL;
bool have_match = true;
const char *val;
int l;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 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;
}
while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "name")) {
name = (char*)val;
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) {
char *factory = NULL, *args = NULL, *flags = NULL;
bool have_match = true;
const char *val;
int l;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 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;
}
while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "factory")) {
factory = (char*)val;
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) {
char *path = NULL;
const char *args_val = "[]";
int args_len = 2;
const char *args_val = "[]", *val;
int args_len = 2, l;
bool have_match = true;
while (spa_json_get_string(&it[1], key, sizeof(key)) > 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;
}
while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
if (spa_streq(key, "path")) {
path = (char*)val;
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) {
char key[64];
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_json_enter_array(&it[1], &it[2]) < 0) {
if (!spa_json_is_array(val, l)) {
pw_log_warn("expected array as matches in '%.*s'",
(int)len, str);
break;
}
spa_json_enter(&it[1], &it[2]);
have_match = find_match(&it[2], props, false);
}
else if (spa_streq(key, "actions")) {
if (spa_json_enter_object(&it[1], &actions) > 0)
have_actions = true;
else
if (!spa_json_is_object(val, l)) {
pw_log_warn("expected object as match actions in '%.*s'",
(int)len, str);
} else {
have_actions = true;
spa_json_enter(&it[1], &actions);
}
}
else {
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)
@ -1348,16 +1318,9 @@ int pw_conf_match_rules(const char *str, size_t len, const char *location,
continue;
}
while (spa_json_get_string(&actions, key, sizeof(key)) > 0) {
int res, len;
while ((len = spa_json_object_next(&actions, key, sizeof(key), &val)) > 0) {
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))
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) {
char *props = NULL;
const char *val;
int l;
if (i >= MAX_LOOPS) {
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_set(pr, PW_KEY_LIBRARY_NAME_SYSTEM, lib_name);
while (spa_json_get_string(&it[1], key, sizeof(key)) > 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;
}
while ((l = spa_json_object_next(&it[1], key, sizeof(key), &val)) > 0) {
if (spa_json_is_container(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];
struct spa_error_location el;
bool err;
int res, cnt = 0;
int len, res, cnt = 0;
struct properties changes;
const char *value;
if (props)
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)
return res;
while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) {
int len;
const char *value;
while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) {
char *val = NULL;
if ((len = spa_json_next(&it[0], &value)) <= 0)
break;
if (spa_json_is_null(value, len))
val = NULL;
else {
@ -887,14 +883,12 @@ static int dump(struct dump_config *c, int indent, struct spa_json *it, const ch
fprintf(file, "{");
spa_json_enter(it, &sub);
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",
count++ > 0 ? "," : "",
c->sep, indent, "");
encode_string(c, KEY(c), key, strlen(key), NORMAL(c));
fprintf(file, ": ");
if ((len = spa_json_next(&sub, &value)) <= 0)
break;
dump(c, indent, &sub, value, len);
}
indent -= c->indent;