Statistics
| Branch: | Revision:

root / scripts / qapi.py @ 0f923be2

History | View | Annotate | Download (4.8 kB)

1
#
2
# QAPI helper library
3
#
4
# Copyright IBM, Corp. 2011
5
#
6
# Authors:
7
#  Anthony Liguori <aliguori@us.ibm.com>
8
#
9
# This work is licensed under the terms of the GNU GPLv2.
10
# See the COPYING.LIB file in the top-level directory.
11

    
12
from ordereddict import OrderedDict
13

    
14
def tokenize(data):
15
    while len(data):
16
        if data[0] in ['{', '}', ':', ',', '[', ']']:
17
            yield data[0]
18
            data = data[1:]
19
        elif data[0] in ' \n':
20
            data = data[1:]
21
        elif data[0] == "'":
22
            data = data[1:]
23
            string = ''
24
            while data[0] != "'":
25
                string += data[0]
26
                data = data[1:]
27
            data = data[1:]
28
            yield string
29

    
30
def parse(tokens):
31
    if tokens[0] == '{':
32
        ret = OrderedDict()
33
        tokens = tokens[1:]
34
        while tokens[0] != '}':
35
            key = tokens[0]
36
            tokens = tokens[1:]
37

    
38
            tokens = tokens[1:] # :
39

    
40
            value, tokens = parse(tokens)
41

    
42
            if tokens[0] == ',':
43
                tokens = tokens[1:]
44

    
45
            ret[key] = value
46
        tokens = tokens[1:]
47
        return ret, tokens
48
    elif tokens[0] == '[':
49
        ret = []
50
        tokens = tokens[1:]
51
        while tokens[0] != ']':
52
            value, tokens = parse(tokens)
53
            if tokens[0] == ',':
54
                tokens = tokens[1:]
55
            ret.append(value)
56
        tokens = tokens[1:]
57
        return ret, tokens
58
    else:
59
        return tokens[0], tokens[1:]
60

    
61
def evaluate(string):
62
    return parse(map(lambda x: x, tokenize(string)))[0]
63

    
64
def parse_schema(fp):
65
    exprs = []
66
    expr = ''
67
    expr_eval = None
68

    
69
    for line in fp:
70
        if line.startswith('#') or line == '\n':
71
            continue
72

    
73
        if line.startswith(' '):
74
            expr += line
75
        elif expr:
76
            expr_eval = evaluate(expr)
77
            if expr_eval.has_key('enum'):
78
                add_enum(expr_eval['enum'])
79
            elif expr_eval.has_key('union'):
80
                add_enum('%sKind' % expr_eval['union'])
81
            exprs.append(expr_eval)
82
            expr = line
83
        else:
84
            expr += line
85

    
86
    if expr:
87
        expr_eval = evaluate(expr)
88
        if expr_eval.has_key('enum'):
89
            add_enum(expr_eval['enum'])
90
        elif expr_eval.has_key('union'):
91
            add_enum('%sKind' % expr_eval['union'])
92
        exprs.append(expr_eval)
93

    
94
    return exprs
95

    
96
def parse_args(typeinfo):
97
    for member in typeinfo:
98
        argname = member
99
        argentry = typeinfo[member]
100
        optional = False
101
        structured = False
102
        if member.startswith('*'):
103
            argname = member[1:]
104
            optional = True
105
        if isinstance(argentry, OrderedDict):
106
            structured = True
107
        yield (argname, argentry, optional, structured)
108

    
109
def de_camel_case(name):
110
    new_name = ''
111
    for ch in name:
112
        if ch.isupper() and new_name:
113
            new_name += '_'
114
        if ch == '-':
115
            new_name += '_'
116
        else:
117
            new_name += ch.lower()
118
    return new_name
119

    
120
def camel_case(name):
121
    new_name = ''
122
    first = True
123
    for ch in name:
124
        if ch in ['_', '-']:
125
            first = True
126
        elif first:
127
            new_name += ch.upper()
128
            first = False
129
        else:
130
            new_name += ch.lower()
131
    return new_name
132

    
133
def c_var(name):
134
    return '_'.join(name.split('-')).lstrip("*")
135

    
136
def c_list_type(name):
137
    return '%sList' % name
138

    
139
def type_name(name):
140
    if type(name) == list:
141
        return c_list_type(name[0])
142
    return name
143

    
144
enum_types = []
145

    
146
def add_enum(name):
147
    global enum_types
148
    enum_types.append(name)
149

    
150
def is_enum(name):
151
    global enum_types
152
    return (name in enum_types)
153

    
154
def c_type(name):
155
    if name == 'str':
156
        return 'char *'
157
    elif name == 'int':
158
        return 'int64_t'
159
    elif name == 'bool':
160
        return 'bool'
161
    elif name == 'number':
162
        return 'double'
163
    elif type(name) == list:
164
        return '%s *' % c_list_type(name[0])
165
    elif is_enum(name):
166
        return name
167
    elif name == None or len(name) == 0:
168
        return 'void'
169
    elif name == name.upper():
170
        return '%sEvent *' % camel_case(name)
171
    else:
172
        return '%s *' % name
173

    
174
def genindent(count):
175
    ret = ""
176
    for i in range(count):
177
        ret += " "
178
    return ret
179

    
180
indent_level = 0
181

    
182
def push_indent(indent_amount=4):
183
    global indent_level
184
    indent_level += indent_amount
185

    
186
def pop_indent(indent_amount=4):
187
    global indent_level
188
    indent_level -= indent_amount
189

    
190
def cgen(code, **kwds):
191
    indent = genindent(indent_level)
192
    lines = code.split('\n')
193
    lines = map(lambda x: indent + x, lines)
194
    return '\n'.join(lines) % kwds + '\n'
195

    
196
def mcgen(code, **kwds):
197
    return cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
198

    
199
def basename(filename):
200
    return filename.split("/")[-1]
201

    
202
def guardname(filename):
203
    return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()