| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 from code import Code | 5 from code import Code |
| 6 from model import PropertyType | 6 from model import PropertyType, Type |
| 7 import any_helper | |
| 8 import cpp_util | 7 import cpp_util |
| 9 import model | 8 import model |
| 10 import schema_util | 9 import schema_util |
| 11 import sys | 10 import sys |
| 12 import util_cc_helper | 11 import util_cc_helper |
| 13 | 12 |
| 14 class CCGenerator(object): | 13 class CCGenerator(object): |
| 15 """A .cc generator for a namespace. | 14 """A .cc generator for a namespace. |
| 16 """ | 15 """ |
| 17 def __init__(self, namespace, cpp_type_generator): | 16 def __init__(self, namespace, cpp_type_generator): |
| 18 self._cpp_type_generator = cpp_type_generator | 17 self._type_helper = cpp_type_generator |
| 19 self._namespace = namespace | 18 self._namespace = namespace |
| 20 self._target_namespace = ( | 19 self._target_namespace = ( |
| 21 self._cpp_type_generator.GetCppNamespaceName(self._namespace)) | 20 self._type_helper.GetCppNamespaceName(self._namespace)) |
| 22 self._util_cc_helper = ( | 21 self._util_cc_helper = ( |
| 23 util_cc_helper.UtilCCHelper(self._cpp_type_generator)) | 22 util_cc_helper.UtilCCHelper(self._type_helper)) |
| 24 self._any_helper = any_helper.AnyHelper() | |
| 25 | 23 |
| 26 def Generate(self): | 24 def Generate(self): |
| 27 """Generates a Code object with the .cc for a single namespace. | 25 """Generates a Code object with the .cc for a single namespace. |
| 28 """ | 26 """ |
| 29 c = Code() | 27 c = Code() |
| 30 (c.Append(cpp_util.CHROMIUM_LICENSE) | 28 (c.Append(cpp_util.CHROMIUM_LICENSE) |
| 31 .Append() | 29 .Append() |
| 32 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) | 30 .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file) |
| 33 .Append() | 31 .Append() |
| 34 .Append(self._util_cc_helper.GetIncludePath()) | 32 .Append(self._util_cc_helper.GetIncludePath()) |
| 35 .Append('#include "%s/%s.h"' % | 33 .Append('#include "%s/%s.h"' % |
| 36 (self._namespace.source_file_dir, self._namespace.unix_name)) | 34 (self._namespace.source_file_dir, self._namespace.unix_name)) |
| 37 ) | 35 .Append('#include "base/logging.h"') |
| 38 includes = self._cpp_type_generator.GenerateIncludes() | 36 .Cblock(self._type_helper.GenerateIncludes()) |
| 39 if not includes.IsEmpty(): | 37 .Concat(self._type_helper.GetRootNamespaceStart()) |
| 40 (c.Concat(includes) | 38 .Cblock(self._type_helper.GetNamespaceStart()) |
| 41 .Append() | |
| 42 ) | |
| 43 | |
| 44 (c.Append() | |
| 45 .Concat(self._cpp_type_generator.GetRootNamespaceStart()) | |
| 46 .Concat(self._cpp_type_generator.GetNamespaceStart()) | |
| 47 .Append() | |
| 48 ) | 39 ) |
| 49 if self._namespace.properties: | 40 if self._namespace.properties: |
| 50 (c.Append('//') | 41 (c.Append('//') |
| 51 .Append('// Properties') | 42 .Append('// Properties') |
| 52 .Append('//') | 43 .Append('//') |
| 53 .Append() | 44 .Append() |
| 54 ) | 45 ) |
| 55 for property in self._namespace.properties.values(): | 46 for property in self._namespace.properties.values(): |
| 56 property_code = self._cpp_type_generator.GeneratePropertyValues( | 47 property_code = self._type_helper.GeneratePropertyValues( |
| 57 property, | 48 property, |
| 58 'const %(type)s %(name)s = %(value)s;', | 49 'const %(type)s %(name)s = %(value)s;', |
| 59 nodoc=True) | 50 nodoc=True) |
| 60 if property_code: | 51 if property_code: |
| 61 c.Concat(property_code).Append() | 52 c.Cblock(property_code) |
| 62 if self._namespace.types: | 53 if self._namespace.types: |
| 63 (c.Append('//') | 54 (c.Append('//') |
| 64 .Append('// Types') | 55 .Append('// Types') |
| 65 .Append('//') | 56 .Append('//') |
| 66 .Append() | 57 .Append() |
| 67 ) | 58 .Cblock(self._GenerateTypes(None, self._namespace.types.values())) |
| 68 for type_ in self._namespace.types.values(): | |
| 69 (c.Concat(self._GenerateType( | |
| 70 schema_util.StripSchemaNamespace(type_.name), type_)).Append() | |
| 71 ) | 59 ) |
| 72 if self._namespace.functions: | 60 if self._namespace.functions: |
| 73 (c.Append('//') | 61 (c.Append('//') |
| 74 .Append('// Functions') | 62 .Append('// Functions') |
| 75 .Append('//') | 63 .Append('//') |
| 76 .Append() | 64 .Append() |
| 77 ) | 65 ) |
| 78 for function in self._namespace.functions.values(): | 66 for function in self._namespace.functions.values(): |
| 79 (c.Concat(self._GenerateFunction( | 67 c.Cblock(self._GenerateFunction(function)) |
| 80 cpp_util.Classname(function.name), function)) | |
| 81 .Append() | |
| 82 ) | |
| 83 if self._namespace.events: | 68 if self._namespace.events: |
| 84 (c.Append('//') | 69 (c.Append('//') |
| 85 .Append('// Events') | 70 .Append('// Events') |
| 86 .Append('//') | 71 .Append('//') |
| 87 .Append() | 72 .Append() |
| 88 ) | 73 ) |
| 89 for event in self._namespace.events.values(): | 74 for event in self._namespace.events.values(): |
| 90 (c.Concat(self._GenerateCreateCallbackArguments( | 75 c.Cblock(self._GenerateEvent(event)) |
| 91 cpp_util.Classname(event.name), event, generate_to_json=True)) | 76 (c.Concat(self._type_helper.GetNamespaceEnd()) |
| 92 .Append() | 77 .Cblock(self._type_helper.GetRootNamespaceEnd()) |
| 93 ) | |
| 94 (c.Concat(self._cpp_type_generator.GetNamespaceEnd()) | |
| 95 .Concat(self._cpp_type_generator.GetRootNamespaceEnd()) | |
| 96 .Append() | |
| 97 ) | 78 ) |
| 98 return c | 79 return c |
| 99 | 80 |
| 100 def _GenerateType(self, cpp_namespace, type_): | 81 def _GenerateType(self, cpp_namespace, type_): |
| 101 """Generates the function definitions for a type. | 82 """Generates the function definitions for a type. |
| 102 """ | 83 """ |
| 103 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) | 84 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 104 c = Code() | 85 c = Code() |
| 105 | 86 |
| 106 if type_.functions: | 87 if type_.functions: |
| 88 # Wrap functions within types in the type's namespace. |
| 89 (c.Append('namespace %s {' % classname) |
| 90 .Append()) |
| 107 for function in type_.functions.values(): | 91 for function in type_.functions.values(): |
| 108 (c.Concat( | 92 c.Cblock(self._GenerateFunction(function)) |
| 109 self._GenerateFunction( | 93 c.Append('} // namespace %s' % classname) |
| 110 cpp_namespace + '::' + cpp_util.Classname(function.name), | 94 elif type_.property_type == PropertyType.ARRAY: |
| 111 function)) | 95 c.Cblock(self._GenerateType(cpp_namespace, type_.item_type)) |
| 112 .Append()) | 96 elif (type_.property_type == PropertyType.OBJECT or |
| 113 elif type_.type_ == PropertyType.OBJECT: | 97 type_.property_type == PropertyType.CHOICES): |
| 114 (c.Concat(self._GeneratePropertyFunctions( | 98 if cpp_namespace is None: |
| 115 cpp_namespace, type_.properties.values())) | 99 classname_in_namespace = classname |
| 116 .Sblock('%(namespace)s::%(classname)s()') | 100 else: |
| 117 .Concat(self._GenerateInitializersAndBody(type_)) | 101 classname_in_namespace = '%s::%s' % (cpp_namespace, classname) |
| 118 .Eblock('%(namespace)s::~%(classname)s() {}') | 102 |
| 119 .Append()) | 103 if type_.property_type == PropertyType.OBJECT: |
| 120 if type_.from_json: | 104 c.Cblock(self._GeneratePropertyFunctions(classname_in_namespace, |
| 121 (c.Concat(self._GenerateTypePopulate(cpp_namespace, type_)) | 105 type_.properties.values())) |
| 122 .Append()) | 106 else: |
| 123 if type_.from_client: | 107 c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices)) |
| 124 (c.Concat(self._GenerateTypeToValue(cpp_namespace, type_)) | 108 |
| 125 .Append()) | 109 (c.Append('%s::%s()' % (classname_in_namespace, classname)) |
| 126 elif self._cpp_type_generator.IsEnumOrEnumRef(type_): | 110 .Cblock(self._GenerateInitializersAndBody(type_)) |
| 127 (c.Concat(self._GenerateCreateEnumTypeValue(cpp_namespace, type_)) | 111 .Append('%s::~%s() {}' % (classname_in_namespace, classname)) |
| 128 .Append() | 112 .Append() |
| 129 .Concat(self._GenerateEnumFromString(cpp_namespace, type_)) | 113 ) |
| 130 .Append() | 114 if type_.origin.from_json: |
| 131 .Concat(self._GenerateEnumToString(cpp_namespace, type_)) | 115 c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_)) |
| 132 .Append()) | 116 if type_.origin.from_client: |
| 133 c.Substitute({'classname': classname, 'namespace': cpp_namespace}) | 117 c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_)) |
| 118 elif type_.property_type == PropertyType.ENUM: |
| 119 (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_)) |
| 120 .Cblock(self._GenerateEnumFromString(cpp_namespace, type_)) |
| 121 ) |
| 134 | 122 |
| 135 return c | 123 return c |
| 136 | 124 |
| 137 def _GenerateInitializersAndBody(self, type_): | 125 def _GenerateInitializersAndBody(self, type_): |
| 138 items = [] | 126 items = [] |
| 139 for prop in type_.properties.values(): | 127 for prop in type_.properties.values(): |
| 140 if prop.optional: | 128 if prop.optional: |
| 141 continue | 129 continue |
| 142 | 130 |
| 143 t = prop.type_ | 131 t = prop.type_ |
| 144 if t == PropertyType.INTEGER: | 132 if t.property_type == PropertyType.INTEGER: |
| 145 items.append('%s(0)' % prop.unix_name) | 133 items.append('%s(0)' % prop.unix_name) |
| 146 elif t == PropertyType.DOUBLE: | 134 elif t.property_type == PropertyType.DOUBLE: |
| 147 items.append('%s(0.0)' % prop.unix_name) | 135 items.append('%s(0.0)' % prop.unix_name) |
| 148 elif t == PropertyType.BOOLEAN: | 136 elif t.property_type == PropertyType.BOOLEAN: |
| 149 items.append('%s(false)' % prop.unix_name) | 137 items.append('%s(false)' % prop.unix_name) |
| 150 elif t == PropertyType.BINARY: | 138 elif t.property_type == PropertyType.BINARY: |
| 151 items.append('%s(NULL)' % prop.unix_name) | 139 items.append('%s(NULL)' % prop.unix_name) |
| 152 elif (t == PropertyType.ADDITIONAL_PROPERTIES or | 140 elif (t.property_type == PropertyType.ANY or |
| 153 t == PropertyType.ANY or | 141 t.property_type == PropertyType.ARRAY or |
| 154 t == PropertyType.ARRAY or | 142 t.property_type == PropertyType.CHOICES or |
| 155 t == PropertyType.CHOICES or | 143 t.property_type == PropertyType.ENUM or |
| 156 t == PropertyType.ENUM or | 144 t.property_type == PropertyType.OBJECT or |
| 157 t == PropertyType.OBJECT or | 145 t.property_type == PropertyType.FUNCTION or |
| 158 t == PropertyType.FUNCTION or | 146 t.property_type == PropertyType.REF or |
| 159 t == PropertyType.REF or | 147 t.property_type == PropertyType.STRING): |
| 160 t == PropertyType.STRING): | |
| 161 # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we | 148 # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we |
| 162 # don't presently have the semantics to indicate which one of a set | 149 # don't presently have the semantics to indicate which one of a set |
| 163 # should be the default. | 150 # should be the default. |
| 164 continue | 151 continue |
| 165 else: | 152 else: |
| 166 sys.exit("Unhandled PropertyType: %s" % t) | 153 raise TypeError(t) |
| 167 | 154 |
| 168 if items: | 155 if items: |
| 169 s = ': %s' % (', '.join(items)) | 156 s = ': %s' % (', '.join(items)) |
| 170 else: | 157 else: |
| 171 s = '' | 158 s = '' |
| 172 s = s + ' {}' | 159 s = s + ' {}' |
| 173 return Code().Append(s) | 160 return Code().Append(s) |
| 174 | 161 |
| 175 def _GenerateTypePopulate(self, cpp_namespace, type_): | 162 def _GenerateTypePopulate(self, cpp_namespace, type_): |
| 176 """Generates the function for populating a type given a pointer to it. | 163 """Generates the function for populating a type given a pointer to it. |
| 177 | 164 |
| 178 E.g for type "Foo", generates Foo::Populate() | 165 E.g for type "Foo", generates Foo::Populate() |
| 179 """ | 166 """ |
| 180 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) | 167 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 181 c = Code() | 168 c = Code() |
| 182 (c.Append('// static') | 169 (c.Append('// static') |
| 183 .Sblock('bool %(namespace)s::Populate' | 170 .Append('bool %(namespace)s::Populate(') |
| 184 '(const base::Value& value, %(name)s* out) {') | 171 .Sblock(' const base::Value& value, %(name)s* out) {') |
| 185 .Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))') | 172 ) |
| 173 if type_.property_type == PropertyType.CHOICES: |
| 174 for choice in type_.choices: |
| 175 value_type = cpp_util.GetValueType(self._type_helper.FollowRef(choice)) |
| 176 (c.Sblock('if (value.IsType(%s)) {' % value_type) |
| 177 .Concat(self._GeneratePopulateVariableFromValue( |
| 178 choice, |
| 179 '(&value)', |
| 180 'out->as_%s' % choice.unix_name, |
| 181 'false', |
| 182 is_ptr=True)) |
| 183 .Append('return true;') |
| 184 .Eblock('}') |
| 185 ) |
| 186 c.Append('return false;') |
| 187 elif type_.property_type == PropertyType.OBJECT: |
| 188 (c.Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))') |
| 186 .Append(' return false;') | 189 .Append(' return false;') |
| 187 ) | |
| 188 if type_.properties: | |
| 189 (c.Append('const base::DictionaryValue* dict = ' | |
| 190 'static_cast<const base::DictionaryValue*>(&value);') | |
| 191 .Append() | |
| 192 ) | 190 ) |
| 191 if type_.properties or type_.additional_properties is not None: |
| 192 c.Append('const base::DictionaryValue* dict = ' |
| 193 'static_cast<const base::DictionaryValue*>(&value);') |
| 193 for prop in type_.properties.values(): | 194 for prop in type_.properties.values(): |
| 194 c.Concat(self._InitializePropertyToDefault(prop, 'out')) | 195 c.Concat(self._InitializePropertyToDefault(prop, 'out')) |
| 195 for prop in type_.properties.values(): | 196 for prop in type_.properties.values(): |
| 196 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 197 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) |
| 198 if type_.additional_properties is not None: |
| 199 if type_.additional_properties.property_type == PropertyType.ANY: |
| 197 c.Append('out->additional_properties.MergeDictionary(dict);') | 200 c.Append('out->additional_properties.MergeDictionary(dict);') |
| 198 # remove all keys that are actual properties | |
| 199 for cur_prop in type_.properties.values(): | |
| 200 if prop != cur_prop: | |
| 201 c.Append('out->additional_properties' | |
| 202 '.RemoveWithoutPathExpansion("%s", NULL);' % cur_prop.name) | |
| 203 c.Append() | |
| 204 else: | 201 else: |
| 205 c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out')) | 202 cpp_type = self._type_helper.GetCppType(type_.additional_properties, |
| 206 (c.Append('return true;') | 203 is_in_container=True) |
| 207 .Eblock('}') | 204 (c.Append('for (base::DictionaryValue::Iterator it(*dict);') |
| 208 ) | 205 .Sblock(' it.HasNext(); it.Advance()) {') |
| 209 c.Substitute({'namespace': cpp_namespace, 'name': classname}) | 206 .Append('%s tmp;' % cpp_type) |
| 207 .Concat(self._GeneratePopulateVariableFromValue( |
| 208 type_.additional_properties, |
| 209 '(&it.value())', |
| 210 'tmp', |
| 211 'false')) |
| 212 .Append('out->additional_properties[it.key()] = tmp;') |
| 213 .Eblock('}') |
| 214 ) |
| 215 c.Append('return true;') |
| 216 (c.Eblock('}') |
| 217 .Substitute({'namespace': cpp_namespace, 'name': classname})) |
| 210 return c | 218 return c |
| 211 | 219 |
| 212 def _GenerateTypePopulateProperty(self, prop, src, dst): | 220 def _GenerateTypePopulateProperty(self, prop, src, dst): |
| 213 """Generate the code to populate a single property in a type. | 221 """Generate the code to populate a single property in a type. |
| 214 | 222 |
| 215 src: base::DictionaryValue* | 223 src: base::DictionaryValue* |
| 216 dst: Type* | 224 dst: Type* |
| 217 """ | 225 """ |
| 218 c = Code() | 226 c = Code() |
| 219 value_var = prop.unix_name + '_value' | 227 value_var = prop.unix_name + '_value' |
| 220 c.Append('const base::Value* %(value_var)s = NULL;') | 228 c.Append('const base::Value* %(value_var)s = NULL;') |
| 221 if prop.optional: | 229 if prop.optional: |
| 222 (c.Sblock( | 230 (c.Sblock( |
| 223 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {') | 231 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {') |
| 224 .Concat(self._GeneratePopulatePropertyFromValue( | 232 .Concat(self._GeneratePopulatePropertyFromValue( |
| 225 prop, value_var, dst, 'false'))) | 233 prop, value_var, dst, 'false'))) |
| 226 if self._cpp_type_generator.IsEnumOrEnumRef(prop): | 234 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 235 if underlying_type.property_type == PropertyType.ENUM: |
| 227 (c.Append('} else {') | 236 (c.Append('} else {') |
| 228 .Append('%%(dst)s->%%(name)s = %s;' % | 237 .Append('%%(dst)s->%%(name)s = %s;' % |
| 229 self._cpp_type_generator.GetEnumNoneValue(prop))) | 238 self._type_helper.GetEnumNoneValue(prop.type_))) |
| 230 c.Eblock('}') | 239 c.Eblock('}') |
| 231 else: | 240 else: |
| 232 (c.Append( | 241 (c.Append( |
| 233 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') | 242 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))') |
| 234 .Append(' return false;') | 243 .Append(' return false;') |
| 235 .Concat(self._GeneratePopulatePropertyFromValue( | 244 .Concat(self._GeneratePopulatePropertyFromValue( |
| 236 prop, value_var, dst, 'false')) | 245 prop, value_var, dst, 'false')) |
| 237 ) | 246 ) |
| 238 c.Append() | 247 c.Append() |
| 239 c.Substitute({ | 248 c.Substitute({ |
| 240 'value_var': value_var, | 249 'value_var': value_var, |
| 241 'key': prop.name, | 250 'key': prop.name, |
| 242 'src': src, | 251 'src': src, |
| 243 'dst': dst, | 252 'dst': dst, |
| 244 'name': prop.unix_name | 253 'name': prop.unix_name |
| 245 }) | 254 }) |
| 246 return c | 255 return c |
| 247 | 256 |
| 248 def _GenerateTypeToValue(self, cpp_namespace, type_): | 257 def _GenerateTypeToValue(self, cpp_namespace, type_): |
| 249 """Generates a function that serializes the type into a | 258 """Generates a function that serializes the type into a base::Value. |
| 250 |base::DictionaryValue|. | 259 E.g. for type "Foo" generates Foo::ToValue() |
| 260 """ |
| 261 if type_.property_type == PropertyType.OBJECT: |
| 262 return self._GenerateObjectTypeToValue(cpp_namespace, type_) |
| 263 elif type_.property_type == PropertyType.CHOICES: |
| 264 return self._GenerateChoiceTypeToValue(cpp_namespace, type_) |
| 265 else: |
| 266 raise ValueError("Unsupported property type %s" % type_.type_) |
| 251 | 267 |
| 252 E.g. for type "Foo" generates Foo::ToValue() | 268 def _GenerateObjectTypeToValue(self, cpp_namespace, type_): |
| 269 """Generates a function that serializes an object-representing type |
| 270 into a base::DictionaryValue. |
| 253 """ | 271 """ |
| 254 c = Code() | 272 c = Code() |
| 255 (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % | 273 (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % |
| 256 cpp_namespace) | 274 cpp_namespace) |
| 257 .Append('scoped_ptr<base::DictionaryValue> value(' | 275 .Append('scoped_ptr<base::DictionaryValue> value(' |
| 258 'new base::DictionaryValue());') | 276 'new base::DictionaryValue());') |
| 259 .Append() | 277 .Append() |
| 260 ) | 278 ) |
| 279 |
| 261 for prop in type_.properties.values(): | 280 for prop in type_.properties.values(): |
| 262 if prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 281 if prop.optional: |
| 263 c.Append('value->MergeDictionary(&%s);' % prop.unix_name) | 282 # Optional enum values are generated with a NONE enum value. |
| 283 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 284 if underlying_type.property_type == PropertyType.ENUM: |
| 285 c.Sblock('if (%s != %s) {' % |
| 286 (prop.unix_name, |
| 287 self._type_helper.GetEnumNoneValue(prop.type_))) |
| 288 else: |
| 289 c.Sblock('if (%s.get()) {' % prop.unix_name) |
| 290 |
| 291 # ANY is a base::Value which is abstract and cannot be a direct member, so |
| 292 # it will always be a pointer. |
| 293 is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY |
| 294 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( |
| 295 prop.name, |
| 296 self._CreateValueFromType(prop.type_, |
| 297 'this->%s' % prop.unix_name, |
| 298 is_ptr=is_ptr))) |
| 299 |
| 300 if prop.optional: |
| 301 c.Eblock('}'); |
| 302 |
| 303 if type_.additional_properties is not None: |
| 304 if type_.additional_properties.property_type == PropertyType.ANY: |
| 305 c.Append('value->MergeDictionary(&additional_properties);') |
| 264 else: | 306 else: |
| 265 if prop.optional: | 307 # Non-copyable types will be wrapped in a linked_ptr for inclusion in |
| 266 if self._cpp_type_generator.IsEnumOrEnumRef(prop): | 308 # maps, so we need to unwrap them. |
| 267 c.Sblock('if (%s != %s) {' % | 309 needs_unwrap = ( |
| 268 (prop.unix_name, | 310 not self._type_helper.IsCopyable(type_.additional_properties)) |
| 269 self._cpp_type_generator.GetEnumNoneValue(prop))) | 311 cpp_type = self._type_helper.GetCppType(type_.additional_properties, |
| 270 elif prop.type_ == PropertyType.CHOICES: | 312 is_in_container=True) |
| 271 c.Sblock('if (%s_type != %s) {' % | 313 (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' % |
| 272 (prop.unix_name, | 314 cpp_util.PadForGenerics(cpp_type)) |
| 273 self._cpp_type_generator.GetEnumNoneValue(prop))) | 315 .Append(' additional_properties.begin();') |
| 274 else: | 316 .Append(' it != additional_properties.end(); ++it) {') |
| 275 c.Sblock('if (%s.get()) {' % prop.unix_name) | 317 .Append('value->SetWithoutPathExpansion(it->first, %s);' % |
| 318 self._CreateValueFromType( |
| 319 type_.additional_properties, |
| 320 '%sit->second' % ('*' if needs_unwrap else ''))) |
| 321 .Eblock('}') |
| 322 ) |
| 276 | 323 |
| 277 if prop.type_ == prop.compiled_type: | 324 return (c.Append() |
| 278 c.Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 325 .Append('return value.Pass();') |
| 279 prop.name, | 326 .Eblock('}')) |
| 280 self._CreateValueFromProperty(prop, 'this->' + prop.unix_name))) | 327 |
| 281 else: | 328 def _GenerateChoiceTypeToValue(self, cpp_namespace, type_): |
| 282 conversion_src = 'this->' + prop.unix_name | 329 """Generates a function that serializes a choice-representing type |
| 283 if prop.optional: | 330 into a base::Value. |
| 284 conversion_src = '*' + conversion_src | 331 """ |
| 285 (c.Append('%s %s;' % (self._cpp_type_generator.GetType(prop), | 332 c = Code() |
| 286 prop.unix_name)) | 333 c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace) |
| 287 .Append(cpp_util.GenerateCompiledTypeToTypeConversion( | 334 c.Append('scoped_ptr<base::Value> result;'); |
| 288 self._cpp_type_generator.GetReferencedProperty(prop), | 335 for choice in type_.choices: |
| 289 conversion_src, | 336 choice_var = 'as_%s' % choice.unix_name |
| 290 prop.unix_name) + ';') | 337 (c.Sblock('if (%s) {' % choice_var) |
| 291 .Append('value->SetWithoutPathExpansion("%s", %s);' % ( | 338 .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' % |
| 292 prop.unix_name, | 339 type_.unix_name) |
| 293 self._CreateValueFromProperty(prop, prop.unix_name))) | 340 .Append('result.reset(%s);' % |
| 294 ) | 341 self._CreateValueFromType(choice, '*%s' % choice_var)) |
| 295 if prop.optional: | 342 .Eblock('}') |
| 296 c.Eblock('}'); | 343 ) |
| 297 (c.Append() | 344 (c.Append('DCHECK(result) << "Must set at least one choice for %s";' % |
| 298 .Append('return value.Pass();') | 345 type_.unix_name) |
| 346 .Append('return result.Pass();') |
| 299 .Eblock('}') | 347 .Eblock('}') |
| 300 ) | 348 ) |
| 301 return c | 349 return c |
| 302 | 350 |
| 303 def _GenerateFunction(self, cpp_namespace, function): | 351 def _GenerateFunction(self, function): |
| 304 """Generates the definitions for function structs. | 352 """Generates the definitions for function structs. |
| 305 """ | 353 """ |
| 306 c = Code() | 354 c = Code() |
| 307 | 355 |
| 356 # TODO(kalman): use function.unix_name not Classname. |
| 357 function_namespace = cpp_util.Classname(function.name) |
| 358 (c.Append('namespace %s {' % function_namespace) |
| 359 .Append() |
| 360 ) |
| 361 |
| 308 # Params::Populate function | 362 # Params::Populate function |
| 309 if function.params: | 363 if function.params: |
| 310 c.Concat(self._GeneratePropertyFunctions(cpp_namespace + '::Params', | 364 c.Concat(self._GeneratePropertyFunctions('Params', function.params)) |
| 311 function.params)) | 365 (c.Append('Params::Params() {}') |
| 312 (c.Append('%(cpp_namespace)s::Params::Params() {}') | 366 .Append('Params::~Params() {}') |
| 313 .Append('%(cpp_namespace)s::Params::~Params() {}') | |
| 314 .Append() | 367 .Append() |
| 315 .Concat(self._GenerateFunctionParamsCreate(cpp_namespace, function)) | 368 .Cblock(self._GenerateFunctionParamsCreate(function)) |
| 316 .Append() | |
| 317 ) | 369 ) |
| 318 | 370 |
| 319 # Results::Create function | 371 # Results::Create function |
| 320 if function.callback: | 372 if function.callback: |
| 321 c.Concat(self._GenerateCreateCallbackArguments( | 373 c.Concat(self._GenerateCreateCallbackArguments('Results', |
| 322 "%s::Results" % cpp_namespace, function.callback)) | 374 function.callback)) |
| 323 | 375 |
| 324 c.Substitute({'cpp_namespace': cpp_namespace}) | 376 c.Append('} // namespace %s' % function_namespace) |
| 325 | |
| 326 return c | 377 return c |
| 327 | 378 |
| 328 def _CreateValueFromProperty(self, prop, var): | 379 def _GenerateEvent(self, event): |
| 329 """Creates a base::Value given a property. Generated code passes ownership | 380 # TODO(kalman): use event.unix_name not Classname. |
| 381 c = Code() |
| 382 event_namespace = cpp_util.Classname(event.name) |
| 383 (c.Append('namespace %s {' % event_namespace) |
| 384 .Append() |
| 385 .Cblock(self._GenerateCreateCallbackArguments(None, event)) |
| 386 .Append('} // namespace %s' % event_namespace) |
| 387 ) |
| 388 return c |
| 389 |
| 390 def _CreateValueFromType(self, type_, var, is_ptr=False): |
| 391 """Creates a base::Value given a type. Generated code passes ownership |
| 330 to caller. | 392 to caller. |
| 331 | 393 |
| 332 var: variable or variable* | 394 var: variable or variable* |
| 333 | 395 |
| 334 E.g for std::string, generate base::Value::CreateStringValue(var) | 396 E.g for std::string, generate base::Value::CreateStringValue(var) |
| 335 """ | 397 """ |
| 336 if prop.type_ == PropertyType.CHOICES: | 398 underlying_type = self._type_helper.FollowRef(type_) |
| 337 return 'Get%sChoiceValue().release()' % cpp_util.Classname(prop.name) | 399 if (underlying_type.property_type == PropertyType.CHOICES or |
| 338 elif self._IsObjectOrObjectRef(prop): | 400 underlying_type.property_type == PropertyType.OBJECT): |
| 339 if prop.optional: | 401 if is_ptr: |
| 340 return '%s->ToValue().release()' % var | 402 return '(%s)->ToValue().release()' % var |
| 341 else: | 403 else: |
| 342 return '%s.ToValue().release()' % var | 404 return '(%s).ToValue().release()' % var |
| 343 elif prop.type_ == PropertyType.ANY: | 405 elif (underlying_type.property_type == PropertyType.ANY or |
| 344 return '%s.DeepCopy()' % self._any_helper.GetValue(prop, var) | 406 underlying_type.property_type == PropertyType.FUNCTION): |
| 345 elif prop.type_ == PropertyType.ADDITIONAL_PROPERTIES: | 407 if is_ptr: |
| 346 return '%s.DeepCopy()' % var | 408 vardot = '(%s)->' % var |
| 347 elif prop.type_ == PropertyType.FUNCTION: | |
| 348 if prop.optional: | |
| 349 vardot = var + '->' | |
| 350 else: | 409 else: |
| 351 vardot = var + '.' | 410 vardot = '(%s).' % var |
| 352 return '%sDeepCopy()' % vardot | 411 return '%sDeepCopy()' % vardot |
| 353 elif self._cpp_type_generator.IsEnumOrEnumRef(prop): | 412 elif underlying_type.property_type == PropertyType.ENUM: |
| 354 return 'base::Value::CreateStringValue(ToString(%s))' % var | 413 return 'base::Value::CreateStringValue(ToString(%s))' % var |
| 355 elif prop.type_ == PropertyType.BINARY: | 414 elif underlying_type.property_type == PropertyType.BINARY: |
| 356 if prop.optional: | 415 if is_ptr: |
| 357 vardot = var + '->' | 416 vardot = var + '->' |
| 358 else: | 417 else: |
| 359 vardot = var + '.' | 418 vardot = var + '.' |
| 360 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % | 419 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' % |
| 361 (vardot, vardot)) | 420 (vardot, vardot)) |
| 362 elif self._IsArrayOrArrayRef(prop): | 421 elif underlying_type.property_type == PropertyType.ARRAY: |
| 363 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( | 422 return '%s.release()' % self._util_cc_helper.CreateValueFromArray( |
| 364 self._cpp_type_generator.GetReferencedProperty(prop), var, | 423 underlying_type, |
| 365 prop.optional) | 424 var, |
| 366 elif self._IsFundamentalOrFundamentalRef(prop): | 425 is_ptr) |
| 367 # If prop.type != prop.compiled_type, then no asterisk is necessary | 426 elif underlying_type.property_type.is_fundamental: |
| 368 # because the target is a local variable and not a dereferenced scoped | 427 if is_ptr: |
| 369 # pointer. The asterisk is instead prepended to conversion_src around line | 428 var = '*%s' % var |
| 370 # 273. | 429 if underlying_type.property_type == PropertyType.STRING: |
| 371 if prop.optional and prop.type_ == prop.compiled_type: | 430 return 'new base::StringValue(%s)' % var |
| 372 var = '*' + var | 431 else: |
| 373 prop = self._cpp_type_generator.GetReferencedProperty(prop); | 432 return 'new base::FundamentalValue(%s)' % var |
| 374 return { | |
| 375 PropertyType.STRING: 'base::Value::CreateStringValue(%s)', | |
| 376 PropertyType.BOOLEAN: 'base::Value::CreateBooleanValue(%s)', | |
| 377 PropertyType.INTEGER: 'base::Value::CreateIntegerValue(%s)', | |
| 378 PropertyType.DOUBLE: 'base::Value::CreateDoubleValue(%s)', | |
| 379 }[prop.type_] % var | |
| 380 else: | 433 else: |
| 381 raise NotImplementedError('Conversion of %s to base::Value not ' | 434 raise NotImplementedError('Conversion of %s to base::Value not ' |
| 382 'implemented' % repr(prop.type_)) | 435 'implemented' % repr(type_.type_)) |
| 383 | 436 |
| 384 def _GenerateParamsCheck(self, function, var): | 437 def _GenerateParamsCheck(self, function, var): |
| 385 """Generates a check for the correct number of arguments when creating | 438 """Generates a check for the correct number of arguments when creating |
| 386 Params. | 439 Params. |
| 387 """ | 440 """ |
| 388 c = Code() | 441 c = Code() |
| 389 num_required = 0 | 442 num_required = 0 |
| 390 for param in function.params: | 443 for param in function.params: |
| 391 if not param.optional: | 444 if not param.optional: |
| 392 num_required += 1 | 445 num_required += 1 |
| 393 if num_required == len(function.params): | 446 if num_required == len(function.params): |
| 394 c.Append('if (%(var)s.GetSize() != %(total)d)') | 447 c.Append('if (%(var)s.GetSize() != %(total)d)') |
| 395 elif not num_required: | 448 elif not num_required: |
| 396 c.Append('if (%(var)s.GetSize() > %(total)d)') | 449 c.Append('if (%(var)s.GetSize() > %(total)d)') |
| 397 else: | 450 else: |
| 398 c.Append('if (%(var)s.GetSize() < %(required)d' | 451 c.Append('if (%(var)s.GetSize() < %(required)d' |
| 399 ' || %(var)s.GetSize() > %(total)d)') | 452 ' || %(var)s.GetSize() > %(total)d)') |
| 400 c.Append(' return scoped_ptr<Params>();') | 453 c.Append(' return scoped_ptr<Params>();') |
| 401 c.Substitute({ | 454 c.Substitute({ |
| 402 'var': var, | 455 'var': var, |
| 403 'required': num_required, | 456 'required': num_required, |
| 404 'total': len(function.params), | 457 'total': len(function.params), |
| 405 }) | 458 }) |
| 406 return c | 459 return c |
| 407 | 460 |
| 408 def _GenerateFunctionParamsCreate(self, cpp_namespace, function): | 461 def _GenerateFunctionParamsCreate(self, function): |
| 409 """Generate function to create an instance of Params. The generated | 462 """Generate function to create an instance of Params. The generated |
| 410 function takes a base::ListValue of arguments. | 463 function takes a base::ListValue of arguments. |
| 411 | 464 |
| 412 E.g for function "Bar", generate Bar::Params::Create() | 465 E.g for function "Bar", generate Bar::Params::Create() |
| 413 """ | 466 """ |
| 414 c = Code() | 467 c = Code() |
| 415 (c.Append('// static') | 468 (c.Append('// static') |
| 416 .Sblock('scoped_ptr<%(cpp_namespace)s::Params> ' | 469 .Sblock('scoped_ptr<Params> ' |
| 417 '%(cpp_namespace)s::Params::Create(const base::ListValue& args) {') | 470 'Params::Create(const base::ListValue& args) {') |
| 418 .Concat(self._GenerateParamsCheck(function, 'args')) | 471 .Concat(self._GenerateParamsCheck(function, 'args')) |
| 419 .Append('scoped_ptr<Params> params(new Params());') | 472 .Append('scoped_ptr<Params> params(new Params());') |
| 420 ) | 473 ) |
| 421 c.Substitute({'cpp_namespace': cpp_namespace}) | |
| 422 | 474 |
| 423 for param in function.params: | 475 for param in function.params: |
| 424 c.Concat(self._InitializePropertyToDefault(param, 'params')) | 476 c.Concat(self._InitializePropertyToDefault(param, 'params')) |
| 425 | 477 |
| 426 for i, param in enumerate(function.params): | 478 for i, param in enumerate(function.params): |
| 427 # Any failure will cause this function to return. If any argument is | 479 # Any failure will cause this function to return. If any argument is |
| 428 # incorrect or missing, those following it are not processed. Note that | 480 # incorrect or missing, those following it are not processed. Note that |
| 429 # for optional arguments, we allow missing arguments and proceed because | 481 # for optional arguments, we allow missing arguments and proceed because |
| 430 # there may be other arguments following it. | 482 # there may be other arguments following it. |
| 431 failure_value = 'scoped_ptr<Params>()' | 483 failure_value = 'scoped_ptr<Params>()' |
| 432 c.Append() | 484 c.Append() |
| 433 value_var = param.unix_name + '_value' | 485 value_var = param.unix_name + '_value' |
| 434 (c.Append('const base::Value* %(value_var)s = NULL;') | 486 (c.Append('const base::Value* %(value_var)s = NULL;') |
| 435 .Append('if (args.Get(%(i)s, &%(value_var)s) &&\n' | 487 .Append('if (args.Get(%(i)s, &%(value_var)s) &&') |
| 436 ' !%(value_var)s->IsType(base::Value::TYPE_NULL))') | 488 .Sblock(' !%(value_var)s->IsType(base::Value::TYPE_NULL)) {') |
| 437 .Sblock('{') | |
| 438 .Concat(self._GeneratePopulatePropertyFromValue( | 489 .Concat(self._GeneratePopulatePropertyFromValue( |
| 439 param, value_var, 'params', failure_value)) | 490 param, value_var, 'params', failure_value)) |
| 440 .Eblock('}') | 491 .Eblock('}') |
| 441 ) | 492 ) |
| 442 if not param.optional: | 493 if not param.optional: |
| 443 (c.Sblock('else {') | 494 (c.Sblock('else {') |
| 444 .Append('return %s;' % failure_value) | 495 .Append('return %s;' % failure_value) |
| 445 .Eblock('}') | 496 .Eblock('}') |
| 446 ) | 497 ) |
| 447 c.Substitute({'value_var': value_var, 'i': i}) | 498 c.Substitute({'value_var': value_var, 'i': i}) |
| 448 (c.Append() | 499 (c.Append() |
| 449 .Append('return params.Pass();') | 500 .Append('return params.Pass();') |
| 450 .Eblock('}') | 501 .Eblock('}') |
| 451 .Append() | 502 .Append() |
| 452 ) | 503 ) |
| 453 | 504 |
| 454 return c | 505 return c |
| 455 | 506 |
| 456 def _GeneratePopulatePropertyFromValue( | 507 def _GeneratePopulatePropertyFromValue(self, |
| 457 self, prop, value_var, dst, failure_value, check_type=True): | 508 prop, |
| 458 """Generates code to populate a model.Property given a base::Value*. The | 509 src_var, |
| 459 existence of data inside the base::Value* is assumed so checks for existence | 510 dst_class_var, |
| 460 should be performed before the code this generates. | 511 failure_value): |
| 461 | 512 """Generates code to populate property |prop| of |dst_class_var| (a |
| 462 prop: the property the code is populating. | 513 pointer) from a Value*. See |_GeneratePopulateVariableFromValue| for |
| 463 value_var: a base::Value* that should represent |prop|. | 514 semantics. |
| 464 dst: the object with |prop| as a member. | 515 """ |
| 465 failure_value: the value to return if |prop| cannot be extracted from | 516 return self._GeneratePopulateVariableFromValue(prop.type_, |
| 466 |value_var| | 517 src_var, |
| 467 check_type: if true, will check if |value_var| is the correct | 518 '%s->%s' % (dst_class_var, |
| 468 base::Value::Type | 519 prop.unix_name), |
| 520 failure_value, |
| 521 is_ptr=prop.optional) |
| 522 |
| 523 def _GeneratePopulateVariableFromValue(self, |
| 524 type_, |
| 525 src_var, |
| 526 dst_var, |
| 527 failure_value, |
| 528 is_ptr=False): |
| 529 """Generates code to populate a variable |dst_var| of type |type_| from a |
| 530 Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated |
| 531 code, if |dst_var| fails to be populated then Populate will return |
| 532 |failure_value|. |
| 469 """ | 533 """ |
| 470 c = Code() | 534 c = Code() |
| 471 c.Sblock('{') | 535 c.Sblock('{') |
| 472 | 536 |
| 473 if self._IsFundamentalOrFundamentalRef(prop): | 537 underlying_type = self._type_helper.FollowRef(type_) |
| 474 self._GenerateFundamentalOrFundamentalRefPopulate(c, prop, value_var, dst) | 538 |
| 475 elif self._IsObjectOrObjectRef(prop): | 539 if underlying_type.property_type.is_fundamental: |
| 476 self._GenerateObjectOrObjectRefPopulate(c, prop) | 540 if is_ptr: |
| 477 elif prop.type_ == PropertyType.FUNCTION: | 541 (c.Append('%(cpp_type)s temp;') |
| 478 self._GenerateFunctionPopulate(c, prop) | 542 .Append('if (!%s)' % cpp_util.GetAsFundamentalValue( |
| 479 elif prop.type_ == PropertyType.ANY: | 543 self._type_helper.FollowRef(type_), src_var, '&temp')) |
| 480 self._GenerateAnyPopulate(c, prop, value_var, dst) | 544 .Append(' return %(failure_value)s;') |
| 481 elif self._IsArrayOrArrayRef(prop): | 545 .Append('%(dst_var)s.reset(new %(cpp_type)s(temp));') |
| 482 self._GenerateArrayOrArrayRefPopulate(c, prop, dst) | 546 ) |
| 483 elif prop.type_ == PropertyType.CHOICES: | 547 else: |
| 484 self._GenerateChoicePopulate(c, prop, value_var, dst, failure_value) | 548 (c.Append('if (!%s)' % cpp_util.GetAsFundamentalValue( |
| 485 elif self._cpp_type_generator.IsEnumOrEnumRef(prop): | 549 self._type_helper.FollowRef(type_), |
| 486 self._GenerateEnumPopulate(c, prop, value_var) | 550 src_var, |
| 487 elif prop.type_ == PropertyType.BINARY: | 551 '&%s' % dst_var)) |
| 488 self._GenerateBinaryPopulate(c, prop) | 552 .Append(' return %(failure_value)s;') |
| 553 ) |
| 554 elif underlying_type.property_type == PropertyType.OBJECT: |
| 555 if is_ptr: |
| 556 (c.Append('const base::DictionaryValue* dictionary = NULL;') |
| 557 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))') |
| 558 .Append(' return %(failure_value)s;') |
| 559 .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') |
| 560 .Append('if (!%(cpp_type)s::Populate(*dictionary, temp.get()))') |
| 561 .Append(' return %(failure_value)s;') |
| 562 .Append('%(dst_var)s = temp.Pass();') |
| 563 ) |
| 564 else: |
| 565 (c.Append('const base::DictionaryValue* dictionary = NULL;') |
| 566 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))') |
| 567 .Append(' return %(failure_value)s;') |
| 568 .Append('if (!%(cpp_type)s::Populate(*dictionary, &%(dst_var)s))') |
| 569 .Append(' return %(failure_value)s;') |
| 570 ) |
| 571 elif underlying_type.property_type == PropertyType.FUNCTION: |
| 572 if is_ptr: |
| 573 c.Append('%(dst_var)s.reset(new base::DictionaryValue());') |
| 574 elif underlying_type.property_type == PropertyType.ANY: |
| 575 c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());') |
| 576 elif underlying_type.property_type == PropertyType.ARRAY: |
| 577 # util_cc_helper deals with optional and required arrays |
| 578 (c.Append('const base::ListValue* list = NULL;') |
| 579 .Append('if (!%(src_var)s->GetAsList(&list))') |
| 580 .Append(' return %(failure_value)s;')) |
| 581 item_type = underlying_type.item_type |
| 582 if item_type.property_type == PropertyType.ENUM: |
| 583 c.Concat(self._GenerateListValueToEnumArrayConversion( |
| 584 item_type, |
| 585 'list', |
| 586 dst_var, |
| 587 failure_value, |
| 588 is_ptr=is_ptr)) |
| 589 else: |
| 590 (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( |
| 591 underlying_type, |
| 592 'list', |
| 593 dst_var, |
| 594 is_ptr)) |
| 595 .Append(' return %(failure_value)s;') |
| 596 ) |
| 597 elif underlying_type.property_type == PropertyType.CHOICES: |
| 598 if is_ptr: |
| 599 (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') |
| 600 .Append('if (!%(cpp_type)s::Populate(*%(src_var)s, temp.get()))') |
| 601 .Append(' return %(failure_value)s;') |
| 602 .Append('%(dst_var)s = temp.Pass();') |
| 603 ) |
| 604 else: |
| 605 (c.Append('if (!%(cpp_type)s::Populate(*%(src_var)s, &%(dst_var)s))') |
| 606 .Append(' return %(failure_value)s;') |
| 607 ) |
| 608 elif underlying_type.property_type == PropertyType.ENUM: |
| 609 c.Concat(self._GenerateStringToEnumConversion(type_, |
| 610 src_var, |
| 611 dst_var, |
| 612 failure_value)) |
| 613 elif underlying_type.property_type == PropertyType.BINARY: |
| 614 (c.Append('if (!%(src_var)s->IsType(%(value_type)s))') |
| 615 .Append(' return %(failure_value)s;') |
| 616 .Append('const base::BinaryValue* binary_value =') |
| 617 .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);') |
| 618 ) |
| 619 if is_ptr: |
| 620 (c.Append('%(dst_var)s.reset(') |
| 621 .Append(' new std::string(binary_value->GetBuffer(),') |
| 622 .Append(' binary_value->GetSize()));') |
| 623 ) |
| 624 else: |
| 625 (c.Append('%(dst_var)s.assign(binary_value->GetBuffer(),') |
| 626 .Append(' binary_value->GetSize());') |
| 627 ) |
| 489 else: | 628 else: |
| 490 raise NotImplementedError(prop.type_) | 629 raise NotImplementedError(type_) |
| 491 c.Eblock('}') | 630 |
| 492 sub = { | 631 sub = { |
| 493 'value_var': value_var, | 632 'cpp_type': self._type_helper.GetCppType(type_), |
| 494 'name': prop.unix_name, | 633 'src_var': src_var, |
| 495 'dst': dst, | 634 'dst_var': dst_var, |
| 496 'failure_value': failure_value, | 635 'failure_value': failure_value, |
| 497 } | 636 } |
| 498 if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY): | 637 |
| 499 sub['ctype'] = self._cpp_type_generator.GetType(prop) | 638 if underlying_type.property_type not in (PropertyType.ANY, |
| 500 sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(prop) | 639 PropertyType.CHOICES): |
| 501 sub['value_type'] = cpp_util.GetValueType(self._cpp_type_generator | 640 sub['value_type'] = cpp_util.GetValueType(underlying_type) |
| 502 .GetReferencedProperty(prop).type_) | 641 |
| 503 c.Substitute(sub) | 642 return c.Eblock('}').Substitute(sub) |
| 504 return c | 643 |
| 505 | 644 def _GenerateListValueToEnumArrayConversion(self, |
| 506 def _GenerateFundamentalOrFundamentalRefPopulate(self, | 645 item_type, |
| 507 c, | 646 src_var, |
| 508 prop, | 647 dst_var, |
| 509 value_var, | 648 failure_value, |
| 510 dst): | 649 is_ptr=False): |
| 511 if prop.optional: | 650 """Returns Code that converts a ListValue of string constants from |
| 512 (c.Append('%(ctype)s temp;') | 651 |src_var| into an array of enums of |type_| in |dst_var|. On failure, |
| 513 .Append('if (!%s)' % | 652 returns |failure_value|. |
| 514 cpp_util.GetAsFundamentalValue( | 653 """ |
| 515 self._cpp_type_generator.GetReferencedProperty(prop), | 654 c = Code() |
| 516 value_var, | 655 accessor = '.' |
| 517 '&temp')) | 656 if is_ptr: |
| 518 .Append(' return %(failure_value)s;') | 657 accessor = '->' |
| 519 ) | 658 cpp_type = self._type_helper.GetCppType(item_type, is_in_container=True) |
| 520 if prop.type_ != prop.compiled_type: | 659 c.Append('%s.reset(new std::vector<%s>);' % |
| 521 (c.Append('%(compiled_ctype)s temp2;') | 660 (dst_var, cpp_util.PadForGenerics(cpp_type))) |
| 522 .Append('if (!%s)' % | 661 (c.Sblock('for (base::ListValue::const_iterator it = %s->begin(); ' |
| 523 cpp_util.GenerateTypeToCompiledTypeConversion( | 662 'it != %s->end(); ++it) {' % (src_var, src_var)) |
| 524 self._cpp_type_generator.GetReferencedProperty(prop), | 663 .Append('%s tmp;' % self._type_helper.GetCppType(item_type)) |
| 525 'temp', | 664 .Concat(self._GenerateStringToEnumConversion(item_type, |
| 526 'temp2')) | 665 '(*it)', |
| 527 .Append(' return %(failure_value)s;') | 666 'tmp', |
| 528 .Append('%(dst)s->%(name)s.reset(new %(compiled_ctype)s(temp2));') | 667 failure_value)) |
| 529 ) | 668 .Append('%s%spush_back(tmp);' % (dst_var, accessor)) |
| 530 else: | |
| 531 c.Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));') | |
| 532 | |
| 533 else: | |
| 534 if prop.type_ == prop.compiled_type: | |
| 535 assignment_target = '&%s->%s' % (dst, prop.unix_name) | |
| 536 else: | |
| 537 c.Append('%(ctype)s temp;') | |
| 538 assignment_target = '&temp' | |
| 539 (c.Append('if (!%s)' % | |
| 540 cpp_util.GetAsFundamentalValue( | |
| 541 self._cpp_type_generator.GetReferencedProperty(prop), | |
| 542 value_var, | |
| 543 assignment_target)) | |
| 544 .Append(' return %(failure_value)s;') | |
| 545 ) | |
| 546 if prop.type_ != prop.compiled_type: | |
| 547 (c.Append('if (!%s)' % | |
| 548 cpp_util.GenerateTypeToCompiledTypeConversion( | |
| 549 self._cpp_type_generator.GetReferencedProperty(prop), | |
| 550 'temp', | |
| 551 '%s->%s' % (dst, prop.unix_name))) | |
| 552 .Append(' return %(failure_value)s;') | |
| 553 ) | |
| 554 | |
| 555 def _GenerateObjectOrObjectRefPopulate(self, c, prop): | |
| 556 if prop.optional: | |
| 557 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
| 558 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | |
| 559 .Append(' return %(failure_value)s;') | |
| 560 .Append('scoped_ptr<%(ctype)s> temp(new %(ctype)s());') | |
| 561 .Append('if (!%(ctype)s::Populate(*dictionary, temp.get()))') | |
| 562 .Append(' return %(failure_value)s;') | |
| 563 .Append('%(dst)s->%(name)s = temp.Pass();') | |
| 564 ) | |
| 565 else: | |
| 566 (c.Append('const base::DictionaryValue* dictionary = NULL;') | |
| 567 .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') | |
| 568 .Append(' return %(failure_value)s;') | |
| 569 .Append( | |
| 570 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))') | |
| 571 .Append(' return %(failure_value)s;') | |
| 572 ) | |
| 573 | |
| 574 def _GenerateFunctionPopulate(self, c, prop): | |
| 575 if prop.optional: | |
| 576 c.Append('%(dst)s->%(name)s.reset(new base::DictionaryValue());') | |
| 577 | |
| 578 def _GenerateAnyPopulate(self, c, prop, value_var, dst): | |
| 579 if prop.optional: | |
| 580 c.Append('%(dst)s->%(name)s.reset(new ' + any_helper.ANY_CLASS + '());') | |
| 581 c.Append(self._any_helper.Init(prop, value_var, dst) + ';') | |
| 582 | |
| 583 def _GenerateArrayOrArrayRefPopulate(self, c, prop, dst): | |
| 584 # util_cc_helper deals with optional and required arrays | |
| 585 (c.Append('const base::ListValue* list = NULL;') | |
| 586 .Append('if (!%(value_var)s->GetAsList(&list))') | |
| 587 .Append(' return %(failure_value)s;')) | |
| 588 if prop.item_type.type_ == PropertyType.ENUM: | |
| 589 self._GenerateListValueToEnumArrayConversion(c, prop) | |
| 590 else: | |
| 591 (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( | |
| 592 self._cpp_type_generator.GetReferencedProperty(prop), 'list', | |
| 593 dst + '->' + prop.unix_name, prop.optional)) | |
| 594 .Append(' return %(failure_value)s;') | |
| 595 ) | |
| 596 | |
| 597 def _GenerateChoicePopulate(self, c, prop, value_var, dst, failure_value): | |
| 598 type_var = '%(dst)s->%(name)s_type' | |
| 599 c.Sblock('switch (%(value_var)s->GetType()) {') | |
| 600 for choice in self._cpp_type_generator.ExpandParams([prop]): | |
| 601 (c.Sblock('case %s: {' % cpp_util.GetValueType( | |
| 602 self._cpp_type_generator.GetReferencedProperty(choice).type_)) | |
| 603 .Concat(self._GeneratePopulatePropertyFromValue( | |
| 604 choice, value_var, dst, failure_value, check_type=False)) | |
| 605 .Append('%s = %s;' % | |
| 606 (type_var, | |
| 607 self._cpp_type_generator.GetEnumValue( | |
| 608 prop, choice.type_.name))) | |
| 609 .Append('break;') | |
| 610 .Eblock('}') | 669 .Eblock('}') |
| 611 ) | 670 ) |
| 612 (c.Append('default:') | 671 return c |
| 613 .Append(' return %(failure_value)s;') | 672 |
| 614 ) | 673 def _GenerateStringToEnumConversion(self, |
| 615 c.Eblock('}') | 674 type_, |
| 616 | 675 src_var, |
| 617 def _GenerateEnumPopulate(self, c, prop, value_var): | 676 dst_var, |
| 618 c.Sblock('{') | 677 failure_value): |
| 619 self._GenerateStringToEnumConversion(c, prop, value_var, 'enum_temp') | 678 """Returns Code that converts a string type in |src_var| to an enum with |
| 620 c.Append('%(dst)s->%(name)s = enum_temp;') | 679 type |type_| in |dst_var|. In the generated code, if |src_var| is not |
| 621 c.Eblock('}') | 680 a valid enum name then the function will return |failure_value|. |
| 622 | 681 """ |
| 623 def _GenerateBinaryPopulate(self, c, prop): | 682 c = Code() |
| 624 (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') | 683 enum_as_string = '%s_as_string' % type_.unix_name |
| 625 .Append(' return %(failure_value)s;') | 684 (c.Append('std::string %s;' % enum_as_string) |
| 626 .Append('const base::BinaryValue* binary_value =') | 685 .Append('if (!%s->GetAsString(&%s))' % (src_var, enum_as_string)) |
| 627 .Append(' static_cast<const base::BinaryValue*>(%(value_var)s);') | 686 .Append(' return %s;' % failure_value) |
| 628 ) | 687 .Append('%s = Parse%s(%s);' % (dst_var, |
| 629 if prop.optional: | 688 self._type_helper.GetCppType(type_), |
| 630 (c.Append('%(dst)s->%(name)s.reset(') | 689 enum_as_string)) |
| 631 .Append(' new std::string(binary_value->GetBuffer(),') | 690 .Append('if (%s == %s)' % (dst_var, |
| 632 .Append(' binary_value->GetSize()));') | 691 self._type_helper.GetEnumNoneValue(type_))) |
| 633 ) | 692 .Append(' return %s;' % failure_value) |
| 634 else: | 693 ) |
| 635 (c.Append('%(dst)s->%(name)s.assign(binary_value->GetBuffer(),') | 694 return c |
| 636 .Append(' binary_value->GetSize());') | 695 |
| 637 ) | 696 def _GeneratePropertyFunctions(self, namespace, params): |
| 638 | 697 """Generates the member functions for a list of parameters. |
| 639 def _GenerateListValueToEnumArrayConversion(self, c, prop): | 698 """ |
| 640 """Appends code that converts a ListValue of string contstants to | 699 return self._GenerateTypes(namespace, (param.type_ for param in params)) |
| 641 an array of enums in dst. | 700 |
| 642 Leaves dst, name, and failure_value unsubstituted. | 701 def _GenerateTypes(self, namespace, types): |
| 643 | 702 """Generates the member functions for a list of types. |
| 644 c: the Code object that is being appended to. | 703 """ |
| 645 prop: the property that the code is populating. | 704 c = Code() |
| 646 """ | 705 for type_ in types: |
| 647 accessor = '.' | 706 c.Cblock(self._GenerateType(namespace, type_)) |
| 648 if prop.optional: | 707 return c |
| 649 c.Append('%(dst)s->%(name)s.reset(new std::vector<' + ( | 708 |
| 650 self._cpp_type_generator.GetType(prop.item_type) + '>);')) | 709 def _GenerateEnumToString(self, cpp_namespace, type_): |
| 651 accessor = '->' | |
| 652 c.Sblock('for (ListValue::const_iterator it = list->begin(); ' | |
| 653 'it != list->end(); ++it) {') | |
| 654 self._GenerateStringToEnumConversion( | |
| 655 c, prop.item_type, '(*it)', 'enum_temp') | |
| 656 c.Append('%(dst)s->%(name)s' + accessor + 'push_back(enum_temp);') | |
| 657 c.Eblock('}') | |
| 658 | |
| 659 def _GenerateStringToEnumConversion(self, c, prop, value_var, enum_temp): | |
| 660 """Appends code that converts a string to an enum. | |
| 661 Leaves failure_value unsubstituted. | |
| 662 | |
| 663 c: the code that is appended to. | |
| 664 prop: the property that the code is populating. | |
| 665 value_var: the string value that is being converted. | |
| 666 enum_temp: the name used to store the temporary enum value. | |
| 667 """ | |
| 668 (c.Append('std::string enum_as_string;') | |
| 669 .Append('if (!%s->GetAsString(&enum_as_string))' % value_var) | |
| 670 .Append(' return %(failure_value)s;') | |
| 671 .Append('%(type)s %(enum)s = From%(type)sString(enum_as_string);' % { | |
| 672 'type': self._cpp_type_generator.GetCompiledType(prop), | |
| 673 'enum': enum_temp | |
| 674 }) | |
| 675 .Append('if (%s == %s)' % | |
| 676 (enum_temp, self._cpp_type_generator.GetEnumNoneValue(prop))) | |
| 677 .Append(' return %(failure_value)s;')) | |
| 678 | |
| 679 def _GeneratePropertyFunctions(self, param_namespace, params): | |
| 680 """Generate the functions for structures generated by a property such as | |
| 681 CreateEnumValue for ENUMs and Populate/ToValue for Params/Results objects. | |
| 682 """ | |
| 683 c = Code() | |
| 684 for param in params: | |
| 685 if param.type_ == PropertyType.OBJECT: | |
| 686 c.Concat(self._GenerateType( | |
| 687 param_namespace + '::' + cpp_util.Classname(param.name), | |
| 688 param)) | |
| 689 c.Append() | |
| 690 elif param.type_ == PropertyType.ARRAY: | |
| 691 c.Concat(self._GeneratePropertyFunctions( | |
| 692 param_namespace, [param.item_type])) | |
| 693 elif param.type_ == PropertyType.CHOICES: | |
| 694 c.Concat(self._GeneratePropertyFunctions( | |
| 695 param_namespace, param.choices.values())) | |
| 696 if param.from_client: | |
| 697 c.Concat(self._GenerateGetChoiceValue(param_namespace, param)) | |
| 698 elif param.type_ == PropertyType.ENUM: | |
| 699 (c.Concat(self._GenerateCreateEnumValue(param_namespace, param)) | |
| 700 .Append() | |
| 701 .Concat(self._GenerateEnumFromString(param_namespace, | |
| 702 param, | |
| 703 use_namespace=True)) | |
| 704 .Append() | |
| 705 .Concat(self._GenerateEnumToString(param_namespace, | |
| 706 param, | |
| 707 use_namespace=True)) | |
| 708 .Append()) | |
| 709 return c | |
| 710 | |
| 711 def _GenerateGetChoiceValue(self, cpp_namespace, prop): | |
| 712 """Generates Get<Type>ChoiceValue() that returns a scoped_ptr<base::Value> | |
| 713 representing the choice value. | |
| 714 """ | |
| 715 c = Code() | |
| 716 (c.Sblock('scoped_ptr<base::Value> ' | |
| 717 '%(cpp_namespace)s::Get%(choice)sChoiceValue() const {') | |
| 718 .Sblock('switch (%s_type) {' % prop.unix_name) | |
| 719 .Concat(self._GenerateReturnCase( | |
| 720 self._cpp_type_generator.GetEnumNoneValue(prop), | |
| 721 'scoped_ptr<base::Value>()'))) | |
| 722 for choice in self._cpp_type_generator.ExpandParams([prop]): | |
| 723 c.Concat(self._GenerateReturnCase( | |
| 724 self._cpp_type_generator.GetEnumValue(prop, choice.type_.name), | |
| 725 'make_scoped_ptr<base::Value>(%s)' % | |
| 726 self._CreateValueFromProperty(choice, choice.unix_name))) | |
| 727 (c.Eblock('}') | |
| 728 .Append('return scoped_ptr<base::Value>();') | |
| 729 .Eblock('}') | |
| 730 .Append() | |
| 731 .Substitute({ | |
| 732 'cpp_namespace': cpp_namespace, | |
| 733 'choice': cpp_util.Classname(prop.name) | |
| 734 }) | |
| 735 ) | |
| 736 return c | |
| 737 | |
| 738 def _GenerateCreateEnumTypeValue(self, cpp_namespace, prop): | |
| 739 """Generates CreateEnumValue() that returns the base::StringValue | |
| 740 representation of an enum type. | |
| 741 """ | |
| 742 c = Code() | |
| 743 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | |
| 744 (c.Sblock('scoped_ptr<base::Value> CreateEnumValue(%s %s) {' % | |
| 745 (classname, classname.lower())) | |
| 746 .Append('std::string enum_temp = ToString(%s);' % classname.lower()) | |
| 747 .Append('if (enum_temp.empty())') | |
| 748 .Append(' return scoped_ptr<base::Value>();') | |
| 749 .Append('return scoped_ptr<base::Value>(' | |
| 750 'base::Value::CreateStringValue(enum_temp));') | |
| 751 .Eblock('}')) | |
| 752 return c | |
| 753 | |
| 754 def _GenerateEnumToString(self, cpp_namespace, prop, use_namespace=False): | |
| 755 """Generates ToString() which gets the string representation of an enum. | 710 """Generates ToString() which gets the string representation of an enum. |
| 756 """ | 711 """ |
| 757 c = Code() | 712 c = Code() |
| 758 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | 713 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 759 if use_namespace: | 714 |
| 760 namespace = '%s::' % cpp_namespace | 715 if cpp_namespace is not None: |
| 761 else: | 716 c.Append('// static') |
| 762 namespace = '' | 717 maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace |
| 763 | 718 |
| 764 (c.Append('// static') | 719 c.Sblock('std::string %sToString(%s enum_param) {' % |
| 765 .Sblock('std::string %(namespace)sToString(%(class)s enum_param) {')) | 720 (maybe_namespace, classname)) |
| 766 enum_prop = self._cpp_type_generator.GetReferencedProperty(prop) | |
| 767 c.Sblock('switch (enum_param) {') | 721 c.Sblock('switch (enum_param) {') |
| 768 for enum_value in enum_prop.enum_values: | 722 for enum_value in self._type_helper.FollowRef(type_).enum_values: |
| 769 c.Concat(self._GenerateReturnCase( | 723 (c.Append('case %s: ' % self._type_helper.GetEnumValue(type_, enum_value)) |
| 770 self._cpp_type_generator.GetEnumValue(prop, enum_value), | 724 .Append(' return "%s";' % enum_value)) |
| 771 '"%s"' % enum_value)) | 725 (c.Append('case %s:' % self._type_helper.GetEnumNoneValue(type_)) |
| 772 (c.Append('case %s:' % self._cpp_type_generator.GetEnumNoneValue(prop)) | |
| 773 .Append(' return "";') | 726 .Append(' return "";') |
| 774 .Eblock('}') | 727 .Eblock('}') |
| 728 .Append('NOTREACHED();') |
| 775 .Append('return "";') | 729 .Append('return "";') |
| 776 .Eblock('}') | 730 .Eblock('}') |
| 777 .Substitute({ | 731 ) |
| 778 'namespace': namespace, | 732 return c |
| 779 'class': classname | 733 |
| 780 })) | 734 def _GenerateEnumFromString(self, cpp_namespace, type_): |
| 781 return c | |
| 782 | |
| 783 def _GenerateEnumFromString(self, cpp_namespace, prop, use_namespace=False): | |
| 784 """Generates FromClassNameString() which gets an enum from its string | 735 """Generates FromClassNameString() which gets an enum from its string |
| 785 representation. | 736 representation. |
| 786 """ | 737 """ |
| 787 c = Code() | 738 c = Code() |
| 788 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name)) | 739 classname = cpp_util.Classname(schema_util.StripSchemaNamespace(type_.name)) |
| 789 if use_namespace: | 740 |
| 790 namespace = '%s::' % cpp_namespace | 741 if cpp_namespace is not None: |
| 791 else: | 742 c.Append('// static') |
| 792 namespace = '' | 743 maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace |
| 793 | 744 |
| 794 (c.Append('// static') | 745 c.Sblock('%s%s %sParse%s(const std::string& enum_string) {' % |
| 795 .Sblock('%(namespace)s%(class)s' | 746 (maybe_namespace, classname, maybe_namespace, classname)) |
| 796 ' %(namespace)sFrom%(class)sString(' | |
| 797 'const std::string& enum_string) {')) | |
| 798 enum_prop = self._cpp_type_generator.GetReferencedProperty(prop) | |
| 799 for i, enum_value in enumerate( | 747 for i, enum_value in enumerate( |
| 800 self._cpp_type_generator.GetReferencedProperty(prop).enum_values): | 748 self._type_helper.FollowRef(type_).enum_values): |
| 801 # This is broken up into all ifs with no else ifs because we get | 749 # This is broken up into all ifs with no else ifs because we get |
| 802 # "fatal error C1061: compiler limit : blocks nested too deeply" | 750 # "fatal error C1061: compiler limit : blocks nested too deeply" |
| 803 # on Windows. | 751 # on Windows. |
| 804 (c.Append('if (enum_string == "%s")' % enum_value) | 752 (c.Append('if (enum_string == "%s")' % enum_value) |
| 805 .Append(' return %s;' % | 753 .Append(' return %s;' % |
| 806 self._cpp_type_generator.GetEnumValue(prop, enum_value))) | 754 self._type_helper.GetEnumValue(type_, enum_value))) |
| 807 (c.Append('return %s;' % | 755 (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_)) |
| 808 self._cpp_type_generator.GetEnumNoneValue(prop)) | |
| 809 .Eblock('}') | 756 .Eblock('}') |
| 810 .Substitute({ | 757 ) |
| 811 'namespace': namespace, | 758 return c |
| 812 'class': classname | 759 |
| 813 })) | 760 def _GenerateCreateCallbackArguments(self, function_scope, callback): |
| 814 return c | |
| 815 | |
| 816 # TODO(chebert): This is basically the same as GenerateCreateEnumTypeValue(). | |
| 817 # The plan is to phase out the old-style enums, and make all enums into REF | |
| 818 # types. | |
| 819 def _GenerateCreateEnumValue(self, cpp_namespace, prop): | |
| 820 """Generates CreateEnumValue() that returns the base::StringValue | |
| 821 representation of an enum. | |
| 822 """ | |
| 823 c = Code() | |
| 824 (c.Append('// static') | |
| 825 .Sblock('scoped_ptr<base::Value> %(cpp_namespace)s::CreateEnumValue(' | |
| 826 '%(arg)s) {') | |
| 827 .Append('std::string enum_temp = ToString(%s);' % prop.unix_name) | |
| 828 .Append('if (enum_temp.empty())') | |
| 829 .Append(' return scoped_ptr<base::Value>();') | |
| 830 .Append('return scoped_ptr<base::Value>(' | |
| 831 'base::Value::CreateStringValue(enum_temp));') | |
| 832 .Eblock('}') | |
| 833 .Substitute({ | |
| 834 'cpp_namespace': cpp_namespace, | |
| 835 'arg': cpp_util.GetParameterDeclaration( | |
| 836 prop, self._cpp_type_generator.GetType(prop)) | |
| 837 })) | |
| 838 return c | |
| 839 | |
| 840 def _GenerateReturnCase(self, case_value, return_value): | |
| 841 """Generates a single return case for a switch block. | |
| 842 """ | |
| 843 c = Code() | |
| 844 (c.Append('case %s:' % case_value) | |
| 845 .Append(' return %s;' % return_value) | |
| 846 ) | |
| 847 return c | |
| 848 | |
| 849 def _GenerateCreateCallbackArguments(self, | |
| 850 function_scope, | |
| 851 callback, | |
| 852 generate_to_json=False): | |
| 853 """Generate all functions to create Value parameters for a callback. | 761 """Generate all functions to create Value parameters for a callback. |
| 854 | 762 |
| 855 E.g for function "Bar", generate Bar::Results::Create | 763 E.g for function "Bar", generate Bar::Results::Create |
| 856 E.g for event "Baz", generate Baz::Create | 764 E.g for event "Baz", generate Baz::Create |
| 857 | 765 |
| 858 function_scope: the function scope path, e.g. Foo::Bar for the function | 766 function_scope: the function scope path, e.g. Foo::Bar for the function |
| 859 Foo::Bar::Baz(). | 767 Foo::Bar::Baz(). May be None if there is no function scope. |
| 860 callback: the Function object we are creating callback arguments for. | 768 callback: the Function object we are creating callback arguments for. |
| 861 generate_to_json: Generate a ToJson method. | |
| 862 """ | 769 """ |
| 863 c = Code() | 770 c = Code() |
| 864 params = callback.params | 771 params = callback.params |
| 865 expanded_params = self._cpp_type_generator.ExpandParams(params) | 772 c.Concat(self._GeneratePropertyFunctions(function_scope, params)) |
| 866 c.Concat(self._GeneratePropertyFunctions(function_scope, expanded_params)) | 773 |
| 867 | 774 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s' |
| 868 param_lists = self._cpp_type_generator.GetAllPossibleParameterLists(params) | 775 'Create(%(declaration_list)s) {') |
| 869 for param_list in param_lists: | 776 .Append('scoped_ptr<base::ListValue> create_results(' |
| 870 (c.Sblock('scoped_ptr<base::ListValue> %(function_scope)s::' | 777 'new base::ListValue());') |
| 871 'Create(%(declaration_list)s) {') | 778 ) |
| 872 .Append('scoped_ptr<base::ListValue> create_results(' | 779 declaration_list = [] |
| 873 'new base::ListValue());') | 780 for param in params: |
| 874 ) | 781 declaration_list.append(cpp_util.GetParameterDeclaration( |
| 875 declaration_list = [] | 782 param, self._type_helper.GetCppType(param.type_))) |
| 876 for param in param_list: | 783 c.Append('create_results->Append(%s);' % |
| 877 # We treat this argument as 'required' to avoid wrapping it in a | 784 self._CreateValueFromType(param.type_, param.unix_name)) |
| 878 # scoped_ptr if it's optional. | 785 c.Append('return create_results.Pass();') |
| 879 param_copy = param.Copy() | 786 c.Eblock('}') |
| 880 param_copy.optional = False | 787 c.Substitute({ |
| 881 declaration_list.append("const %s" % cpp_util.GetParameterDeclaration( | 788 'function_scope': ('%s::' % function_scope) if function_scope else '', |
| 882 param_copy, self._cpp_type_generator.GetCompiledType(param_copy))) | 789 'declaration_list': ', '.join(declaration_list), |
| 883 param_name = param_copy.unix_name | 790 'param_names': ', '.join(param.unix_name for param in params) |
| 884 if param_copy.type_ != param_copy.compiled_type: | 791 }) |
| 885 param_name = 'temp_' + param_name | |
| 886 (c.Append('%s %s;' % (self._cpp_type_generator.GetType(param_copy), | |
| 887 param_name)) | |
| 888 .Append(cpp_util.GenerateCompiledTypeToTypeConversion( | |
| 889 param_copy, | |
| 890 param_copy.unix_name, | |
| 891 param_name) + ';') | |
| 892 ) | |
| 893 c.Append('create_results->Append(%s);' % | |
| 894 self._CreateValueFromProperty(param_copy, param_name)) | |
| 895 | |
| 896 c.Append('return create_results.Pass();') | |
| 897 c.Eblock('}') | |
| 898 if generate_to_json: | |
| 899 c.Append() | |
| 900 (c.Sblock('std::string %(function_scope)s::' | |
| 901 'ToJson(%(declaration_list)s) {') | |
| 902 .Append('scoped_ptr<base::ListValue> create_results = ' | |
| 903 '%(function_scope)s::Create(%(param_list)s);') | |
| 904 .Append('std::string json;') | |
| 905 .Append('base::JSONWriter::Write(create_results.get(), &json);') | |
| 906 .Append('return json;') | |
| 907 ) | |
| 908 c.Eblock('}') | |
| 909 | |
| 910 c.Substitute({ | |
| 911 'function_scope': function_scope, | |
| 912 'declaration_list': ', '.join(declaration_list), | |
| 913 'param_list': ', '.join(param.unix_name for param in param_list) | |
| 914 }) | |
| 915 | |
| 916 return c | 792 return c |
| 917 | 793 |
| 918 def _InitializePropertyToDefault(self, prop, dst): | 794 def _InitializePropertyToDefault(self, prop, dst): |
| 919 """Initialize a model.Property to its default value inside an object. | 795 """Initialize a model.Property to its default value inside an object. |
| 920 | 796 |
| 921 E.g for optional enum "state", generate dst->state = STATE_NONE; | 797 E.g for optional enum "state", generate dst->state = STATE_NONE; |
| 922 | 798 |
| 923 dst: Type* | 799 dst: Type* |
| 924 """ | 800 """ |
| 925 c = Code() | 801 c = Code() |
| 926 if (self._cpp_type_generator.IsEnumOrEnumRef(prop) or | 802 underlying_type = self._type_helper.FollowRef(prop.type_) |
| 927 prop.type_ == PropertyType.CHOICES): | 803 if (underlying_type.property_type == PropertyType.ENUM and |
| 928 if prop.optional: | 804 prop.optional): |
| 929 prop_name = prop.unix_name | 805 c.Append('%s->%s = %s;' % ( |
| 930 if prop.type_ == PropertyType.CHOICES: | 806 dst, |
| 931 prop_name = prop.unix_name + '_type' | 807 prop.unix_name, |
| 932 c.Append('%s->%s = %s;' % ( | 808 self._type_helper.GetEnumNoneValue(prop.type_))) |
| 933 dst, | |
| 934 prop_name, | |
| 935 self._cpp_type_generator.GetEnumNoneValue(prop))) | |
| 936 return c | 809 return c |
| 937 | |
| 938 def _IsObjectOrObjectRef(self, prop): | |
| 939 """Determines if this property is an Object or is a ref to an Object. | |
| 940 """ | |
| 941 return (self._cpp_type_generator.GetReferencedProperty(prop).type_ == | |
| 942 PropertyType.OBJECT) | |
| 943 | |
| 944 def _IsArrayOrArrayRef(self, prop): | |
| 945 """Determines if this property is an Array or is a ref to an Array. | |
| 946 """ | |
| 947 return (self._cpp_type_generator.GetReferencedProperty(prop).type_ == | |
| 948 PropertyType.ARRAY) | |
| 949 | |
| 950 def _IsFundamentalOrFundamentalRef(self, prop): | |
| 951 """Determines if this property is a Fundamental type or is a ref to a | |
| 952 Fundamental type. | |
| 953 """ | |
| 954 return (self._cpp_type_generator.GetReferencedProperty(prop).type_. | |
| 955 is_fundamental) | |
| OLD | NEW |