-
Notifications
You must be signed in to change notification settings - Fork 1
/
key.go
78 lines (64 loc) · 1.26 KB
/
key.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
package statter
import (
"sync"
"unsafe"
)
const (
keySep = ':'
keyTagSep = '='
)
var keyPool = sync.Pool{
New: func() interface{} {
return &key{b: make([]byte, 0, 256)}
},
}
type key struct {
b []byte
}
func newKey(name string, tags []Tag) *key {
k := keyPool.Get().(*key)
k.b = k.b[:0]
k.b = append(k.b, name...)
// Short path for no tags.
if len(tags) == 0 {
return k
}
// The tags must be sorted to create a consistent key.
sortTags(tags)
for _, tag := range tags {
k.b = append(k.b, keySep)
k.b = append(k.b, tag[0]...)
k.b = append(k.b, keyTagSep)
k.b = append(k.b, tag[1]...)
}
return k
}
// String returns the key as a string.
//
// The returned string should only be used while
// holding a reference to the key, nor should it be
// stored.
func (k *key) String() string {
return *(*string)(unsafe.Pointer(&k.b))
}
// SafeString returns the key as a string that
// is safe to use after releasing the key.
func (k *key) SafeString() string {
return string(k.b)
}
func putKey(k *key) {
keyPool.Put(k)
}
func sortTags(tags []Tag) {
var sorted bool
for !sorted {
sorted = true
lmo := len(tags) - 1
for i := range lmo {
if tags[i+1][0] < tags[i][0] {
tags[i+1], tags[i] = tags[i], tags[i+1]
sorted = false
}
}
}
}