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. |