-
Notifications
You must be signed in to change notification settings - Fork 7
/
string.go
118 lines (95 loc) · 2.52 KB
/
string.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package gostrutils
import (
"bytes"
"errors"
"strings"
"unicode/utf8"
)
// IsEmptyChars return true if after cleaning given chars the string is empty
func IsEmptyChars(s string, chars []rune) bool {
toMapSet := make(map[rune]bool)
for _, ch := range chars {
toMapSet[ch] = true
}
result := strings.TrimFunc(s, func(ch rune) bool {
_, found := toMapSet[ch]
return found
})
return result == ""
}
// IsEmpty returns true if a string with whitespace only was provided or an
// empty string
func IsEmpty(s string) bool {
return strings.TrimSpace(s) == ""
}
// Truncate a string to smaller parts, UTF8 multi-byte wise.
//
// When using s[:3] to truncate to 3 chars, it will not take runes but rather
// bytes. A multi-byte char (rune) can contain between one to 4 bytes, but not
// all of them will be returned.
//
// The following function will return the number of runes, and not the number of
// bytes inside a string.
func Truncate(s string, length int) string {
if s == "" {
return s
}
runeLength := utf8.RuneCountInString(s)
if length >= runeLength {
return s
}
result := []rune{}
for len(result) != length {
r, size := utf8.DecodeRuneInString(s)
result = append(result, r)
s = s[size:]
}
return string(result)
}
// CopyRange returns a copy of a string based on start and end of a rune
// for multi-byte chars instead of byte based chars (ASCII).
// 'to' is the amount of chars interested plus one.
// for example, for a string 'foo' extracting 'oo' by from: 1 and to 3.
func CopyRange(src string, from, to int) (string, error) {
if src == "" {
return src, nil
}
tmp := []rune(src)
runeLength := len(tmp)
if to <= 0 {
to = runeLength
}
if from >= runeLength {
return "", errors.New("from is larger then length")
}
if to > runeLength+1 {
return "", errors.New("to is bigger then length")
}
if (from + to) > runeLength+2 {
return "", errors.New("from + to is out of range")
}
return string(tmp[from:to]), nil
}
// KeepByteChars removes all chars that are not part of toKeep
// and return a new slice of bytes
func KeepByteChars(buf []byte, toKeep []byte) []byte {
var runes []rune
r := bytes.Runes(buf)
for _, ch := range r {
if IsRuneInByteSlice(toKeep, ch) {
runes = append(runes, ch)
}
}
return []byte(string(runes))
}
// ClearByteChars removes chars from buffer
func ClearByteChars(buf []byte, chars []byte) []byte {
var runes []rune
r := bytes.Runes(buf)
for _, ch := range r {
if !IsRuneInByteSlice(chars, ch) {
runes = append(runes, ch)
}
}
return []byte(string(runes))
}