OLD | NEW |
---|---|
(Empty) | |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 # Use of this source code is governed by a BSD-style license that can be | |
3 # found in the LICENSE file. | |
4 | |
5 from model import PropertyType | |
6 import code | |
7 import cpp_type_generator | |
Yoyo Zhou
2012/01/23 23:16:42
Looks like you're not using this import. (Same in
calamity
2012/01/24 22:57:22
Done.
| |
8 import cpp_util | |
9 | |
10 class CCGenerator(object): | |
11 """A .cc generator for a namespace. | |
12 """ | |
13 def __init__(self, namespace, model, cpp_type_generator): | |
14 self._cpp_type_generator = cpp_type_generator | |
15 self._namespace = namespace | |
16 self._target_namespace = ( | |
17 self._cpp_type_generator.getCppNamespaceName(self._namespace)) | |
18 | |
19 def generate(self): | |
Yoyo Zhou
2012/01/23 23:16:42
Method names should start with caps.
calamity
2012/01/24 22:57:22
Done.
| |
20 """Generates a code.Code object with the .cc for a single namespace. | |
21 """ | |
22 c = code.Code() | |
23 (c.append(cpp_util.CHROMIUM_LICENSE) | |
24 .append() | |
25 .append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | |
26 .append() | |
27 .append('#include "tools/json_schema_compiler/util.h"') | |
28 .append('#include "%s/%s.h"' % | |
29 (self._namespace.source_file_dir, self._target_namespace)) | |
30 .append() | |
31 .concat(self._cpp_type_generator.getCppNamespaceStart()) | |
32 .append() | |
33 .append('//') | |
34 .append('// Types') | |
35 .append('//') | |
36 .append() | |
37 ) | |
38 for type_ in self._namespace.types.values(): | |
39 (c.concat(self._generateType(type_)) | |
40 .append() | |
41 ) | |
42 (c.append('//') | |
43 .append('// Functions') | |
44 .append('//') | |
45 .append() | |
46 ) | |
47 for function in self._namespace.functions.values(): | |
48 (c.concat(self._generateFunction(function)) | |
49 .append() | |
50 ) | |
51 (c.concat(self._cpp_type_generator.getCppNamespaceEnd()) | |
52 .append() | |
53 ) | |
54 # TODO(calamity): Events | |
55 return c | |
56 | |
57 def _generateType(self, type_): | |
58 """Generates the function definitions for a type. | |
59 """ | |
60 c = code.Code() | |
61 | |
62 (c.append('%(classname)s::%(classname)s() {}') | |
63 .append('%(classname)s::~%(classname)s() {}') | |
64 .append() | |
65 ) | |
66 c.substitute({'classname': type_.name}) | |
67 | |
68 c.concat(self._generateTypePopulate(type_)) | |
69 c.append() | |
70 # TODO(calamity): deal with non-serializable | |
71 c.concat(self._generateTypeTovalue(type_)) | |
72 c.append() | |
73 | |
74 return c | |
75 | |
76 def _generateTypePopulate(self, type_): | |
77 """Generates the function for populating a type given a pointer to it. | |
78 """ | |
79 c = code.Code() | |
80 (c.append('// static') | |
81 .sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {') | |
82 .append('if (!value.IsType(Value::TYPE_DICTIONARY))') | |
83 .append(' return false;') | |
84 .append('const DictionaryValue* dict = ' | |
85 'static_cast<const DictionaryValue*>(&value);') | |
86 .append() | |
87 ) | |
88 c.substitute({'name': type_.name}) | |
89 | |
90 # TODO(calamity): this handle single PropertyType.REF properties. | |
Yoyo Zhou
2012/01/23 23:16:42
This comment seems incomplete.
calamity
2012/01/24 22:57:22
Done.
| |
91 # add ALL the types | |
92 for prop in type_.properties.values(): | |
93 sub = {'name': prop.name} | |
94 if prop.type_ == PropertyType.ARRAY: | |
95 if prop.item_type.type_ == PropertyType.REF: | |
96 if prop.optional: | |
97 (c.append('if (!json_schema_compiler::util::' | |
98 'GetOptionalTypes<%(type)s>(*dict,') | |
99 .append(' "%(name)s", &out->%(name)s))') | |
100 .append(' return false;') | |
101 ) | |
102 else: | |
103 (c.append('if (!json_schema_compiler::util::' | |
104 'GetTypes<%(type)s>(*dict,') | |
105 .append(' "%(name)s", &out->%(name)s))') | |
106 .append(' return false;') | |
107 ) | |
108 sub['type'] = self._cpp_type_generator.getType(prop.item_type, | |
109 pad_for_generics=True) | |
110 elif prop.item_type.type_ == PropertyType.STRING: | |
111 if prop.optional: | |
112 (c.append('if (!json_schema_compiler::util::GetOptionalStrings' | |
113 '(*dict, "%(name)s", &out->%(name)s))') | |
114 .append(' return false;') | |
115 ) | |
116 else: | |
117 (c.append('if (!json_schema_compiler::util::GetStrings' | |
118 '(*dict, "%(name)s", &out->%(name)s))') | |
119 .append(' return false;') | |
120 ) | |
121 else: | |
122 raise NotImplementedError(prop.item_type.type_) | |
123 elif proptype_.is_fundamental: | |
Yoyo Zhou
2012/01/23 23:16:42
prop.type_?
calamity
2012/01/24 22:57:22
Done.
| |
124 c.append('if (!dict->%s)' % | |
125 cpp_util.getFundamentalValue(prop, '&out->%s' % prop.name)) | |
126 c.append(' return false;') | |
127 else: | |
128 raise NotImplementedError(prop.type_) | |
129 c.substitute(sub) | |
130 (c.append('return true;') | |
131 .eblock('}') | |
132 ) | |
133 return c | |
134 | |
135 def _generateTypeTovalue(self, type_): | |
Yoyo Zhou
2012/01/23 23:16:42
ToValue
calamity
2012/01/24 22:57:22
Done.
| |
136 """Generates a function that serializes the type into a |DictionaryValue|. | |
137 """ | |
138 c = code.Code() | |
139 (c.sblock('DictionaryValue* %s::ToValue() const {' % type_.name) | |
140 .append('DictionaryValue* value = new DictionaryValue();') | |
141 .append() | |
142 ) | |
143 name = type_.name.lower() | |
144 for prop in type_.properties.values(): | |
145 prop_name = name + '_' + prop.name if name else prop.name | |
146 this_var = prop.name | |
147 c.concat(self._createValueFromProperty(prop_name, prop, this_var)) | |
148 (c.append() | |
149 .append('return value;') | |
150 .eblock('}') | |
151 ) | |
152 return c | |
153 | |
154 # TODO(calamity): object and choices proptypes | |
155 def _createValueFromProperty(self, name, prop, var): | |
156 """Generates code to serialize a single property in a type. | |
157 """ | |
158 c = code.Code() | |
159 if prop.type_.is_fundamental: | |
160 c.append('Value* %s_value = %s;' % | |
161 (name, cpp_util.createFundamentalValue(prop, var))) | |
162 elif prop.type_ == PropertyType.ARRAY: | |
163 if prop.item_type.type_ == PropertyType.STRING: | |
164 if prop.optional: | |
165 c.append('json_schema_compiler::util::' | |
166 'SetOptionalStrings(%s, "%s", value);' % (var, prop.name)) | |
167 else: | |
168 c.append('json_schema_compiler::util::' | |
169 'SetStrings(%s, "%s", value);' % (var, prop.name)) | |
170 else: | |
171 item_name = name + '_single' | |
172 (c.append('ListValue* %(name)s_value = new ListValue();') | |
173 .append('for (%(it_type)s::iterator it = %(var)s->begin();') | |
174 .sblock(' it != %(var)s->end(); ++it) {') | |
175 .concat(self._createValueFromProperty(item_name, prop.item_type, | |
176 '*it')) | |
177 .append('%(name)s_value->Append(%(prop_val)s_value);') | |
178 .eblock('}') | |
179 ) | |
180 c.substitute( | |
181 {'it_type': self._cpp_type_generator.getType(prop), | |
182 'name': name, 'var': var, 'prop_val': item_name}) | |
183 elif prop.type_ == PropertyType.REF: | |
184 c.append('Value* %s_value = %s.ToValue();' % (name, var)) | |
185 else: | |
186 raise NotImplementedError | |
187 return c | |
188 | |
189 def _generateFunction(self, function): | |
190 """Generates the definitions for function structs. | |
191 """ | |
192 classname = cpp_util.cppName(function.name) | |
193 c = code.Code() | |
194 | |
195 # Params::Populate function | |
196 if function.params: | |
197 (c.append('%(name)s::Params::Params() {}') | |
198 .append('%(name)s::Params::~Params() {}') | |
199 .append() | |
200 .concat(self._generateFunctionParamsCreate(function)) | |
201 .append() | |
202 ) | |
203 | |
204 # Result::Create function | |
205 c.concat(self._generateFunctionResultCreate(function)) | |
206 | |
207 c.substitute({'name': classname}) | |
208 | |
209 return c | |
210 | |
211 def _generateFunctionParamsCreate(self, function): | |
212 """Generate function to create an instance of Params given a pointer. | |
213 """ | |
214 classname = cpp_util.cppName(function.name) | |
215 c = code.Code() | |
216 c.append('// static') | |
217 c.append('%(classname)s::Params* %(classname)s::Params::Create' | |
218 '(const ListValue& args) {') | |
219 c.substitute({'classname': classname}) | |
220 c.append('if (args.GetSize() != %d)' % len(function.params)) | |
221 c.append(' return NULL;') | |
222 | |
223 # TODO(calamity): generalize, needs to move to function to do populates for | |
224 # wider variety of args | |
225 for i, param in enumerate(function.params): | |
226 sub = {'name': param.name, 'pos': i} | |
227 c.append() | |
228 # TODO(calamity): Make valid for not just objects | |
229 c.append('DictionaryValue* %(name)s_param = NULL;') | |
230 c.append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))') | |
231 c.append(' return NULL;') | |
232 c.append('scoped_ptr<Params> out;') | |
Yoyo Zhou
2012/01/23 23:16:42
Should this be outside the for loop?
Why not use
calamity
2012/01/24 22:57:22
Done. I made it a scoped_ptr so it would clean up
| |
233 if param.type_ == PropertyType.REF: | |
234 c.append('if (!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))') | |
235 c.append(' return NULL;') | |
236 sub['ctype'] = self._cpp_type_generator.getType(param) | |
237 elif param.type_.is_fundamental: | |
238 raise NotImplementedError('Fundamental types are unimplemented') | |
239 elif param.type_ == PropertyType.OBJECT: | |
240 c.append('if (!%(ctype)s::Populate(*%(name)s_param, &out->%(name)s))') | |
241 c.append(' return NULL;') | |
242 sub['ctype'] = self._cpp_type_generator.getType(param) | |
243 elif param.type_ == PropertyType.CHOICES: | |
244 raise NotImplementedError('Choices is unimplemented') | |
245 else: | |
246 raise NotImplementedError(param.type_) | |
247 c.substitute(sub) | |
248 c.append() | |
249 c.append('return out.release();') | |
250 c.eblock('}') | |
251 | |
252 return c | |
253 | |
254 def _generateFunctionResultCreate(self, function): | |
255 """Generate function to create a Result given the return value. | |
256 """ | |
257 classname = cpp_util.cppName(function.name) | |
258 c = code.Code() | |
259 c.append('// static') | |
260 param = function.callback.param | |
261 arg = '' | |
262 if param: | |
263 if param.type_ == PropertyType.REF: | |
264 arg = 'const %(type)s& %(name)s' | |
265 else: | |
266 arg = 'const %(type)s %(name)s' | |
267 arg = arg % { | |
268 'type': self._cpp_type_generator.getType(param), | |
269 'name': param.name | |
270 } | |
271 c.sblock('Value* %(classname)s::Result::Create(%(arg)s) {') | |
272 sub = {'classname': classname, 'arg': arg} | |
273 # TODO(calamity): Choices | |
274 if not param: | |
275 c.append('return Value::CreateNullValue();') | |
276 else: | |
277 sub['argname'] = param.name | |
278 if param.type_.is_fundamental: | |
279 c.append('return %s;' % | |
280 cpp_util.createFundamentalValue(param, param.name)) | |
281 elif param.type_ == PropertyType.REF: | |
282 c.append('DictionaryValue* result = new DictionaryValue();') | |
283 c.append('result->SetWithoutPathExpansion("%(argname)s",' | |
284 '%(argname)s.ToValue());') | |
285 c.append('return result;') | |
286 elif param.type_ == PropertyType.OBJECT: | |
287 raise NotImplementedError('Objects not implemented') | |
288 elif param.type_ == PropertyType.ARRAY: | |
289 raise NotImplementedError('Arrays not implemented') | |
290 else: | |
291 raise NotImplementedError(param.type_) | |
292 c.substitute(sub) | |
293 c.eblock('}') | |
294 return c | |
OLD | NEW |