package strutil import ( "errors" "reflect" "regexp" "strconv" "strings" "time" "unsafe" "github.com/gookit/goutil/internal/comfunc" "github.com/gookit/goutil/mathutil" ) var ( // ErrDateLayout error ErrDateLayout = errors.New("invalid date layout string") // ErrInvalidParam error ErrInvalidParam = errors.New("invalid input for parse time") // some regex for convert string. toSnakeReg = regexp.MustCompile("[A-Z][a-z]") toCamelRegs = map[string]*regexp.Regexp{ " ": regexp.MustCompile(" +[a-zA-Z]"), "-": regexp.MustCompile("-+[a-zA-Z]"), "_": regexp.MustCompile("_+[a-zA-Z]"), } ) // Internal func refers: // strconv.QuoteRune() // strconv.QuoteToASCII() // strconv.AppendQuote() // strconv.AppendQuoteRune() // Quote alias of strings.Quote func Quote(s string) string { return strconv.Quote(s) } // Unquote remove start and end quotes by single-quote or double-quote // // tip: strconv.Unquote cannot unquote single-quote func Unquote(s string) string { ln := len(s) if ln < 2 { return s } qs, qe := s[0], s[ln-1] var valid bool if qs == '"' && qe == '"' { valid = true } else if qs == '\'' && qe == '\'' { valid = true } if valid { s = s[1 : ln-1] // exclude quotes } // strconv.Unquote cannot unquote single-quote // if ns, err := strconv.Unquote(s); err == nil { // return ns // } return s } // Join alias of strings.Join func Join(sep string, ss ...string) string { return strings.Join(ss, sep) } // JoinList alias of strings.Join func JoinList(sep string, ss []string) string { return strings.Join(ss, sep) } // JoinComma quick join strings by comma func JoinComma(ss []string) string { return strings.Join(ss, ",") } // JoinAny type to string func JoinAny(sep string, parts ...any) string { ss := make([]string, 0, len(parts)) for _, part := range parts { ss = append(ss, QuietString(part)) } return strings.Join(ss, sep) } // Implode alias of strings.Join func Implode(sep string, ss ...string) string { return strings.Join(ss, sep) } /************************************************************* * region value to string *************************************************************/ // String convert value to string, return error on failed func String(val any) (string, error) { return ToStringWith(val) } // ToString convert value to string, return error on failed func ToString(val any) (string, error) { return ToStringWith(val) } // StringOrErr convert value to string, return error on failed func StringOrErr(val any) (string, error) { return ToStringWith(val) } // QuietString convert value to string, will ignore error. same as SafeString() func QuietString(val any) string { return SafeString(val) } // SafeString convert value to string. Will ignore error func SafeString(in any) string { s, _ := AnyToString(in, false) return s } // StringOrPanic convert value to string, will panic on error func StringOrPanic(val any) string { return MustString(val) } // MustString convert value to string. will panic on error func MustString(val any) string { s, err := ToStringWith(val) if err != nil { panic(err) } return s } // StringOrDefault convert any value to string, return default value on failed func StringOrDefault(val any, defVal string) string { return StringOr(val, defVal) } // StringOr convert any value to string, return default value on failed func StringOr(val any, defVal string) string { s, err := ToStringWith(val) if err != nil { return defVal } return s } // AnyToString convert any value to string. // // For defaultAsErr: // // - False will use fmt.Sprint convert unsupported type // - True will return error on convert fail. func AnyToString(val any, defaultAsErr bool) (s string, err error) { var optFn comfunc.ConvOptionFn if !defaultAsErr { optFn = comfunc.WithUserConvFn(comfunc.StrBySprintFn) } return comfunc.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...) } /************************************************************* * region string value to bool *************************************************************/ // ToBool convert string to bool func ToBool(s string) (bool, error) { return comfunc.StrToBool(strings.TrimSpace(s)) } // QuietBool convert to bool, will ignore error func QuietBool(s string) bool { return SafeBool(s) } // SafeBool convert to bool and will ignore error func SafeBool(s string) bool { val, _ := comfunc.StrToBool(strings.TrimSpace(s)) return val } // MustBool convert to bool and will panic on error func MustBool(s string) bool { val, err := ToBool(s) if err != nil { panic(err) } return val } // Bool parse string to bool. like strconv.ParseBool() func Bool(s string) (bool, error) { return comfunc.StrToBool(strings.TrimSpace(s)) } /************************************************************* * region string value to int *************************************************************/ // Int convert string to int, alias of ToInt() func Int(s string) (int, error) { return strconv.Atoi(strings.TrimSpace(s)) } // ToInt convert string to int, return error on fail func ToInt(s string) (int, error) { return strconv.Atoi(strings.TrimSpace(s)) } // IntOrDefault convert string to int, return default value on fail func IntOrDefault(s string, defVal int) int { return IntOr(s, defVal) } // IntOr convert string to int, return default value on fail func IntOr(s string, defVal int) int { val, err := ToInt(s) if err != nil { return defVal } return val } // SafeInt convert string to int, will ignore error func SafeInt(s string) int { val, _ := ToInt(s) return val } // QuietInt convert string to int, will ignore error func QuietInt(s string) int { return SafeInt(s) } // MustInt convert string to int, will panic on error func MustInt(s string) int { return IntOrPanic(s) } // IntOrPanic convert value to int, will panic on error func IntOrPanic(s string) int { val, err := ToInt(s) if err != nil { panic(err) } return val } /************************************************************* * region convert string to int64 *************************************************************/ // Int64 convert string to int, will ignore error func Int64(s string) int64 { return SafeInt64(s) } // QuietInt64 convert string to int, will ignore error func QuietInt64(s string) int64 { return SafeInt64(s) } // SafeInt64 convert string to int, will ignore error func SafeInt64(s string) int64 { val, _ := Int64OrErr(s) return val } // ToInt64 convert string to int, return error on fail func ToInt64(s string) (int64, error) { return strconv.ParseInt(s, 10, 0) } // Int64OrDefault convert string to int, return default value on fail func Int64OrDefault(s string, defVal int64) int64 { return Int64Or(s, defVal) } // Int64Or convert string to int, return default value on fail func Int64Or(s string, defVal int64) int64 { val, err := ToInt64(s) if err != nil { return defVal } return val } // Int64OrErr convert string to int, return error on fail func Int64OrErr(s string) (int64, error) { return strconv.ParseInt(s, 10, 0) } // MustInt64 convert value to int, will panic on error func MustInt64(s string) int64 { return Int64OrPanic(s) } // Int64OrPanic convert value to int, will panic on error func Int64OrPanic(s string) int64 { val, err := strconv.ParseInt(s, 10, 0) if err != nil { panic(err) } return val } /************************************************************* * region string value to uint *************************************************************/ // Uint convert string to uint, will ignore error func Uint(s string) uint64 { return SafeUint(s) } // SafeUint convert string to uint, will ignore error func SafeUint(s string) uint64 { val, _ := UintOrErr(s) return val } // ToUint convert string to uint, return error on fail. alias of UintOrErr() func ToUint(s string) (uint64, error) { return strconv.ParseUint(s, 10, 0) } // UintOrErr convert string to uint, return error on fail func UintOrErr(s string) (uint64, error) { return strconv.ParseUint(s, 10, 0) } // MustUint convert value to uint, will panic on error. alias of UintOrPanic() func MustUint(s string) uint64 { return UintOrPanic(s) } // UintOrPanic convert value to uint, will panic on error func UintOrPanic(s string) uint64 { val, err := UintOrErr(s) if err != nil { panic(err) } return val } // UintOrDefault convert string to uint, return default value on fail func UintOrDefault(s string, defVal uint64) uint64 { return UintOr(s, defVal) } // UintOr convert string to uint, return default value on fail func UintOr(s string, defVal uint64) uint64 { val, err := UintOrErr(s) if err != nil { return defVal } return val } /************************************************************* * region string value to byte * refer from https://github.com/valyala/fastjson/blob/master/util.go *************************************************************/ // Byte2str convert bytes to string func Byte2str(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } // Byte2string convert bytes to string func Byte2string(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } // ToBytes convert string to bytes func ToBytes(s string) (b []byte) { strh := (*reflect.StringHeader)(unsafe.Pointer(&s)) sh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) sh.Data = strh.Data sh.Len = strh.Len sh.Cap = strh.Len return b } /************************************************************* * region string to int/string slice, time.Time *************************************************************/ // Ints alias of the ToIntSlice(). default sep is comma(,) func Ints(s string, sep ...string) []int { ints, _ := ToIntSlice(s, sep...) return ints } // ToInts alias of the ToIntSlice(). default sep is comma(,) func ToInts(s string, sep ...string) ([]int, error) { return ToIntSlice(s, sep...) } // ToIntSlice split string to slice and convert item to int. // // Default sep is comma func ToIntSlice(s string, sep ...string) (ints []int, err error) { ss := ToSlice(s, sep...) for _, item := range ss { iVal, err := mathutil.ToInt(item) if err != nil { return []int{}, err } ints = append(ints, iVal) } return } // ToArray alias of the ToSlice() func ToArray(s string, sep ...string) []string { return ToSlice(s, sep...) } // Strings alias of the ToSlice() func Strings(s string, sep ...string) []string { return ToSlice(s, sep...) } // ToStrings alias of the ToSlice() func ToStrings(s string, sep ...string) []string { return ToSlice(s, sep...) } // ToSlice split string to array. func ToSlice(s string, sep ...string) []string { if len(sep) > 0 { return Split(s, sep[0]) } return Split(s, ",") } // ToDuration parses a duration string. such as "300ms", "-1.5h" or "2h45m". // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". func ToDuration(s string) (time.Duration, error) { return comfunc.ToDuration(s) }