예제 #1
0
파일: encode.go 프로젝트: sreis/go
// encodeStruct encodes a single struct value.
func (enc *Encoder) encodeStruct(b *encBuffer, engine *encEngine, value reflect.Value) {
	if !valid(value) {
		return
	}
	state := enc.newEncoderState(b)
	defer enc.freeEncoderState(state)
	state.fieldnum = -1
	for i := 0; i < len(engine.instr); i++ {
		instr := &engine.instr[i]
		if i >= value.NumField() {
			// encStructTerminator
			instr.op(instr, state, reflect.Value{})
			break
		}
		field := value.FieldByIndex(instr.index)
		if instr.indir > 0 {
			field = encIndirect(field, instr.indir)
			// TODO: Is field guaranteed valid? If so we could avoid this check.
			if !valid(field) {
				continue
			}
		}
		instr.op(instr, state, field)
	}
}
예제 #2
0
func structToMap(vstruct reflect.Value, schema Schema) (map[string]Value, error) {
	if vstruct.Kind() == reflect.Ptr {
		vstruct = vstruct.Elem()
	}
	if !vstruct.IsValid() {
		return nil, nil
	}
	m := map[string]Value{}
	if vstruct.Kind() != reflect.Struct {
		return nil, fmt.Errorf("bigquery: type is %s, need struct or struct pointer", vstruct.Type())
	}
	fields, err := fieldCache.Fields(vstruct.Type())
	if err != nil {
		return nil, err
	}
	for _, schemaField := range schema {
		// Look for an exported struct field with the same name as the schema
		// field, ignoring case.
		structField := fields.Match(schemaField.Name)
		if structField == nil {
			continue
		}
		val, err := structFieldToUploadValue(vstruct.FieldByIndex(structField.Index), schemaField)
		if err != nil {
			return nil, err
		}
		// Add the value to the map, unless it is nil.
		if val != nil {
			m[schemaField.Name] = val
		}
	}
	return m, nil
}
예제 #3
0
파일: marshal.go 프로젝트: cmars/oo
// marshal is the internal version of Marshal.
func marshal(p *Params, xv reflect.Value, pt *requestType) error {
	xv = xv.Elem()
	for _, f := range pt.fields {
		fv := xv.FieldByIndex(f.index)
		if f.isPointer {
			if fv.IsNil() {
				continue
			}
			fv = fv.Elem()
		}
		// TODO store the field name in the field so
		// that we can produce a nice error message.
		if err := f.marshal(fv, p); err != nil {
			return errgo.WithCausef(err, ErrUnmarshal, "cannot marshal field")
		}
	}
	path, err := buildPath(p.Request.URL.Path, p.PathVar)
	if err != nil {
		return errgo.Mask(err)
	}
	p.Request.URL.Path = path
	if q := p.Request.Form.Encode(); q != "" && p.Request.URL.RawQuery != "" {
		p.Request.URL.RawQuery += "&" + q
	} else {
		p.Request.URL.RawQuery += q
	}
	return nil
}
예제 #4
0
func marshalStruct(value reflect.Value) map[string]*dynamodb.AttributeValue {
	t := value.Type()

	numField := t.NumField()

	ret := make(map[string]*dynamodb.AttributeValue)
	for i := 0; i < numField; i++ {
		f := t.Field(i)

		if f.PkgPath != "" {
			continue
		}

		name, option := parseTag(f.Tag.Get("json"))
		if name == "-" {
			continue
		}
		if option == "omitifempty" {
			continue
		}
		if name == "" {
			name = f.Name
		}
		ret[name] = marshalValue(value.FieldByIndex(f.Index))
	}

	return ret
}
예제 #5
0
파일: read.go 프로젝트: Quantumboost/gcc
// unmarshalPaths walks down an XML structure looking for
// wanted paths, and calls unmarshal on them.
func (p *Parser) unmarshalPaths(sv reflect.Value, paths map[string]pathInfo, path string, start *StartElement) os.Error {
	if info, _ := paths[path]; info.complete {
		return p.unmarshal(sv.FieldByIndex(info.fieldIdx), start)
	}
	for {
		tok, err := p.Token()
		if err != nil {
			return err
		}
		switch t := tok.(type) {
		case StartElement:
			k := path + ">" + fieldName(t.Name.Local)
			if _, found := paths[k]; found {
				if err := p.unmarshalPaths(sv, paths, k, &t); err != nil {
					return err
				}
				continue
			}
			if err := p.Skip(); err != nil {
				return err
			}
		case EndElement:
			return nil
		}
	}
	panic("unreachable")
}
예제 #6
0
파일: result.go 프로젝트: aodin/sol
// oneStruct scans the result into a single struct type
func (r Result) oneStruct(columns []string, elem reflect.Value, obj interface{}) error {
	fields := DeepFields(obj)
	aligned := AlignFields(columns, fields)

	// Create an interface pointer for each column's destination.
	// Unmatched scanner values will be discarded
	dest := make([]interface{}, len(columns))

	// If nothing matched and the number of fields equals the number
	// columns, then blindly align columns and fields
	// TODO This may be too friendly of a feature
	if NoMatchingFields(aligned) && len(fields) == len(columns) {
		aligned = fields
	}
	for i, field := range aligned {
		if field.Exists() {
			dest[i] = elem.FieldByIndex(field.Type.Index).Addr().Interface()
		} else {
			dest[i] = &dest[i] // Discard
		}
	}

	if err := r.Scan(dest...); err != nil {
		return fmt.Errorf("sol: error scanning struct: %s", err)
	}
	return r.Err() // Check for delayed scan errors
}
예제 #7
0
func (f Fields) Pack(buf []byte, val reflect.Value) error {
	for val.Kind() == reflect.Ptr {
		val = val.Elem()
	}
	pos := 0
	for i, field := range f {
		if !field.CanSet {
			continue
		}
		v := val.Field(i)
		length := field.Len
		if field.Sizefrom != nil {
			length = int(val.FieldByIndex(field.Sizefrom).Int())
		}
		if length <= 0 && field.Slice {
			length = field.Size(v)
		}
		if field.Sizeof != nil {
			length := val.FieldByIndex(field.Sizeof).Len()
			v = reflect.ValueOf(length)
		}
		err := field.Pack(buf[pos:], v, length)
		if err != nil {
			return err
		}
		pos += field.Size(v)
	}
	return nil
}
예제 #8
0
// support multiple name casting: snake, lowercases
func (m Master) getField(v reflect.Value, schema string) (f reflect.Value, pos int) {
	// TODO: indirect(v) here is overkill?
	names := strings.Split(schema, m.SchemaSeparator)
	for _, name := range names {
		v = indirect(v)
		if v.Kind() != reflect.Struct {
			break
		}

		num := v.NumField()
		vt := v.Type()
		for i := 0; i < num; i++ {
			sf := vt.FieldByIndex([]int{i})
			options := strings.Split(sf.Tag.Get("sqlkungfu"), ",")
			if options[0] == name || strings.ToLower(sf.Name) == name {
				f = v.FieldByIndex([]int{i})
				break
			}

			if indirectT(sf.Type).Kind() == reflect.Struct && (sf.Anonymous || optionsContain(options[1:], "inline") || len(names) > 1) {
				if f, _ = m.getField(v.FieldByIndex([]int{i}), name); f.IsValid() {
					break
				}
			}
		}

		if f.IsValid() {
			v = f
			pos++
			continue
		}
	}

	return
}
예제 #9
0
파일: scan.go 프로젝트: hongzhen/redigo
func flattenStruct(args Args, v reflect.Value) Args {
	ss := structSpecForType(v.Type())
	for _, fs := range ss.l {
		fv := v.FieldByIndex(fs.index)
		if fv.CanAddr() {
			addr := fv.Addr().Interface()
			if ec, ok := addr.(gob.GobEncoder); ok {
				if buf, err := ec.GobEncode(); err == nil {
					args = append(args, fs.name, buf)
					return args
				}
			} else if ec, ok := addr.(json.Marshaler); ok {
				if buf, err := ec.MarshalJSON(); err == nil {
					args = append(args, fs.name, buf)
					return args
				}
			} else if ec, ok := addr.(encoding.BinaryMarshaler); ok {
				if buf, err := ec.MarshalBinary(); err != nil {
					args = append(args, fs.name, buf)
					return args
				}
			}
		}
		args = append(args, fs.name, fv.Interface())
	}
	return args
}
예제 #10
0
파일: same.go 프로젝트: russolsen/same
// isSameUnknownStruct returns true if the two struct values are the same length
// and have the same contents as defined by IsSame. This function explicitly
// ignores the declared type of the struct.
func isSameStruct(x, y reflect.Value) bool {

	sx, okx := x.Interface().(StringConvertable)
	sy, oky := x.Interface().(StringConvertable)

	if okx && oky {
		//log.Println("Stringable", x, y)
		return sx.String() == sy.String()
	}

	numFields := x.NumField()

	if numFields != y.NumField() {
		return false
	}

	typeX := x.Type()

	for i := 0; i < numFields; i++ {
		path := []int{i}
		vx := x.FieldByIndex(path)
		vy := y.FieldByName(typeX.Field(i).Name)
		if vx.CanInterface() && vy.CanInterface() {
			if !IsSame(vx.Interface(), vy.Interface()) {
				return false
			}
		}
	}

	return true
}
예제 #11
0
func walkStruct(v reflect.Value, w interface{}) (err error) {
	vt := v.Type()
	for i := 0; i < vt.NumField(); i++ {
		sf := vt.Field(i)
		f := v.FieldByIndex([]int{i})

		if sw, ok := w.(StructWalker); ok {
			err = sw.StructField(sf, f)
			if err != nil {
				return
			}
		}

		ew, ok := w.(EnterExitWalker)
		if ok {
			ew.Enter(StructField)
		}

		err = walk(f, w)
		if err != nil {
			return
		}

		if ok {
			ew.Exit(StructField)
		}
	}

	return nil
}
예제 #12
0
파일: sphinxql.go 프로젝트: Carbyn/sphinx
func GetColVals(val reflect.Value, cols []string) (values []string, err error) {
	typ := val.Type()
	// if not struct, then must just have one column.
	if val.Kind() != reflect.Struct && len(cols) != 1 {
		return nil, fmt.Errorf("GetColVals> If not a struct(%s), must have one column: %v", val.Kind(), cols)
	}

	values = make([]string, len(cols))
	for i, col := range cols {
		var fieldVal reflect.Value
		if val.Kind() == reflect.Struct {
			fieldIndex := getFieldIndexByName(typ, col)
			if fieldIndex[0] < 0 {
				return nil, fmt.Errorf("GetColVals> Can't found struct field(column): '%s'\n", col)
			}
			fieldVal = val.FieldByIndex(fieldIndex)
		} else {
			fieldVal = val
		}

		if values[i], err = GetValQuoteStr(fieldVal); err != nil {
			return
		}
	}

	return
}
예제 #13
0
파일: db.go 프로젝트: GrimTheReaper/beego
// execute delete sql dbQuerier with given struct reflect.Value.
// delete index is pk.
func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) {
	pkName, pkValue, ok := getExistPk(mi, ind)
	if ok == false {
		return 0, ErrMissPK
	}

	Q := d.ins.TableQuote()

	query := fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s = ?", Q, mi.table, Q, Q, pkName, Q)

	d.ins.ReplaceMarks(&query)
	res, err := q.Exec(query, pkValue)
	if err == nil {
		num, err := res.RowsAffected()
		if err != nil {
			return 0, err
		}
		if num > 0 {
			if mi.fields.pk.auto {
				if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 {
					ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(0)
				} else {
					ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(0)
				}
			}
			err := d.deleteRels(q, mi, []interface{}{pkValue}, tz)
			if err != nil {
				return num, err
			}
		}
		return num, err
	}
	return 0, err
}
예제 #14
0
파일: encode.go 프로젝트: Xercoy/aws-sdk-go
func (e *Encoder) encodeStruct(av *dynamodb.AttributeValue, v reflect.Value) error {

	// To maintain backwards compatibility with ConvertTo family of methods which
	// converted time.Time structs to strings
	if t, ok := v.Interface().(time.Time); ok {
		s := t.Format(time.RFC3339Nano)
		av.S = &s
		return nil
	}

	av.M = map[string]*dynamodb.AttributeValue{}
	fields := unionStructFields(v.Type(), e.MarshalOptions)
	for _, f := range fields {
		if f.Name == "" {
			return &InvalidMarshalError{msg: "map key cannot be empty"}
		}

		fv := v.FieldByIndex(f.Index)
		elem := &dynamodb.AttributeValue{}
		err := e.encode(elem, fv, f.tag)
		skip, err := keepOrOmitEmpty(f.OmitEmpty, elem, err)
		if err != nil {
			return err
		} else if skip {
			continue
		}

		av.M[f.Name] = elem
	}
	if len(av.M) == 0 {
		encodeNull(av)
	}

	return nil
}
예제 #15
0
func (f *field) AppendValue(dst []byte, v reflect.Value, quote bool) []byte {
	fv := v.FieldByIndex(f.index)
	if f.Is(nullEmpty) && isEmptyValue(fv) {
		return appendNull(dst, quote)
	}
	return f.appender(dst, fv, quote)
}
예제 #16
0
파일: structType.go 프로젝트: iizotop/kmg
func (t *structType) HtmlView(v reflect.Value) (html template.HTML, err error) {
	err = t.init()
	if err != nil {
		return
	}
	type templateRow struct {
		Path string
		Name string
		Html template.HTML
	}
	var templateData []templateRow
	for _, sf := range t.fields {
		var thisHtml template.HTML
		thisHtml, err = sf.Type.HtmlView(v.FieldByIndex(sf.Index))
		if err != nil {
			return
		}
		templateData = append(templateData, templateRow{
			Path: sf.Name,
			Name: sf.Name,
			Html: thisHtml,
		})
	}
	return theTemplate.ExecuteNameToHtml("Struct", templateData)
}
예제 #17
0
파일: slice_diff.go 프로젝트: snikch/api
func sliceKeys(mapper KeyMapper, val reflect.Value) (map[string]interface{}, error) {
	lookup := map[string]interface{}{}
	for i := 0; i < val.Len(); i++ {
		val := val.Index(i)
		// Get the key indexes and names for changes we care about.
		keyIndexes, err := mapper.KeyIndexes(val)
		if err != nil {
			return nil, err
		}

		// Loop over the key indexes and generate a key for each to match on.
		keyParts := []string{}
		for _, key := range keyIndexes.Keys {
			// Retrieve the field, and then append to the key parts.
			field := val.FieldByIndex(keyIndexes.Indexes[key])
			switch fieldVal := field.Interface().(type) {
			case int, bool, float64, string, time.Time:
				keyParts = append(keyParts, fmt.Sprintf("%v", fieldVal))
				break
			}
		}
		lookup[strings.Join(keyParts, ":")] = val.Interface()
	}
	return lookup, nil
}
예제 #18
0
파일: encode.go 프로젝트: RyouZhang/mgo
func (e *encoder) addStruct(v reflect.Value) {
	sinfo, err := getStructInfo(v.Type())
	if err != nil {
		panic(err)
	}
	var value reflect.Value
	if sinfo.InlineMap >= 0 {
		m := v.Field(sinfo.InlineMap)
		if m.Len() > 0 {
			for _, k := range m.MapKeys() {
				ks := k.String()
				if _, found := sinfo.FieldsMap[ks]; found {
					panic(fmt.Sprintf("Can't have key %q in inlined map; conflicts with struct field", ks))
				}
				e.addElem(ks, m.MapIndex(k), false)
			}
		}
	}
	for _, info := range sinfo.FieldsList {
		if info.Inline == nil {
			value = v.Field(info.Num)
		} else {
			value = v.FieldByIndex(info.Inline)
		}
		if info.OmitEmpty && isZero(value) {
			continue
		}
		e.addElem(info.Key, value, info.MinSize)
	}
}
예제 #19
0
파일: scan.go 프로젝트: ninjasphere/redigo
func flattenStruct(args Args, v reflect.Value) Args {
	ss := structSpecForType(v.Type())
	for _, fs := range ss.l {
		fv := v.FieldByIndex(fs.index)
		if fs.json {

			js, err := json.Marshal(fv.Interface())
			if err != nil {
				log.Printf("redigo: WARNING: Failed to json marshal property %s error: %s", fs.name, err)
			} else {
				args = append(args, fs.name, string(js))
			}

		} else {

			if fv.Kind() == reflect.Ptr {
				if fv.IsNil() {
					args = append(args, fs.name, fv.Interface())
				} else {
					args = append(args, fs.name, fv.Elem().Interface())
				}
			} else {
				args = append(args, fs.name, fv.Interface())
			}

		}
	}
	return args
}
예제 #20
0
파일: scan.go 프로젝트: 42wim/ulog2queue
func flattenStruct(args Args, v reflect.Value) Args {
	ss := structSpecForType(v.Type())
	for _, fs := range ss.l {
		fv := v.FieldByIndex(fs.index)
		if fs.omitEmpty {
			var empty = false
			switch fv.Kind() {
			case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
				empty = fv.Len() == 0
			case reflect.Bool:
				empty = !fv.Bool()
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				empty = fv.Int() == 0
			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
				empty = fv.Uint() == 0
			case reflect.Float32, reflect.Float64:
				empty = fv.Float() == 0
			case reflect.Interface, reflect.Ptr:
				empty = fv.IsNil()
			}
			if empty {
				continue
			}
		}
		args = append(args, fs.name, fv.Interface())
	}
	return args
}
예제 #21
0
파일: exec.go 프로젝트: bibbyflyaway/go
// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
// The 'final' argument represents the return value from the preceding
// value of the pipeline, if any.
func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
	if !receiver.IsValid() {
		return zero
	}
	typ := receiver.Type()
	receiver, _ = indirect(receiver)
	// Unless it's an interface, need to get to a value of type *T to guarantee
	// we see all methods of T and *T.
	ptr := receiver
	if ptr.Kind() != reflect.Interface && ptr.CanAddr() {
		ptr = ptr.Addr()
	}
	if method := ptr.MethodByName(fieldName); method.IsValid() {
		return s.evalCall(dot, method, node, fieldName, args, final)
	}
	hasArgs := len(args) > 1 || final.IsValid()
	// It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
	receiver, isNil := indirect(receiver)
	if isNil {
		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
	}
	switch receiver.Kind() {
	case reflect.Struct:
		tField, ok := receiver.Type().FieldByName(fieldName)
		if ok {
			field := receiver.FieldByIndex(tField.Index)
			if tField.PkgPath != "" { // field is unexported
				s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
			}
			// If it's a function, we must call it.
			if hasArgs {
				s.errorf("%s has arguments but cannot be invoked as function", fieldName)
			}
			return field
		}
		s.errorf("%s is not a field of struct type %s", fieldName, typ)
	case reflect.Map:
		// If it's a map, attempt to use the field name as a key.
		nameVal := reflect.ValueOf(fieldName)
		if nameVal.Type().AssignableTo(receiver.Type().Key()) {
			if hasArgs {
				s.errorf("%s is not a method but has arguments", fieldName)
			}
			result := receiver.MapIndex(nameVal)
			if !result.IsValid() {
				switch s.tmpl.option.missingKey {
				case mapInvalid:
					// Just use the invalid value.
				case mapZeroValue:
					result = reflect.Zero(receiver.Type().Elem())
				case mapError:
					s.errorf("map has no entry for key %q", fieldName)
				}
			}
			return result
		}
	}
	s.errorf("can't evaluate field %s in type %s", fieldName, typ)
	panic("not reached")
}
예제 #22
0
func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
	sinfo, err := getStructInfo(out.Type())
	if err != nil {
		panic(err)
	}
	name := settableValueOf("")
	l := len(n.children)
	for i := 0; i < l; i += 2 {
		ni := n.children[i]
		if isMerge(ni) {
			d.merge(n.children[i+1], out)
			continue
		}
		if !d.unmarshal(ni, name) {
			continue
		}
		if info, ok := sinfo.FieldsMap[name.String()]; ok {
			var field reflect.Value
			if info.Inline == nil {
				field = out.Field(info.Num)
			} else {
				field = out.FieldByIndex(info.Inline)
			}
			d.unmarshal(n.children[i+1], field)
		}
	}
	return true
}
예제 #23
0
func (e *Encoder) encodeStruct(av *dynamodb.AttributeValue, v reflect.Value) error {
	av.M = map[string]*dynamodb.AttributeValue{}
	fields := unionStructFields(v.Type(), e.MarshalOptions)
	for _, f := range fields {
		if f.Name == "" {
			return &InvalidMarshalError{msg: "map key cannot be empty"}
		}

		fv := v.FieldByIndex(f.Index)
		elem := &dynamodb.AttributeValue{}
		err := e.encode(elem, fv, f.tag)
		skip, err := keepOrOmitEmpty(f.OmitEmpty, elem, err)
		if err != nil {
			return err
		} else if skip {
			continue
		}

		av.M[f.Name] = elem
	}
	if len(av.M) == 0 {
		encodeNull(av)
	}

	return nil
}
예제 #24
0
파일: load.go 프로젝트: snikch/api
// relatedEntityIDsFromStruct traverses a single struct instance for fields that
// contain sideload ids. It adds those ids to the ids map if the ids are required.
func relatedEntityIDsFromStruct(val reflect.Value, fields map[string][][]int, ids map[string]map[string]bool, required map[string]bool) {
	for entityName, indexes := range fields {
		// If we have required fields, and this entity isn't in it, skip this one.
		if len(required) > 0 && !required[entityName] {
			continue
		}

		for _, index := range indexes {
			// Get the field at the registered index.
			field := val.FieldByIndex(index)
			if field.Kind() == reflect.Ptr {
				field = field.Elem()
			}

			// Ensure it's a string type.
			if field.Kind() != reflect.String {
				continue
			}

			// Get the string value.
			id := field.String()
			if id == "" {
				continue
			}
			// Ensure we have a map for this entity type.
			if _, ok := ids[entityName]; !ok {
				ids[entityName] = map[string]bool{}
			}

			// Add the id.
			ids[entityName][id] = true
		}
	}
}
예제 #25
0
// decodeStruct decodes a top-level struct and stores it in value.
// Indir is for the value, not the type.  At the time of the call it may
// differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly
// from the user's value, not from the innards of an engine.
func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, value reflect.Value) {
	state := dec.newDecoderState(&dec.buf)
	defer dec.freeDecoderState(state)
	state.fieldnum = -1
	for state.b.Len() > 0 {
		delta := int(state.decodeUint())
		if delta < 0 {
			errorf("decode: corrupted data: negative delta")
		}
		if delta == 0 { // struct terminator is zero delta fieldnum
			break
		}
		fieldnum := state.fieldnum + delta
		if fieldnum >= len(engine.instr) {
			error_(errRange)
			break
		}
		instr := &engine.instr[fieldnum]
		var field reflect.Value
		if instr.index != nil {
			// Otherwise the field is unknown to us and instr.op is an ignore op.
			field = value.FieldByIndex(instr.index)
			if field.Kind() == reflect.Ptr {
				field = decAlloc(field)
			}
		}
		instr.op(instr, state, field)
		state.fieldnum = fieldnum
	}
}
예제 #26
0
// unmarshalPath walks down an XML structure looking for wanted
// paths, and calls unmarshal on them.
// The consumed result tells whether XML elements have been consumed
// from the Decoder until start's matching end element, or if it's
// still untouched because start is uninteresting for sv's fields.
func (p *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
	recurse := false
Loop:
	for i := range tinfo.fields {
		finfo := &tinfo.fields[i]
		if finfo.flags&fElement == 0 || len(finfo.parents) < len(parents) {
			continue
		}
		for j := range parents {
			if parents[j] != finfo.parents[j] {
				continue Loop
			}
		}
		if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
			// It's a perfect match, unmarshal the field.
			return true, p.unmarshal(sv.FieldByIndex(finfo.idx), start)
		}
		if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
			// It's a prefix for the field. Break and recurse
			// since it's not ok for one field path to be itself
			// the prefix for another field path.
			recurse = true

			// We can reuse the same slice as long as we
			// don't try to append to it.
			parents = finfo.parents[:len(parents)+1]
			break
		}
	}
	if !recurse {
		// We have no business with this element.
		return false, nil
	}
	// The element is not a perfect match for any field, but one
	// or more fields have the path to this element as a parent
	// prefix. Recurse and attempt to match these.
	for {
		var tok Token
		tok, err = p.Token()
		if err != nil {
			return true, err
		}
		switch t := tok.(type) {
		case StartElement:
			consumed2, err := p.unmarshalPath(tinfo, sv, parents, &t)
			if err != nil {
				return true, err
			}
			if !consumed2 {
				if err := p.Skip(); err != nil {
					return true, err
				}
			}
		case EndElement:
			return true, nil
		}
	}
	panic("unreachable")
}
예제 #27
0
파일: encode.go 프로젝트: postfix/confl
func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
	// Write keys for fields directly under this key first, because if we write
	// a field that creates a new table, then all keys under it will be in that
	// table (not the one we're writing here).
	rt := rv.Type()
	var fieldsDirect, fieldsSub [][]int
	var addFields func(rt reflect.Type, rv reflect.Value, start []int)
	addFields = func(rt reflect.Type, rv reflect.Value, start []int) {
		for i := 0; i < rt.NumField(); i++ {
			f := rt.Field(i)
			// skip unexporded fields
			if f.PkgPath != "" {
				continue
			}
			frv := rv.Field(i)
			if f.Anonymous {
				frv := eindirect(frv)
				t := frv.Type()
				if t.Kind() != reflect.Struct {
					encPanic(errAnonNonStruct)
				}
				addFields(t, frv, f.Index)
			} else if typeIsHash(confTypeOfGo(frv)) {
				fieldsSub = append(fieldsSub, append(start, f.Index...))
			} else {
				fieldsDirect = append(fieldsDirect, append(start, f.Index...))
			}
		}
	}
	addFields(rt, rv, nil)

	var writeFields = func(fields [][]int) {
		for _, fieldIndex := range fields {
			sft := rt.FieldByIndex(fieldIndex)
			sf := rv.FieldByIndex(fieldIndex)
			if isNil(sf) {
				// Don't write anything for nil fields.
				continue
			}

			keyName := sft.Tag.Get("confl")
			if keyName == "-" {
				continue
			}
			if keyName == "" {
				keyName = sft.Tag.Get("json")
				if keyName == "-" {
					continue
				} else if keyName == "" {
					keyName = sft.Name
				}
			}
			//u.Infof("found key: depth?%v  keyName='%v'\t\tsf=%v", len(key), keyName, sf)
			enc.encode(key.add(keyName), sf)
		}
	}
	writeFields(fieldsDirect)
	writeFields(fieldsSub)
}
예제 #28
0
파일: form.go 프로젝트: elos/gaia
func marshalField(namespace string, s reflect.Value, f reflect.StructField) ([]byte, error) {
	switch field := s.FieldByIndex(f.Index); f.PkgPath {
	case "": // exported
		return marshalValue(path.Join(namespace, f.Name), field)
	default: // unexported
		return nil, nil
	}
}
예제 #29
0
파일: scan.go 프로젝트: qwo/abelana-gcp
func flattenStruct(args Args, v reflect.Value) Args {
	ss := structSpecForType(v.Type())
	for _, fs := range ss.l {
		fv := v.FieldByIndex(fs.index)
		args = append(args, fs.name, fv.Interface())
	}
	return args
}
예제 #30
0
파일: form.go 프로젝트: elos/gaia
func unmarshalField(form url.Values, namespace string, s reflect.Value, f reflect.StructField) error {
	switch field := s.FieldByIndex(f.Index); field.CanSet() {
	case false: // unexported
		return nil
	default:
		return unmarshalValue(form, field, path.Join(namespace, f.Name))
	}
}