-
Notifications
You must be signed in to change notification settings - Fork 0
/
byteseq.go
100 lines (91 loc) · 2.15 KB
/
byteseq.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
package nstd
import (
"unicode/utf8"
)
// A ByteSeq is either a string or a byte slice.
type ByteSeq interface{ ~string | ~[]byte }
// ByteSeqCommonPrefixes returns the common prefixes of two [ByteSeq] values.
func ByteSeqCommonPrefix[X, Y ByteSeq](x X, y Y) (x2 X, y2 Y) {
// Tried several coding mamners and found
// the current one is inline-able, with cost 80.
min := minOfTwo(len(x), len(y))
x2, y2 = x[:min], y[:min]
if len(x2) == len(y2) { // BCE hint
for i := 0; i < len(x2); i++ {
if x2[i] != y2[i] {
return x2[:i], y2[:i]
}
}
}
return
}
var (
_, _ = ByteSeqCommonPrefix("", []byte{})
_, _ = ByteSeqCommonPrefix("", "")
_, _ = ByteSeqCommonPrefix([]byte{}, "")
_, _ = ByteSeqCommonPrefix([]byte{}, []byte{})
)
// ReverseBytes inverts the bytes in a byte slice.
// The argument is returned so that calls to ReverseBytes can be used as expressions.
func ReverseBytes[Bytes ~[]byte](s Bytes) Bytes {
if len(s) == 0 {
return s[:0]
}
var i, j = len(s) - 1, 0
for i > j {
s[i], s[j] = s[j], s[i]
j++
i--
}
return s
}
// ReverseByteSeq returnes a copy (in the form of byte slice) of
// a byte sequence (in the form of either string or byte slice) but reversed.
func ReverseByteSeq[Seq ByteSeq](s Seq) []byte {
if len(s) == 0 {
return []byte(s[:0])
}
var into = make([]byte, len(s))
var j = 0
for i := len(s) - 1; i >= 0; i-- {
into[j] = s[i]
j++
}
return into
}
// ReverseRuneSeq returnes a copy (in the form of byte slice) of
// a rune sequence (in the form of either string or byte slice) but reversed.
//
// See:
//
// * https://github.com/golang/go/issues/14777
// * https://github.com/golang/go/issues/68348
func ReverseRuneSeq[Seq ByteSeq](s Seq) []byte {
if len(s) == 0 {
return []byte(s[:0])
}
var into = make([]byte, len(s))
var bytes = []byte(s) // doesn't allocate since Go toolchain 1.22
var i = len(bytes)
for {
_, size := utf8.DecodeRune(bytes)
if size == 0 {
if i != 0 {
Panicf("i (%v) != 0", i)
}
break
}
if i < size {
Panicf("i (%v) < size (%v)", i, size)
}
i -= size
var j, k = i, 0
for k < size {
into[j] = bytes[k]
j++
k++
}
bytes = bytes[size:]
}
return into
}