-
Notifications
You must be signed in to change notification settings - Fork 0
/
endianness.go
90 lines (80 loc) · 2.54 KB
/
endianness.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
package byteutils
// Endian represents the endianness for conversion.
type Endian bool
const (
// LittleEndian places the least significant byte at the end (right side) of
// a byte sequence.
LittleEndian Endian = false
// BigEndian places the most significant byte at the end (right side) of a
// byte sequence
BigEndian Endian = true
)
// ByteIteratorFunc takes a byte and the enumeration (count of calls to
// function). A pointer is passed so that the byte can be potentially
// modified.
type ByteIteratorFunc = func(b *byte, enumeration int)
// IterateSmallestToLargest iterates from the smallest byte to the largest
// byte given the endianness. It will call the provided function on each byte.
func (e Endian) IterateSmallestToLargest(b Bytes, f ByteIteratorFunc) {
smallest, largest := e.byteRange(len(b))
if e == BigEndian {
for i := smallest; i <= largest; i++ {
f(&b[i], i)
}
} else {
for i := smallest; i >= largest; i-- {
f(&b[i], smallest-i)
}
}
}
// IterateUint16 iterates over a uint16 as bytes, from smallest to largest.
// Endianness determines if iteration goes from the left-most byte to the
// right-most (big endian), or the right-most byte to the left-most (little
// endian).
func (e Endian) IterateUint16(n uint16, f ByteIteratorFunc) {
e.iterateNumber(n, f)
}
// IterateUint32 iterates over a uint32 as bytes, from smallest to largest.
// Endianness determines if iteration goes from the left-most byte to the
// right-most (big endian), or the right-most byte to the left-most (little
// endian).
func (e Endian) IterateUint32(n uint32, f ByteIteratorFunc) {
e.iterateNumber(n, f)
}
// IterateNumber iterates over a number as bytes, from smallest to largest.
func (e Endian) iterateNumber(n interface{}, f ByteIteratorFunc) {
var smallest, largest int
var value uint32
switch v := n.(type) {
case uint16:
smallest, largest = e.byteRange(2)
value = uint32(v)
case uint32:
smallest, largest = e.byteRange(4)
value = v
}
if e == BigEndian {
for i := smallest; i <= largest; i++ {
shift := (largest - i) * 8
var intersect uint32 = 0xFF << shift
b := byte((value & intersect) >> shift)
f(&b, i)
}
} else {
for i := largest; i <= smallest; i++ {
shift := i * 8
var intersect uint32 = 0xFF << shift
b := byte((value & intersect) >> shift)
f(&b, i)
}
}
}
// ByteRange returns the index of the smallest and the largest bytes.
func (e Endian) byteRange(byteCount int) (smallest, largest int) {
if e == LittleEndian {
smallest = byteCount - 1
} else {
largest = byteCount - 1
}
return
}