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.
6 from model
import PropertyType
, Type
13 class CCGenerator(object):
14 def __init__(self
, type_generator
, cpp_namespace
):
15 self
._type
_generator
= type_generator
16 self
._cpp
_namespace
= cpp_namespace
18 def Generate(self
, namespace
):
19 return _Generator(namespace
,
21 self
._cpp
_namespace
).Generate()
23 class _Generator(object):
24 """A .cc generator for a namespace.
26 def __init__(self
, namespace
, cpp_type_generator
, cpp_namespace
):
27 self
._namespace
= namespace
28 self
._type
_helper
= cpp_type_generator
29 self
._cpp
_namespace
= cpp_namespace
30 self
._target
_namespace
= (
31 self
._type
_helper
.GetCppNamespaceName(self
._namespace
))
32 self
._util
_cc
_helper
= (
33 util_cc_helper
.UtilCCHelper(self
._type
_helper
))
36 """Generates a Code object with the .cc for a single namespace.
39 (c
.Append(cpp_util
.CHROMIUM_LICENSE
)
41 .Append(cpp_util
.GENERATED_FILE_MESSAGE
% self
._namespace
.source_file
)
43 .Append(self
._util
_cc
_helper
.GetIncludePath())
44 .Append('#include "base/logging.h"')
45 .Append('#include "base/string_number_conversions.h"')
46 .Append('#include "%s/%s.h"' %
47 (self
._namespace
.source_file_dir
, self
._namespace
.unix_name
))
48 .Cblock(self
._type
_helper
.GenerateIncludes(include_soft
=True))
50 .Concat(cpp_util
.OpenNamespace(self
._cpp
_namespace
))
51 .Cblock(self
._type
_helper
.GetNamespaceStart())
53 if self
._namespace
.properties
:
55 .Append('// Properties')
59 for property in self
._namespace
.properties
.values():
60 property_code
= self
._type
_helper
.GeneratePropertyValues(
62 'const %(type)s %(name)s = %(value)s;',
65 c
.Cblock(property_code
)
66 if self
._namespace
.types
:
71 .Cblock(self
._GenerateTypes
(None, self
._namespace
.types
.values()))
73 if self
._namespace
.functions
:
75 .Append('// Functions')
79 for function
in self
._namespace
.functions
.values():
80 c
.Cblock(self
._GenerateFunction
(function
))
81 if self
._namespace
.events
:
87 for event
in self
._namespace
.events
.values():
88 c
.Cblock(self
._GenerateEvent
(event
))
89 (c
.Concat(self
._type
_helper
.GetNamespaceEnd())
90 .Cblock(cpp_util
.CloseNamespace(self
._cpp
_namespace
))
94 def _GenerateType(self
, cpp_namespace
, type_
):
95 """Generates the function definitions for a type.
97 classname
= cpp_util
.Classname(schema_util
.StripNamespace(type_
.name
))
101 # Wrap functions within types in the type's namespace.
102 (c
.Append('namespace %s {' % classname
)
104 for function
in type_
.functions
.values():
105 c
.Cblock(self
._GenerateFunction
(function
))
106 c
.Append('} // namespace %s' % classname
)
107 elif type_
.property_type
== PropertyType
.ARRAY
:
108 c
.Cblock(self
._GenerateType
(cpp_namespace
, type_
.item_type
))
109 elif (type_
.property_type
== PropertyType
.OBJECT
or
110 type_
.property_type
== PropertyType
.CHOICES
):
111 if cpp_namespace
is None:
112 classname_in_namespace
= classname
114 classname_in_namespace
= '%s::%s' % (cpp_namespace
, classname
)
116 if type_
.property_type
== PropertyType
.OBJECT
:
117 c
.Cblock(self
._GeneratePropertyFunctions
(classname_in_namespace
,
118 type_
.properties
.values()))
120 c
.Cblock(self
._GenerateTypes
(classname_in_namespace
, type_
.choices
))
122 (c
.Append('%s::%s()' % (classname_in_namespace
, classname
))
123 .Cblock(self
._GenerateInitializersAndBody
(type_
))
124 .Append('%s::~%s() {}' % (classname_in_namespace
, classname
))
127 if type_
.origin
.from_json
:
128 c
.Cblock(self
._GenerateTypePopulate
(classname_in_namespace
, type_
))
129 if cpp_namespace
is None: # only generate for top-level types
130 c
.Cblock(self
._GenerateTypeFromValue
(classname_in_namespace
, type_
))
131 if type_
.origin
.from_client
:
132 c
.Cblock(self
._GenerateTypeToValue
(classname_in_namespace
, type_
))
133 elif type_
.property_type
== PropertyType
.ENUM
:
134 (c
.Cblock(self
._GenerateEnumToString
(cpp_namespace
, type_
))
135 .Cblock(self
._GenerateEnumFromString
(cpp_namespace
, type_
))
140 def _GenerateInitializersAndBody(self
, type_
):
142 for prop
in type_
.properties
.values():
147 if t
.property_type
== PropertyType
.INTEGER
:
148 items
.append('%s(0)' % prop
.unix_name
)
149 elif t
.property_type
== PropertyType
.DOUBLE
:
150 items
.append('%s(0.0)' % prop
.unix_name
)
151 elif t
.property_type
== PropertyType
.BOOLEAN
:
152 items
.append('%s(false)' % prop
.unix_name
)
153 elif t
.property_type
== PropertyType
.BINARY
:
154 items
.append('%s(NULL)' % prop
.unix_name
)
155 elif (t
.property_type
== PropertyType
.ANY
or
156 t
.property_type
== PropertyType
.ARRAY
or
157 t
.property_type
== PropertyType
.CHOICES
or
158 t
.property_type
== PropertyType
.ENUM
or
159 t
.property_type
== PropertyType
.OBJECT
or
160 t
.property_type
== PropertyType
.FUNCTION
or
161 t
.property_type
== PropertyType
.REF
or
162 t
.property_type
== PropertyType
.STRING
):
163 # TODO(miket): It would be nice to initialize CHOICES and ENUM, but we
164 # don't presently have the semantics to indicate which one of a set
165 # should be the default.
171 s
= ': %s' % (', '.join(items
))
175 return Code().Append(s
)
177 def _GenerateTypePopulate(self
, cpp_namespace
, type_
):
178 """Generates the function for populating a type given a pointer to it.
180 E.g for type "Foo", generates Foo::Populate()
182 classname
= cpp_util
.Classname(schema_util
.StripNamespace(type_
.name
))
184 (c
.Append('// static')
185 .Append('bool %(namespace)s::Populate(')
186 .Sblock(' const base::Value& value, %(name)s* out) {')
188 if type_
.property_type
== PropertyType
.CHOICES
:
189 for choice
in type_
.choices
:
190 value_type
= cpp_util
.GetValueType(self
._type
_helper
.FollowRef(choice
))
191 (c
.Sblock('if (value.IsType(%s)) {' % value_type
)
192 .Concat(self
._GeneratePopulateVariableFromValue
(
195 'out->as_%s' % choice
.unix_name
,
198 .Append('return true;')
201 c
.Append('return false;')
202 elif type_
.property_type
== PropertyType
.OBJECT
:
203 (c
.Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))')
204 .Append(' return false;')
206 if type_
.properties
or type_
.additional_properties
is not None:
207 c
.Append('const base::DictionaryValue* dict = '
208 'static_cast<const base::DictionaryValue*>(&value);')
209 for prop
in type_
.properties
.values():
210 c
.Concat(self
._InitializePropertyToDefault
(prop
, 'out'))
211 for prop
in type_
.properties
.values():
212 c
.Concat(self
._GenerateTypePopulateProperty
(prop
, 'dict', 'out'))
213 if type_
.additional_properties
is not None:
214 if type_
.additional_properties
.property_type
== PropertyType
.ANY
:
215 c
.Append('out->additional_properties.MergeDictionary(dict);')
217 cpp_type
= self
._type
_helper
.GetCppType(type_
.additional_properties
,
218 is_in_container
=True)
219 (c
.Append('for (base::DictionaryValue::Iterator it(*dict);')
220 .Sblock(' !it.IsAtEnd(); it.Advance()) {')
221 .Append('%s tmp;' % cpp_type
)
222 .Concat(self
._GeneratePopulateVariableFromValue
(
223 type_
.additional_properties
,
227 .Append('out->additional_properties[it.key()] = tmp;')
230 c
.Append('return true;')
232 .Substitute({'namespace': cpp_namespace
, 'name': classname
}))
235 def _GenerateTypePopulateProperty(self
, prop
, src
, dst
):
236 """Generate the code to populate a single property in a type.
238 src: base::DictionaryValue*
242 value_var
= prop
.unix_name
+ '_value'
243 c
.Append('const base::Value* %(value_var)s = NULL;')
246 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
247 .Concat(self
._GeneratePopulatePropertyFromValue
(
248 prop
, value_var
, dst
, 'false')))
249 underlying_type
= self
._type
_helper
.FollowRef(prop
.type_
)
250 if underlying_type
.property_type
== PropertyType
.ENUM
:
251 (c
.Append('} else {')
252 .Append('%%(dst)s->%%(name)s = %s;' %
253 self
._type
_helper
.GetEnumNoneValue(prop
.type_
)))
257 'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s))')
258 .Append(' return false;')
259 .Concat(self
._GeneratePopulatePropertyFromValue
(
260 prop
, value_var
, dst
, 'false'))
264 'value_var': value_var
,
268 'name': prop
.unix_name
272 def _GenerateTypeFromValue(self
, cpp_namespace
, type_
):
273 classname
= cpp_util
.Classname(schema_util
.StripNamespace(type_
.name
))
275 (c
.Append('// static')
276 .Append('scoped_ptr<%s> %s::FromValue(const base::Value& value) {' % (
277 classname
, cpp_namespace
))
278 .Append(' scoped_ptr<%s> out(new %s());' % (classname
, classname
))
279 .Append(' if (!Populate(value, out.get()))')
280 .Append(' return scoped_ptr<%s>();' % classname
)
281 .Append(' return out.Pass();')
286 def _GenerateTypeToValue(self
, cpp_namespace
, type_
):
287 """Generates a function that serializes the type into a base::Value.
288 E.g. for type "Foo" generates Foo::ToValue()
290 if type_
.property_type
== PropertyType
.OBJECT
:
291 return self
._GenerateObjectTypeToValue
(cpp_namespace
, type_
)
292 elif type_
.property_type
== PropertyType
.CHOICES
:
293 return self
._GenerateChoiceTypeToValue
(cpp_namespace
, type_
)
295 raise ValueError("Unsupported property type %s" % type_
.type_
)
297 def _GenerateObjectTypeToValue(self
, cpp_namespace
, type_
):
298 """Generates a function that serializes an object-representing type
299 into a base::DictionaryValue.
302 (c
.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' %
304 .Append('scoped_ptr<base::DictionaryValue> value('
305 'new base::DictionaryValue());')
309 for prop
in type_
.properties
.values():
311 # Optional enum values are generated with a NONE enum value.
312 underlying_type
= self
._type
_helper
.FollowRef(prop
.type_
)
313 if underlying_type
.property_type
== PropertyType
.ENUM
:
314 c
.Sblock('if (%s != %s) {' %
316 self
._type
_helper
.GetEnumNoneValue(prop
.type_
)))
318 c
.Sblock('if (%s.get()) {' % prop
.unix_name
)
320 # ANY is a base::Value which is abstract and cannot be a direct member, so
321 # it will always be a pointer.
322 is_ptr
= prop
.optional
or prop
.type_
.property_type
== PropertyType
.ANY
323 c
.Append('value->SetWithoutPathExpansion("%s", %s);' % (
325 self
._CreateValueFromType
(prop
.type_
,
326 'this->%s' % prop
.unix_name
,
332 if type_
.additional_properties
is not None:
333 if type_
.additional_properties
.property_type
== PropertyType
.ANY
:
334 c
.Append('value->MergeDictionary(&additional_properties);')
336 # Non-copyable types will be wrapped in a linked_ptr for inclusion in
337 # maps, so we need to unwrap them.
339 not self
._type
_helper
.IsCopyable(type_
.additional_properties
))
340 cpp_type
= self
._type
_helper
.GetCppType(type_
.additional_properties
,
341 is_in_container
=True)
342 (c
.Sblock('for (std::map<std::string, %s>::const_iterator it =' %
343 cpp_util
.PadForGenerics(cpp_type
))
344 .Append(' additional_properties.begin();')
345 .Append(' it != additional_properties.end(); ++it) {')
346 .Append('value->SetWithoutPathExpansion(it->first, %s);' %
347 self
._CreateValueFromType
(
348 type_
.additional_properties
,
349 '%sit->second' % ('*' if needs_unwrap
else '')))
354 .Append('return value.Pass();')
357 def _GenerateChoiceTypeToValue(self
, cpp_namespace
, type_
):
358 """Generates a function that serializes a choice-representing type
362 c
.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace
)
363 c
.Append('scoped_ptr<base::Value> result;');
364 for choice
in type_
.choices
:
365 choice_var
= 'as_%s' % choice
.unix_name
366 (c
.Sblock('if (%s) {' % choice_var
)
367 .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' %
369 .Append('result.reset(%s);' %
370 self
._CreateValueFromType
(choice
, '*%s' % choice_var
))
373 (c
.Append('DCHECK(result) << "Must set at least one choice for %s";' %
375 .Append('return result.Pass();')
380 def _GenerateFunction(self
, function
):
381 """Generates the definitions for function structs.
385 # TODO(kalman): use function.unix_name not Classname.
386 function_namespace
= cpp_util
.Classname(function
.name
)
387 """Windows has a #define for SendMessage, so to avoid any issues, we need
390 if function_namespace
== 'SendMessage':
391 function_namespace
= 'PassMessage'
392 (c
.Append('namespace %s {' % function_namespace
)
396 # Params::Populate function
398 c
.Concat(self
._GeneratePropertyFunctions
('Params', function
.params
))
399 (c
.Append('Params::Params() {}')
400 .Append('Params::~Params() {}')
402 .Cblock(self
._GenerateFunctionParamsCreate
(function
))
405 # Results::Create function
406 if function
.callback
:
407 c
.Concat(self
._GenerateCreateCallbackArguments
('Results',
410 c
.Append('} // namespace %s' % function_namespace
)
413 def _GenerateEvent(self
, event
):
414 # TODO(kalman): use event.unix_name not Classname.
416 event_namespace
= cpp_util
.Classname(event
.name
)
417 (c
.Append('namespace %s {' % event_namespace
)
419 .Cblock(self
._GenerateCreateCallbackArguments
(None, event
))
420 .Append('} // namespace %s' % event_namespace
)
424 def _CreateValueFromType(self
, type_
, var
, is_ptr
=False):
425 """Creates a base::Value given a type. Generated code passes ownership
428 var: variable or variable*
430 E.g for std::string, generate base::Value::CreateStringValue(var)
432 underlying_type
= self
._type
_helper
.FollowRef(type_
)
433 if (underlying_type
.property_type
== PropertyType
.CHOICES
or
434 underlying_type
.property_type
== PropertyType
.OBJECT
):
436 return '(%s)->ToValue().release()' % var
438 return '(%s).ToValue().release()' % var
439 elif (underlying_type
.property_type
== PropertyType
.ANY
or
440 underlying_type
.property_type
== PropertyType
.FUNCTION
):
442 vardot
= '(%s)->' % var
444 vardot
= '(%s).' % var
445 return '%sDeepCopy()' % vardot
446 elif underlying_type
.property_type
== PropertyType
.ENUM
:
447 return 'base::Value::CreateStringValue(ToString(%s))' % var
448 elif underlying_type
.property_type
== PropertyType
.BINARY
:
453 return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' %
455 elif underlying_type
.property_type
== PropertyType
.ARRAY
:
456 return '%s.release()' % self
._util
_cc
_helper
.CreateValueFromArray(
460 elif underlying_type
.property_type
.is_fundamental
:
463 if underlying_type
.property_type
== PropertyType
.STRING
:
464 return 'new base::StringValue(%s)' % var
466 return 'new base::FundamentalValue(%s)' % var
468 raise NotImplementedError('Conversion of %s to base::Value not '
469 'implemented' % repr(type_
.type_
))
471 def _GenerateParamsCheck(self
, function
, var
):
472 """Generates a check for the correct number of arguments when creating
477 for param
in function
.params
:
478 if not param
.optional
:
480 if num_required
== len(function
.params
):
481 c
.Append('if (%(var)s.GetSize() != %(total)d)')
482 elif not num_required
:
483 c
.Append('if (%(var)s.GetSize() > %(total)d)')
485 c
.Append('if (%(var)s.GetSize() < %(required)d'
486 ' || %(var)s.GetSize() > %(total)d)')
487 c
.Append(' return scoped_ptr<Params>();')
490 'required': num_required
,
491 'total': len(function
.params
),
495 def _GenerateFunctionParamsCreate(self
, function
):
496 """Generate function to create an instance of Params. The generated
497 function takes a base::ListValue of arguments.
499 E.g for function "Bar", generate Bar::Params::Create()
502 (c
.Append('// static')
503 .Sblock('scoped_ptr<Params> '
504 'Params::Create(const base::ListValue& args) {')
505 .Concat(self
._GenerateParamsCheck
(function
, 'args'))
506 .Append('scoped_ptr<Params> params(new Params());')
509 for param
in function
.params
:
510 c
.Concat(self
._InitializePropertyToDefault
(param
, 'params'))
512 for i
, param
in enumerate(function
.params
):
513 # Any failure will cause this function to return. If any argument is
514 # incorrect or missing, those following it are not processed. Note that
515 # for optional arguments, we allow missing arguments and proceed because
516 # there may be other arguments following it.
517 failure_value
= 'scoped_ptr<Params>()'
519 value_var
= param
.unix_name
+ '_value'
520 (c
.Append('const base::Value* %(value_var)s = NULL;')
521 .Append('if (args.Get(%(i)s, &%(value_var)s) &&')
522 .Sblock(' !%(value_var)s->IsType(base::Value::TYPE_NULL)) {')
523 .Concat(self
._GeneratePopulatePropertyFromValue
(
524 param
, value_var
, 'params', failure_value
))
527 if not param
.optional
:
529 .Append('return %s;' % failure_value
)
532 c
.Substitute({'value_var': value_var
, 'i': i
})
534 .Append('return params.Pass();')
541 def _GeneratePopulatePropertyFromValue(self
,
546 """Generates code to populate property |prop| of |dst_class_var| (a
547 pointer) from a Value*. See |_GeneratePopulateVariableFromValue| for
550 return self
._GeneratePopulateVariableFromValue
(prop
.type_
,
552 '%s->%s' % (dst_class_var
,
555 is_ptr
=prop
.optional
)
557 def _GeneratePopulateVariableFromValue(self
,
563 """Generates code to populate a variable |dst_var| of type |type_| from a
564 Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated
565 code, if |dst_var| fails to be populated then Populate will return
571 underlying_type
= self
._type
_helper
.FollowRef(type_
)
573 if underlying_type
.property_type
.is_fundamental
:
575 (c
.Append('%(cpp_type)s temp;')
576 .Append('if (!%s)' % cpp_util
.GetAsFundamentalValue(
577 self
._type
_helper
.FollowRef(type_
), src_var
, '&temp'))
578 .Append(' return %(failure_value)s;')
579 .Append('%(dst_var)s.reset(new %(cpp_type)s(temp));')
582 (c
.Append('if (!%s)' % cpp_util
.GetAsFundamentalValue(
583 self
._type
_helper
.FollowRef(type_
),
586 .Append(' return %(failure_value)s;')
588 elif underlying_type
.property_type
== PropertyType
.OBJECT
:
590 (c
.Append('const base::DictionaryValue* dictionary = NULL;')
591 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))')
592 .Append(' return %(failure_value)s;')
593 .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
594 .Append('if (!%(cpp_type)s::Populate(*dictionary, temp.get()))')
595 .Append(' return %(failure_value)s;')
596 .Append('%(dst_var)s = temp.Pass();')
599 (c
.Append('const base::DictionaryValue* dictionary = NULL;')
600 .Append('if (!%(src_var)s->GetAsDictionary(&dictionary))')
601 .Append(' return %(failure_value)s;')
602 .Append('if (!%(cpp_type)s::Populate(*dictionary, &%(dst_var)s))')
603 .Append(' return %(failure_value)s;')
605 elif underlying_type
.property_type
== PropertyType
.FUNCTION
:
607 c
.Append('%(dst_var)s.reset(new base::DictionaryValue());')
608 elif underlying_type
.property_type
== PropertyType
.ANY
:
609 c
.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());')
610 elif underlying_type
.property_type
== PropertyType
.ARRAY
:
611 # util_cc_helper deals with optional and required arrays
612 (c
.Append('const base::ListValue* list = NULL;')
613 .Append('if (!%(src_var)s->GetAsList(&list))')
614 .Append(' return %(failure_value)s;'))
615 item_type
= underlying_type
.item_type
616 if item_type
.property_type
== PropertyType
.ENUM
:
617 c
.Concat(self
._GenerateListValueToEnumArrayConversion
(
624 (c
.Append('if (!%s)' % self
._util
_cc
_helper
.PopulateArrayFromList(
629 .Append(' return %(failure_value)s;')
631 elif underlying_type
.property_type
== PropertyType
.CHOICES
:
633 (c
.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
634 .Append('if (!%(cpp_type)s::Populate(*%(src_var)s, temp.get()))')
635 .Append(' return %(failure_value)s;')
636 .Append('%(dst_var)s = temp.Pass();')
639 (c
.Append('if (!%(cpp_type)s::Populate(*%(src_var)s, &%(dst_var)s))')
640 .Append(' return %(failure_value)s;')
642 elif underlying_type
.property_type
== PropertyType
.ENUM
:
643 c
.Concat(self
._GenerateStringToEnumConversion
(type_
,
647 elif underlying_type
.property_type
== PropertyType
.BINARY
:
648 (c
.Append('if (!%(src_var)s->IsType(%(value_type)s))')
649 .Append(' return %(failure_value)s;')
650 .Append('const base::BinaryValue* binary_value =')
651 .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);')
654 (c
.Append('%(dst_var)s.reset(')
655 .Append(' new std::string(binary_value->GetBuffer(),')
656 .Append(' binary_value->GetSize()));')
659 (c
.Append('%(dst_var)s.assign(binary_value->GetBuffer(),')
660 .Append(' binary_value->GetSize());')
663 raise NotImplementedError(type_
)
666 'cpp_type': self
._type
_helper
.GetCppType(type_
),
669 'failure_value': failure_value
,
672 if underlying_type
.property_type
not in (PropertyType
.ANY
,
673 PropertyType
.CHOICES
):
674 sub
['value_type'] = cpp_util
.GetValueType(underlying_type
)
676 return c
.Eblock('}').Substitute(sub
)
678 def _GenerateListValueToEnumArrayConversion(self
,
684 """Returns Code that converts a ListValue of string constants from
685 |src_var| into an array of enums of |type_| in |dst_var|. On failure,
686 returns |failure_value|.
692 cpp_type
= self
._type
_helper
.GetCppType(item_type
, is_in_container
=True)
693 c
.Append('%s.reset(new std::vector<%s>);' %
694 (dst_var
, cpp_util
.PadForGenerics(cpp_type
)))
695 (c
.Sblock('for (base::ListValue::const_iterator it = %s->begin(); '
696 'it != %s->end(); ++it) {' % (src_var
, src_var
))
697 .Append('%s tmp;' % self
._type
_helper
.GetCppType(item_type
))
698 .Concat(self
._GenerateStringToEnumConversion
(item_type
,
702 .Append('%s%spush_back(tmp);' % (dst_var
, accessor
))
707 def _GenerateStringToEnumConversion(self
,
712 """Returns Code that converts a string type in |src_var| to an enum with
713 type |type_| in |dst_var|. In the generated code, if |src_var| is not
714 a valid enum name then the function will return |failure_value|.
717 enum_as_string
= '%s_as_string' % type_
.unix_name
718 (c
.Append('std::string %s;' % enum_as_string
)
719 .Append('if (!%s->GetAsString(&%s))' % (src_var
, enum_as_string
))
720 .Append(' return %s;' % failure_value
)
721 .Append('%s = Parse%s(%s);' % (dst_var
,
722 self
._type
_helper
.GetCppType(type_
),
724 .Append('if (%s == %s)' % (dst_var
,
725 self
._type
_helper
.GetEnumNoneValue(type_
)))
726 .Append(' return %s;' % failure_value
)
730 def _GeneratePropertyFunctions(self
, namespace
, params
):
731 """Generates the member functions for a list of parameters.
733 return self
._GenerateTypes
(namespace
, (param
.type_
for param
in params
))
735 def _GenerateTypes(self
, namespace
, types
):
736 """Generates the member functions for a list of types.
740 c
.Cblock(self
._GenerateType
(namespace
, type_
))
743 def _GenerateEnumToString(self
, cpp_namespace
, type_
):
744 """Generates ToString() which gets the string representation of an enum.
747 classname
= cpp_util
.Classname(schema_util
.StripNamespace(type_
.name
))
749 if cpp_namespace
is not None:
750 c
.Append('// static')
751 maybe_namespace
= '' if cpp_namespace
is None else '%s::' % cpp_namespace
753 c
.Sblock('std::string %sToString(%s enum_param) {' %
754 (maybe_namespace
, classname
))
755 c
.Sblock('switch (enum_param) {')
756 for enum_value
in self
._type
_helper
.FollowRef(type_
).enum_values
:
757 (c
.Append('case %s: ' % self
._type
_helper
.GetEnumValue(type_
, enum_value
))
758 .Append(' return "%s";' % enum_value
))
759 (c
.Append('case %s:' % self
._type
_helper
.GetEnumNoneValue(type_
))
760 .Append(' return "";')
762 .Append('NOTREACHED();')
763 .Append('return "";')
768 def _GenerateEnumFromString(self
, cpp_namespace
, type_
):
769 """Generates FromClassNameString() which gets an enum from its string
773 classname
= cpp_util
.Classname(schema_util
.StripNamespace(type_
.name
))
775 if cpp_namespace
is not None:
776 c
.Append('// static')
777 maybe_namespace
= '' if cpp_namespace
is None else '%s::' % cpp_namespace
779 c
.Sblock('%s%s %sParse%s(const std::string& enum_string) {' %
780 (maybe_namespace
, classname
, maybe_namespace
, classname
))
781 for i
, enum_value
in enumerate(
782 self
._type
_helper
.FollowRef(type_
).enum_values
):
783 # This is broken up into all ifs with no else ifs because we get
784 # "fatal error C1061: compiler limit : blocks nested too deeply"
786 (c
.Append('if (enum_string == "%s")' % enum_value
)
787 .Append(' return %s;' %
788 self
._type
_helper
.GetEnumValue(type_
, enum_value
)))
789 (c
.Append('return %s;' % self
._type
_helper
.GetEnumNoneValue(type_
))
794 def _GenerateCreateCallbackArguments(self
, function_scope
, callback
):
795 """Generate all functions to create Value parameters for a callback.
797 E.g for function "Bar", generate Bar::Results::Create
798 E.g for event "Baz", generate Baz::Create
800 function_scope: the function scope path, e.g. Foo::Bar for the function
801 Foo::Bar::Baz(). May be None if there is no function scope.
802 callback: the Function object we are creating callback arguments for.
805 params
= callback
.params
806 c
.Concat(self
._GeneratePropertyFunctions
(function_scope
, params
))
808 (c
.Sblock('scoped_ptr<base::ListValue> %(function_scope)s'
809 'Create(%(declaration_list)s) {')
810 .Append('scoped_ptr<base::ListValue> create_results('
811 'new base::ListValue());')
813 declaration_list
= []
815 declaration_list
.append(cpp_util
.GetParameterDeclaration(
816 param
, self
._type
_helper
.GetCppType(param
.type_
)))
817 c
.Append('create_results->Append(%s);' %
818 self
._CreateValueFromType
(param
.type_
, param
.unix_name
))
819 c
.Append('return create_results.Pass();')
822 'function_scope': ('%s::' % function_scope
) if function_scope
else '',
823 'declaration_list': ', '.join(declaration_list
),
824 'param_names': ', '.join(param
.unix_name
for param
in params
)
828 def _InitializePropertyToDefault(self
, prop
, dst
):
829 """Initialize a model.Property to its default value inside an object.
831 E.g for optional enum "state", generate dst->state = STATE_NONE;
836 underlying_type
= self
._type
_helper
.FollowRef(prop
.type_
)
837 if (underlying_type
.property_type
== PropertyType
.ENUM
and
839 c
.Append('%s->%s = %s;' % (
842 self
._type
_helper
.GetEnumNoneValue(prop
.type_
)))