Exemplo n.º 1
0
/*
	Given a thing (field value in a struct), set the thing with the element in the map (key)
	the map value to the proper type.
*/
func set_value(thing reflect.Value, kind reflect.Kind, key string, tag_id string, pfx string, annon bool, m map[string]string) {

	if !thing.CanAddr() { // prevent stack dump
		return
	}

	switch kind {
	default:
		fmt.Fprintf(os.Stderr, "transform.mts: tagged sturct member cannot be converted from map: tag=%s kind=%v\n", key, thing.Kind())

	case reflect.String:
		thing.SetString(m[key])

	case reflect.Ptr:
		p := thing.Elem() // get the pointer value; allows us to suss the type
		if !p.IsValid() { // ptr is nill in the struct so we must allocate a pointer to 0 so it can be changed below
			thing.Set(reflect.New(thing.Type().Elem()))
			p = thing.Elem()
		}
		switch p.Kind() {
		case reflect.String:
			s := m[key] // copy it and then point to the copy
			thing.Set(reflect.ValueOf(&s))

		case reflect.Int:
			i := clike.Atoi(m[key]) // convert to integer and then point at the value
			thing.Set(reflect.ValueOf(&i))

		case reflect.Int64:
			i := clike.Atoi64(m[key])
			thing.Set(reflect.ValueOf(&i))

		case reflect.Int32:
			i := clike.Atoi32(m[key])
			thing.Set(reflect.ValueOf(&i))

		case reflect.Int16:
			i := clike.Atoi16(m[key])
			thing.Set(reflect.ValueOf(&i))

		case reflect.Int8:
			i := int8(clike.Atoi16(m[key]))
			thing.Set(reflect.ValueOf(&i))

		case reflect.Uint:
			ui := clike.Atou(m[key])
			thing.Set(reflect.ValueOf(&ui))

		case reflect.Uint64:
			ui := clike.Atou64(m[key])
			thing.Set(reflect.ValueOf(&ui))

		case reflect.Uint32:
			ui := clike.Atou32(m[key])
			thing.Set(reflect.ValueOf(&ui))

		case reflect.Uint16:
			ui := clike.Atou16(m[key])
			thing.Set(reflect.ValueOf(&ui))

		case reflect.Uint8:
			ui := uint8(clike.Atou16(m[key]))
			thing.Set(reflect.ValueOf(&ui))

		case reflect.Float64:
			fv := clike.Atof(m[key])
			thing.Set(reflect.ValueOf(&fv))

		case reflect.Float32:
			fv := float32(clike.Atof(m[key]))
			thing.Set(reflect.ValueOf(&fv))

		case reflect.Bool:
			b := m[key] == "true" || m[key] == "True" || m[key] == "TRUE"
			thing.Set(reflect.ValueOf(&b))

		case reflect.Struct:
			map_to_struct(m, p, p.Type(), tag_id, pfx) // recurse to process
		}

	case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
		thing.SetInt(clike.Atoi64(m[key]))

	case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8:
		thing.SetUint(uint64(clike.Atoi64(m[key])))

	case reflect.Float64, reflect.Float32:
		thing.SetFloat(clike.Atof(m[key]))

	case reflect.Bool:
		thing.SetBool(m[key] == "true")

	case reflect.Map:
		new_map := reflect.MakeMap(thing.Type()) // create the map
		thing.Set(new_map)                       // put it in the struct

		idx := key + "/" // now populate the map
		ilen := len(idx)
		for k, _ := range m { // we could keep a separate list of keys, but for now this should do
			if strings.HasPrefix(k, key) {
				tokens := strings.Split(k[ilen:], "/")
				map_key := reflect.ValueOf(tokens[0]) // map key is everything past the tag to the next slant
				map_ele_type := new_map.Type().Elem() // the type of the element that the map references

				mthing := reflect.New(map_ele_type).Elem() // new returns pointer, so dereference with Elem() (value not type!)

				set_value(mthing, mthing.Kind(), idx+tokens[0], tag_id, idx+tokens[0]+"/", false, m) // put the value into the map thing
				new_map.SetMapIndex(map_key, mthing)                                                 // put it into the map (order IS important; add to map after recursion)
				//fmt.Fprintf( os.Stderr, "saving: %s  thing-type=%s mthing=%s\n", map_key, thing.Type(), mthing )
			}
		}

	case reflect.Slice:
		c := clike.Atoi(m[key+".cap"])
		l := clike.Atoi(m[key+".len"])

		thing.Set(reflect.MakeSlice(thing.Type(), l, c)) // create a new slice with the same len/cap that it had
		for j := 0; j < l; j++ {
			idx := fmt.Sprintf("%s/%d", key, j)
			set_value(thing.Index(j), thing.Type().Elem().Kind(), idx, tag_id, idx+"/", false, m) // populate each value of the slice up to len
		}

	case reflect.Struct:
		if annon {
			map_to_struct(m, thing, thing.Type(), tag_id, key) // anon structs share namespace, so prefix is the same
		} else {
			map_to_struct(m, thing, thing.Type(), tag_id, pfx) // dive to get the substruct adding a level to the prefix
		}

	}

}
Exemplo n.º 2
0
/*
	Internal funciton to convert an interface into a supported desired value.
*/
func cvt2desired(v interface{}, desired int) interface{} {
	switch v.(type) {

	case string:
		switch desired {
		case ET_STRING:
			return v
		case ET_STRINGP:
			return &v
		case ET_INT:
			return v.(int)
		case ET_UINT:
			return v.(uint)
		case ET_INT64:
			return v.(int64)
		case ET_FLOAT:
			return v.(float64)
		case ET_BOOL:
			return v == "true"
		}

	case *string:
		switch desired {
		case ET_STRING:
			return *(v.(*string))
		case ET_STRINGP:
			return v
		case ET_INT:
			return clike.Atoi(*(v.(*string)))
		case ET_UINT:
			return clike.Atou(*(v.(*string)))
		case ET_INT64:
			return clike.Atoll(*(v.(*string)))
		case ET_FLOAT:
			return clike.Atof(*(v.(*string)))
		case ET_BOOL:
			return *(v.(*string)) == "true"
		}

	case float64:
		switch desired {
		case ET_STRING:
			return fmt.Sprintf("%.2f", v)
		case ET_STRINGP:
			s := fmt.Sprintf("%.2f", v)
			return &s
		case ET_INT:
			return int(v.(float64))
		case ET_UINT:
			return uint(v.(float64))
		case ET_INT64:
			return int64(v.(float64))
		case ET_FLOAT:
			return v
		case ET_BOOL:
			return v.(float64) != 0.0
		}

	case int:
		switch desired {
		case ET_STRING:
			return fmt.Sprintf("%d", v)
		case ET_STRINGP:
			s := fmt.Sprintf("%d", v)
			return &s
		case ET_INT:
			return v
		case ET_UINT:
			return uint(v.(int))
		case ET_INT64:
			return int64(v.(int))
		case ET_FLOAT:
			return float64(v.(int))
		case ET_BOOL:
			return v.(int) != 0
		}

	case int64:
		switch desired {
		case ET_STRING:
			return fmt.Sprintf("%d", v)
		case ET_STRINGP:
			s := fmt.Sprintf("%d", v)
			return &s
		case ET_INT:
			return int(v.(int64))
		case ET_UINT:
			return uint(v.(int64))
		case ET_INT64:
			return v
		case ET_FLOAT:
			return float64(v.(int64))
		case ET_BOOL:
			return v.(int64) != 0
		}

	case bool:
		switch desired {
		case ET_STRING:
			return fmt.Sprintf("%v", v)
		case ET_STRINGP:
			s := fmt.Sprintf("%v", v)
			return &s
		case ET_INT:
			if v.(bool) {
				return int(1)
			} else {
				return int(0)
			}
		case ET_UINT:
			if v.(bool) {
				return uint(1)
			} else {
				return uint(0)
			}
		case ET_INT64:
			if v.(bool) {
				return int64(1)
			} else {
				return int64(0)
			}
		case ET_FLOAT:
			if v.(bool) {
				return 1.0
			} else {
				return 0.0
			}
		case ET_BOOL:
			return v
		}
	}

	return nil
}