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_util | |
8 | |
9 class CCGenerator(object): | |
10 """A .cc generator for a namespace. | |
11 """ | |
12 def __init__(self, namespace, cpp_type_generator): | |
13 self._cpp_type_generator = cpp_type_generator | |
14 self._namespace = namespace | |
15 self._target_namespace = ( | |
16 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | |
17 | |
18 def Generate(self): | |
19 """Generates a code.Code object with the .cc for a single namespace. | |
20 """ | |
21 c = code.Code() | |
22 (c.Append(cpp_util.CHROMIUM_LICENSE) | |
23 .Append() | |
24 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | |
25 .Append() | |
26 .Append('#include "tools/json_schema_compiler/util.h"') | |
27 .Append('#include "%s/%s.h"' % | |
28 (self._namespace.source_file_dir, self._target_namespace)) | |
29 .Append() | |
30 .Concat(self._cpp_type_generator.GetCppNamespaceStart()) | |
31 .Append() | |
32 .Append('//') | |
33 .Append('// Types') | |
34 .Append('//') | |
35 .Append() | |
36 ) | |
37 for type_ in self._namespace.types.values(): | |
38 (c.Concat(self._GenerateType(type_)) | |
39 .Append() | |
40 ) | |
41 (c.Append('//') | |
42 .Append('// Functions') | |
43 .Append('//') | |
44 .Append() | |
45 ) | |
46 for function in self._namespace.functions.values(): | |
47 (c.Concat(self._GenerateFunction(function)) | |
48 .Append() | |
49 ) | |
50 (c.Concat(self._cpp_type_generator.GetCppNamespaceEnd()) | |
51 .Append() | |
52 ) | |
53 # TODO(calamity): Events | |
54 return c | |
55 | |
56 def _GenerateType(self, type_): | |
57 """Generates the function definitions for a type. | |
58 """ | |
59 c = code.Code() | |
60 | |
61 (c.Append('%(classname)s::%(classname)s() {}') | |
62 .Append('%(classname)s::~%(classname)s() {}') | |
63 .Append() | |
64 ) | |
65 c.Substitute({'classname': type_.name}) | |
66 | |
67 c.Concat(self._GenerateTypePopulate(type_)) | |
68 c.Append() | |
69 # TODO(calamity): deal with non-serializable | |
70 c.Concat(self._GenerateTypeTovalue(type_)) | |
71 c.Append() | |
72 | |
73 return c | |
74 | |
75 def _GenerateTypePopulate(self, type_): | |
76 """Generates the function for populating a type given a pointer to it. | |
77 """ | |
78 c = code.Code() | |
79 (c.Append('// static') | |
80 .Sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {') | |
81 .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') | |
82 .Append(' return false;') | |
83 .Append('const DictionaryValue* dict = ' | |
84 'static_cast<const DictionaryValue*>(&value);') | |
85 .Append() | |
86 ) | |
87 c.Substitute({'name': type_.name}) | |
88 | |
89 # TODO(calamity): this handle single PropertyType.REF properties. | |
90 # add ALL the types | |
91 for prop in type_.properties.values(): | |
92 sub = {'name': prop.name} | |
93 if prop.type_ == PropertyType.ARRAY: | |
94 if prop.item_type.type_ == PropertyType.REF: | |
95 if prop.optional: | |
96 (c.Append('if (!json_schema_compiler::util::' | |
97 'GetOptionalTypes<%(type)s>(*dict,') | |
98 .Append(' "%(name)s", &out->%(name)s))') | |
99 .Append(' return false;') | |
100 ) | |
101 else: | |
102 (c.Append('if (!json_schema_compiler::util::' | |
103 'GetTypes<%(type)s>(*dict,') | |
104 .Append(' "%(name)s", &out->%(name)s))') | |
105 .Append(' return false;') | |
106 ) | |
107 sub['type'] = self._cpp_type_generator.GetType(prop.item_type, | |
108 pad_for_generics=True) | |
109 elif prop.item_type.type_ == PropertyType.STRING: | |
110 if prop.optional: | |
111 (c.Append('if (!json_schema_compiler::util::GetOptionalStrings' | |
112 '(*dict, "%(name)s", &out->%(name)s))') | |
113 .Append(' return false;') | |
114 ) | |
115 else: | |
116 (c.Append('if (!json_schema_compiler::util::GetStrings' | |
117 '(*dict, "%(name)s", &out->%(name)s))') | |
118 .Append(' return false;') | |
119 ) | |
120 else: | |
121 raise NotImplementedError(prop.item_type.type_) | |
122 elif prop.type_.is_fundamental: | |
123 c.Append('if (!dict->%s)' % | |
124 cpp_util.GetFundamentalValue(prop, '&out->%s' % prop.name)) | |
125 c.Append(' return false;') | |
126 else: | |
127 raise NotImplementedError(prop.type_) | |
128 c.Substitute(sub) | |
129 (c.Append('return true;') | |
130 .Eblock('}') | |
131 ) | |
132 return c | |
133 | |
134 def _GenerateTypeTovalue(self, type_): | |
135 """Generates a function that serializes the type into a |DictionaryValue|. | |
136 """ | |
137 c = code.Code() | |
138 (c.Sblock('DictionaryValue* %s::ToValue() const {' % type_.name) | |
139 .Append('DictionaryValue* value = new DictionaryValue();') | |
140 .Append() | |
141 ) | |
142 name = type_.name.lower() | |
143 for prop in type_.properties.values(): | |
144 prop_name = name + '_' + prop.name if name else prop.name | |
145 this_var = prop.name | |
146 c.Concat(self._CreateValueFromProperty(prop_name, prop, this_var)) | |
147 (c.Append() | |
148 .Append('return value;') | |
149 .Eblock('}') | |
150 ) | |
151 return c | |
152 | |
153 # TODO(calamity): object and choices prop types | |
154 def _CreateValueFromProperty(self, name, prop, var): | |
155 """Generates code to serialize a single property in a type. | |
156 """ | |
157 c = code.Code() | |
158 if prop.type_.is_fundamental: | |
159 c.Append('Value* %s_value = %s;' % | |
160 (name, cpp_util.CreateFundamentalValue(prop, var))) | |
161 elif prop.type_ == PropertyType.ARRAY: | |
162 if prop.item_type.type_ == PropertyType.STRING: | |
163 if prop.optional: | |
164 c.Append('json_schema_compiler::util::' | |
165 'SetOptionalStrings(%s, "%s", value);' % (var, prop.name)) | |
166 else: | |
167 c.Append('json_schema_compiler::util::' | |
168 'SetStrings(%s, "%s", value);' % (var, prop.name)) | |
169 else: | |
170 item_name = name + '_single' | |
171 (c.Append('ListValue* %(name)s_value = new ListValue();') | |
172 .Append('for (%(it_type)s::iterator it = %(var)s->begin();') | |
173 .Sblock(' it != %(var)s->end(); ++it) {') | |
174 .Concat(self._CreateValueFromProperty(item_name, prop.item_type, | |
175 '*it')) | |
176 .Append('%(name)s_value->Append(%(prop_val)s_value);') | |
177 .Eblock('}') | |
178 ) | |
179 c.Substitute( | |
180 {'it_type': self._cpp_type_generator.GetType(prop), | |
181 'name': name, 'var': var, 'prop_val': item_name}) | |
182 elif prop.type_ == PropertyType.REF: | |
183 c.Append('Value* %s_value = %s.ToValue();' % (name, var)) | |
184 else: | |
185 raise NotImplementedError | |
186 return c | |
187 | |
188 def _GenerateFunction(self, function): | |
189 """Generates the definitions for function structs. | |
190 """ | |
191 classname = cpp_util.CppName(function.name) | |
192 c = code.Code() | |
193 | |
194 # Params::Populate function | |
195 if function.params: | |
196 (c.Append('%(name)s::Params::Params() {}') | |
197 .Append('%(name)s::Params::~Params() {}') | |
198 .Append() | |
199 .Concat(self._GenerateFunctionParamsCreate(function)) | |
200 .Append() | |
201 ) | |
202 | |
203 # Result::Create function | |
204 c.Concat(self._GenerateFunctionResultCreate(function)) | |
205 | |
206 c.Substitute({'name': classname}) | |
207 | |
208 return c | |
209 | |
210 def _GenerateFunctionParamsCreate(self, function): | |
211 """Generate function to create an instance of Params given a pointer. | |
212 """ | |
213 classname = cpp_util.CppName(function.name) | |
214 c = code.Code() | |
215 (c.Append('// static') | |
216 .Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create' | |
217 '(const ListValue& args) {') | |
218 .Append('if (args.GetSize() != %d)' % len(function.params)) | |
219 .Append(' return scoped_ptr<Params>();') | |
220 .Append() | |
221 .Append('scoped_ptr<Params> params(new Params());') | |
222 ) | |
223 c.Substitute({'classname': classname}) | |
224 | |
225 # TODO(calamity): generalize, needs to move to function to do populates for | |
226 # wider variety of args | |
227 for i, param in enumerate(function.params): | |
228 sub = {'name': param.name, 'pos': i} | |
229 c.Append() | |
230 # TODO(calamity): Make valid for not just objects | |
231 c.Append('DictionaryValue* %(name)s_param = NULL;') | |
232 c.Append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))') | |
233 c.Append(' return scoped_ptr<Params>();') | |
234 if param.type_ == PropertyType.REF: | |
235 c.Append('if (!%(ctype)s::Populate(*%(name)s_param, ' | |
236 '¶ms->%(name)s))') | |
237 c.Append(' return scoped_ptr<Params>();') | |
238 sub['ctype'] = self._cpp_type_generator.GetType(param) | |
239 elif param.type_.is_fundamental: | |
240 raise NotImplementedError('Fundamental types are unimplemented') | |
241 elif param.type_ == PropertyType.OBJECT: | |
242 c.Append('if (!%(ctype)s::Populate(*%(name)s_param, ' | |
243 '¶ms->%(name)s))') | |
244 c.Append(' return scoped_ptr<Params>();') | |
245 sub['ctype'] = self._cpp_type_generator.GetType(param) | |
246 elif param.type_ == PropertyType.CHOICES: | |
247 raise NotImplementedError('Choices is unimplemented') | |
248 else: | |
249 raise NotImplementedError(param.type_) | |
250 c.Substitute(sub) | |
251 c.Append() | |
252 c.Append('return params.Pass();') | |
253 c.Eblock('}') | |
254 | |
255 return c | |
256 | |
257 def _GenerateFunctionResultCreate(self, function): | |
258 """Generate function to create a Result given the return value. | |
259 """ | |
260 classname = cpp_util.CppName(function.name) | |
261 c = code.Code() | |
262 c.Append('// static') | |
263 param = function.callback.param | |
264 arg = '' | |
265 if param: | |
266 if param.type_ == PropertyType.REF: | |
267 arg = 'const %(type)s& %(name)s' | |
268 else: | |
269 arg = 'const %(type)s %(name)s' | |
270 arg = arg % { | |
271 'type': self._cpp_type_generator.GetType(param), | |
272 'name': param.name | |
273 } | |
274 c.Sblock('Value* %(classname)s::Result::Create(%(arg)s) {') | |
275 sub = {'classname': classname, 'arg': arg} | |
276 # TODO(calamity): Choices | |
277 if not param: | |
278 c.Append('return Value::CreateNullValue();') | |
279 else: | |
280 sub['argname'] = param.name | |
281 if param.type_.is_fundamental: | |
282 c.Append('return %s;' % | |
283 cpp_util.CreateFundamentalValue(param, param.name)) | |
284 elif param.type_ == PropertyType.REF: | |
285 c.Append('return %(argname)s.ToValue();') | |
Yoyo Zhou
2012/01/26 00:10:38
I notice this is different. Is this more correct?
calamity
2012/01/27 00:46:57
Before it was setting a DictionaryValue which cont
| |
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 |