aboutsummaryrefslogtreecommitdiff
path: root/qapi/qapi-util.c
blob: fda7044539040e7683b4735a302f51b1cbad8531 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
 * QAPI util functions
 *
 * Authors:
 *  Hu Tao       <hutao@cn.fujitsu.com>
 *  Peter Lieven <pl@kamp.de>
 * 
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */

#include "qemu/osdep.h"
#include "qapi/compat-policy.h"
#include "qapi/error.h"
#include "qemu/ctype.h"
#include "qapi/qmp/qerror.h"

CompatPolicy compat_policy;

static bool compat_policy_input_ok1(const char *adjective,
                                    CompatPolicyInput policy,
                                    ErrorClass error_class,
                                    const char *kind, const char *name,
                                    Error **errp)
{
    switch (policy) {
    case COMPAT_POLICY_INPUT_ACCEPT:
        return true;
    case COMPAT_POLICY_INPUT_REJECT:
        error_set(errp, error_class, "%s %s %s disabled by policy",
                  adjective, kind, name);
        return false;
    case COMPAT_POLICY_INPUT_CRASH:
    default:
        abort();
    }
}

bool compat_policy_input_ok(unsigned special_features,
                            const CompatPolicy *policy,
                            ErrorClass error_class,
                            const char *kind, const char *name,
                            Error **errp)
{
    if ((special_features & 1u << QAPI_DEPRECATED)
        && !compat_policy_input_ok1("Deprecated",
                                    policy->deprecated_input,
                                    error_class, kind, name, errp)) {
        return false;
    }
    if ((special_features & (1u << QAPI_UNSTABLE))
        && !compat_policy_input_ok1("Unstable",
                                    policy->unstable_input,
                                    error_class, kind, name, errp)) {
        return false;
    }
    return true;
}

const char *qapi_enum_lookup(const QEnumLookup *lookup, int val)
{
    assert(val >= 0 && val < lookup->size);

    return lookup->array[val];
}

int qapi_enum_parse(const QEnumLookup *lookup, const char *buf,
                    int def, Error **errp)
{
    int i;

    if (!buf) {
        return def;
    }

    for (i = 0; i < lookup->size; i++) {
        if (!strcmp(buf, lookup->array[i])) {
            return i;
        }
    }

    error_setg(errp, "invalid parameter value: %s", buf);
    return def;
}

bool qapi_bool_parse(const char *name, const char *value, bool *obj, Error **errp)
{
    if (g_str_equal(value, "on") ||
        g_str_equal(value, "yes") ||
        g_str_equal(value, "true") ||
        g_str_equal(value, "y")) {
        *obj = true;
        return true;
    }
    if (g_str_equal(value, "off") ||
        g_str_equal(value, "no") ||
        g_str_equal(value, "false") ||
        g_str_equal(value, "n")) {
        *obj = false;
        return true;
    }

    error_setg(errp, QERR_INVALID_PARAMETER_VALUE, name,
               "'on' or 'off'");
    return false;
}

/*
 * 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/devel/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;
}