This repository has been archived by the owner on May 9, 2020. It is now read-only.
forked from bakanis/uuid
-
Notifications
You must be signed in to change notification settings - Fork 13
/
format.go
161 lines (143 loc) · 4.02 KB
/
format.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package uuid
import (
"strings"
)
// Format represents different styles a UUID can be printed in constants
// represent a pattern used by the package with which to print a UUID.
type Format string
// The following are the default Formats supplied by the uuid package.
const (
FormatHex Format = "%x%x%x%x%x"
FormatHexCurly Format = "{%x%x%x%x%x}"
FormatHexBracket Format = "(%x%x%x%x%x)"
// FormatCanonical is the default format.
FormatCanonical Format = "%x-%x-%x-%x-%x"
FormatCanonicalCurly Format = "{%x-%x-%x-%x-%x}"
FormatCanonicalBracket Format = "(%x-%x-%x-%x-%x)"
FormatUrn Format = "urn:uuid:" + FormatCanonical
)
var (
printFormat = FormatCanonical
defaultFormats map[Format]bool = make(map[Format]bool)
)
func init() {
defaultFormats[FormatHex] = true
defaultFormats[FormatHexCurly] = true
defaultFormats[FormatHexBracket] = true
defaultFormats[FormatCanonical] = true
defaultFormats[FormatCanonicalCurly] = true
defaultFormats[FormatCanonicalBracket] = true
defaultFormats[FormatUrn] = true
}
// SwitchFormat switches the default printing format for ALL UUIDs.
//
// The default is canonical uuid.Format.FormatCanonical which has been
// optimised for use with this package. It is twice as fast compared to other
// formats. However, non package formats are still very quick.
//
// A valid format will have 5 groups of [%x|%X] or follow the pattern,
// *%[xX]*%[xX]*%[xX]*%[xX]*%[xX]*. If the supplied format does not meet this
// standard the function will panic. Note any extra uses of [%] outside of the
// [%x|%X] will also cause a panic.
// Constant uuid.Formats have been provided for most likely formats.
func SwitchFormat(form Format) {
checkFormat(form)
printFormat = form
}
// SwitchFormatToUpper is a convenience function to set the uuid.Format to uppercase
// versions.
func SwitchFormatToUpper(form Format) {
SwitchFormat(Format(strings.ToUpper(string(form))))
}
// Formatter will return a string representation of the given UUID.
//
// Use this for one time formatting when setting the Format using
// uuid.SwitchFormat would be overkill.
//
// A valid format will have 5 groups of [%x|%X] or follow the pattern,
// *%[xX]*%[xX]*%[xX]*%[xX]*%[xX]*. If the supplied format does not meet this
// standard the function will panic. Note any extra uses of [%] outside of the
// [%x|%X] will also cause a panic.
func Formatter(id Implementation, form Format) string {
checkFormat(form)
return formatUuid(id.Bytes(), form)
}
func checkFormat(form Format) {
if defaultFormats[form] {
return
}
s := strings.ToLower(string(form))
if strings.Count(s, "%x") != 5 {
panic("uuid: invalid format")
}
s = strings.Replace(s, "%x", "", -1)
if strings.Count(s, "%") > 0 {
panic("uuid: invalid format")
}
}
const (
hexTable = "0123456789abcdef"
hexUpperTable = "0123456789ABCDEF"
canonicalLength = length*2 + 4
formatArgCount = 10
uuidStringBufferSize = length*2 - formatArgCount
)
var groups = [...]int{4, 2, 2, 2, 6}
func formatUuid(src []byte, form Format) string {
if form == FormatCanonical {
return string(formatCanonical(src))
}
return string(format(src, string(form)))
}
func format(src []byte, form string) []byte {
end := len(form)
buf := make([]byte, end+uuidStringBufferSize)
var s, ls, b, e, p int
var u bool
for _, v := range groups {
ls = s
for ; s < end && form[s] != '%'; s++ {
}
copy(buf[p:], form[ls:s])
p += s - ls
s++
u = form[s] == 'X'
s++
e = b + v
for i, t := range src[b:e] {
j := p + i + i
table := hexTable
if u {
table = hexUpperTable
}
buf[j] = table[t>>4]
buf[j+1] = table[t&0x0f]
}
b = e
p += v + v
}
ls = s
for ; s < end && form[s] != '%'; s++ {
}
copy(buf[p:], form[ls:s])
return buf
}
func formatCanonical(src []byte) []byte {
buf := make([]byte, canonicalLength)
var b, p, e int
for h, v := range groups {
e = b + v
for i, t := range src[b:e] {
j := p + i + i
buf[j] = hexTable[t>>4]
buf[j+1] = hexTable[t&0x0f]
}
b = e
p += v + v
if h < 4 {
buf[p] = '-'
p += 1
}
}
return buf
}