mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-04 06:03:26 -04:00
The goutil that OpenCloud currently uses is one version from the release that adds FreeBSD support, this now compiles successfully on FreeBSD.
304 lines
8.1 KiB
Go
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...)
|
|
}
|