Files
opencloud/vendor/github.com/gookit/goutil/mathutil/convert.go
PC Kitty d97217f22c Update github.com/gookit/goutil to v0.7.4 for FreeBSD compatibility
The goutil that OpenCloud currently uses is one version from the release that adds FreeBSD support, this now compiles successfully on FreeBSD.
2026-04-28 18:03:17 +02:00

304 lines
8.1 KiB
Go

package mathutil
import (
"reflect"
"strconv"
"strings"
"time"
"github.com/gookit/goutil/comdef"
"github.com/gookit/goutil/internal/checkfn"
"github.com/gookit/goutil/internal/comfunc"
)
// ConvOption convert options
type ConvOption[T any] struct {
// if ture: value is nil, will return convert error;
// if false(default): value is nil, will convert to zero value
NilAsFail bool
// HandlePtr auto convert ptr type(int,float,string) value. eg: *int to int
// - if true: will use real type try convert. default is false
// - NOTE: current T type's ptr is default support.
HandlePtr bool
// StrictMode for convert value. default is false
//
// TRUE:
// - to int: string, float will return error
StrictMode bool
// set custom fallback convert func for not supported type.
UserConvFn ToTypeFunc[T]
}
// NewConvOption create a new ConvOption
func NewConvOption[T any](optFns ...ConvOptionFn[T]) *ConvOption[T] {
opt := &ConvOption[T]{}
opt.WithOption(optFns...)
return opt
}
// WithOption set convert option
func (opt *ConvOption[T]) WithOption(optFns ...ConvOptionFn[T]) {
for _, fn := range optFns {
if fn != nil {
fn(opt)
}
}
}
// ConvOptionFn convert option func
type ConvOptionFn[T any] func(opt *ConvOption[T])
// WithNilAsFail set ConvOption.NilAsFail option
//
// Example:
//
// ToIntWithFunc(val, mathutil.WithNilAsFail[int])
func WithNilAsFail[T any](opt *ConvOption[T]) { opt.NilAsFail = true }
// WithHandlePtr set ConvOption.HandlePtr option
func WithHandlePtr[T any](opt *ConvOption[T]) { opt.HandlePtr = true }
// WithStrictMode set ConvOption.StrictMode option
func WithStrictMode[T any](opt *ConvOption[T]) { opt.StrictMode = true }
// WithUserConvFn set ConvOption.UserConvFn option
func WithUserConvFn[T any](fn ToTypeFunc[T]) ConvOptionFn[T] {
return func(opt *ConvOption[T]) {
opt.UserConvFn = fn
}
}
/*************************************************************
* region Strict to int/uint
*************************************************************/
// StrictInt check the given value is an integer(intX,uintX), return the int64 value and true if success
func StrictInt(val any) (int64, bool) {
switch tVal := val.(type) {
case int:
return int64(tVal), true
case int8:
return int64(tVal), true
case int16:
return int64(tVal), true
case int32:
return int64(tVal), true
case int64:
return tVal, true
case uint:
return int64(tVal), true
case uint8:
return int64(tVal), true
case uint16:
return int64(tVal), true
case uint32:
return int64(tVal), true
case uint64:
return int64(tVal), true
case uintptr:
return int64(tVal), true
default:
return 0, false
}
}
// StrictUint strict check value is integer(intX,uintX) and convert to uint64.
func StrictUint(val any) (uint64, bool) {
switch tVal := val.(type) {
case int:
return uint64(tVal), true
case int8:
return uint64(tVal), true
case int16:
return uint64(tVal), true
case int32:
return uint64(tVal), true
case int64:
return uint64(tVal), true
case uint:
return uint64(tVal), true
case uint8:
return uint64(tVal), true
case uint16:
return uint64(tVal), true
case uint32:
return uint64(tVal), true
case uint64:
return tVal, true
case uintptr:
return uint64(tVal), true
default:
return 0, false
}
}
/*************************************************************
* region convert to float64
*************************************************************/
// QuietFloat convert value to float64, will ignore error. alias of SafeFloat
func QuietFloat(in any) float64 { return SafeFloat(in) }
// SafeFloat convert value to float64, will ignore error
func SafeFloat(in any) float64 {
val, _ := ToFloatWith(in)
return val
}
// FloatOrPanic convert value to float64, will panic on error
func FloatOrPanic(in any) float64 { return MustFloat(in) }
// MustFloat convert value to float64, will panic on error
func MustFloat(in any) float64 {
val, err := ToFloatWith(in)
if err != nil {
panic(err)
}
return val
}
// FloatOrDefault convert value to float64, will return default value on error
func FloatOrDefault(in any, defVal float64) float64 { return FloatOr(in, defVal) }
// FloatOr convert value to float64, will return default value on error
func FloatOr(in any, defVal float64) float64 {
val, err := ToFloatWith(in)
if err != nil {
return defVal
}
return val
}
// Float convert value to float64, return error on failed
func Float(in any) (float64, error) { return ToFloatWith(in) }
// FloatOrErr convert value to float64, return error on failed
func FloatOrErr(in any) (float64, error) { return ToFloatWith(in) }
// ToFloat convert value to float64, return error on failed
func ToFloat(in any) (float64, error) { return ToFloatWith(in) }
// ToFloatWith try to convert value to float64. can with some option func, more see ConvOption.
func ToFloatWith(in any, optFns ...ConvOptionFn[float64]) (f64 float64, err error) {
opt := NewConvOption(optFns...)
if !opt.NilAsFail && in == nil {
return 0, nil
}
switch tVal := in.(type) {
case string:
f64, err = strconv.ParseFloat(strings.TrimSpace(tVal), 64)
case int:
f64 = float64(tVal)
case int8:
f64 = float64(tVal)
case int16:
f64 = float64(tVal)
case int32:
f64 = float64(tVal)
case int64:
f64 = float64(tVal)
case uint:
f64 = float64(tVal)
case uint8:
f64 = float64(tVal)
case uint16:
f64 = float64(tVal)
case uint32:
f64 = float64(tVal)
case uint64:
f64 = float64(tVal)
case float32:
f64 = float64(tVal)
case float64:
f64 = tVal
case *float64: // default support float64 ptr type
f64 = *tVal
case time.Duration:
f64 = float64(tVal)
case comdef.Float64able: // eg: json.Number
f64, err = tVal.Float64()
default:
if opt.HandlePtr {
if rv := reflect.ValueOf(in); rv.Kind() == reflect.Pointer {
rv = rv.Elem()
if checkfn.IsSimpleKind(rv.Kind()) {
return ToFloatWith(rv.Interface(), optFns...)
}
}
}
if opt.UserConvFn != nil {
f64, err = opt.UserConvFn(in)
} else {
err = comdef.ErrConvType
}
}
return
}
/*************************************************************
* region intX/floatX to string
*************************************************************/
// MustString convert intX/floatX value to string, will panic on error
func MustString(val any) string {
str, err := ToStringWith(val)
if err != nil {
panic(err)
}
return str
}
// StringOrPanic convert intX/floatX value to string, will panic on error
func StringOrPanic(val any) string { return MustString(val) }
// StringOrDefault convert intX/floatX value to string, will return default value on error
func StringOrDefault(val any, defVal string) string { return StringOr(val, defVal) }
// StringOr convert intX/floatX value to string, will return default value on error
func StringOr(val any, defVal string) string {
str, err := ToStringWith(val)
if err != nil {
return defVal
}
return str
}
// ToString convert intX/floatX value to string, return error on failed
func ToString(val any) (string, error) { return ToStringWith(val) }
// StringOrErr convert intX/floatX value to string, return error on failed
func StringOrErr(val any) (string, error) { return ToStringWith(val) }
// QuietString convert intX/floatX value to string, other type convert by fmt.Sprint
func QuietString(val any) string { return SafeString(val) }
// String convert intX/floatX value to string, other type convert by fmt.Sprint
func String(val any) string {
str, _ := TryToString(val, false)
return str
}
// SafeString convert intX/floatX value to string, other type convert by fmt.Sprint
func SafeString(val any) string {
str, _ := TryToString(val, false)
return str
}
// TryToString try convert intX/floatX value to string
//
// if defaultAsErr is False, will use fmt.Sprint convert other type
func TryToString(val any, defaultAsErr bool) (string, error) {
var optFn comfunc.ConvOptionFn
if !defaultAsErr {
optFn = comfunc.WithUserConvFn(comfunc.StrBySprintFn)
}
return ToStringWith(val, optFn)
}
// ToStringWith try to convert value to string. can with some option func, more see comfunc.ConvOption.
func ToStringWith(in any, optFns ...comfunc.ConvOptionFn) (string, error) {
return comfunc.ToStringWith(in, optFns...)
}