-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathsort.go
125 lines (113 loc) · 2.37 KB
/
sort.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
// Copyright 2013 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.
package ipaddr
import (
"bytes"
"net"
"sort"
)
type byAddrFamily []Prefix
func (ps byAddrFamily) newIPv4Prefixes() []Prefix {
nps := make([]Prefix, 0, len(ps))
for _, p := range ps {
if p.IP.To4() != nil {
np := clonePrefix(&p)
nps = append(nps, *np)
}
}
return nps
}
func (ps byAddrFamily) newIPv6Prefixes() []Prefix {
nps := make([]Prefix, 0, len(ps))
for _, p := range ps {
if p.IP.To16() != nil && p.IP.To4() == nil {
np := clonePrefix(&p)
nps = append(nps, *np)
}
}
return nps
}
func compareAscending(a, b *Prefix) int {
if n := bytes.Compare(a.IP, b.IP); n != 0 {
return n
}
if n := bytes.Compare(a.Mask, b.Mask); n != 0 {
return n
}
return 0
}
type sortDir int
const (
sortAscending sortDir = iota
sortDescending
)
func newSortedPrefixes(ps []Prefix, dir sortDir, strict bool) []Prefix {
if len(ps) == 0 {
return nil
}
if strict {
if ps[0].IP.To4() != nil {
ps = byAddrFamily(ps).newIPv4Prefixes()
}
if ps[0].IP.To16() != nil && ps[0].IP.To4() == nil {
ps = byAddrFamily(ps).newIPv6Prefixes()
}
if dir == sortAscending {
sortByAscending(ps)
} else {
sortByDescending(ps)
}
} else {
nps := make([]Prefix, 0, len(ps))
for i := range ps {
np := clonePrefix(&ps[i])
nps = append(nps, *np)
}
if dir == sortAscending {
sortByAscending(nps)
} else {
sortByDescending(nps)
}
ps = nps
}
nps := ps[:0]
var p *Prefix
for i := range ps {
if p == nil {
nps = append(nps, ps[i])
} else if !p.Equal(&ps[i]) {
nps = append(nps, ps[i])
}
p = &ps[i]
}
return nps
}
func clonePrefix(s *Prefix) *Prefix {
d := &Prefix{IPNet: net.IPNet{IP: make(net.IP, net.IPv6len), Mask: make(net.IPMask, len(s.Mask))}}
copy(d.IP, s.IP.To16())
copy(d.Mask, s.Mask)
return d
}
func sortByAscending(ps []Prefix) {
sort.Slice(ps, func(i, j int) bool {
if n := bytes.Compare(ps[i].IP, ps[j].IP); n != 0 {
return n < 0
}
if n := bytes.Compare(ps[i].Mask, ps[j].Mask); n != 0 {
return n < 0
}
return false
})
}
func sortByDescending(ps []Prefix) {
sort.Slice(ps, func(i, j int) bool {
if n := bytes.Compare(ps[i].Mask, ps[j].Mask); n != 0 {
return n >= 0
}
if n := bytes.Compare(ps[i].IP, ps[i].IP); n != 0 {
return n >= 0
}
return false
})
}