| Index: tools/json_schema_compiler/cc_generator.py
|
| diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py
|
| index d0c57decdf8deabcf78dd63adb105fc611407945..3d51d28c2a62ec45c6680ee95827e7162a004b45 100644
|
| --- a/tools/json_schema_compiler/cc_generator.py
|
| +++ b/tools/json_schema_compiler/cc_generator.py
|
| @@ -5,6 +5,7 @@
|
| from model import PropertyType
|
| import code
|
| import cpp_util
|
| +import util_cc_helper
|
|
|
| class CCGenerator(object):
|
| """A .cc generator for a namespace.
|
| @@ -14,6 +15,8 @@ class CCGenerator(object):
|
| self._namespace = namespace
|
| self._target_namespace = (
|
| self._cpp_type_generator.GetCppNamespaceName(self._namespace))
|
| + self._util_cc_helper = (
|
| + util_cc_helper.UtilCCHelper(self._cpp_type_generator))
|
|
|
| def Generate(self):
|
| """Generates a code.Code object with the .cc for a single namespace.
|
| @@ -23,11 +26,19 @@ class CCGenerator(object):
|
| .Append()
|
| .Append(cpp_util.GENERATED_FILE_MESSAGE % self._namespace.source_file)
|
| .Append()
|
| - .Append('#include "tools/json_schema_compiler/util.h"')
|
| + .Append(self._util_cc_helper.GetIncludePath())
|
| .Append('#include "%s/%s.h"' %
|
| - (self._namespace.source_file_dir, self._target_namespace))
|
| - .Append()
|
| - .Concat(self._cpp_type_generator.GetCppNamespaceStart())
|
| + (self._namespace.source_file_dir, self._namespace.name))
|
| + )
|
| + includes = self._cpp_type_generator.GenerateIncludes()
|
| + if not includes.IsEmpty():
|
| + (c.Concat(includes)
|
| + .Append()
|
| + )
|
| +
|
| + (c.Append()
|
| + .Concat(self._cpp_type_generator.GetRootNamespaceStart())
|
| + .Concat(self._cpp_type_generator.GetNamespaceStart())
|
| .Append()
|
| .Append('//')
|
| .Append('// Types')
|
| @@ -35,7 +46,7 @@ class CCGenerator(object):
|
| .Append()
|
| )
|
| for type_ in self._namespace.types.values():
|
| - (c.Concat(self._GenerateType(type_))
|
| + (c.Concat(self._GenerateType(type_.name, type_))
|
| .Append()
|
| )
|
| (c.Append('//')
|
| @@ -47,103 +58,91 @@ class CCGenerator(object):
|
| (c.Concat(self._GenerateFunction(function))
|
| .Append()
|
| )
|
| - (c.Concat(self._cpp_type_generator.GetCppNamespaceEnd())
|
| + (c.Concat(self._cpp_type_generator.GetNamespaceEnd())
|
| + .Concat(self._cpp_type_generator.GetRootNamespaceEnd())
|
| .Append()
|
| )
|
| # TODO(calamity): Events
|
| return c
|
|
|
| - def _GenerateType(self, type_):
|
| + def _GenerateType(self, cpp_namespace, type_, serializable=True):
|
| """Generates the function definitions for a type.
|
| """
|
| + classname = cpp_util.Classname(type_.name)
|
| c = code.Code()
|
|
|
| - (c.Append('%(classname)s::%(classname)s() {}')
|
| - .Append('%(classname)s::~%(classname)s() {}')
|
| + (c.Append('%(namespace)s::%(classname)s() {}')
|
| + .Append('%(namespace)s::~%(classname)s() {}')
|
| .Append()
|
| )
|
| - c.Substitute({'classname': type_.name})
|
| + c.Substitute({'classname': classname, 'namespace': cpp_namespace})
|
|
|
| - c.Concat(self._GenerateTypePopulate(type_))
|
| + c.Concat(self._GenerateTypePopulate(cpp_namespace, type_))
|
| c.Append()
|
| - # TODO(calamity): deal with non-serializable
|
| - c.Concat(self._GenerateTypeTovalue(type_))
|
| + if serializable:
|
| + c.Concat(self._GenerateTypeToValue(cpp_namespace, type_))
|
| c.Append()
|
|
|
| return c
|
|
|
| - def _GenerateTypePopulate(self, type_):
|
| + def _GenerateTypePopulate(self, cpp_namespace, type_):
|
| """Generates the function for populating a type given a pointer to it.
|
| """
|
| + classname = cpp_util.Classname(type_.name)
|
| c = code.Code()
|
| (c.Append('// static')
|
| - .Sblock('bool %(name)s::Populate(const Value& value, %(name)s* out) {')
|
| + .Sblock('bool %(namespace)s::Populate(const Value& value, %(name)s* out) {')
|
| .Append('if (!value.IsType(Value::TYPE_DICTIONARY))')
|
| .Append(' return false;')
|
| .Append('const DictionaryValue* dict = '
|
| 'static_cast<const DictionaryValue*>(&value);')
|
| .Append()
|
| )
|
| - c.Substitute({'name': type_.name})
|
| + c.Substitute({'namespace': cpp_namespace, 'name': classname})
|
|
|
| # TODO(calamity): this handle single PropertyType.REF properties.
|
| # add ALL the types
|
| for prop in type_.properties.values():
|
| - sub = {'name': prop.name}
|
| + dst = 'out->' + prop.unix_name
|
| + src = 'dict'
|
| if prop.type_ == PropertyType.ARRAY:
|
| - if prop.item_type.type_ == PropertyType.REF:
|
| - if prop.optional:
|
| - (c.Append('if (!json_schema_compiler::util::'
|
| - 'GetOptionalTypes<%(type)s>(*dict,')
|
| - .Append(' "%(name)s", &out->%(name)s))')
|
| - .Append(' return false;')
|
| - )
|
| - else:
|
| - (c.Append('if (!json_schema_compiler::util::'
|
| - 'GetTypes<%(type)s>(*dict,')
|
| - .Append(' "%(name)s", &out->%(name)s))')
|
| - .Append(' return false;')
|
| - )
|
| - sub['type'] = self._cpp_type_generator.GetType(prop.item_type,
|
| - pad_for_generics=True)
|
| - elif prop.item_type.type_ == PropertyType.STRING:
|
| - if prop.optional:
|
| - (c.Append('if (!json_schema_compiler::util::GetOptionalStrings'
|
| - '(*dict, "%(name)s", &out->%(name)s))')
|
| - .Append(' return false;')
|
| - )
|
| - else:
|
| - (c.Append('if (!json_schema_compiler::util::GetStrings'
|
| - '(*dict, "%(name)s", &out->%(name)s))')
|
| - .Append(' return false;')
|
| - )
|
| + populate_line = self._util_cc_helper.GetArray(prop, src, prop.name, dst)
|
| + else:
|
| + if prop.optional:
|
| + dst = dst + '.get()'
|
| else:
|
| - raise NotImplementedError(prop.item_type.type_)
|
| - elif prop.type_.is_fundamental:
|
| - c.Append('if (!dict->%s)' %
|
| - cpp_util.GetFundamentalValue(prop, '&out->%s' % prop.name))
|
| - c.Append(' return false;')
|
| + dst = '&' + dst
|
| + if prop.type_.is_fundamental:
|
| + populate_line = cpp_util.GetFundamentalValue(prop, src, prop.name, dst)
|
| + elif prop.type_ == PropertyType.REF or prop.type_ == PropertyType.OBJECT:
|
| + populate_line = '%(ctype)s::Populate(*%(src)s, %(dst)s)' % {
|
| + 'src': src, 'dst': dst,
|
| + 'ctype': self._cpp_type_generator.GetType(prop)
|
| + }
|
| + if prop.optional:
|
| + (c.Append('out->%s.reset(new %s);' % (prop.unix_name, self._cpp_type_generator.GetType(prop)))
|
| + .Append('%s;' % populate_line)
|
| + )
|
| else:
|
| - raise NotImplementedError(prop.type_)
|
| - c.Substitute(sub)
|
| + (c.Append('if(!%s)' % populate_line)
|
| + .Append(' return false;')
|
| + )
|
| (c.Append('return true;')
|
| .Eblock('}')
|
| )
|
| return c
|
|
|
| - def _GenerateTypeTovalue(self, type_):
|
| + def _GenerateTypeToValue(self, cpp_namespace, type_):
|
| """Generates a function that serializes the type into a |DictionaryValue|.
|
| """
|
| c = code.Code()
|
| - (c.Sblock('DictionaryValue* %s::ToValue() const {' % type_.name)
|
| + (c.Sblock('DictionaryValue* %s::ToValue() const {' % cpp_namespace)
|
| .Append('DictionaryValue* value = new DictionaryValue();')
|
| .Append()
|
| )
|
| - name = type_.name.lower()
|
| for prop in type_.properties.values():
|
| - prop_name = name + '_' + prop.name if name else prop.name
|
| - this_var = prop.name
|
| - c.Concat(self._CreateValueFromProperty(prop_name, prop, this_var))
|
| + prop_name = prop.unix_name
|
| + c.Concat(self._CreateValueFromProperty(prop_name, prop, prop_name, 'value'))
|
| (c.Append()
|
| .Append('return value;')
|
| .Eblock('}')
|
| @@ -151,48 +150,30 @@ class CCGenerator(object):
|
| return c
|
|
|
| # TODO(calamity): object and choices prop types
|
| - def _CreateValueFromProperty(self, name, prop, var):
|
| + def _CreateValueFromProperty(self, name, prop, var, dst):
|
| """Generates code to serialize a single property in a type.
|
| """
|
| c = code.Code()
|
| - if prop.type_.is_fundamental:
|
| - c.Append('Value* %s_value = %s;' %
|
| - (name, cpp_util.CreateFundamentalValue(prop, var)))
|
| - elif prop.type_ == PropertyType.ARRAY:
|
| - if prop.item_type.type_ == PropertyType.STRING:
|
| - if prop.optional:
|
| - c.Append('json_schema_compiler::util::'
|
| - 'SetOptionalStrings(%s, "%s", value);' % (var, prop.name))
|
| - else:
|
| - c.Append('json_schema_compiler::util::'
|
| - 'SetStrings(%s, "%s", value);' % (var, prop.name))
|
| - else:
|
| - item_name = name + '_single'
|
| - (c.Append('ListValue* %(name)s_value = new ListValue();')
|
| - .Append('for (%(it_type)s::iterator it = %(var)s->begin();')
|
| - .Sblock(' it != %(var)s->end(); ++it) {')
|
| - .Concat(self._CreateValueFromProperty(item_name, prop.item_type,
|
| - '*it'))
|
| - .Append('%(name)s_value->Append(%(prop_val)s_value);')
|
| - .Eblock('}')
|
| - )
|
| - c.Substitute(
|
| - {'it_type': self._cpp_type_generator.GetType(prop),
|
| - 'name': name, 'var': var, 'prop_val': item_name})
|
| - elif prop.type_ == PropertyType.REF:
|
| - c.Append('Value* %s_value = %s.ToValue();' % (name, var))
|
| + if prop.type_ == PropertyType.ARRAY:
|
| + c.Append('%s;' % self._util_cc_helper.SetArray(prop, var, prop.name, dst))
|
| else:
|
| - raise NotImplementedError
|
| + c.Append('%s->SetWithoutPathExpansion("%s", %s);' %
|
| + (dst, prop.name, cpp_util.CreateValueFromSingleProperty(prop, var)))
|
| return c
|
|
|
| def _GenerateFunction(self, function):
|
| """Generates the definitions for function structs.
|
| """
|
| - classname = cpp_util.CppName(function.name)
|
| + classname = cpp_util.Classname(function.name)
|
| c = code.Code()
|
|
|
| # Params::Populate function
|
| if function.params:
|
| + for param in function.params:
|
| + if param.type_ == PropertyType.OBJECT:
|
| + param_namespace = '%s::Params::%s' % (classname, cpp_util.Classname(param.name))
|
| + c.Concat(self._GenerateType(param_namespace, param, serializable=False))
|
| + c.Append()
|
| (c.Append('%(name)s::Params::Params() {}')
|
| .Append('%(name)s::Params::~Params() {}')
|
| .Append()
|
| @@ -210,13 +191,13 @@ class CCGenerator(object):
|
| def _GenerateFunctionParamsCreate(self, function):
|
| """Generate function to create an instance of Params given a pointer.
|
| """
|
| - classname = cpp_util.CppName(function.name)
|
| + classname = cpp_util.Classname(function.name)
|
| c = code.Code()
|
| (c.Append('// static')
|
| .Sblock('scoped_ptr<%(classname)s::Params> %(classname)s::Params::Create'
|
| '(const ListValue& args) {')
|
| - .Append('if (args.GetSize() != %d)' % len(function.params))
|
| - .Append(' return scoped_ptr<Params>();')
|
| + #.Append('if (args.GetSize() != %d)' % len(function.params))
|
| + #.Append(' return scoped_ptr<Params>();')
|
| .Append()
|
| .Append('scoped_ptr<Params> params(new Params());')
|
| )
|
| @@ -225,29 +206,44 @@ class CCGenerator(object):
|
| # TODO(calamity): generalize, needs to move to function to do populates for
|
| # wider variety of args
|
| for i, param in enumerate(function.params):
|
| - sub = {'name': param.name, 'pos': i}
|
| + dst = 'params->' + param.unix_name
|
| + if param.optional:
|
| + return_line = ' return params.Pass();'
|
| + else:
|
| + return_line = ' return scoped_ptr<Params>();'
|
| c.Append()
|
| - # TODO(calamity): Make valid for not just objects
|
| - c.Append('DictionaryValue* %(name)s_param = NULL;')
|
| - c.Append('if (!args.GetDictionary(%(pos)d, &%(name)s_param))')
|
| - c.Append(' return scoped_ptr<Params>();')
|
| - if param.type_ == PropertyType.REF:
|
| - c.Append('if (!%(ctype)s::Populate(*%(name)s_param, '
|
| - '¶ms->%(name)s))')
|
| - c.Append(' return scoped_ptr<Params>();')
|
| - sub['ctype'] = self._cpp_type_generator.GetType(param)
|
| - elif param.type_.is_fundamental:
|
| - raise NotImplementedError('Fundamental types are unimplemented')
|
| - elif param.type_ == PropertyType.OBJECT:
|
| - c.Append('if (!%(ctype)s::Populate(*%(name)s_param, '
|
| - '¶ms->%(name)s))')
|
| - c.Append(' return scoped_ptr<Params>();')
|
| - sub['ctype'] = self._cpp_type_generator.GetType(param)
|
| - elif param.type_ == PropertyType.CHOICES:
|
| - raise NotImplementedError('Choices is unimplemented')
|
| + param_var = param.unix_name + '_param'
|
| + if param.type_ == PropertyType.ARRAY:
|
| + (c.Append('ListValue* %(var)s = NULL;')
|
| + .Append('if (!args.GetList(%(index)d, &%(var)s))')
|
| + .Append(return_line)
|
| + .Append('if (!%s)' % self._util_cc_helper.GetArrayFromList(
|
| + param, param_var, 'params->%s' % param.unix_name))
|
| + .Append(return_line)
|
| + )
|
| + c.Substitute({'var': param_var, 'index': i})
|
| else:
|
| - raise NotImplementedError(param.type_)
|
| - c.Substitute(sub)
|
| + if param.optional:
|
| + dst = dst + '.get()'
|
| + else:
|
| + dst = '&' + dst
|
| + if param.type_ == PropertyType.REF or param.type_ == PropertyType.OBJECT:
|
| + (c.Append('DictionaryValue* %s = NULL;' % param_var)
|
| + .Append('if (!args.GetDictionary(%d, &%s))' % (i, param_var))
|
| + .Append(return_line)
|
| + )
|
| + if param.optional:
|
| + c.Append('params->%s.reset(new %s());' % (param.unix_name, cpp_util.Classname(param.name)))
|
| + (c.Append('if(!%(ctype)s::Populate(*%(var)s, %(dst)s))' % {
|
| + 'var': param_var, 'dst': dst,
|
| + 'ctype': self._cpp_type_generator.GetType(param)
|
| + })
|
| + .Append(return_line)
|
| + )
|
| + elif param.type_.is_fundamental:
|
| + (c.Append('if(!%s)' % cpp_util.GetValueFromList(param, 'args', i, dst))
|
| + .Append(return_line)
|
| + )
|
| c.Append()
|
| c.Append('return params.Pass();')
|
| c.Eblock('}')
|
| @@ -257,38 +253,43 @@ class CCGenerator(object):
|
| def _GenerateFunctionResultCreate(self, function):
|
| """Generate function to create a Result given the return value.
|
| """
|
| - classname = cpp_util.CppName(function.name)
|
| + classname = cpp_util.Classname(function.name)
|
| c = code.Code()
|
| c.Append('// static')
|
| - param = function.callback.param
|
| - arg = ''
|
| - if param:
|
| - if param.type_ == PropertyType.REF:
|
| - arg = 'const %(type)s& %(name)s'
|
| - else:
|
| - arg = 'const %(type)s %(name)s'
|
| - arg = arg % {
|
| - 'type': self._cpp_type_generator.GetType(param),
|
| - 'name': param.name
|
| - }
|
| - c.Sblock('Value* %(classname)s::Result::Create(%(arg)s) {')
|
| - sub = {'classname': classname, 'arg': arg}
|
| - # TODO(calamity): Choices
|
| - if not param:
|
| - c.Append('return Value::CreateNullValue();')
|
| + params = function.callback.params
|
| + args = []
|
| +
|
| + if not params:
|
| + (c.Append('Value* %s::Result::Create() {' % classname)
|
| + .Append(' return Value::CreateNullValue();')
|
| + .Append('}')
|
| + )
|
| else:
|
| - sub['argname'] = param.name
|
| - if param.type_.is_fundamental:
|
| - c.Append('return %s;' %
|
| - cpp_util.CreateFundamentalValue(param, param.name))
|
| - elif param.type_ == PropertyType.REF:
|
| - c.Append('return %(argname)s.ToValue();')
|
| - elif param.type_ == PropertyType.OBJECT:
|
| - raise NotImplementedError('Objects not implemented')
|
| - elif param.type_ == PropertyType.ARRAY:
|
| - raise NotImplementedError('Arrays not implemented')
|
| - else:
|
| - raise NotImplementedError(param.type_)
|
| - c.Substitute(sub)
|
| - c.Eblock('}')
|
| + for param in params:
|
| + sub = {
|
| + 'type': self._cpp_type_generator.GetType(param),
|
| + 'name': param.unix_name,
|
| + }
|
| + arg = 'const %(type)s %(name)s'
|
| + if param.type_ == PropertyType.REF:
|
| + arg = 'const %(type)s& %(name)s'
|
| + arg = arg % sub
|
| + if param and param.description:
|
| + c.Comment(param.description)
|
| + c.Sblock('Value* %(classname)s::Result::Create(%(arg)s) {')
|
| + sub = {'classname': classname, 'arg': arg}
|
| + if param.type_ == PropertyType.ARRAY:
|
| + (c.Append('ListValue* l = new ListValue();')
|
| + .Append('for (' + self._cpp_type_generator.GetType(param) +
|
| + '::const_iterator it = %(var)s.begin(); it != %(var)s.end(); ++it) {')
|
| + .Append(' l->Append(%s);' % cpp_util.CreateValueFromSingleProperty(param.item_type, '(**it)'))
|
| + .Append('}')
|
| + .Append('return l;')
|
| + )
|
| + sub['var'] = param.unix_name
|
| + else:
|
| + c.Append('return %s;' % cpp_util.CreateValueFromSingleProperty(param, param.unix_name))
|
| + c.Substitute(sub)
|
| + c.Eblock('}')
|
| +
|
| return c
|
|
|