123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- package dirty
- import (
- "fmt"
- "reflect"
- "unicode"
- )
- func getStructPair(e Element) Array {
- if e.getType() != ElemArray && len(e.(Array)) != 2 {
- // todo error: not a pair
- fmt.Println("not a pair")
- return nil
- }
- return e.(Array)
- }
- func getStructFieldName(pair Array) string {
- k := reflect.TypeOf(pair[0]).Kind()
- if k != reflect.String {
- // todo error: name not string
- fmt.Println("name not string")
- return ""
- }
- fieldName := string(pair[0].(String))
- runes := []rune(fieldName)
- runes[0] = unicode.ToUpper(runes[0])
- fieldName = string(runes)
- return fieldName
- }
- func getStructMapKey(pair Array, mk reflect.Kind) reflect.Value {
- sk := reflect.ValueOf(pair[0]).Type().String()
- if (sk == "dirty.String" && mk != reflect.String) ||
- (sk == "dirty.Int" && mk != reflect.Int && mk != reflect.Int8 &&
- mk != reflect.Int16 && mk != reflect.Int32 && mk != reflect.Int64 &&
- mk != reflect.Uint && mk != reflect.Uint8 &&
- mk != reflect.Uint16 && mk != reflect.Uint32 && mk != reflect.Uint64) ||
- (sk == "dirty.Const" && mk != reflect.Bool) /*test sk ==dirty.Const but not dirty::Bool */ {
- // todo error
- fmt.Printf("pair[0] (%v) not map key (%v)\n", sk, mk)
- return reflect.ValueOf(nil)
- }
- switch mk {
- case reflect.String:
- return reflect.ValueOf(string(pair[0].(String)))
- case reflect.Bool:
- return reflect.ValueOf(pair[0].(Const).Bool())
- case reflect.Uint:
- return reflect.ValueOf(uint(pair[0].(Int)))
- case reflect.Uint8:
- return reflect.ValueOf(uint8(pair[0].(Int)))
- case reflect.Uint16:
- return reflect.ValueOf(uint16(pair[0].(Int)))
- case reflect.Uint32:
- return reflect.ValueOf(uint32(pair[0].(Int)))
- case reflect.Uint64:
- return reflect.ValueOf(uint64(pair[0].(Int)))
- case reflect.Int:
- return reflect.ValueOf(int(pair[0].(Int)))
- case reflect.Int8:
- return reflect.ValueOf(int8(pair[0].(Int)))
- case reflect.Int16:
- return reflect.ValueOf(int16(pair[0].(Int)))
- case reflect.Int32:
- return reflect.ValueOf(int32(pair[0].(Int)))
- case reflect.Int64:
- return reflect.ValueOf(int64(pair[0].(Int)))
- default:
- return reflect.ValueOf(nil)
- }
- }
- func setStructValue(value Element, f reflect.Value) error {
- switch value.getType() {
- case ElemArray:
- err := convertStruct(value.(Array), f)
- if err != nil {
- return err
- }
- case ElemConst:
- if value == NULL && f.Kind() == reflect.Ptr {
- // do nothing; default value is nil
- } else if (value == TRUE || value == FALSE) && f.Kind() == reflect.Bool {
- f.SetBool(value.(Const).Bool())
- } else {
- // todo error: type mismatch
- fmt.Println("type mismatch")
- return nil
- }
- case ElemFloat:
- if f.Kind() == reflect.Float64 || f.Kind() == reflect.Float32 {
- f.SetFloat(float64(value.(Float)))
- } else {
- // todo error: type mismatch
- fmt.Println("type mismatch")
- return nil
- }
- case ElemInt:
- if f.Kind() == reflect.Int || f.Kind() == reflect.Int8 || f.Kind() == reflect.Int16 || f.Kind() == reflect.Int32 || f.Kind() == reflect.Int64 {
- f.SetInt(int64(value.(Int)))
- } else {
- // todo error: type mismatch
- fmt.Println("type mismatch")
- return nil
- }
- case ElemString:
- if f.Kind() == reflect.String {
- f.SetString(string(value.(String)))
- } else {
- // todo error: type mismatch
- fmt.Println("type mismatch")
- return nil
- }
- default:
- // todo error: unknown type
- fmt.Println("unknown type")
- return nil
- }
- return nil
- }
- func convertStruct(array Array, s reflect.Value) error {
- kind := s.Kind()
- if kind == reflect.Struct {
- for _, e := range array {
- pair := getStructPair(e)
- fieldName := getStructFieldName(pair)
- f := s.FieldByName(fieldName)
- if !f.IsValid() {
- // todo error no such field
- fmt.Println("no such field", fieldName)
- return nil
- }
- if f.Kind() == reflect.Ptr && pair[1] != NULL {
- f.Set(reflect.New(f.Type().Elem()))
- f = f.Elem()
- }
- setStructValue(pair[1], f)
- }
- //fmt.Printf("%+v\n", s)
- return nil
- }
- if kind == reflect.Slice {
- elemType := s.Type().Elem()
- if s.Len() != 0 {
- // todo error slice not empty
- fmt.Println("slice len != 0")
- return nil
- }
- capacity := s.Cap()
- s.SetLen(capacity)
- s2 := s
- for i, e := range array {
- if i < capacity {
- f := s2.Index(i)
- setStructValue(e, f)
- } else {
- f := reflect.New(elemType).Elem()
- setStructValue(e, f)
- s2 = reflect.Append(s2, f)
- }
- }
- s.Set(s2)
- //fmt.Printf("%+v\n", s)
- return nil
- }
- if kind == reflect.Array {
- if s.Len() != len(array) {
- // todo error array len not Array len
- fmt.Println("array len not length of Array")
- return nil
- }
- for i, e := range array {
- f := s.Index(i)
- setStructValue(e, f)
- }
- //fmt.Printf("%+v\n", s)
- return nil
- }
- if kind == reflect.Map {
- keyType := s.Type().Key()
- keyKind := keyType.Kind()
- valueType := s.Type().Elem()
- for _, e := range array {
- pair := getStructPair(e)
- k := getStructMapKey(pair, keyKind)
- v := reflect.New(valueType).Elem()
- setStructValue(pair[1], v)
- if s.IsNil() {
- var mapType = reflect.MapOf(keyType, valueType)
- s.Set(reflect.MakeMapWithSize(mapType, 0))
- }
- s.SetMapIndex(k, v)
- }
- //fmt.Printf("%+v\n", s)
- return nil
- }
- //fmt.Println(kind)
- return nil
- }
|