blob: b8953f655c9c5f323ab0a8efc6e0b62d2dc06d86 (
plain) (
blame)
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
|
package middleware
import (
"bytes"
"github.com/miekg/dns"
)
// Less returns <0 when a is less than b, 0 when they are equal and
// >0 when a is larger than b.
// The function order names in DNSSEC canonical order.
//
// See http://bert-hubert.blogspot.co.uk/2015/10/how-to-do-fast-canonical-ordering-of.html
// for a blog article on how we do this. And https://tools.ietf.org/html/rfc4034#section-6.1 .
func Less(a, b string) int {
i := 1
aj := len(a)
bj := len(b)
for {
ai, oka := dns.PrevLabel(a, i)
bi, okb := dns.PrevLabel(b, i)
if oka && okb {
return 0
}
// sadly this []byte will allocate...
ab := []byte(a[ai:aj])
toLowerAndDDD(ab)
bb := []byte(b[bi:bj])
toLowerAndDDD(bb)
res := bytes.Compare(ab, bb)
if res != 0 {
return res
}
i++
aj, bj = ai, bi
}
return 0
}
func toLowerAndDDD(b []byte) {
lb := len(b)
for i := 0; i < lb; i++ {
if b[i] >= 'A' && b[i] <= 'Z' {
b[i] += 32
continue
}
if i+3 < lb && b[i] == '\\' && isDigit(b[i+1]) && isDigit(b[i+2]) && isDigit(b[i+3]) {
b[i] = dddToByte(b[i:])
for j := i + 1; j < lb-3; j++ {
b[j] = b[j+3]
}
lb -= 3
}
}
}
func isDigit(b byte) bool { return b >= '0' && b <= '9' }
func dddToByte(s []byte) byte { return byte((s[1]-'0')*100 + (s[2]-'0')*10 + (s[3] - '0')) }
|