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, '&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));') 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)' % 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;'))
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() underlying_type = self._type_helper.FollowRef(type_) if underlying_type.property_type.is_fundamental: if is_ptr: (c.Append('%(cpp_type)s temp;') .Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue( self._type_helper.FollowRef(type_), src_var, '&temp')) .Concat(self._GenerateError( '"\'%%(key)s\': expected ' + '%s, got " + %s' % ( type_.name, self._util_cc_helper.GetValueTypeString( '%%(src_var)s', True))))) c.Append('%(dst_var)s.reset();') if not self._generate_error_messages: c.Append('return %(failure_value)s;') (c.Eblock('}') .Append('else') .Append(' %(dst_var)s.reset(new %(cpp_type)s(temp));') ) else: (c.Sblock('if (!%s) {' % cpp_util.GetAsFundamentalValue( self._type_helper.FollowRef(type_), src_var, '&%s' % dst_var)) .Concat(self._GenerateError( '"\'%%(key)s\': expected ' + '%s, got " + %s' % ( type_.name, self._util_cc_helper.GetValueTypeString( '%%(src_var)s', True)))) .Append('return %(failure_value)s;') .Eblock('}') ) elif underlying_type.property_type == PropertyType.OBJECT: if is_ptr: (c.Append('const base::DictionaryValue* dictionary = NULL;') .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected dictionary, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True)))) # If an optional property fails to populate, the population can still # succeed with a warning. If no error messages are generated, this # warning is not set and we fail out instead. if not self._generate_error_messages: c.Append('return %(failure_value)s;') (c.Eblock('}') .Sblock('else {') .Append('scoped_ptr<%(cpp_type)s> temp(new %(cpp_type)s());') .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs( ('*dictionary', 'temp.get()'))) .Append(' return %(failure_value)s;') ) (c.Append('}') .Append('else') .Append(' %(dst_var)s = temp.Pass();') .Eblock('}') ) else: (c.Append('const base::DictionaryValue* dictionary = NULL;') .Sblock('if (!%(src_var)s->GetAsDictionary(&dictionary)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected dictionary, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))) .Append('return %(failure_value)s;') .Eblock('}') .Append('if (!%%(cpp_type)s::Populate(%s)) {' % self._GenerateArgs( ('*dictionary', '&%(dst_var)s'))) .Append(' return %(failure_value)s;') .Append('}') ) 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;') .Sblock('if (!%(src_var)s->GetAsList(&list)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected list, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))) ) if is_ptr and self._generate_error_messages: c.Append('%(dst_var)s.reset();') else: c.Append('return %(failure_value)s;') c.Eblock('}') c.Sblock('else {') item_type = self._type_helper.FollowRef(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.Sblock('if (!%s(%s)) {' % ( self._util_cc_helper.PopulateArrayFromListFunction(is_ptr), self._GenerateArgs(('*list', '&%(dst_var)s')))) c.Concat(self._GenerateError( '"unable to populate array \'%%(parent_key)s\'"')) if is_ptr and self._generate_error_messages: c.Append('%(dst_var)s.reset();') else: c.Append('return %(failure_value)s;') c.Eblock('}') c.Eblock('}') 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(%s))' % self._GenerateArgs( ('*%(src_var)s', 'temp.get()'))) .Append(' return %(failure_value)s;') .Append('%(dst_var)s = temp.Pass();') ) else: (c.Append('if (!%%(cpp_type)s::Populate(%s))' % self._GenerateArgs( ('*%(src_var)s', '&%(dst_var)s'))) .Append(' return %(failure_value)s;')) elif underlying_type.property_type == PropertyType.ENUM: c.Concat(self._GenerateStringToEnumConversion(underlying_type, src_var, dst_var, failure_value)) elif underlying_type.property_type == PropertyType.BINARY: (c.Append('const base::BinaryValue* binary_value = NULL;') .Sblock('if (!%(src_var)s->IsType(base::Value::TYPE_BINARY)) {') .Concat(self._GenerateError( '"\'%%(key)s\': expected binary, got " + ' + self._util_cc_helper.GetValueTypeString('%%(src_var)s', True))) ) if not self._generate_error_messages: c.Append('return %(failure_value)s;') (c.Eblock('}') .Sblock('else {') .Append(' binary_value =') .Append(' static_cast<const base::BinaryValue*>(%(src_var)s);') ) if is_ptr: (c.Append('%(dst_var)s.reset(new std::vector<char>(') .Append(' binary_value->GetBuffer(),') .Append(' binary_value->GetBuffer() + binary_value->GetSize()));') ) else: (c.Append('%(dst_var)s.assign(') .Append(' binary_value->GetBuffer(),') .Append(' binary_value->GetBuffer() + binary_value->GetSize());') ) c.Eblock('}') else: raise NotImplementedError(type_) if c.IsEmpty(): return c return Code().Sblock('{').Concat(c.Substitute({ 'cpp_type': self._type_helper.GetCppType(type_), 'src_var': src_var, 'dst_var': dst_var, 'failure_value': failure_value, 'key': type_.name, 'parent_key': type_.parent.name, })).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)