Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: tools/json_schema_compiler/cc_generator.py

Issue 10828407: JSON Schema Compiler supports Enums as types. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: more testing of optional enums Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 d09d32584754bfee863b2672e1a038951b3eaa5a..843fe9606e0de9885f88d179c79c1922a3f25e76 100644
--- a/tools/json_schema_compiler/cc_generator.py
+++ b/tools/json_schema_compiler/cc_generator.py
@@ -127,6 +127,9 @@ class CCGenerator(object):
(c.Concat(self._GenerateTypeToValue(cpp_namespace, type_))
.Append()
)
+ elif self._IsEnumRef(type_):
+ c.Concat(self._GenerateCreateEnumTypeValue(cpp_namespace, type_))
+ c.Append()
c.Substitute({'classname': classname, 'namespace': cpp_namespace})
return c
@@ -252,7 +255,7 @@ class CCGenerator(object):
c.Append('value->MergeDictionary(&%s);' % prop.unix_name)
else:
if prop.optional:
- if prop.type_ == PropertyType.ENUM:
+ if self._cpp_type_generator.IsEnumOrEnumRef(prop):
c.Sblock('if (%s != %s) {' %
(prop.unix_name,
self._cpp_type_generator.GetEnumNoneValue(prop)))
@@ -339,7 +342,7 @@ class CCGenerator(object):
else:
vardot = var + '.'
return '%sDeepCopy()' % vardot
- elif prop.type_ == PropertyType.ENUM:
+ elif self._cpp_type_generator.IsEnumOrEnumRef(prop):
return 'CreateEnumValue(%s).release()' % var
elif prop.type_ == PropertyType.BINARY:
if prop.optional:
@@ -460,89 +463,130 @@ class CCGenerator(object):
c.Sblock('{')
if self._IsFundamentalOrFundamentalRef(prop):
- if prop.optional:
- (c.Append('%(ctype)s temp;')
- .Append('if (!%s)' %
- cpp_util.GetAsFundamentalValue(
- self._cpp_type_generator.GetReferencedProperty(prop),
- value_var,
- '&temp'))
- .Append(' return %(failure_value)s;')
- )
- if prop.type_ != prop.compiled_type:
- (c.Append('%(compiled_ctype)s temp2;')
- .Append('if (!%s)' %
- cpp_util.GenerateTypeToCompiledTypeConversion(
- self._cpp_type_generator.GetReferencedProperty(prop),
- 'temp',
- 'temp2'))
- .Append(' return %(failure_value)s;')
- .Append('%(dst)s->%(name)s.reset(new %(compiled_ctype)s(temp2));')
- )
- else:
- c.Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));')
+ self._GenerateFundamentalOrFundamentalRefPopulate(c, prop, value_var, dst)
+ elif self._IsObjectOrObjectRef(prop):
+ self._GenerateObjectOrObjectRefPopulate(c, prop)
+ elif prop.type_ == PropertyType.FUNCTION:
+ self._GenerateFunctionPopulate(c, prop)
+ elif prop.type_ == PropertyType.ANY:
+ self._GenerateAnyPopulate(c, prop, value_var, dst)
+ elif self._IsArrayOrArrayRef(prop):
+ self._GenerateArrayOrArrayRefPopulate(c, prop, dst)
+ elif prop.type_ == PropertyType.CHOICES:
+ self._GenerateChoicePopulate(c, prop, value_var, dst, failure_value)
+ elif self._cpp_type_generator.IsEnumOrEnumRef(prop):
+ self._GenerateEnumPopulate(c, prop, value_var)
+ elif prop.type_ == PropertyType.BINARY:
+ self._GenerateBinaryPopulate(c, prop)
+ else:
+ raise NotImplementedError(prop.type_)
+ c.Eblock('}')
+ sub = {
+ 'value_var': value_var,
+ 'name': prop.unix_name,
+ 'dst': dst,
+ 'failure_value': failure_value,
+ }
+ if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY):
+ sub['ctype'] = self._cpp_type_generator.GetType(prop)
+ sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(prop)
+ sub['value_type'] = cpp_util.GetValueType(self._cpp_type_generator
+ .GetReferencedProperty(prop).type_)
+ c.Substitute(sub)
+ return c
- else:
- if prop.type_ == prop.compiled_type:
- assignment_target = '&%s->%s' % (dst, prop.unix_name)
- else:
- c.Append('%(ctype)s temp;')
- assignment_target = '&temp'
- (c.Append('if (!%s)' %
+ def _GenerateFundamentalOrFundamentalRefPopulate(self,
+ c,
+ prop,
+ value_var,
+ dst):
+ if prop.optional:
+ (c.Append('%(ctype)s temp;')
+ .Append('if (!%s)' %
cpp_util.GetAsFundamentalValue(
self._cpp_type_generator.GetReferencedProperty(prop),
value_var,
- assignment_target))
- .Append(' return %(failure_value)s;')
- )
- if prop.type_ != prop.compiled_type:
- (c.Append('if (!%s)' %
- cpp_util.GenerateTypeToCompiledTypeConversion(
- self._cpp_type_generator.GetReferencedProperty(prop),
- 'temp',
- '%s->%s' % (dst, prop.unix_name)))
- .Append(' return %(failure_value)s;')
- )
-
- elif self._IsObjectOrObjectRef(prop):
- if prop.optional:
- (c.Append('const base::DictionaryValue* dictionary = NULL;')
- .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))')
- .Append(' return %(failure_value)s;')
- .Append('scoped_ptr<%(ctype)s> temp(new %(ctype)s());')
- .Append('if (!%(ctype)s::Populate(*dictionary, temp.get()))')
+ '&temp'))
+ .Append(' return %(failure_value)s;')
+ )
+ if prop.type_ != prop.compiled_type:
+ (c.Append('%(compiled_ctype)s temp2;')
+ .Append('if (!%s)' %
+ cpp_util.GenerateTypeToCompiledTypeConversion(
+ self._cpp_type_generator.GetReferencedProperty(prop),
+ 'temp',
+ 'temp2'))
.Append(' return %(failure_value)s;')
- .Append('%(dst)s->%(name)s = temp.Pass();')
+ .Append('%(dst)s->%(name)s.reset(new %(compiled_ctype)s(temp2));')
)
else:
- (c.Append('const base::DictionaryValue* dictionary = NULL;')
- .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))')
- .Append(' return %(failure_value)s;')
- .Append(
- 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))')
- .Append(' return %(failure_value)s;')
- )
- elif prop.type_ == PropertyType.FUNCTION:
- if prop.optional:
- c.Append('%(dst)s->%(name)s.reset(new base::DictionaryValue());')
- elif prop.type_ == PropertyType.ANY:
- if prop.optional:
- c.Append('%(dst)s->%(name)s.reset(new ' + any_helper.ANY_CLASS + '());')
- c.Append(self._any_helper.Init(prop, value_var, dst) + ';')
- elif self._IsArrayOrArrayRef(prop):
- # util_cc_helper deals with optional and required arrays
- (c.Append('const base::ListValue* list = NULL;')
- .Append('if (!%(value_var)s->GetAsList(&list))')
- .Append(' return %(failure_value)s;'))
- if prop.item_type.type_ == PropertyType.ENUM:
- self._GenerateListValueToEnumArrayConversion(c, prop)
+ c.Append('%(dst)s->%(name)s.reset(new %(ctype)s(temp));')
+
+ else:
+ if prop.type_ == prop.compiled_type:
+ assignment_target = '&%s->%s' % (dst, prop.unix_name)
else:
- (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList(
- self._cpp_type_generator.GetReferencedProperty(prop), 'list',
- dst + '->' + prop.unix_name, prop.optional))
+ c.Append('%(ctype)s temp;')
+ assignment_target = '&temp'
+ (c.Append('if (!%s)' %
+ cpp_util.GetAsFundamentalValue(
+ self._cpp_type_generator.GetReferencedProperty(prop),
+ value_var,
+ assignment_target))
+ .Append(' return %(failure_value)s;')
+ )
+ if prop.type_ != prop.compiled_type:
+ (c.Append('if (!%s)' %
+ cpp_util.GenerateTypeToCompiledTypeConversion(
+ self._cpp_type_generator.GetReferencedProperty(prop),
+ 'temp',
+ '%s->%s' % (dst, prop.unix_name)))
.Append(' return %(failure_value)s;')
)
- elif prop.type_ == PropertyType.CHOICES:
+
+ def _GenerateObjectOrObjectRefPopulate(self, c, prop):
+ if prop.optional:
+ (c.Append('const base::DictionaryValue* dictionary = NULL;')
+ .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))')
+ .Append(' return %(failure_value)s;')
+ .Append('scoped_ptr<%(ctype)s> temp(new %(ctype)s());')
+ .Append('if (!%(ctype)s::Populate(*dictionary, temp.get()))')
+ .Append(' return %(failure_value)s;')
+ .Append('%(dst)s->%(name)s = temp.Pass();')
+ )
+ else:
+ (c.Append('const base::DictionaryValue* dictionary = NULL;')
+ .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))')
+ .Append(' return %(failure_value)s;')
+ .Append(
+ 'if (!%(ctype)s::Populate(*dictionary, &%(dst)s->%(name)s))')
+ .Append(' return %(failure_value)s;')
+ )
+
+ def _GenerateFunctionPopulate(self, c, prop):
+ if prop.optional:
+ c.Append('%(dst)s->%(name)s.reset(new base::DictionaryValue());')
+
+ def _GenerateAnyPopulate(self, c, prop, value_var, dst):
+ if prop.optional:
+ c.Append('%(dst)s->%(name)s.reset(new ' + any_helper.ANY_CLASS + '());')
+ c.Append(self._any_helper.Init(prop, value_var, dst) + ';')
+
+ def _GenerateArrayOrArrayRefPopulate(self, c, prop, dst):
+ # util_cc_helper deals with optional and required arrays
+ (c.Append('const base::ListValue* list = NULL;')
+ .Append('if (!%(value_var)s->GetAsList(&list))')
+ .Append(' return %(failure_value)s;'))
+ if prop.item_type.type_ == PropertyType.ENUM:
+ self._GenerateListValueToEnumArrayConversion(c, prop)
+ else:
+ (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList(
+ self._cpp_type_generator.GetReferencedProperty(prop), 'list',
+ dst + '->' + prop.unix_name, prop.optional))
+ .Append(' return %(failure_value)s;')
+ )
+
+ def _GenerateChoicePopulate(self, c, prop, value_var, dst, failure_value):
type_var = '%(dst)s->%(name)s_type'
Yoyo Zhou 2012/08/27 23:56:04 nit: indent is 2
chebert 2012/08/28 21:31:14 Done.
c.Sblock('switch (%(value_var)s->GetType()) {')
for choice in self._cpp_type_generator.ExpandParams([prop]):
@@ -561,42 +605,39 @@ class CCGenerator(object):
.Append(' return %(failure_value)s;')
)
c.Eblock('}')
- elif prop.type_ == PropertyType.ENUM:
- c.Sblock('{')
- self._GenerateStringToEnumConversion(c, prop, value_var, 'enum_temp')
+
+ def _GenerateEnumTypePopulate(self, c, prop, value_var):
Yoyo Zhou 2012/08/27 23:56:04 Is this ever called?
chebert 2012/08/28 21:31:14 Nope. Deleting it. On 2012/08/27 23:56:04, Yoyo Zh
+ c.Sblock('{')
+ self._GenerateStringToEnumConversion(c, prop, value_var, 'enum_temp',
+ self._cpp_type_generator.GetReferencedProperty(prop).enum_values)
Yoyo Zhou 2012/08/27 23:56:04 indentation is either 4 spaces after an open paren
chebert 2012/08/28 21:31:14 Done.
+ if prop.optional:
+ c.Append('%(dst)s->%(name)s.reset(enum_temp);')
+ else:
c.Append('%(dst)s->%(name)s = enum_temp;')
- c.Eblock('}')
- elif prop.type_ == PropertyType.BINARY:
- (c.Append('if (!%(value_var)s->IsType(%(value_type)s))')
- .Append(' return %(failure_value)s;')
- .Append('const base::BinaryValue* binary_value =')
- .Append(' static_cast<const base::BinaryValue*>(%(value_var)s);')
+ c.Eblock('}')
+
+ def _GenerateEnumPopulate(self, c, prop, value_var):
+ c.Sblock('{')
+ self._GenerateStringToEnumConversion(c, prop, value_var, 'enum_temp',
+ self._cpp_type_generator.GetReferencedProperty(prop).enum_values)
Yoyo Zhou 2012/08/27 23:56:04 Seems like you can use this inside GenerateStringT
chebert 2012/08/28 21:31:14 Done.
+ c.Append('%(dst)s->%(name)s = enum_temp;')
+ c.Eblock('}')
+
+ def _GenerateBinaryPopulate(self, c, prop):
+ (c.Append('if (!%(value_var)s->IsType(%(value_type)s))')
+ .Append(' return %(failure_value)s;')
+ .Append('const base::BinaryValue* binary_value =')
+ .Append(' static_cast<const base::BinaryValue*>(%(value_var)s);')
+ )
+ if prop.optional:
+ (c.Append('%(dst)s->%(name)s.reset(')
+ .Append(' new std::string(binary_value->GetBuffer(),')
+ .Append(' binary_value->GetSize()));')
)
- if prop.optional:
- (c.Append('%(dst)s->%(name)s.reset(')
- .Append(' new std::string(binary_value->GetBuffer(),')
- .Append(' binary_value->GetSize()));')
- )
- else:
- (c.Append('%(dst)s->%(name)s.assign(binary_value->GetBuffer(),')
- .Append(' binary_value->GetSize());')
- )
else:
- raise NotImplementedError(prop.type_)
- c.Eblock('}')
- sub = {
- 'value_var': value_var,
- 'name': prop.unix_name,
- 'dst': dst,
- 'failure_value': failure_value,
- }
- if prop.type_ not in (PropertyType.CHOICES, PropertyType.ANY):
- sub['ctype'] = self._cpp_type_generator.GetType(prop)
- sub['compiled_ctype'] = self._cpp_type_generator.GetCompiledType(prop)
- sub['value_type'] = cpp_util.GetValueType(self._cpp_type_generator
- .GetReferencedProperty(prop).type_)
- c.Substitute(sub)
- return c
+ (c.Append('%(dst)s->%(name)s.assign(binary_value->GetBuffer(),')
+ .Append(' binary_value->GetSize());')
+ )
def _GenerateListValueToEnumArrayConversion(self, c, prop):
"""Appends code that converts a ListValue of string contstants to
@@ -613,12 +654,17 @@ class CCGenerator(object):
accessor = '->'
c.Sblock('for (ListValue::const_iterator it = list->begin(); '
'it != list->end(); ++it) {')
- self._GenerateStringToEnumConversion(c, prop.item_type,
- '(*it)', 'enum_temp')
+ self._GenerateStringToEnumConversion(c, prop.item_type, '(*it)',
+ 'enum_temp', prop.item_type.enum_values)
Yoyo Zhou 2012/08/27 23:56:04 same comment about indent.
chebert 2012/08/28 21:31:14 Done.
c.Append('%(dst)s->%(name)s' + accessor + 'push_back(enum_temp);')
c.Eblock('}')
- def _GenerateStringToEnumConversion(self, c, prop, value_var, enum_temp):
+ def _GenerateStringToEnumConversion(self,
+ c,
+ prop,
+ value_var,
+ enum_temp,
+ enum_values):
"""Appends code that converts a string to an enum.
Leaves failure_value unsubstituded.
Yoyo Zhou 2012/08/27 23:56:04 typo: unsubstituted
chebert 2012/08/28 21:31:14 Done.
@@ -626,13 +672,15 @@ class CCGenerator(object):
prop: the property that the code is populating.
value_var: the string value that is being converted.
enum_temp: the name used to store the temporary enum value.
+ enum_values: the list of possible enum values.
"""
- (c.Append('%s %s;' % (self._cpp_type_generator.GetType(prop), enum_temp))
+ (c.Append('%s %s;' % (self._cpp_type_generator.GetCompiledType(prop),
+ enum_temp))
.Append('std::string enum_as_string;')
.Append('if (!%s->GetAsString(&enum_as_string))' % value_var)
.Append(' return %(failure_value)s;')
)
- for i, enum_value in enumerate(prop.enum_values):
+ for i, enum_value in enumerate(enum_values):
(c.Append(
('if' if i == 0 else 'else if') +
'(enum_as_string == "%s")' % enum_value)
@@ -697,6 +745,29 @@ class CCGenerator(object):
)
return c
+ def _GenerateCreateEnumTypeValue(self, cpp_namespace, prop):
+ """Generates CreateEnumValue() that returns the base::StringValue
Yoyo Zhou 2012/08/27 23:56:04 Sorry, but I'm confused as to how this function di
chebert 2012/08/28 21:31:14 The plan I believe is to phase out the old-style o
+ representation of an enum type.
+ """
+ c = Code()
+ classname = cpp_util.Classname(schema_util.StripSchemaNamespace(prop.name))
+ c.Sblock('scoped_ptr<base::Value> CreateEnumValue(%s %s) {' % (
+ classname, classname.lower()))
+ c.Sblock('switch (%s) {' % classname.lower())
+
+ enum_prop = self._cpp_type_generator.GetReferencedProperty(prop)
+ for enum_value in enum_prop.enum_values:
+ c.Concat(self._GenerateReturnCase(
+ '%s_%s' % (classname.upper(), enum_value.upper()),
+ 'scoped_ptr<base::Value>(base::Value::CreateStringValue("%s"))' %
+ enum_value))
+ (c.Eblock('}')
+ .Append('NOTREACHED();')
+ .Append('return scoped_ptr<base::Value>();')
+ .Eblock('}')
+ )
+ return c
+
def _GenerateCreateEnumValue(self, cpp_namespace, prop):
"""Generates CreateEnumValue() that returns the base::StringValue
representation of an enum.
@@ -813,7 +884,8 @@ class CCGenerator(object):
dst: Type*
"""
c = Code()
- if prop.type_ in (PropertyType.ENUM, PropertyType.CHOICES):
+ if (self._cpp_type_generator.IsEnumOrEnumRef(prop) or
+ prop.type_ == PropertyType.CHOICES):
if prop.optional:
prop_name = prop.unix_name
if prop.type_ == PropertyType.CHOICES:
@@ -836,6 +908,12 @@ class CCGenerator(object):
return (self._cpp_type_generator.GetReferencedProperty(prop).type_ ==
PropertyType.ARRAY)
+ def _IsEnumRef(self, type_):
+ """Determines if this type is an Enum ref but not an Enum.
+ """
+ return (self._cpp_type_generator.IsEnumOrEnumRef(type_) and
+ type_ != PropertyType.ENUM)
+
def _IsFundamentalOrFundamentalRef(self, prop):
"""Determines if this property is a Fundamental type or is a ref to a
Fundamental type.
« no previous file with comments | « no previous file | tools/json_schema_compiler/cpp_type_generator.py » ('j') | tools/json_schema_compiler/cpp_type_generator.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698