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();') |
| 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 |