Skip to content

Commit

Permalink
fix(util/gconv): #3764 fix bool converting issue (#3765)
Browse files Browse the repository at this point in the history
  • Loading branch information
wln32 authored Sep 12, 2024
1 parent 3d63ebf commit 0e471ea
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 90 deletions.
45 changes: 33 additions & 12 deletions util/gconv/gconv.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,6 @@ func String(any interface{}) string {
}
return value.String()
default:
// Empty checks.
if value == nil {
return ""
}
if f, ok := value.(localinterface.IString); ok {
// If the variable implements the String() interface,
// then use that interface to perform the conversion
Expand All @@ -201,21 +197,33 @@ func String(any interface{}) string {
kind = rv.Kind()
)
switch kind {
case reflect.Chan,
case
reflect.Chan,
reflect.Map,
reflect.Slice,
reflect.Func,
reflect.Ptr,
reflect.Interface,
reflect.UnsafePointer:
if rv.IsNil() {
return ""
}
case reflect.String:
return rv.String()
}
if kind == reflect.Ptr {
case reflect.Ptr:
if rv.IsNil() {
return ""
}
return String(rv.Elem().Interface())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(rv.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.FormatUint(rv.Uint(), 10)
case reflect.Uintptr:
return strconv.FormatUint(rv.Uint(), 10)
case reflect.Float32, reflect.Float64:
return strconv.FormatFloat(rv.Float(), 'f', -1, 64)
case reflect.Bool:
return strconv.FormatBool(rv.Bool())
}
// Finally, we use json.Marshal to convert.
if jsonContent, err := json.Marshal(value); err != nil {
Expand Down Expand Up @@ -252,10 +260,23 @@ func Bool(any interface{}) bool {
rv := reflect.ValueOf(any)
switch rv.Kind() {
case reflect.Ptr:
return !rv.IsNil()
case reflect.Map:
fallthrough
case reflect.Array:
if rv.IsNil() {
return false
}
if rv.Type().Elem().Kind() == reflect.Bool {
return rv.Elem().Bool()
}
return Bool(rv.Elem().Interface())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int() != 0
case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return rv.Uint() != 0
case reflect.Float32, reflect.Float64:
return rv.Float() != 0
case reflect.Bool:
return rv.Bool()
// TODO:(Map,Array,Slice,Struct) It might panic here for these types.
case reflect.Map, reflect.Array:
fallthrough
case reflect.Slice:
return rv.Len() != 0
Expand Down
76 changes: 68 additions & 8 deletions util/gconv/gconv_float.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package gconv

import (
"reflect"
"strconv"

"github.com/gogf/gf/v2/encoding/gbinary"
Expand All @@ -24,13 +25,40 @@ func Float32(any interface{}) float32 {
case float64:
return float32(value)
case []byte:
// TODO: It might panic here for these types.
return gbinary.DecodeToFloat32(value)
default:
if f, ok := value.(localinterface.IFloat32); ok {
return f.Float32()
rv := reflect.ValueOf(any)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return float32(rv.Int())
case reflect.Uintptr, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return float32(rv.Uint())
case reflect.Float32, reflect.Float64:
return float32(rv.Float())
case reflect.Bool:
if rv.Bool() {
return 1
}
return 0
case reflect.String:
f, _ := strconv.ParseFloat(rv.String(), 32)
return float32(f)
case reflect.Ptr:
if rv.IsNil() {
return 0
}
if f, ok := value.(localinterface.IFloat32); ok {
return f.Float32()
}
return Float32(rv.Elem().Interface())
default:
if f, ok := value.(localinterface.IFloat32); ok {
return f.Float32()
}
v, _ := strconv.ParseFloat(String(any), 32)
return float32(v)
}
v, _ := strconv.ParseFloat(String(any), 64)
return float32(v)
}
}

Expand All @@ -45,12 +73,44 @@ func Float64(any interface{}) float64 {
case float64:
return value
case []byte:
// TODO: It might panic here for these types.
return gbinary.DecodeToFloat64(value)
default:
if f, ok := value.(localinterface.IFloat64); ok {
return f.Float64()
rv := reflect.ValueOf(any)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return float64(rv.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return float64(rv.Uint())
case reflect.Uintptr:
return float64(rv.Uint())
case reflect.Float32, reflect.Float64:
// Please Note:
// When the type is float32 or a custom type defined based on float32,
// switching to float64 may result in a few extra decimal places.
return rv.Float()
case reflect.Bool:
if rv.Bool() {
return 1
}
return 0
case reflect.String:
f, _ := strconv.ParseFloat(rv.String(), 64)
return f
case reflect.Ptr:
if rv.IsNil() {
return 0
}
if f, ok := value.(localinterface.IFloat64); ok {
return f.Float64()
}
return Float64(rv.Elem().Interface())
default:
if f, ok := value.(localinterface.IFloat64); ok {
return f.Float64()
}
v, _ := strconv.ParseFloat(String(any), 64)
return v
}
v, _ := strconv.ParseFloat(String(any), 64)
return v
}
}
71 changes: 35 additions & 36 deletions util/gconv/gconv_int.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package gconv

import (
"math"
"reflect"
"strconv"

"github.com/gogf/gf/v2/encoding/gbinary"
Expand Down Expand Up @@ -63,44 +64,37 @@ func Int64(any interface{}) int64 {
if any == nil {
return 0
}
switch value := any.(type) {
case int:
return int64(value)
case int8:
return int64(value)
case int16:
return int64(value)
case int32:
return int64(value)
case int64:
return value
case uint:
return int64(value)
case uint8:
return int64(value)
case uint16:
return int64(value)
case uint32:
return int64(value)
case uint64:
return int64(value)
case float32:
return int64(value)
case float64:
return int64(value)
case bool:
if value {
rv := reflect.ValueOf(any)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return int64(rv.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return int64(rv.Uint())
case reflect.Uintptr:
return int64(rv.Uint())
case reflect.Float32, reflect.Float64:
return int64(rv.Float())
case reflect.Bool:
if rv.Bool() {
return 1
}
return 0
case []byte:
return gbinary.DecodeToInt64(value)
default:
if f, ok := value.(localinterface.IInt64); ok {
case reflect.Ptr:
if rv.IsNil() {
return 0
}
if f, ok := any.(localinterface.IInt64); ok {
return f.Int64()
}
return Int64(rv.Elem().Interface())
case reflect.Slice:
// TODO: It might panic here for these types.
if rv.Type().Elem().Kind() == reflect.Uint8 {
return gbinary.DecodeToInt64(rv.Bytes())
}
case reflect.String:
var (
s = String(value)
s = rv.String()
isMinus = false
)
if len(s) > 0 {
Expand All @@ -111,7 +105,7 @@ func Int64(any interface{}) int64 {
s = s[1:]
}
}
// Hexadecimal
// Hexadecimal.
if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') {
if v, e := strconv.ParseInt(s[2:], 16, 64); e == nil {
if isMinus {
Expand All @@ -120,18 +114,23 @@ func Int64(any interface{}) int64 {
return v
}
}
// Decimal
// Decimal.
if v, e := strconv.ParseInt(s, 10, 64); e == nil {
if isMinus {
return -v
}
return v
}
// Float64
if valueInt64 := Float64(value); math.IsNaN(valueInt64) {
// Float64.
if valueInt64 := Float64(s); math.IsNaN(valueInt64) {
return 0
} else {
return int64(valueInt64)
}
default:
if f, ok := any.(localinterface.IInt64); ok {
return f.Int64()
}
}
return 0
}
67 changes: 34 additions & 33 deletions util/gconv/gconv_uint.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package gconv

import (
"math"
"reflect"
"strconv"

"github.com/gogf/gf/v2/encoding/gbinary"
Expand Down Expand Up @@ -63,43 +64,38 @@ func Uint64(any interface{}) uint64 {
if any == nil {
return 0
}
switch value := any.(type) {
case int:
return uint64(value)
case int8:
return uint64(value)
case int16:
return uint64(value)
case int32:
return uint64(value)
case int64:
return uint64(value)
case uint:
return uint64(value)
case uint8:
return uint64(value)
case uint16:
return uint64(value)
case uint32:
return uint64(value)
case uint64:
return value
case float32:
return uint64(value)
case float64:
return uint64(value)
case bool:
if value {
rv := reflect.ValueOf(any)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return uint64(rv.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return uint64(rv.Uint())
case reflect.Uintptr:
return uint64(rv.Uint())
case reflect.Float32, reflect.Float64:
return uint64(rv.Float())
case reflect.Bool:
if rv.Bool() {
return 1
}
return 0
case []byte:
return gbinary.DecodeToUint64(value)
default:
if f, ok := value.(localinterface.IUint64); ok {
case reflect.Ptr:
if rv.IsNil() {
return 0
}
if f, ok := any.(localinterface.IUint64); ok {
return f.Uint64()
}
s := String(value)
return Uint64(rv.Elem().Interface())
case reflect.Slice:
// TODO:These types should be panic
if rv.Type().Elem().Kind() == reflect.Uint8 {
return gbinary.DecodeToUint64(rv.Bytes())
}
case reflect.String:
var (
s = rv.String()
)
// Hexadecimal
if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') {
if v, e := strconv.ParseUint(s[2:], 16, 64); e == nil {
Expand All @@ -111,10 +107,15 @@ func Uint64(any interface{}) uint64 {
return v
}
// Float64
if valueFloat64 := Float64(value); math.IsNaN(valueFloat64) {
if valueFloat64 := Float64(any); math.IsNaN(valueFloat64) {
return 0
} else {
return uint64(valueFloat64)
}
default:
if f, ok := any.(localinterface.IUint64); ok {
return f.Uint64()
}
}
return 0
}
Loading

0 comments on commit 0e471ea

Please sign in to comment.