qapi: New parse_qapi_name()

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <1488317230-26248-19-git-send-email-armbru@redhat.com>
This commit is contained in:
Markus Armbruster 2017-02-28 22:27:04 +01:00
parent 6c873d1149
commit 069b64e3fe
3 changed files with 83 additions and 0 deletions

View File

@ -14,4 +14,6 @@
int qapi_enum_parse(const char * const lookup[], const char *buf,
int max, int def, Error **errp);
int parse_qapi_name(const char *name, bool complete);
#endif

View File

@ -33,3 +33,50 @@ int qapi_enum_parse(const char * const lookup[], const char *buf,
error_setg(errp, "invalid parameter value: %s", buf);
return def;
}
/*
* Parse a valid QAPI name from @str.
* A valid name consists of letters, digits, hyphen and underscore.
* It may be prefixed by __RFQDN_ (downstream extension), where RFQDN
* may contain only letters, digits, hyphen and period.
* The special exception for enumeration names is not implemented.
* See docs/qapi-code-gen.txt for more on QAPI naming rules.
* Keep this consistent with scripts/qapi.py!
* If @complete, the parse fails unless it consumes @str completely.
* Return its length on success, -1 on failure.
*/
int parse_qapi_name(const char *str, bool complete)
{
const char *p = str;
if (*p == '_') { /* Downstream __RFQDN_ */
p++;
if (*p != '_') {
return -1;
}
while (*++p) {
if (!qemu_isalnum(*p) && *p != '-' && *p != '.') {
break;
}
}
if (*p != '_') {
return -1;
}
p++;
}
if (!qemu_isalpha(*p)) {
return -1;
}
while (*++p) {
if (!qemu_isalnum(*p) && *p != '-' && *p != '_') {
break;
}
}
if (complete && *p) {
return -1;
}
return p - str;
}

View File

@ -42,10 +42,44 @@ static void test_qapi_enum_parse(void)
g_assert_cmpint(ret, ==, QTYPE__MAX - 1);
}
static void test_parse_qapi_name(void)
{
int ret;
/* Must start with a letter */
ret = parse_qapi_name("a", true);
g_assert(ret == 1);
ret = parse_qapi_name("a$", false);
g_assert(ret == 1);
ret = parse_qapi_name("", false);
g_assert(ret == -1);
ret = parse_qapi_name("1", false);
g_assert(ret == -1);
/* Only letters, digits, hyphen, underscore */
ret = parse_qapi_name("A-Za-z0-9_", true);
g_assert(ret == 10);
ret = parse_qapi_name("A-Za-z0-9_$", false);
g_assert(ret == 10);
ret = parse_qapi_name("A-Za-z0-9_$", true);
g_assert(ret == -1);
/* __RFQDN_ */
ret = parse_qapi_name("__com.redhat_supports", true);
g_assert(ret == 21);
ret = parse_qapi_name("_com.example_", false);
g_assert(ret == -1);
ret = parse_qapi_name("__com.example", false);
g_assert(ret == -1);
ret = parse_qapi_name("__com.example_", false);
g_assert(ret == -1);
}
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/qapi/util/qapi_enum_parse", test_qapi_enum_parse);
g_test_add_func("/qapi/util/parse_qapi_name", test_parse_qapi_name);
g_test_run();
return 0;
}