You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
7.2 KiB
Go
312 lines
7.2 KiB
Go
1 year ago
|
package nstr
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"git.noahlan.cn/noahlan/ntool/internal/convert"
|
||
|
"git.noahlan.cn/noahlan/ntool/ndef"
|
||
|
"git.noahlan.cn/noahlan/ntool/nmath"
|
||
|
"reflect"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"time"
|
||
|
"unsafe"
|
||
|
)
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
|
||
|
// JoinAny type to string
|
||
|
func JoinAny(sep string, parts ...any) string {
|
||
|
ss := make([]string, 0, len(parts))
|
||
|
for _, part := range parts {
|
||
|
ss = append(ss, SafeString(part))
|
||
|
}
|
||
|
|
||
|
return strings.Join(ss, sep)
|
||
|
}
|
||
|
|
||
|
/*************************************************************
|
||
|
* convert value to string
|
||
|
*************************************************************/
|
||
|
|
||
|
// ToString convert value to string, return error on failed
|
||
|
func ToString(val any) (string, error) {
|
||
|
return AnyToString(val, true)
|
||
|
}
|
||
|
|
||
|
// SafeString convert value to string, will ignore error
|
||
|
func SafeString(in any) string {
|
||
|
val, _ := AnyToString(in, false)
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
// MustString convert value to string, will panic on error
|
||
|
func MustString(in any) string {
|
||
|
val, err := AnyToString(in, false)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
// AnyToString convert value to string.
|
||
|
//
|
||
|
// For defaultAsErr:
|
||
|
//
|
||
|
// - False will use fmt.Sprint convert complex type
|
||
|
// - True will return error on fail.
|
||
|
func AnyToString(val any, defaultAsErr bool) (str string, err error) {
|
||
|
if val == nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
switch value := val.(type) {
|
||
|
case int:
|
||
|
str = strconv.Itoa(value)
|
||
|
case int8:
|
||
|
str = strconv.Itoa(int(value))
|
||
|
case int16:
|
||
|
str = strconv.Itoa(int(value))
|
||
|
case int32: // same as `rune`
|
||
|
str = strconv.Itoa(int(value))
|
||
|
case int64:
|
||
|
str = strconv.FormatInt(value, 10)
|
||
|
case uint:
|
||
|
str = strconv.FormatUint(uint64(value), 10)
|
||
|
case uint8:
|
||
|
str = strconv.FormatUint(uint64(value), 10)
|
||
|
case uint16:
|
||
|
str = strconv.FormatUint(uint64(value), 10)
|
||
|
case uint32:
|
||
|
str = strconv.FormatUint(uint64(value), 10)
|
||
|
case uint64:
|
||
|
str = strconv.FormatUint(value, 10)
|
||
|
case float32:
|
||
|
str = strconv.FormatFloat(float64(value), 'f', -1, 32)
|
||
|
case float64:
|
||
|
str = strconv.FormatFloat(value, 'f', -1, 64)
|
||
|
case bool:
|
||
|
str = strconv.FormatBool(value)
|
||
|
case string:
|
||
|
str = value
|
||
|
case []byte:
|
||
|
str = string(value)
|
||
|
case time.Duration:
|
||
|
str = strconv.FormatInt(int64(value), 10)
|
||
|
case fmt.Stringer:
|
||
|
str = value.String()
|
||
|
default:
|
||
|
if defaultAsErr {
|
||
|
err = ndef.ErrConvType
|
||
|
} else {
|
||
|
str = fmt.Sprint(value)
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
/*************************************************************
|
||
|
* convert 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
|
||
|
}
|
||
|
|
||
|
/*************************************************************
|
||
|
* convert string value to bool
|
||
|
*************************************************************/
|
||
|
|
||
|
// ToBool convert string to bool
|
||
|
func ToBool(s string) (bool, error) {
|
||
|
return Bool(s)
|
||
|
}
|
||
|
|
||
|
// QuietBool convert to bool, will ignore error
|
||
|
func QuietBool(s string) bool {
|
||
|
val, _ := Bool(strings.TrimSpace(s))
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
// MustBool convert, will panic on error
|
||
|
func MustBool(s string) bool {
|
||
|
val, err := Bool(strings.TrimSpace(s))
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
// Bool parse string to bool. like strconv.ParseBool()
|
||
|
func Bool(s string) (bool, error) {
|
||
|
return convert.StrToBool(s)
|
||
|
}
|
||
|
|
||
|
/*************************************************************
|
||
|
* convert string value to int, float
|
||
|
*************************************************************/
|
||
|
|
||
|
// 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))
|
||
|
}
|
||
|
|
||
|
// Int2 convert string to int, will ignore error
|
||
|
func Int2(s string) int {
|
||
|
val, _ := ToInt(s)
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
// QuietInt convert string to int, will ignore error
|
||
|
func QuietInt(s string) int {
|
||
|
val, _ := ToInt(s)
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
|
||
|
// Int64 convert string to int, will ignore error
|
||
|
func Int64(s string) int64 {
|
||
|
val, _ := Int64OrErr(s)
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
// QuietInt64 convert string to int, will ignore error
|
||
|
func QuietInt64(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)
|
||
|
}
|
||
|
|
||
|
// 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
|
||
|
}
|
||
|
|
||
|
/*************************************************************
|
||
|
* convert string value 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 := nmath.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, ",")
|
||
|
}
|