Upstream gookit/goutil state of the touched files before 5ac074d77b
This commit is contained in:
commit
17b49be136
2 files changed
+191
No files matched your search
@@ -0,0 +1,108 @@
|
||||
package strutil
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gookit/goutil/x/basefn"
|
||||
)
|
||||
|
||||
//
|
||||
// -------------------- convert base --------------------
|
||||
//
|
||||
|
||||
const (
|
||||
Base10Chars = "0123456789"
|
||||
Base16Chars = "0123456789abcdef"
|
||||
Base32Chars = "0123456789abcdefghjkmnpqrstvwxyz"
|
||||
Base36Chars = "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
Base48Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKL"
|
||||
Base62Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
Base64Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
|
||||
)
|
||||
|
||||
// Base10Conv convert base10 string to new base string.
|
||||
func Base10Conv(src string, to int) string { return BaseConv(src, 10, to) }
|
||||
|
||||
// BaseConv convert base string by from and to base.
|
||||
//
|
||||
// Note: from and to base must be in [2, 64]
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// BaseConv("123", 10, 16) // Output: "7b"
|
||||
// BaseConv("7b", 16, 10) // Output: "123"
|
||||
func BaseConv(src string, from, to int) string {
|
||||
if from > 64 || from < 2 {
|
||||
from = 10
|
||||
}
|
||||
if to > 64 || to < 2 {
|
||||
to = 16
|
||||
}
|
||||
return BaseConvByTpl(src, Base64Chars[:from], Base64Chars[:to])
|
||||
}
|
||||
|
||||
// BaseConvInt convert base int to new base string.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// BaseConv(123, 16) // Output: "7b"
|
||||
func BaseConvInt(src uint64, toBase int) string {
|
||||
if toBase > 64 || toBase < 2 {
|
||||
toBase = 16
|
||||
}
|
||||
|
||||
// bigInt 支持 2-62 进制转换处理 TODO
|
||||
if toBase <= 36 {
|
||||
return strconv.FormatUint(src, toBase)
|
||||
}
|
||||
if toBase <= 62 {
|
||||
bigInt := new(big.Int).SetUint64(src)
|
||||
return bigInt.Text(toBase)
|
||||
}
|
||||
|
||||
return BaseConvIntByTpl(src, Base64Chars[:toBase])
|
||||
}
|
||||
|
||||
// BaseConvByTpl convert base string by template.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// BaseConvert("123", Base62Chars, Base16Chars) // Output: "1e"
|
||||
// BaseConvert("1e", Base16Chars, Base62Chars) // Output: "123"
|
||||
func BaseConvByTpl(src string, fromBase, toBase string) string {
|
||||
if fromBase == toBase {
|
||||
return src
|
||||
}
|
||||
|
||||
// convert to base 10
|
||||
var dec uint64
|
||||
if fromBase == Base10Chars {
|
||||
var err error
|
||||
dec, err = strconv.ParseUint(src, 10, 0)
|
||||
if err != nil {
|
||||
basefn.Panicf("input is not a valid decimal number: %s(%v)", src, err)
|
||||
}
|
||||
} else {
|
||||
fLen := uint64(len(fromBase))
|
||||
for _, c := range src {
|
||||
dec = dec*fLen + uint64(strings.IndexRune(fromBase, c))
|
||||
}
|
||||
}
|
||||
|
||||
// convert to new base
|
||||
return BaseConvIntByTpl(dec, toBase)
|
||||
}
|
||||
|
||||
// BaseConvIntByTpl convert base int to new base string.
|
||||
func BaseConvIntByTpl(dec uint64, toBase string) string {
|
||||
// convert to new base
|
||||
var res string
|
||||
toLen := uint64(len(toBase))
|
||||
for dec > 0 {
|
||||
res = string(toBase[dec%toLen]) + res
|
||||
dec /= toLen
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package strutil_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gookit/goutil/strutil"
|
||||
"github.com/gookit/goutil/x/assert"
|
||||
)
|
||||
|
||||
func TestBaseConv(t *testing.T) {
|
||||
tests := []struct {
|
||||
give string
|
||||
from int
|
||||
to int
|
||||
want string
|
||||
}{
|
||||
// 10 -> 16
|
||||
{"123", 10, 16, "7b"},
|
||||
{"7b", 16, 10, "123"},
|
||||
// 10 -> 32
|
||||
{"123", 10, 32, "3r"},
|
||||
{"3r", 32, 10, "123"},
|
||||
// 10 -> 62
|
||||
{"123", 10, 62, "1Z"},
|
||||
{"1Z", 62, 10, "123"},
|
||||
// 10 -> 64
|
||||
{"123", 10, 64, "1X"},
|
||||
{"1X", 64, 10, "123"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.give, func(t *testing.T) {
|
||||
got := strutil.BaseConv(tt.give, tt.from, tt.to)
|
||||
if got != tt.want {
|
||||
t.Errorf("BaseConv() got = %v, want %v; give=%s", got, tt.want, tt.give)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
assert.Eq(t, "7b", strutil.BaseConvInt(123, 16))
|
||||
assert.Eq(t, "2f", strutil.BaseConvInt(123, 54))
|
||||
assert.Eq(t, "1X", strutil.BaseConvInt(123, 64))
|
||||
}
|
||||
|
||||
func TestBase10Conv(t *testing.T) {
|
||||
// fmt.Println(time.Now().Format("20060102150405"))
|
||||
date := "20230829194900" // seconds
|
||||
t.Run("date sec", func(t *testing.T) {
|
||||
base16 := strutil.Base10Conv(date, 16)
|
||||
assert.Eq(t, "12665b633e94", base16)
|
||||
|
||||
base32 := strutil.Base10Conv(date, 32)
|
||||
assert.Eq(t, "icpdm6fkk", base32)
|
||||
|
||||
base62 := strutil.Base10Conv(date, 62)
|
||||
assert.Eq(t, "5KaR3zRW", base62)
|
||||
|
||||
base64 := strutil.Base10Conv(date, 64)
|
||||
assert.Eq(t, "4CproPWk", base64)
|
||||
})
|
||||
|
||||
// fmt.Println(time.Now().Format("20060102150405.000"))
|
||||
msDate := "20230829195105843"
|
||||
t.Run("date ms", func(t *testing.T) {
|
||||
base16 := strutil.Base10Conv(msDate, 16)
|
||||
assert.Eq(t, "47dfd4fbaf9633", base16)
|
||||
|
||||
base32 := strutil.Base10Conv(msDate, 32)
|
||||
assert.Eq(t, "huvqjtqv5hj", base32)
|
||||
|
||||
base62 := strutil.Base10Conv(msDate, 62)
|
||||
assert.Eq(t, "1uEL5LJptx", base62)
|
||||
|
||||
base64 := strutil.Base10Conv(msDate, 64)
|
||||
assert.Eq(t, "17TZjXHVoP", base64)
|
||||
})
|
||||
|
||||
t.Run("panic", func(t *testing.T) {
|
||||
assert.Panics(t, func() {
|
||||
strutil.Base10Conv("invalid", 16)
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user