15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from code import Code
658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)from model import PropertyType
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import cpp_util
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import schema_util
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import util_cc_helper
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifrom cpp_namespace_environment import CppNamespaceEnvironment
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CCGenerator(object):
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def __init__(self, type_generator):
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._type_generator = type_generator
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def Generate(self, namespace):
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return _Generator(namespace, self._type_generator).Generate()
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class _Generator(object):
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A .cc generator for a namespace.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  def __init__(self, namespace, cpp_type_generator):
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    assert type(namespace.environment) is CppNamespaceEnvironment
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._namespace = namespace
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self._type_helper = cpp_type_generator
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._util_cc_helper = (
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        util_cc_helper.UtilCCHelper(self._type_helper))
29c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    self._generate_error_messages = namespace.compiler_options.get(
30c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        'generate_error_messages', False)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Generate(self):
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates a Code object with the .cc for a single namespace.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cpp_namespace = cpp_util.GetCppNamespace(
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        self._namespace.environment.namespace_pattern,
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        self._namespace.unix_name)
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (c.Append(cpp_util.CHROMIUM_LICENSE)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append(self._util_cc_helper.GetIncludePath())
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('#include "base/logging.h"')
465e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      .Append('#include "base/strings/string_number_conversions.h"')
473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      .Append('#include "base/strings/utf_string_conversions.h"')
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('#include "%s/%s.h"' %
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              (self._namespace.source_file_dir, self._namespace.short_filename))
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      .Append('#include <set>')
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Cblock(self._type_helper.GenerateIncludes(include_soft=True))
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Append()
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Append('using base::UTF8ToUTF16;')
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Append()
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      .Concat(cpp_util.OpenNamespace(cpp_namespace))
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.properties:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Properties')
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for property in self._namespace.properties.values():
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        property_code = self._type_helper.GeneratePropertyValues(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            property,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            'const %(type)s %(name)s = %(value)s;',
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            nodoc=True)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if property_code:
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          c.Cblock(property_code)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.types:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Types')
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Cblock(self._GenerateTypes(None, self._namespace.types.values()))
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.functions:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Functions')
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for function in self._namespace.functions.values():
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Cblock(self._GenerateFunction(function))
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if self._namespace.events:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('//')
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('// Events')
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('//')
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for event in self._namespace.events.values():
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateEvent(event))
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    c.Cblock(cpp_util.CloseNamespace(cpp_namespace))
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    c.Append()
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateType(self, cpp_namespace, type_):
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the function definitions for a type.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if type_.functions:
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # Wrap functions within types in the type's namespace.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Append('namespace %s {' % classname)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append())
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for function in type_.functions.values():
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateFunction(function))
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Append('}  // namespace %s' % classname)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif type_.property_type == PropertyType.ARRAY:
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Cblock(self._GenerateType(cpp_namespace, type_.item_type))
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif type_.property_type in (PropertyType.CHOICES,
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                 PropertyType.OBJECT):
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if cpp_namespace is None:
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        classname_in_namespace = classname
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        classname_in_namespace = '%s::%s' % (cpp_namespace, classname)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.property_type == PropertyType.OBJECT:
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GeneratePropertyFunctions(classname_in_namespace,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 type_.properties.values()))
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateTypes(classname_in_namespace, type_.choices))
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Append('%s::%s()' % (classname_in_namespace, classname))
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Cblock(self._GenerateInitializersAndBody(type_))
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append('%s::~%s() {}' % (classname_in_namespace, classname))
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      )
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.origin.from_json:
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateTypePopulate(classname_in_namespace, type_))
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if cpp_namespace is None:  # only generate for top-level types
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          c.Cblock(self._GenerateTypeFromValue(classname_in_namespace, type_))
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.origin.from_client:
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Cblock(self._GenerateTypeToValue(classname_in_namespace, type_))
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif type_.property_type == PropertyType.ENUM:
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Cblock(self._GenerateEnumToString(cpp_namespace, type_))
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Cblock(self._GenerateEnumFromString(cpp_namespace, type_))
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      )
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateInitializersAndBody(self, type_):
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items = []
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for prop in type_.properties.values():
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      t = prop.type_
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      real_t = self._type_helper.FollowRef(t)
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if real_t.property_type == PropertyType.ENUM:
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        items.append('%s(%s)' % (
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            prop.unix_name,
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            self._type_helper.GetEnumNoneValue(t)))
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      elif prop.optional:
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        continue
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      elif t.property_type == PropertyType.INTEGER:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        items.append('%s(0)' % prop.unix_name)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      elif t.property_type == PropertyType.DOUBLE:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        items.append('%s(0.0)' % prop.unix_name)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      elif t.property_type == PropertyType.BOOLEAN:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        items.append('%s(false)' % prop.unix_name)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      elif (t.property_type == PropertyType.ANY or
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            t.property_type == PropertyType.ARRAY or
1632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch            t.property_type == PropertyType.BINARY or  # mapped to std::string
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            t.property_type == PropertyType.CHOICES or
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            t.property_type == PropertyType.OBJECT or
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            t.property_type == PropertyType.FUNCTION or
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            t.property_type == PropertyType.REF or
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            t.property_type == PropertyType.STRING):
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        # TODO(miket): It would be nice to initialize CHOICES, but we
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # don't presently have the semantics to indicate which one of a set
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # should be the default.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        raise TypeError(t)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if items:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      s = ': %s' % (', '.join(items))
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      s = ''
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s = s + ' {}'
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Code().Append(s)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateTypePopulate(self, cpp_namespace, type_):
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the function for populating a type given a pointer to it.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    E.g for type "Foo", generates Foo::Populate()
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (c.Append('// static')
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('bool %(namespace)s::Populate(')
192c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Sblock('    %s) {' % self._GenerateParams(
193c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          ('const base::Value& value', '%(name)s* out'))))
194c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if self._generate_error_messages:
196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      c.Append('DCHECK(error);')
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if type_.property_type == PropertyType.CHOICES:
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for choice in type_.choices:
2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        (c.Sblock('if (%s) {' % self._GenerateValueIsTypeExpression('value',
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                                    choice))
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            .Concat(self._GeneratePopulateVariableFromValue(
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                choice,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                '(&value)',
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                'out->as_%s' % choice.unix_name,
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                'false',
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                is_ptr=True))
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            .Append('return true;')
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Eblock('}')
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        )
211c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      (c.Concat(self._GenerateError(
212c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          '"expected %s, got " +  %s' %
213c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch              (" or ".join(choice.name for choice in type_.choices),
214c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch              self._util_cc_helper.GetValueTypeString('value'))))
215c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Append('return false;'))
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif type_.property_type == PropertyType.OBJECT:
217c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      (c.Sblock('if (!value.IsType(base::Value::TYPE_DICTIONARY)) {')
218c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Concat(self._GenerateError(
219c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          '"expected dictionary, got " + ' +
220c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          self._util_cc_helper.GetValueTypeString('value')))
221c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Append('return false;')
222c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Eblock('}'))
223c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.properties or type_.additional_properties is not None:
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Append('const base::DictionaryValue* dict = '
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     'static_cast<const base::DictionaryValue*>(&value);')
227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if self._generate_error_messages:
228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            c.Append('std::set<std::string> keys;')
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      for prop in type_.properties.itervalues():
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        c.Concat(self._InitializePropertyToDefault(prop, 'out'))
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      for prop in type_.properties.itervalues():
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        if self._generate_error_messages:
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          c.Append('keys.insert("%s");' % (prop.name))
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Concat(self._GenerateTypePopulateProperty(prop, 'dict', 'out'))
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      # Check for extra values.
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if self._generate_error_messages:
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        (c.Sblock('for (base::DictionaryValue::Iterator it(*dict); '
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                       '!it.IsAtEnd(); it.Advance()) {')
239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Sblock('if (!keys.count(it.key())) {')
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Concat(self._GenerateError('"found unexpected key \'" + '
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                          'it.key() + "\'"'))
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Eblock('}')
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          .Eblock('}')
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        )
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.additional_properties is not None:
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if type_.additional_properties.property_type == PropertyType.ANY:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          c.Append('out->additional_properties.MergeDictionary(dict);')
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          cpp_type = self._type_helper.GetCppType(type_.additional_properties,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  is_in_container=True)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          (c.Append('for (base::DictionaryValue::Iterator it(*dict);')
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .Sblock('     !it.IsAtEnd(); it.Advance()) {')
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              .Append('%s tmp;' % cpp_type)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              .Concat(self._GeneratePopulateVariableFromValue(
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  type_.additional_properties,
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  '(&it.value())',
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  'tmp',
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  'false'))
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              .Append('out->additional_properties[it.key()] = tmp;')
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            .Eblock('}')
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          )
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Append('return true;')
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Eblock('}')
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Substitute({'namespace': cpp_namespace, 'name': classname}))
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  def _GenerateValueIsTypeExpression(self, var, type_):
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    real_type = self._type_helper.FollowRef(type_)
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if real_type.property_type is PropertyType.CHOICES:
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return '(%s)' % ' || '.join(self._GenerateValueIsTypeExpression(var,
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                                      choice)
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                  for choice in real_type.choices)
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return '%s.IsType(%s)' % (var, cpp_util.GetValueType(real_type))
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateTypePopulateProperty(self, prop, src, dst):
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generate the code to populate a single property in a type.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    src: base::DictionaryValue*
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dst: Type*
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value_var = prop.unix_name + '_value'
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c.Append('const base::Value* %(value_var)s = NULL;')
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if prop.optional:
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Sblock(
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Concat(self._GeneratePopulatePropertyFromValue(
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prop, value_var, dst, 'false')))
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      underlying_type = self._type_helper.FollowRef(prop.type_)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if underlying_type.property_type == PropertyType.ENUM:
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (c.Append('} else {')
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .Append('%%(dst)s->%%(name)s = %s;' %
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              self._type_helper.GetEnumNoneValue(prop.type_)))
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c.Eblock('}')
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
296c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      (c.Sblock(
297c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          'if (!%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {')
298c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Concat(self._GenerateError('"\'%%(key)s\' is required"'))
299c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Append('return false;')
300c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Eblock('}')
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Concat(self._GeneratePopulatePropertyFromValue(
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prop, value_var, dst, 'false'))
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c.Append()
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c.Substitute({
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'value_var': value_var,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'key': prop.name,
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'src': src,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'dst': dst,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      'name': prop.unix_name
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    })
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def _GenerateTypeFromValue(self, cpp_namespace, type_):
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    c = Code()
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    (c.Append('// static')
318c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Append('scoped_ptr<%s> %s::FromValue(%s) {' % (classname,
319c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        cpp_namespace, self._GenerateParams(('const base::Value& value',))))
320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    )
321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if self._generate_error_messages:
322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      c.Append('DCHECK(error);')
323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    (c.Append('  scoped_ptr<%s> out(new %s());' % (classname, classname))
324c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Append('  if (!Populate(%s))' % self._GenerateArgs(
325c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          ('value', 'out.get()')))
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Append('    return scoped_ptr<%s>();' % classname)
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Append('  return out.Pass();')
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      .Append('}')
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    )
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return c
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateTypeToValue(self, cpp_namespace, type_):
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates a function that serializes the type into a base::Value.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    E.g. for type "Foo" generates Foo::ToValue()
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if type_.property_type == PropertyType.OBJECT:
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return self._GenerateObjectTypeToValue(cpp_namespace, type_)
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif type_.property_type == PropertyType.CHOICES:
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return self._GenerateChoiceTypeToValue(cpp_namespace, type_)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else:
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      raise ValueError("Unsupported property type %s" % type_.type_)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateObjectTypeToValue(self, cpp_namespace, type_):
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates a function that serializes an object-representing type
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    into a base::DictionaryValue.
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' %
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cpp_namespace)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('scoped_ptr<base::DictionaryValue> value('
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    'new base::DictionaryValue());')
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for prop in type_.properties.values():
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      prop_var = 'this->%s' % prop.unix_name
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if prop.optional:
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # Optional enum values are generated with a NONE enum value.
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        underlying_type = self._type_helper.FollowRef(prop.type_)
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if underlying_type.property_type == PropertyType.ENUM:
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          c.Sblock('if (%s != %s) {' %
3625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu              (prop_var,
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               self._type_helper.GetEnumNoneValue(prop.type_)))
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
3655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu          c.Sblock('if (%s.get()) {' % prop_var)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # ANY is a base::Value which is abstract and cannot be a direct member, so
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # it will always be a pointer.
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      is_ptr = prop.optional or prop.type_.property_type == PropertyType.ANY
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      c.Cblock(self._CreateValueFromType(
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          'value->SetWithoutPathExpansion("%s", %%s);' % prop.name,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          prop.name,
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          prop.type_,
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          prop_var,
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          is_ptr=is_ptr))
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if prop.optional:
37858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        c.Eblock('}')
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if type_.additional_properties is not None:
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if type_.additional_properties.property_type == PropertyType.ANY:
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Append('value->MergeDictionary(&additional_properties);')
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # Non-copyable types will be wrapped in a linked_ptr for inclusion in
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        # maps, so we need to unwrap them.
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        needs_unwrap = (
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            not self._type_helper.IsCopyable(type_.additional_properties))
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cpp_type = self._type_helper.GetCppType(type_.additional_properties,
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                is_in_container=True)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Sblock('for (std::map<std::string, %s>::const_iterator it =' %
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      cpp_util.PadForGenerics(cpp_type))
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('       additional_properties.begin();')
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('   it != additional_properties.end(); ++it) {')
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Cblock(self._CreateValueFromType(
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              'value->SetWithoutPathExpansion(it->first, %s);',
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              type_.additional_properties.name,
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              type_.additional_properties,
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              '%sit->second' % ('*' if needs_unwrap else '')))
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Eblock('}')
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        )
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return (c.Append()
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             .Append('return value.Pass();')
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           .Eblock('}'))
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateChoiceTypeToValue(self, cpp_namespace, type_):
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates a function that serializes a choice-representing type
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    into a base::Value.
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c = Code()
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.Sblock('scoped_ptr<base::Value> %s::ToValue() const {' % cpp_namespace)
41258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    c.Append('scoped_ptr<base::Value> result;')
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for choice in type_.choices:
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      choice_var = 'as_%s' % choice.unix_name
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Sblock('if (%s) {' % choice_var)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' %
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      type_.unix_name)
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Cblock(self._CreateValueFromType('result.reset(%s);',
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            choice.name,
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            choice,
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            '*%s' % choice_var))
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Eblock('}')
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      )
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('DCHECK(result) << "Must set at least one choice for %s";' %
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  type_.unix_name)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('return result.Pass();')
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Eblock('}')
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateFunction(self, function):
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates the definitions for function structs.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # TODO(kalman): use function.unix_name not Classname.
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    function_namespace = cpp_util.Classname(function.name)
43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    # Windows has a #define for SendMessage, so to avoid any issues, we need
43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    # to not use the name.
44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if function_namespace == 'SendMessage':
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      function_namespace = 'PassMessage'
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('namespace %s {' % function_namespace)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append()
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    )
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Params::Populate function
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if function.params:
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Concat(self._GeneratePropertyFunctions('Params', function.params))
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Append('Params::Params() {}')
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append('Params::~Params() {}')
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append()
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Cblock(self._GenerateFunctionParamsCreate(function))
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Results::Create function
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if function.callback:
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      c.Concat(self._GenerateCreateCallbackArguments(function_namespace,
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                     'Results',
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                     function.callback))
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.Append('}  // namespace %s' % function_namespace)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return c
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateEvent(self, event):
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # TODO(kalman): use event.unix_name not Classname.
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c = Code()
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_namespace = cpp_util.Classname(event.name)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('namespace %s {' % event_namespace)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append()
4702385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      .Cblock(self._GenerateEventNameConstant(None, event))
471010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      .Cblock(self._GenerateCreateCallbackArguments(event_namespace,
472010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                    None,
473010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                                    event))
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('}  // namespace %s' % event_namespace)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    )
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def _CreateValueFromType(self, code, prop_name, type_, var, is_ptr=False):
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Creates a base::Value given a type. Generated code passes ownership
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    to caller.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var: variable or variable*
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    E.g for std::string, generate new base::StringValue(var)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    c = Code()
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    underlying_type = self._type_helper.FollowRef(type_)
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if underlying_type.property_type == PropertyType.ARRAY:
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # Enums are treated specially because C++ templating thinks that they're
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # ints, but really they're strings. So we create a vector of strings and
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # populate it with the names of the enum in the array. The |ToString|
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # function of the enum can be in another namespace when the enum is
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # referenced. Templates can not be used here because C++ templating does
494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      # not support passing a namespace as an argument.
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      item_type = self._type_helper.FollowRef(underlying_type.item_type)
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if item_type.property_type == PropertyType.ENUM:
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        vardot = '(%s)%s' % (var, '->' if is_ptr else '.')
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        maybe_namespace = ''
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if type_.item_type.property_type == PropertyType.REF:
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          maybe_namespace = '%s::' % item_type.namespace.unix_name
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        enum_list_var = '%s_list' % prop_name
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        # Scope the std::vector variable declaration inside braces.
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (c.Sblock('{')
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Append('std::vector<std::string> %s;' % enum_list_var)
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Append('for (std::vector<%s>::const_iterator it = %sbegin();'
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              % (self._type_helper.GetCppType(item_type), vardot))
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Sblock('    it != %send(); ++it) {' % vardot)
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Append('%s.push_back(%sToString(*it));' % (enum_list_var,
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                      maybe_namespace))
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Eblock('}'))
513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        # Because the std::vector above is always created for both required and
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        # optional enum arrays, |is_ptr| is set to false and uses the
516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        # std::vector to create the values.
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        (c.Append(code %
518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            self._GenerateCreateValueFromType(type_, enum_list_var, False))
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          .Eblock('}'))
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return c
521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    c.Append(code % self._GenerateCreateValueFromType(type_, var, is_ptr))
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return c
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  def _GenerateCreateValueFromType(self, type_, var, is_ptr):
526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """Generates the statement to create a base::Value given a type.
527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    type_:  The type of the values being converted.
529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    var:    The name of the variable.
530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    is_ptr: Whether |type_| is optional.
531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    """
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    underlying_type = self._type_helper.FollowRef(type_)
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (underlying_type.property_type == PropertyType.CHOICES or
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        underlying_type.property_type == PropertyType.OBJECT):
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return '(%s)->ToValue().release()' % var
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return '(%s).ToValue().release()' % var
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif (underlying_type.property_type == PropertyType.ANY or
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          underlying_type.property_type == PropertyType.FUNCTION):
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        vardot = '(%s)->' % var
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        vardot = '(%s).' % var
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return '%sDeepCopy()' % vardot
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.ENUM:
547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      maybe_namespace = ''
548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if type_.property_type == PropertyType.REF:
549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        maybe_namespace = '%s::' % underlying_type.namespace.unix_name
550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return 'new base::StringValue(%sToString(%s))' % (maybe_namespace, var)
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.BINARY:
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vardot = var + '->'
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        vardot = var + '.'
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(), %ssize())' %
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (vardot, vardot))
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.ARRAY:
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return '%s.release()' % self._util_cc_helper.CreateValueFromArray(
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          var,
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          is_ptr)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type.is_fundamental:
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        var = '*%s' % var
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if underlying_type.property_type == PropertyType.STRING:
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return 'new base::StringValue(%s)' % var
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return 'new base::FundamentalValue(%s)' % var
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raise NotImplementedError('Conversion of %s to base::Value not '
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                'implemented' % repr(type_.type_))
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GenerateParamsCheck(self, function, var):
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates a check for the correct number of arguments when creating
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Params.
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_required = 0
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for param in function.params:
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not param.optional:
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_required += 1
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if num_required == len(function.params):
583c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      c.Sblock('if (%(var)s.GetSize() != %(total)d) {')
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elif not num_required:
585c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      c.Sblock('if (%(var)s.GetSize() > %(total)d) {')
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
587c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      c.Sblock('if (%(var)s.GetSize() < %(required)d'
588c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          ' || %(var)s.GetSize() > %(total)d) {')
589c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    (c.Concat(self._GenerateError(
590c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        '"expected %%(total)d arguments, got " '
591c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        '+ base::IntToString(%%(var)s.GetSize())'))
592c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Append('return scoped_ptr<Params>();')
593c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Eblock('}')
594c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Substitute({
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'var': var,
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'required': num_required,
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        'total': len(function.params),
598c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    }))
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateFunctionParamsCreate(self, function):
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generate function to create an instance of Params. The generated
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function takes a base::ListValue of arguments.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    E.g for function "Bar", generate Bar::Params::Create()
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (c.Append('// static')
609c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Sblock('scoped_ptr<Params> Params::Create(%s) {' % self._GenerateParams(
610c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        ['const base::ListValue& args']))
611010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    )
612010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if self._generate_error_messages:
613010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      c.Append('DCHECK(error);')
614010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    (c.Concat(self._GenerateParamsCheck(function, 'args'))
615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Append('scoped_ptr<Params> params(new Params());')
616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    )
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for param in function.params:
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c.Concat(self._InitializePropertyToDefault(param, 'params'))
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for i, param in enumerate(function.params):
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # Any failure will cause this function to return. If any argument is
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # incorrect or missing, those following it are not processed. Note that
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # for optional arguments, we allow missing arguments and proceed because
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # there may be other arguments following it.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failure_value = 'scoped_ptr<Params>()'
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c.Append()
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_var = param.unix_name + '_value'
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (c.Append('const base::Value* %(value_var)s = NULL;')
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Append('if (args.Get(%(i)s, &%(value_var)s) &&')
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        .Sblock('    !%(value_var)s->IsType(base::Value::TYPE_NULL)) {')
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Concat(self._GeneratePopulatePropertyFromValue(
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            param, value_var, 'params', failure_value))
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Eblock('}')
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      )
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if not param.optional:
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (c.Sblock('else {')
638c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Concat(self._GenerateError('"\'%%(key)s\' is required"'))
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .Append('return %s;' % failure_value)
640c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Eblock('}'))
641c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      c.Substitute({'value_var': value_var, 'i': i, 'key': param.name})
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (c.Append()
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('return params.Pass();')
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Eblock('}')
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append()
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GeneratePopulatePropertyFromValue(self,
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         prop,
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         src_var,
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         dst_class_var,
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         failure_value):
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates code to populate property |prop| of |dst_class_var| (a
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pointer) from a Value*. See |_GeneratePopulateVariableFromValue| for
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    semantics.
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self._GeneratePopulateVariableFromValue(prop.type_,
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   src_var,
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   '%s->%s' % (dst_class_var,
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                               prop.unix_name),
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   failure_value,
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   is_ptr=prop.optional)
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GeneratePopulateVariableFromValue(self,
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         type_,
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         src_var,
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         dst_var,
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         failure_value,
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         is_ptr=False):
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates code to populate a variable |dst_var| of type |type_| from a
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    code, if |dst_var| fails to be populated then Populate will return
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    |failure_value|.
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    underlying_type = self._type_helper.FollowRef(type_)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if underlying_type.property_type.is_fundamental:
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append('%(cpp_type)s temp;')
684c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue(
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      self._type_helper.FollowRef(type_), src_var, '&temp'))
686c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Concat(self._GenerateError(
687c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            '"\'%%(key)s\': expected ' + '%s, got " + %s' % (
688c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                type_.name,
689c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                self._util_cc_helper.GetValueTypeString(
690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    '%%(src_var)s', True)))))
691a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        c.Append('%(dst_var)s.reset();')
692a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if not self._generate_error_messages:
693a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          c.Append('return %(failure_value)s;')
694a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        (c.Eblock('}')
695a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .Append('else')
696a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .Append('  %(dst_var)s.reset(new %(cpp_type)s(temp));')
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        )
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
699c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        (c.Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue(
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      self._type_helper.FollowRef(type_),
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      src_var,
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      '&%s' % dst_var))
703c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Concat(self._GenerateError(
704c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            '"\'%%(key)s\': expected ' + '%s, got " + %s' % (
705c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                type_.name,
706c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                self._util_cc_helper.GetValueTypeString(
707c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                    '%%(src_var)s', True))))
708c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('return %(failure_value)s;')
709c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Eblock('}')
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        )
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.OBJECT:
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append('const base::DictionaryValue* dictionary = NULL;')
714c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {')
715c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Concat(self._GenerateError(
716c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            '"\'%%(key)s\': expected dictionary, got " + ' +
717a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))))
718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        # If an optional property fails to populate, the population can still
719a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        # succeed with a warning. If no error messages are generated, this
720a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        # warning is not set and we fail out instead.
721a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if not self._generate_error_messages:
722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          c.Append('return %(failure_value)s;')
723a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        (c.Eblock('}')
724a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .Sblock('else {')
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
726c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs(
727c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            ('*dictionary', 'temp.get()')))
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('  return %(failure_value)s;')
729a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        )
730a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        (c.Append('}')
731a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .Append('else')
732a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .Append('  %(dst_var)s = temp.Pass();')
733a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          .Eblock('}')
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        )
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append('const base::DictionaryValue* dictionary = NULL;')
737c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {')
738c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Concat(self._GenerateError(
739c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            '"\'%%(key)s\': expected dictionary, got " + ' +
740c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
741c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('return %(failure_value)s;')
742c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Eblock('}')
743c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs(
744c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            ('*dictionary', '&%(dst_var)s')))
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          .Append('  return %(failure_value)s;')
746c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('}')
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        )
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.FUNCTION:
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Append('%(dst_var)s.reset(new base::DictionaryValue());')
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.ANY:
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());')
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.ARRAY:
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      # util_cc_helper deals with optional and required arrays
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Append('const base::ListValue* list = NULL;')
756c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Sblock('if (!%(src_var)s->GetAsList(&list)) {')
757c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Concat(self._GenerateError(
758c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            '"\'%%(key)s\': expected list, got " + ' +
759c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
760a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      )
761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if is_ptr and self._generate_error_messages:
762a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        c.Append('%(dst_var)s.reset();')
763a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      else:
764a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        c.Append('return %(failure_value)s;')
765a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      c.Eblock('}')
766a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      c.Sblock('else {')
76758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      item_type = self._type_helper.FollowRef(underlying_type.item_type)
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if item_type.property_type == PropertyType.ENUM:
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        c.Concat(self._GenerateListValueToEnumArrayConversion(
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     item_type,
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     'list',
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     dst_var,
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     failure_value,
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     is_ptr=is_ptr))
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
776c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        (c.Sblock('if (!%s) {' % self._util_cc_helper.PopulateArrayFromList(
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              'list',
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              dst_var,
779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              is_ptr)))
780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        c.Concat(self._GenerateError(
781c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            '"unable to populate array \'%%(parent_key)s\'"'))
782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if is_ptr and self._generate_error_messages:
783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          c.Append('%(dst_var)s.reset();')
784a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        else:
785a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          c.Append('return %(failure_value)s;')
786a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        c.Eblock('}')
787a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      c.Eblock('}')
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.CHOICES:
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());')
791c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
792c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            ('*%(src_var)s', 'temp.get()')))
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('  return %(failure_value)s;')
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('%(dst_var)s = temp.Pass();')
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        )
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
797c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        (c.Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs(
798c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch            ('*%(src_var)s', '&%(dst_var)s')))
799c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          .Append('  return %(failure_value)s;'))
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.ENUM:
801c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      c.Concat(self._GenerateStringToEnumConversion(underlying_type,
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    src_var,
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    dst_var,
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    failure_value))
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    elif underlying_type.property_type == PropertyType.BINARY:
806a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      (c.Append('const base::BinaryValue* binary_value = NULL;')
807a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        .Sblock('if (!%(src_var)s->IsType(base::Value::TYPE_BINARY)) {')
808c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        .Concat(self._GenerateError(
809c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          '"\'%%(key)s\': expected binary, got " + ' +
810c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch          self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
811a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      )
812a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if not self._generate_error_messages:
813a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        c.Append('return %(failure_value)s;')
814a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      (c.Eblock('}')
815a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        .Sblock('else {')
816a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        .Append(' binary_value =')
817a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        .Append('   static_cast<const base::BinaryValue*>(%(src_var)s);')
8187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      )
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if is_ptr:
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append('%(dst_var)s.reset(')
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('    new std::string(binary_value->GetBuffer(),')
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('                    binary_value->GetSize()));')
8237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        )
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else:
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        (c.Append('%(dst_var)s.assign(binary_value->GetBuffer(),')
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          .Append('                   binary_value->GetSize());')
8277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        )
828a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      c.Eblock('}')
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      raise NotImplementedError(type_)
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if c.IsEmpty():
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return c
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Code().Sblock('{').Concat(c.Substitute({
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'cpp_type': self._type_helper.GetCppType(type_),
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'src_var': src_var,
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'dst_var': dst_var,
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'failure_value': failure_value,
838c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      'key': type_.name,
839a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      'parent_key': type_.parent.name,
8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    })).Eblock('}')
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateListValueToEnumArrayConversion(self,
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              item_type,
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              src_var,
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              dst_var,
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              failure_value,
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              is_ptr=False):
84858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    """Returns Code that converts a ListValue of string constants from
84958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    |src_var| into an array of enums of |type_| in |dst_var|. On failure,
85058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    returns |failure_value|.
85158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    """
85258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    c = Code()
85358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    accessor = '.'
85458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if is_ptr:
85558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      accessor = '->'
85658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      cpp_type = self._type_helper.GetCppType(item_type, is_in_container=True)
85758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      c.Append('%s.reset(new std::vector<%s>);' %
85858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   (dst_var, cpp_util.PadForGenerics(cpp_type)))
85958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    (c.Sblock('for (base::ListValue::const_iterator it = %s->begin(); '
86058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                   'it != %s->end(); ++it) {' % (src_var, src_var))
86158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .Append('%s tmp;' % self._type_helper.GetCppType(item_type))
86258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .Concat(self._GenerateStringToEnumConversion(item_type,
86358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                   '(*it)',
86458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                   'tmp',
86558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                                   failure_value))
86658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .Append('%s%spush_back(tmp);' % (dst_var, accessor))
86758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      .Eblock('}')
86858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    )
86958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return c
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateStringToEnumConversion(self,
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      type_,
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      src_var,
8742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      dst_var,
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      failure_value):
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Returns Code that converts a string type in |src_var| to an enum with
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    type |type_| in |dst_var|. In the generated code, if |src_var| is not
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    a valid enum name then the function will return |failure_value|.
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
880c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if type_.property_type != PropertyType.ENUM:
881c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      raise TypeError(type_)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    enum_as_string = '%s_as_string' % type_.unix_name
884c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cpp_type_namespace = ''
885c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if type_.namespace != self._namespace:
886c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      cpp_type_namespace = '%s::' % type_.namespace.unix_name
887c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cpp_type_name = self._type_helper.GetCppType(type_)
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('std::string %s;' % enum_as_string)
889c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Sblock('if (!%s->GetAsString(&%s)) {' % (src_var, enum_as_string))
890c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Concat(self._GenerateError(
891c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        '"\'%%(key)s\': expected string, got " + ' +
892c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))
893c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Append('return %s;' % failure_value)
894c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Eblock('}')
895c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      .Append('%s = %sParse%s(%s);' % (dst_var,
896c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       cpp_type_namespace,
897c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       cpp_util.Classname(type_.name),
898c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                       enum_as_string))
899c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      .Sblock('if (%s == %s%s) {' % (dst_var,
900c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     cpp_type_namespace,
901c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     self._type_helper.GetEnumNoneValue(type_)))
902c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Concat(self._GenerateError(
903c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        '\"\'%%(key)s\': expected \\"' +
9041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        '\\" or \\"'.join(
9051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            enum_value.name
9061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            for enum_value in self._type_helper.FollowRef(type_).enum_values) +
907c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch        '\\", got \\"" + %s + "\\""' % enum_as_string))
908c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Append('return %s;' % failure_value)
909c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Eblock('}')
910c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      .Substitute({'src_var': src_var, 'key': type_.name})
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    )
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GeneratePropertyFunctions(self, namespace, params):
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates the member functions for a list of parameters.
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return self._GenerateTypes(namespace, (param.type_ for param in params))
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateTypes(self, namespace, types):
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    """Generates the member functions for a list of types.
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for type_ in types:
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Cblock(self._GenerateType(namespace, type_))
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateEnumToString(self, cpp_namespace, type_):
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates ToString() which gets the string representation of an enum.
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if cpp_namespace is not None:
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Append('// static')
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
937cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    c.Sblock('std::string %sToString(%s enum_param) {' %
938cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 (maybe_namespace, classname))
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c.Sblock('switch (enum_param) {')
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for enum_value in self._type_helper.FollowRef(type_).enum_values:
941cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      name = enum_value.name
942cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if 'camel_case_enum_to_string' in self._namespace.compiler_options:
943cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        name = enum_value.CamelName()
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (c.Append('case %s: ' % self._type_helper.GetEnumValue(type_, enum_value))
945cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        .Append('  return "%s";' % name))
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('case %s:' % self._type_helper.GetEnumNoneValue(type_))
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('  return "";')
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Eblock('}')
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .Append('NOTREACHED();')
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Append('return "";')
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Eblock('}')
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    )
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def _GenerateEnumFromString(self, cpp_namespace, type_):
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Generates FromClassNameString() which gets an enum from its string
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    representation.
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c = Code()
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    classname = cpp_util.Classname(schema_util.StripNamespace(type_.name))
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if cpp_namespace is not None:
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      c.Append('// static')
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    maybe_namespace = '' if cpp_namespace is None else '%s::' % cpp_namespace
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    c.Sblock('%s%s %sParse%s(const std::string& enum_string) {' %
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 (maybe_namespace, classname, maybe_namespace, classname))
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for i, enum_value in enumerate(
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          self._type_helper.FollowRef(type_).enum_values):
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # This is broken up into all ifs with no else ifs because we get
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # "fatal error C1061: compiler limit : blocks nested too deeply"
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # on Windows.
9731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      (c.Append('if (enum_string == "%s")' % enum_value.name)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .Append('  return %s;' %
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            self._type_helper.GetEnumValue(type_, enum_value)))
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (c.Append('return %s;' % self._type_helper.GetEnumNoneValue(type_))
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .Eblock('}')
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    )
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return c
980