-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstrings.go
More file actions
79 lines (65 loc) · 1.92 KB
/
strings.go
File metadata and controls
79 lines (65 loc) · 1.92 KB
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
package strutils
import (
"math/rand"
"strings"
"unsafe"
)
// Concat will return a concatenation of all the given strings
func Concat(strs ...string) string {
if len(strs) == 0 {
return ""
}
var (
totalChars int
b strings.Builder
)
// For long strings its actually faster to make it grow once
for _, s := range strs {
totalChars += len(s)
}
b.Grow(totalChars)
for _, s := range strs {
b.WriteString(s)
}
return b.String()
}
const (
// These are the characters we will use for our random string
charBytes = "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// The maximum number of chars we support in random strings
maxChars = 62
// The number of bits we should use to get a string
// 6 bits allow us to represent 64 characters
bitsNeededPerChar = 6
// This is the mask we use to generate the idx for character
charMask = 1<<bitsNeededPerChar - 1
// This is the maximum chars we can generate per round
// Each int64 will have 63 usable bits
maxCharsPerRand = 63 / bitsNeededPerChar
// one
one = 1
)
// GenRandomString will generate a random string of the given length
// This uses the super optimized version where we pick bits manually
// With current implementation of rand.Read we are efficient when we use 64 characters.
// Even at 64 characters, this is not sub optimal with rand.Read, just on par
// There is wastage when using less than 64 characters as a base for our string
func GenRandomString(n int) string {
if n <= 0 {
return ""
}
b := make([]byte, n)
// A rand.Int63() generates 63 random bits, i.e. maxCharsPerRand random character can be chosen
for i, cache, remain := n-one, rand.Int63(), maxCharsPerRand; i >= 0; {
if remain == 0 {
cache, remain = rand.Int63(), maxCharsPerRand
}
if idx := int(cache & charMask); idx < maxChars {
b[i] = charBytes[idx]
i--
}
cache >>= bitsNeededPerChar
remain--
}
return *(*string)(unsafe.Pointer(&b))
}