def _GenerateValueIsTypeExpression(self, var, type_): real_type = self._type_helper.FollowRef(type_) if real_type.property_type is PropertyType.CHOICES: return '(%s)' % ' || '.join(self._GenerateValueIsTypeExpression(var, choice) for choice in real_type.choices) return '%s.IsType(%s)' % (var, cpp_util.GetValueType(real_type))
def _GeneratePopulatePropertyFromValue(self, prop, value_var, dst, failure_value, check_type=True): """Generates code to populate a model.Property given a base::Value*. The existence of data inside the base::Value* is assumed so checks for existence should be performed before the code this generates. prop: the property the code is populating. value_var: a base::Value* that should represent |prop|. dst: the object with |prop| as a member. failure_value: the value to return if |prop| cannot be extracted from |value_var| check_type: if true, will check if |value_var| is the correct base::Value::Type """ c = Code() c.Sblock('{') if self._IsFundamentalOrFundamentalRef(prop): 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
def _GenerateTypePopulate(self, cpp_namespace, type_): """Generates the function for populating a type given a pointer to it. E.g for type "Foo", generates Foo::Populate() """ classname = cpp_util.Classname(schema_util.StripNamespace(type_.name)) c = Code() (c.Append('// static').Append('bool %(namespace)s::Populate(').Sblock( ' const base::Value& value, %(name)s* out) {')) if type_.property_type == PropertyType.CHOICES: for choice in type_.choices: value_type = cpp_util.GetValueType( self._type_helper.FollowRef(choice)) (c.Sblock('if (value.IsType(%s)) {' % value_type).Concat( self._GeneratePopulateVariableFromValue( choice, '(&value)', 'out->as_%s' % choice.unix_name, 'false', is_ptr=True)).Append('return true;').Eblock('}')) c.Append('return false;') elif type_.property_type == PropertyType.OBJECT: (c.Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))'). Append(' return false;')) if type_.properties or type_.additional_properties is not None: c.Append('const base::DictionaryValue* dict = ' 'static_cast<const base::DictionaryValue*>(&value);') for prop in type_.properties.values(): c.Concat(self._InitializePropertyToDefault(prop, 'out')) for prop in type_.properties.values(): c.Concat( self._GenerateTypePopulateProperty(prop, 'dict', 'out')) if type_.additional_properties is not None: if type_.additional_properties.property_type == PropertyType.ANY: c.Append( 'out->additional_properties.MergeDictionary(dict);') else: cpp_type = self._type_helper.GetCppType( type_.additional_properties, is_in_container=True) (c.Append('for (base::DictionaryValue::Iterator it(*dict);' ).Sblock(' !it.IsAtEnd(); it.Advance()) {'). Append('%s tmp;' % cpp_type).Concat( self._GeneratePopulateVariableFromValue( type_.additional_properties, '(&it.value())', 'tmp', 'false')).Append( 'out->additional_properties[it.key()] = tmp;' ).Eblock('}')) c.Append('return true;') (c.Eblock('}').Substitute({ 'namespace': cpp_namespace, 'name': classname })) return c
def _GenerateChoicePopulate(self, c, prop, value_var, dst, failure_value): type_var = '%(dst)s->%(name)s_type' c.Sblock('switch (%(value_var)s->GetType()) {') for choice in self._cpp_type_generator.ExpandParams([prop]): (c.Sblock('case %s: {' % cpp_util.GetValueType( self._cpp_type_generator.GetReferencedProperty(choice).type_)). Concat( self._GeneratePopulatePropertyFromValue( choice, value_var, dst, failure_value, check_type=False)).Append( '%s = %s;' % (type_var, self._cpp_type_generator.GetEnumValue( prop, choice.type_.name))).Append( 'break;').Eblock('}')) (c.Append('default:').Append(' return %(failure_value)s;')) c.Eblock('}')
def _GeneratePopulatePropertyFromValue(self, prop, value_var, dst, failure_value, check_type=True): """Generates code to populate a model.Property given a Value*. The existence of data inside the Value* is assumed so checks for existence should be performed before the code this generates. prop: the property the code is populating. value_var: a Value* that should represent |prop|. dst: the object with |prop| as a member. failure_value: the value to return if |prop| cannot be extracted from |value_var| check_type: if true, will check if |value_var| is the correct Value::Type """ c = Code() 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;').Append( '%(dst)s->%(name)s.reset(new %(ctype)s(temp));')) else: (c.Append('if (!%s)' % cpp_util.GetAsFundamentalValue( self._cpp_type_generator.GetReferencedProperty(prop), value_var, '&%s->%s' % (dst, prop.unix_name))).Append( ' return %(failure_value)s;')) elif self._IsObjectOrObjectRef(prop): if prop.optional: (c.Append('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('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.ANY: if prop.optional: c.Append('%(dst)s->%(name)s.reset(new Any());') 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('ListValue* list = NULL;'). Append('if (!%(value_var)s->GetAsList(&list))').Append( ' return %(failure_value)s;').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;')) elif prop.type_ == PropertyType.CHOICES: type_var = '%(dst)s->%(name)s_type' c.Sblock('switch (%(value_var)s->GetType()) {') for choice in self._cpp_type_generator.GetExpandedChoicesInParams( [prop]): (c.Sblock('case %s: {' % cpp_util.GetValueType( self._cpp_type_generator.GetReferencedProperty( choice).type_)).Concat( self._GeneratePopulatePropertyFromValue( choice, value_var, dst, failure_value, check_type=False)).Append( '%s = %s;' % (type_var, self._cpp_type_generator.GetEnumValue( prop, choice.type_.name))).Append( 'break;').Eblock('}')) (c.Append('default:').Append(' return %(failure_value)s;')) c.Eblock('}') elif prop.type_ == PropertyType.ENUM: (c.Append('std::string enum_temp;').Append( 'if (!%(value_var)s->GetAsString(&enum_temp))').Append( ' return %(failure_value)s;')) for i, enum_value in enumerate(prop.enum_values): (c.Append(('if' if i == 0 else 'else if') + '(enum_temp == "%s")' % enum_value).Append( ' %s->%s = %s;' % (dst, prop.unix_name, self._cpp_type_generator.GetEnumValue( prop, enum_value)))) (c.Append('else').Append(' return %(failure_value)s;')) elif prop.type_ == PropertyType.BINARY: # This is the same if the property is optional or not. We need a pointer # to the BinaryValue to be able to populate it, so a scoped_ptr is used # whether it is optional or required. (c.Append('if (!%(value_var)s->IsType(%(value_type)s))').Append( ' return %(failure_value)s;'). Append('%(dst)s->%(name)s.reset(').Append( ' static_cast<BinaryValue*>(%(value_var)s)->DeepCopy());')) 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['value_type'] = cpp_util.GetValueType( self._cpp_type_generator.GetReferencedProperty(prop).type_) c.Substitute(sub) return c
def _GeneratePopulateVariableFromValue(self, type_, src_var, dst_var, failure_value, is_ptr=False): """Generates code to populate a variable |dst_var| of type |type_| from a Value* at |src_var|. The Value* is assumed to be non-NULL. In the generated code, if |dst_var| fails to be populated then Populate will return |failure_value|. """ c = Code() c.Sblock('{') underlying_type = self._type_helper.FollowRef(type_) if underlying_type.property_type.is_fundamental: if is_ptr: (c.Append('%(cpp_type)s temp;').Append( 'if (!%s)' % cpp_util.GetAsFundamentalValue( self._type_helper.FollowRef(type_), src_var, '&temp')).Append(' return %(failure_value)s;').Append( '%(dst_var)s.reset(new %(cpp_type)s(temp));')) else: (c.Append('if (!%s)' % cpp_util.GetAsFundamentalValue( self._type_helper.FollowRef(type_), src_var, '&%s' % dst_var)).Append(' return %(failure_value)s;')) elif underlying_type.property_type == PropertyType.OBJECT: if is_ptr: (c.Append('const base::DictionaryValue* dictionary = NULL;'). Append('if (!%(src_var)s->GetAsDictionary(&dictionary))'). Append(' return %(failure_value)s;').Append( 'scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());'). Append('if (!%(cpp_type)s::Populate(*dictionary, temp.get()))' ).Append(' return %(failure_value)s;').Append( '%(dst_var)s = temp.Pass();')) else: (c.Append('const base::DictionaryValue* dictionary = NULL;'). Append('if (!%(src_var)s->GetAsDictionary(&dictionary))'). Append(' return %(failure_value)s;').Append( 'if (!%(cpp_type)s::Populate(*dictionary, &%(dst_var)s))' ).Append(' return %(failure_value)s;')) elif underlying_type.property_type == PropertyType.FUNCTION: if is_ptr: c.Append('%(dst_var)s.reset(new base::DictionaryValue());') elif underlying_type.property_type == PropertyType.ANY: c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());') elif underlying_type.property_type == PropertyType.ARRAY: # util_cc_helper deals with optional and required arrays (c.Append('const base::ListValue* list = NULL;').Append( 'if (!%(src_var)s->GetAsList(&list))').Append( ' return %(failure_value)s;')) item_type = underlying_type.item_type if item_type.property_type == PropertyType.ENUM: c.Concat( self._GenerateListValueToEnumArrayConversion( item_type, 'list', dst_var, failure_value, is_ptr=is_ptr)) else: (c.Append('if (!%s)' % self._util_cc_helper.PopulateArrayFromList( underlying_type, 'list', dst_var, is_ptr)).Append(' return %(failure_value)s;')) elif underlying_type.property_type == PropertyType.CHOICES: if is_ptr: (c.Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') .Append( 'if (!%(cpp_type)s::Populate(*%(src_var)s, temp.get()))'). Append(' return %(failure_value)s;').Append( '%(dst_var)s = temp.Pass();')) else: (c.Append( 'if (!%(cpp_type)s::Populate(*%(src_var)s, &%(dst_var)s))' ).Append(' return %(failure_value)s;')) elif underlying_type.property_type == PropertyType.ENUM: c.Concat( self._GenerateStringToEnumConversion(type_, src_var, dst_var, failure_value)) elif underlying_type.property_type == PropertyType.BINARY: (c.Append('if (!%(src_var)s->IsType(%(value_type)s))').Append( ' return %(failure_value)s;'). Append('const base::BinaryValue* binary_value =').Append( ' static_cast<const base::BinaryValue*>(%(src_var)s);')) if is_ptr: (c.Append('%(dst_var)s.reset(').Append( ' new std::string(binary_value->GetBuffer(),').Append( ' binary_value->GetSize()));')) else: (c.Append('%(dst_var)s.assign(binary_value->GetBuffer(),'). Append(' binary_value->GetSize());')) else: raise NotImplementedError(type_) sub = { 'cpp_type': self._type_helper.GetCppType(type_), 'src_var': src_var, 'dst_var': dst_var, 'failure_value': failure_value, } if underlying_type.property_type not in (PropertyType.ANY, PropertyType.CHOICES): sub['value_type'] = cpp_util.GetValueType(underlying_type) return c.Eblock('}').Substitute(sub)