github.com/hedzr/evendeep@v0.4.8/cvts_tool.go (about) 1 package evendeep 2 3 import ( 4 "fmt" 5 "log" 6 "math" 7 "reflect" 8 "strconv" 9 "strings" 10 11 "github.com/hedzr/evendeep/dbglog" 12 "github.com/hedzr/evendeep/internal/cl" 13 "github.com/hedzr/evendeep/internal/syscalls" 14 "github.com/hedzr/evendeep/internal/tool" 15 16 "gopkg.in/hedzr/errors.v3" 17 ) 18 19 // rForBool transform bool -> string. 20 func rForBool(v reflect.Value) (ret reflect.Value) { 21 vs := strconv.FormatBool(v.Bool()) 22 ret = reflect.ValueOf(vs) 23 return 24 } 25 26 // rToBool transform string (or anything) -> bool. 27 func rToBool(v reflect.Value) (ret reflect.Value) { 28 var b bool 29 30 if !v.IsValid() || tool.IsNil(v) || tool.IsZero(v) { 31 return reflect.ValueOf(b) 32 } 33 34 k := v.Kind() 35 switch k { //nolint:exhaustive //no need 36 case reflect.Bool: 37 b = v.Bool() 38 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 39 b = v.Int() != 0 40 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 41 b = v.Uint() != 0 42 case reflect.Float32, reflect.Float64: 43 b = math.Float64bits(v.Float()) != 0 44 case reflect.Complex64, reflect.Complex128: 45 c := v.Complex() 46 b = math.Float64bits(real(c)) != 0 || math.Float64bits(imag(c)) != 0 47 case reflect.Array: 48 b = !tool.ArrayIsZero(v) 49 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: 50 b = !tool.IsNil(v) 51 case reflect.Struct: 52 b = !tool.StructIsZero(v) 53 case reflect.String: 54 b = internalToBool(v.String()) 55 } 56 57 ret = reflect.ValueOf(b) 58 return 59 } 60 61 func internalToBool(s string) (b bool) { 62 switch val := strings.ToLower(s); val { 63 case "y", "t", "1", "yes", "true", "on", "ok", "m", "male": 64 b = true 65 } 66 return 67 } 68 69 // rForInteger transform integer -> string. 70 func rForInteger(v reflect.Value) (ret reflect.Value) { 71 int64typ := reflect.TypeOf((*int64)(nil)).Elem() 72 if !v.IsValid() { 73 v = reflect.Zero(int64typ) 74 } else if k := v.Kind(); k < reflect.Int || k > reflect.Int64 { 75 if tool.CanConvert(&v, int64typ) { 76 v = v.Convert(int64typ) 77 } else { 78 v = reflect.Zero(int64typ) 79 } 80 } 81 82 vs := strconv.FormatInt(v.Int(), 10) 83 ret = reflect.ValueOf(vs) 84 return 85 } 86 87 const uintSize = 32 << (^uint(0) >> 32 & 1) 88 89 //nolint:dupl //don't 90 func rToInteger(v reflect.Value, desiredType reflect.Type) (ret reflect.Value, err error) { 91 genret := func(ival int64, desiredTypeKind reflect.Kind) (ret reflect.Value) { 92 switch desiredTypeKind { //nolint:exhaustive //no need 93 case reflect.Int: 94 ret = reflect.ValueOf(int(ival)) 95 case reflect.Int32: 96 ret = reflect.ValueOf(int32(ival)) 97 case reflect.Int16: 98 ret = reflect.ValueOf(int16(ival)) 99 case reflect.Int8: 100 ret = reflect.ValueOf(int8(ival)) 101 default: 102 ret = reflect.ValueOf(ival) 103 } 104 return 105 } 106 ret, err = toTypeConverter(v, desiredType, 10, //nolint:gomnd //no need 107 func(str string, base int, bitSize int) (ret reflect.Value, err error) { 108 var ival int64 109 ival, err = strconv.ParseInt(str, base, bitSize) 110 if err == nil { 111 k := desiredType.Kind() 112 ret = genret(ival, k) 113 } else { 114 var fval float64 115 fval, err = strconv.ParseFloat(str, bitSize) 116 if err == nil { 117 ival = int64(math.Floor(fval + 0.5)) //nolint:gomnd //no need 118 k := desiredType.Kind() 119 ret = genret(ival, k) 120 } 121 } 122 return 123 }) 124 return 125 } 126 127 // rForUInteger transform uint64 -> string. 128 func rForUInteger(v reflect.Value) (ret reflect.Value) { 129 uint64typ := reflect.TypeOf((*uint64)(nil)).Elem() 130 if !v.IsValid() { 131 v = reflect.Zero(uint64typ) 132 } else if k := v.Kind(); k < reflect.Uint || k > reflect.Uintptr { 133 if tool.CanConvert(&v, uint64typ) { 134 v = v.Convert(uint64typ) 135 } else { 136 v = reflect.Zero(uint64typ) 137 } 138 } 139 140 vs := strconv.FormatUint(v.Uint(), 10) 141 ret = reflect.ValueOf(vs) 142 return 143 } 144 145 //nolint:dupl //don't 146 func rToUInteger(v reflect.Value, desiredType reflect.Type) (ret reflect.Value, err error) { 147 genret := func(ival uint64, desiredTypeKind reflect.Kind) (ret reflect.Value) { 148 switch desiredTypeKind { //nolint:exhaustive //no need 149 case reflect.Uint: 150 ret = reflect.ValueOf(uint(ival)) 151 case reflect.Uint32: 152 ret = reflect.ValueOf(uint32(ival)) 153 case reflect.Uint16: 154 ret = reflect.ValueOf(uint16(ival)) 155 case reflect.Uint8: 156 ret = reflect.ValueOf(uint8(ival)) 157 default: 158 ret = reflect.ValueOf(ival) 159 } 160 return 161 } 162 ret, err = toTypeConverter(v, desiredType, 10, //nolint:gomnd //no need 163 func(str string, base int, bitSize int) (ret reflect.Value, err error) { 164 var ival uint64 165 ival, err = strconv.ParseUint(str, base, bitSize) 166 if err == nil { 167 k := desiredType.Kind() 168 ret = genret(ival, k) 169 } else { 170 var fval float64 171 fval, err = strconv.ParseFloat(str, bitSize) 172 if err == nil { 173 ival = uint64(math.Floor(fval + 0.5)) //nolint:gomnd //no need 174 k := desiredType.Kind() 175 ret = genret(ival, k) 176 } 177 } 178 return 179 }) 180 return 181 } 182 183 // rForUIntegerHex transform uintptr/... -> string. 184 func rForUIntegerHex(u uintptr) (ret reflect.Value) { 185 vs := syscalls.UintptrToString(u) 186 ret = reflect.ValueOf(vs) 187 return 188 } 189 190 func rToUIntegerHex(s reflect.Value, desiredType reflect.Type) (ret reflect.Value) { 191 vs := syscalls.UintptrFromString(s.String()) 192 log.Printf("vs : %v, k: %v\n", vs, desiredType.Kind()) 193 switch k := desiredType.Kind(); k { //nolint:exhaustive //no need 194 case reflect.Uintptr: 195 ret = reflect.ValueOf(vs) 196 case reflect.UnsafePointer, reflect.Ptr: 197 ret = reflect.ValueOf(vs) 198 // u := getPointerAsUintptr(ret) 199 } 200 return 201 } 202 203 func getPointerAsUintptr(v reflect.Value) uintptr { //nolint:unused // intergrality 204 var p uintptr 205 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { 206 p = v.Pointer() 207 } 208 return p 209 } 210 211 // rForFloat transform float -> string. 212 func rForFloat(v reflect.Value) (ret reflect.Value) { 213 float64typ := reflect.TypeOf((*float64)(nil)).Elem() 214 if !v.IsValid() { 215 v = reflect.Zero(float64typ) 216 } else if k := v.Kind(); k < reflect.Float32 || k > reflect.Float64 { 217 if tool.CanConvert(&v, float64typ) { 218 v = v.Convert(float64typ) 219 } else { 220 v = reflect.Zero(float64typ) 221 } 222 } 223 224 vs := strconv.FormatFloat(v.Float(), 'g', -1, 64) 225 ret = reflect.ValueOf(vs) 226 return 227 } 228 229 func rToFloat(v reflect.Value, desiredType reflect.Type) (ret reflect.Value, err error) { 230 toFloat := func(fval float64, desiredType reflect.Type) (ret reflect.Value) { 231 if desiredType.Kind() == reflect.Float64 { 232 ret = reflect.ValueOf(fval) 233 } else { 234 ret = reflect.ValueOf(float32(fval)) 235 } 236 return 237 } 238 ret, err = toTypeConverter(v, desiredType, 10, //nolint:gomnd //no need 239 func(str string, base int, bitSize int) (ret reflect.Value, err error) { 240 var fval float64 241 fval, err = strconv.ParseFloat(str, bitSize) 242 if err == nil { 243 return toFloat(fval, desiredType), nil 244 } 245 246 var ival int64 247 ival, err = strconv.ParseInt(str, 10, bitSize) 248 if err == nil { 249 return toFloat(float64(ival), desiredType), nil 250 } 251 252 var uval uint64 253 uval, err = strconv.ParseUint(str, 10, bitSize) 254 if err == nil { 255 return toFloat(float64(uval), desiredType), nil 256 } 257 258 var cval complex128 259 cval, err = cl.ParseComplex(str) 260 if err == nil { 261 fval = real(cval) 262 ret = toFloat(fval, desiredType) 263 } 264 return 265 }) 266 return 267 } 268 269 // rForComplex transform complex -> string. 270 func rForComplex(v reflect.Value) (ret reflect.Value) { 271 complex128typ := reflect.TypeOf((*complex128)(nil)).Elem() 272 if !v.IsValid() { 273 v = reflect.Zero(complex128typ) 274 } else if k := v.Kind(); k < reflect.Complex64 || k > reflect.Complex128 { 275 // if canConvert(&v, complex128typ) { 276 // v = v.Convert(complex128typ) 277 // } else { 278 switch k { //nolint:exhaustive //no need 279 case reflect.Float64, reflect.Float32: 280 v = reflect.ValueOf(complex(v.Float(), 0.0)) 281 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 282 v = reflect.ValueOf(complex(float64(v.Int()), 0.0)) 283 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 284 v = reflect.ValueOf(complex(float64(v.Uint()), 0.0)) 285 default: 286 v = reflect.Zero(complex128typ) 287 } 288 // } 289 } 290 291 vs := cl.FormatComplex(v.Complex(), 'g', -1, 128) //nolint:gomnd //no need 292 ret = reflect.ValueOf(vs) 293 return 294 } 295 296 func rToComplex(v reflect.Value, desiredType reflect.Type) (ret reflect.Value, err error) { 297 toComplex := func(cval complex128, desiredType reflect.Type) (ret reflect.Value) { 298 if desiredType.Kind() == reflect.Complex128 { 299 ret = reflect.ValueOf(cval) 300 } else { 301 ret = reflect.ValueOf(complex64(cval)) 302 } 303 return 304 } 305 ret, err = toTypeConverter(v, desiredType, 10, //nolint:gomnd //no need 306 func(str string, base int, bitSize int) (ret reflect.Value, err error) { 307 var cval complex128 308 if str[0] != '(' { 309 str = "(" + str 310 } 311 if lastch := str[len(str)-1]; lastch != ')' { 312 if lastch != 'i' { 313 str += "+0i" 314 } 315 str += ")" 316 } 317 cval, err = cl.ParseComplex(str) 318 if err == nil { 319 ret = toComplex(cval, desiredType) 320 } 321 return 322 }) 323 return 324 } 325 326 func toTypeConverter(v reflect.Value, desiredType reflect.Type, base int, 327 converter func(str string, base int, bitSize int) (ret reflect.Value, err error), 328 ) (ret reflect.Value, err error) { 329 if !v.IsValid() || tool.IsNil(v) || tool.IsZero(v) { 330 ret = reflect.Zero(desiredType) 331 return 332 } 333 334 if tool.CanConvert(&v, desiredType) { 335 ret = v.Convert(desiredType) 336 return 337 } 338 339 val := v.String() 340 bitSize := 64 341 switch k := desiredType.Kind(); k { //nolint:exhaustive //no need 342 case reflect.Int, reflect.Uint: 343 bitSize = uintSize 344 case reflect.Int32, reflect.Uint32, reflect.Float32: 345 bitSize = 32 346 case reflect.Int16, reflect.Uint16: 347 bitSize = 16 348 case reflect.Int8, reflect.Uint8: 349 bitSize = 8 350 case reflect.Complex128: 351 bitSize = 128 352 // case reflect.Float64, reflect.Complex64: 353 // bitSize = 64 354 } 355 ret, err = converter(val, base, bitSize) 356 return 357 } 358 359 func tryStringerIt(source reflect.Value, desiredType reflect.Type) (target reflect.Value, processed bool, err error) { 360 val := source.Interface() 361 if ss, ok := val.(interface{ String() string }); ok { 362 nv := ss.String() 363 target = reflect.ValueOf(nv) 364 processed = true 365 return 366 } 367 368 if tool.CanConvert(&source, desiredType) { 369 nv := source.Convert(desiredType) 370 // target.Set(nv) 371 target = nv 372 processed = true 373 } else { 374 nv := fmt.Sprintf("%v", val) 375 // target.Set(reflect.ValueOf(nv)) 376 target = reflect.ValueOf(nv) 377 processed = true 378 } 379 return 380 } 381 382 func rToString(source reflect.Value, desiredType reflect.Type) (target reflect.Value, err error) { 383 if source.IsValid() { 384 switch k := source.Kind(); k { //nolint:exhaustive //no need 385 case reflect.Bool: 386 target = rForBool(source) 387 case reflect.Int64: 388 var processed bool 389 if target, processed, err = tryStringerIt(source, desiredType); processed { 390 return 391 } 392 fallthrough 393 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: 394 target = rForInteger(source) 395 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 396 target = rForUInteger(source) 397 398 case reflect.Uintptr: 399 target = rForUIntegerHex(uintptr(source.Uint())) 400 // case reflect.UnsafePointer: 401 // target = rForUIntegerHex(uintptr(source.Uint())) 402 // case reflect.Ptr: 403 // target = rForUIntegerHex(source.Pointer()) 404 405 case reflect.Float32, reflect.Float64: 406 target = rForFloat(source) 407 case reflect.Complex64, reflect.Complex128: 408 target = rForComplex(source) 409 410 case reflect.String: 411 target = reflect.ValueOf(source.String()) 412 413 // reflect.Array 414 // reflect.Chan 415 // reflect.Func 416 // reflect.Interface 417 // reflect.Map 418 // reflect.Slice 419 // reflect.Struct 420 421 default: 422 target, _, err = tryStringerIt(source, desiredType) 423 } 424 } else { 425 target = reflect.Zero(tool.StringType) 426 } 427 return 428 } 429 430 //nolint:unused,deadcode,lll //reserved 431 func rToArray(ctx *ValueConverterContext, sources reflect.Value, desiredType reflect.Type, targetLength int) (target reflect.Value, err error) { 432 eltyp := desiredType.Elem() // length := desiredType.Len() 433 dbglog.Log(" desiredType: %v, el.type: %v", tool.Typfmt(desiredType), tool.Typfmt(eltyp)) 434 435 count, length := sources.Len(), targetLength 436 if length <= 0 { 437 length = count 438 } 439 if count > length { 440 count = length 441 } 442 443 target = reflect.New(reflect.ArrayOf(length, eltyp)).Elem() 444 445 for ix := 0; ix < count; ix++ { 446 src := sources.Index(ix) 447 if ix < length && src.IsValid() { 448 if src.Type().AssignableTo(eltyp) { 449 target.Index(ix).Set(src) 450 } else if src.Type().ConvertibleTo(eltyp) { 451 target.Index(ix).Set(src.Convert(eltyp)) 452 } 453 } 454 } 455 return 456 } 457 458 //nolint:unused,deadcode,lll //reserved 459 func rToSlice(ctx *ValueConverterContext, sources reflect.Value, desiredType reflect.Type, targetLength int) (target reflect.Value, err error) { 460 eltyp := desiredType.Elem() // length := desiredType.Len() 461 dbglog.Log(" desiredType: %v, el.type: %v", tool.Typfmt(desiredType), tool.Typfmt(eltyp)) 462 463 count, length := sources.Len(), targetLength 464 if length <= 0 { 465 length = count 466 } 467 if count > length { 468 count = length 469 } 470 471 target = reflect.MakeSlice(desiredType, length, length) 472 for ix := 0; ix < count; ix++ { 473 src := sources.Index(ix) 474 if ix < length && src.IsValid() { 475 if src.Type().AssignableTo(eltyp) { 476 target.Index(ix).Set(src) 477 } else if src.Type().ConvertibleTo(eltyp) { 478 target.Index(ix).Set(src.Convert(eltyp)) 479 } 480 } 481 } 482 return 483 } 484 485 //nolint:unused,deadcode,lll //reserved 486 func rToMap(ctx *ValueConverterContext, source reflect.Value, fromFuncType, desiredType reflect.Type) (target reflect.Value, err error) { 487 ec := errors.New("cannot transform item into map") 488 defer ec.Defer(&err) 489 490 dtyp := desiredType.Elem() 491 styp := source.Type() 492 // srceltyp := styp.Elem() 493 target = reflect.MakeMap(desiredType) 494 495 if source.IsValid() { 496 for ix, key := range source.MapKeys() { 497 val := source.MapIndex(key) 498 if err = rSetMapValue(ix, target, key, val, styp, dtyp); err != nil { 499 ec.Attach(err) 500 continue 501 } 502 } 503 } 504 505 // for i := 0; i < fromFuncType.NumOut(); i++ { 506 // if i >= len(sources) { 507 // continue 508 // } 509 // 510 // styp := fromFuncType.Out(i) 511 // sname := styp.Name() 512 // var key reflect.Value 513 // if key, err = nameToMapKey(sname, desiredType); err != nil { 514 // ec.Attach(err) 515 // continue 516 // } 517 // 518 // if err = rSetMapValue(target, key, sources[i], styp, dtyp); err != nil { 519 // ec.Attach(err) 520 // continue 521 // } 522 // } 523 return 524 } 525 526 //nolint:unused //future 527 func rSetMapValue(ix int, target, key, srcVal reflect.Value, sTyp, dTyp reflect.Type) (err error) { 528 if sTyp.AssignableTo(dTyp) { //nolint:gocritic // no need to switch to 'switch' clause 529 target.SetMapIndex(key, srcVal) 530 } else if sTyp.ConvertibleTo(dTyp) { 531 target.SetMapIndex(key, srcVal.Convert(dTyp)) 532 } else { 533 dstval := target.MapIndex(key) 534 err = errors.New("cannot set map[%v] since transforming/converting failed: %v -> %v", 535 tool.Valfmt(&key), tool.Valfmt(&srcVal), tool.Valfmt(&dstval)) 536 } 537 return 538 } 539 540 //nolint:unused //future 541 func nameToMapKey(name string, mapType reflect.Type) (key reflect.Value, err error) { 542 nameval := reflect.ValueOf(name) 543 nametyp := nameval.Type() 544 545 if keytyp := mapType.Key(); nametyp.AssignableTo(keytyp) { //nolint:gocritic // no need to switch to 'switch' clause 546 key = nameval 547 } else if nametyp.ConvertibleTo(keytyp) { 548 key = nameval.Convert(keytyp) 549 } else { 550 cvt := fromStringConverter{} 551 key, err = cvt.Transform(nil, nameval, keytyp) 552 } 553 return 554 } 555 556 //nolint:unused,deadcode,lll //reserved 557 func rToStruct(ctx *ValueConverterContext, source reflect.Value, fromFuncType, desiredType reflect.Type) (target reflect.Value, err error) { 558 // result (source) -> struct (target) 559 560 return 561 } 562 563 //nolint:unused,deadcode,lll //reserved 564 func rToFunc(ctx *ValueConverterContext, source reflect.Value, fromFuncType, desiredType reflect.Type) (target reflect.Value, err error) { 565 return 566 }