Skip to content

Commit

Permalink
✨ feat(str): add util func ToByteSize(),SafeByteSize() for convert si…
Browse files Browse the repository at this point in the history
…ze string to size byte
  • Loading branch information
inhere committed May 7, 2023
1 parent 6c2f703 commit f8adc83
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 38 deletions.
40 changes: 2 additions & 38 deletions fmtutil/format.go
Expand Up @@ -3,8 +3,6 @@ package fmtutil
import (
"encoding/json"
"strconv"
"strings"
"unicode"

"github.com/gookit/goutil/basefn"
"github.com/gookit/goutil/byteutil"
Expand Down Expand Up @@ -37,42 +35,8 @@ func StringToByte(sizeStr string) uint64 { return ParseByte(sizeStr) }

// ParseByte converts size string like 1GB/1g or 12mb/12M into an unsigned integer number of bytes
func ParseByte(sizeStr string) uint64 {
sizeStr = strings.TrimSpace(sizeStr)
lastPos := len(sizeStr) - 1
if lastPos < 1 {
return 0
}

if sizeStr[lastPos] == 'b' || sizeStr[lastPos] == 'B' {
// last second char is k,m,g
lastSec := sizeStr[lastPos-1]
if lastSec > 'A' {
lastPos--
}
}

multiplier := float64(1)
switch unicode.ToLower(rune(sizeStr[lastPos])) {
case 'k':
multiplier = 1 << 10
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
case 'm':
multiplier = 1 << 20
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
case 'g':
multiplier = 1 << 30
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
default: // b
multiplier = 1
sizeStr = strings.TrimSpace(sizeStr[:lastPos])
}

size, _ := strconv.ParseFloat(sizeStr, 64)
if size < 0 {
return 0
}

return uint64(size * multiplier)
val, _ := strutil.ToByteSize(sizeStr)
return val
}

// PrettyJSON get pretty Json string
Expand Down
1 change: 1 addition & 0 deletions fmtutil/format_test.go
Expand Up @@ -42,6 +42,7 @@ func TestParseByte(t *testing.T) {

for _, tt := range tests {
assert.Eq(t, tt.bytes, fmtutil.StringToByte(tt.sizeS))
assert.Eq(t, tt.bytes, fmtutil.ParseByte(tt.sizeS))
}
}

Expand Down
45 changes: 45 additions & 0 deletions strutil/convert.go
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"
"strings"
"time"
"unicode"
"unsafe"

"github.com/gookit/goutil/comdef"
Expand Down Expand Up @@ -448,3 +449,47 @@ func ToTime(s string, layouts ...string) (t time.Time, err error) {
func ToDuration(s string) (time.Duration, error) {
return time.ParseDuration(s)
}

// SafeByteSize converts size string like 1GB/1g or 12mb/12M into an unsigned integer number of bytes
func SafeByteSize(sizeStr string) uint64 {
size, _ := ToByteSize(sizeStr)
return size
}

// ToByteSize converts size string like 1GB/1g or 12mb/12M into an unsigned integer number of bytes
func ToByteSize(sizeStr string) (uint64, error) {
sizeStr = strings.TrimSpace(sizeStr)
lastPos := len(sizeStr) - 1
if lastPos < 1 {
return 0, nil
}

if sizeStr[lastPos] == 'b' || sizeStr[lastPos] == 'B' {
// last second char is k,m,g,t
lastSec := sizeStr[lastPos-1]
if lastSec > 'A' {
lastPos--
}
}

multiplier := float64(1)
switch unicode.ToLower(rune(sizeStr[lastPos])) {
case 'k':
multiplier = 1 << 10
case 'm':
multiplier = 1 << 20
case 'g':
multiplier = 1 << 30
case 't':
multiplier = 1 << 40
default: // b
multiplier = 1
}

sizeNum := strings.TrimSpace(sizeStr[:lastPos])
size, err := strconv.ParseFloat(sizeNum, 64)
if size < 0 {
return 0, err
}
return uint64(size * multiplier), nil
}
34 changes: 34 additions & 0 deletions strutil/convert_test.go
Expand Up @@ -297,3 +297,37 @@ func TestQuote(t *testing.T) {
is.Eq("a single-quoted string", strutil.Unquote("'a single-quoted string'"))
is.Eq("a double-quoted string", strutil.Unquote(`"a double-quoted string"`))
}

func TestToByteSize(t *testing.T) {
u64 := uint64(0)
assert.Eq(t, u64, strutil.SafeByteSize("0"))
assert.Eq(t, u64, strutil.SafeByteSize("0b"))
assert.Eq(t, u64, strutil.SafeByteSize("0B"))
assert.Eq(t, u64, strutil.SafeByteSize("0M"))

tests := []struct {
bytes uint64
sizeS string
}{
{346, "346"},
{346, "346B"},
{3471, "3.39K"},
{346777, "338.65 Kb"},
{12341739, "11.77 M"},
{1202590842, "1.12GB"},
{1234567890123, "1.12 TB"},
}

for _, tt := range tests {
assert.Eq(t, tt.bytes, strutil.SafeByteSize(tt.sizeS))
}

assert.Eq(t, uint64(1024*1024), strutil.SafeByteSize("1M"))
assert.Eq(t, uint64(1024*1024), strutil.SafeByteSize("1MB"))
assert.Eq(t, uint64(1024*1024), strutil.SafeByteSize("1m"))
assert.Eq(t, uint64(10485760), strutil.SafeByteSize("10mb"))

assert.Eq(t, uint64(1024*1024*1024), strutil.SafeByteSize("1G"))
assert.Eq(t, uint64(1288490188), strutil.SafeByteSize("1.2GB"))
assert.Eq(t, uint64(1288490188), strutil.SafeByteSize("1.2 GB"))
}

0 comments on commit f8adc83

Please sign in to comment.