Commit 069b64e3 authored by Markus Armbruster's avatar Markus Armbruster
Browse files

qapi: New parse_qapi_name()



Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
Message-Id: <1488317230-26248-19-git-send-email-armbru@redhat.com>
parent 6c873d11
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+47 −0
Original line number Diff line number Diff line
@@ -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;
}
+34 −0
Original line number Diff line number Diff line
@@ -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;
}