parser: fix parse of 'V' as Choice

This commit is contained in:
Wim Taymans 2019-01-17 17:19:13 +01:00
parent be1725c67b
commit 767e7efc0e

View file

@ -98,7 +98,8 @@ static inline bool spa_pod_parser_can_collect(struct spa_pod *pod, char type)
return type == 'h'; return type == 'h';
case SPA_TYPE_Choice: case SPA_TYPE_Choice:
return type == 'V' || return type == 'V' ||
spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type); (SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None &&
spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type));
default: default:
return false; return false;
} }
@ -211,7 +212,7 @@ static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list arg
{ {
struct spa_pod *pod = NULL, *current; struct spa_pod *pod = NULL, *current;
struct spa_pod_prop *prop = NULL; struct spa_pod_prop *prop = NULL;
bool required = true, skip = false; bool required = true;
struct spa_pod_iter *it = &parser->iter[parser->depth]; struct spa_pod_iter *it = &parser->iter[parser->depth];
const char *format = ""; const char *format = "";
uint32_t *idp; uint32_t *idp;
@ -248,6 +249,7 @@ static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list arg
if (--parser->depth < 0) if (--parser->depth < 0)
return -EINVAL; return -EINVAL;
it = &parser->iter[parser->depth]; it = &parser->iter[parser->depth];
if (SPA_POD_TYPE(it->data) == SPA_TYPE_Object) if (SPA_POD_TYPE(it->data) == SPA_TYPE_Object)
parser->flags = SPA_POD_PARSER_FLAG_OBJECT; parser->flags = SPA_POD_PARSER_FLAG_OBJECT;
else if (SPA_POD_TYPE(it->data) == SPA_TYPE_Struct) else if (SPA_POD_TYPE(it->data) == SPA_TYPE_Struct)
@ -286,32 +288,21 @@ static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list arg
case '?': case '?':
required = false; required = false;
break; break;
case 'V':
pod = (struct spa_pod *) prop;
if (pod == NULL && required)
return -ESRCH;
goto collect;
default: default:
if (pod == NULL || !spa_pod_parser_can_collect(pod, *format)) { if (pod == NULL || !spa_pod_parser_can_collect(pod, *format)) {
if (required) if (required)
return -ESRCH; return -ESRCH;
skip = true;
}
collect:
if (pod->type == SPA_TYPE_Choice)
pod = SPA_POD_CHOICE_CHILD(pod);
if (skip)
SPA_POD_PARSER_SKIP(*format, args); SPA_POD_PARSER_SKIP(*format, args);
else } else {
if (pod->type == SPA_TYPE_Choice && *format != 'V')
pod = SPA_POD_CHOICE_CHILD(pod);
SPA_POD_PARSER_COLLECT(pod, *format, args); SPA_POD_PARSER_COLLECT(pod, *format, args);
}
spa_pod_iter_advance(it, current); spa_pod_iter_advance(it, current);
required = true;
skip = false;
read_pod: read_pod:
pod = current = spa_pod_iter_current(it); pod = current = spa_pod_iter_current(it);
prop = NULL;
break; break;
} }
format++; format++;