-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsemi_octet.go
61 lines (57 loc) · 1.53 KB
/
semi_octet.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
package charset
import "fmt"
// EncodeSemi packs the given numerical chunks in a semi-octet
// representation as described in 3GPP TS 23.040.
func EncodeSemi(chunks ...uint64) []byte {
digits := make([]uint8, 0, len(chunks))
for _, c := range chunks {
var bucket []uint8
if c < 10 {
digits = append(digits, 0)
}
for c > 0 {
d := c % 10
bucket = append(bucket, uint8(d))
c = (c - d) / 10
}
for i := range bucket {
digits = append(digits, bucket[len(bucket)-1-i])
}
}
octets := make([]byte, 0, len(digits)/2+1)
for i := 0; i < len(digits); i += 2 {
if len(digits)-i < 2 {
octets = append(octets, 0xF0|digits[i])
return octets
}
octets = append(octets, digits[i+1]<<4|digits[i])
}
return octets
}
// DecodeSemi unpacks numerical chunks from the given semi-octet encoded data.
func DecodeSemi(octets []byte) []int {
chunks := make([]int, 0, len(octets)*2)
for _, oct := range octets {
half := oct >> 4
if half == 0xF {
chunks = append(chunks, int(oct&0x0F))
return chunks
}
chunks = append(chunks, int(oct&0x0F)*10+int(half))
}
return chunks
}
// DecodeSemiAddress unpacks phone numbers from the given semi-octet encoded data.
// This method is different from DecodeSemi because a 0x00 byte should be interpreted as
// two distinct digits. There 0x00 will be "00".
func DecodeSemiAddress(octets []byte) (str string) {
for _, oct := range octets {
half := oct >> 4
if half == 0xF {
str += fmt.Sprintf("%d", oct&0x0F)
return
}
str += fmt.Sprintf("%d%d", oct&0x0F, half)
}
return
}