-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathint.go
130 lines (114 loc) · 2.72 KB
/
int.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
package ipv4
import (
"errors"
"net"
)
// ErrBadIP is a generic error that an IP address could not be parsed
var ErrBadIP = errors.New("Bad IP address")
// FromNetIP converts a IPv4 net.IP to uint32, error
func FromNetIP(ip net.IP) (uint32, error) {
ip = ip.To4()
if ip == nil {
return 0, ErrBadIP
}
return uint32(ip[3]) | uint32(ip[2])<<8 | uint32(ip[1])<<16 | uint32(ip[0])<<24, nil
}
// ToNetIP converts a uint32 to a net.IP (net.IPv4 actually)
func ToNetIP(val uint32) net.IP {
return net.IPv4(byte(val>>24), byte(val>>16&0xFF),
byte(val>>8)&0xFF, byte(val&0xFF))
}
// FromDots converts an IPv4 dotted string into a
// uint32 (big endian).
func FromDots(ipstr string) (uint32, error) {
var out uint32
var oct uint32
var num int
var hasOct bool
for i := 0; i < len(ipstr); i++ {
b := ipstr[i]
switch {
case b >= '0' && b <= '9':
oct = oct*10 + uint32(b-'0')
if oct > 255 {
return 0, ErrBadIP
}
hasOct = true
case b == '.':
// test for ".." cases
if !hasOct {
return 0, ErrBadIP
}
out = (out << 8) | oct
oct = 0
hasOct = false
num++
// more than 3 dots
if num > 3 {
return 0, ErrBadIP
}
default:
return 0, ErrBadIP
}
}
// num != 3 --> must have 3 dots
// !hasOct --> input ended in a dot or other char
if num != 3 || !hasOct {
return 0, ErrBadIP
}
out = (out << 8) | oct
return out, nil
}
// ToDots converts a uint32 to a IPv4 Dotted notation
//
// About 10x faster than doing something with fmt.Sprintf
// one allocation per call.
//
// Based on golang's net/IP.String()
// https://golang.org/src/net/ip.go?s=7645:7673#L281
//
func ToDots(p4 uint32) string {
const maxIPv4StringLen = len("255.255.255.255")
b := make([]byte, maxIPv4StringLen)
n := ubtoa(b, 0, byte(p4>>24))
b[n] = '.'
n++
n += ubtoa(b, n, byte((p4>>16)&0xFF))
b[n] = '.'
n++
n += ubtoa(b, n, byte((p4>>8)&0xFF))
b[n] = '.'
n++
n += ubtoa(b, n, byte(p4&0xFF))
return string(b[:n])
}
// from
// https://golang.org/src/net/ip.go?s=7645:7673#L281
//
// ubtoa encodes the string form of the integer v to dst[start:] and
// returns the number of bytes written to dst. The caller must ensure
// that dst has sufficient length.
func ubtoa(dst []byte, start int, v byte) int {
if v < 10 {
dst[start] = v + '0'
return 1
} else if v < 100 {
dst[start+1] = v%10 + '0'
dst[start] = v/10 + '0'
return 2
}
dst[start+2] = v%10 + '0'
dst[start+1] = (v/10)%10 + '0'
dst[start] = v/100 + '0'
return 3
}
// SortUniqueUint32 sorts, and dedups a slice of uint32 (maybe representing
// binary representation of IPv4 address
//
// sorting and uniqueness is done in place
//
func SortUniqueUint32(in []uint32) {
// reuse Set (which is a []unit32 anyways) implimentation
set := Set(in)
set.sort()
}