forked from n10v/id3v2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencoding.go
More file actions
129 lines (109 loc) · 3.17 KB
/
encoding.go
File metadata and controls
129 lines (109 loc) · 3.17 KB
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
package id3v2
import (
"bufio"
xencoding "golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/encoding/unicode"
)
// Encoding is a struct for encodings.
type Encoding struct {
Name string
Key byte
TerminationBytes []byte
}
func (e Encoding) Equals(other Encoding) bool {
return e.Key == other.Key
}
func (e Encoding) String() string {
return e.Name
}
// Available encodings.
var (
// EncodingISO is ISO-8859-1 encoding.
EncodingISO = Encoding{
Name: "ISO-8859-1",
Key: 0,
TerminationBytes: []byte{0},
}
// EncodingUTF16 is UTF-16 encoded Unicode with BOM.
EncodingUTF16 = Encoding{
Name: "UTF-16 encoded Unicode with BOM",
Key: 1,
TerminationBytes: []byte{0, 0},
}
// EncodingUTF16BE is UTF-16BE encoded Unicode without BOM.
EncodingUTF16BE = Encoding{
Name: "UTF-16BE encoded Unicode without BOM",
Key: 2,
TerminationBytes: []byte{0, 0},
}
// EncodingUTF8 is UTF-8 encoded Unicode.
EncodingUTF8 = Encoding{
Name: "UTF-8 encoded Unicode",
Key: 3,
TerminationBytes: []byte{0},
}
encodings = []Encoding{EncodingISO, EncodingUTF16, EncodingUTF16BE, EncodingUTF8}
)
// getEncoding returns Encoding in accordance with ID3v2 key.
func getEncoding(key byte) Encoding {
if key > 3 {
return EncodingUTF8
}
return encodings[key]
}
// encodedSize counts length of UTF-8 src if it's encoded to enc.
func encodedSize(src string, enc Encoding) int {
if enc.Equals(EncodingUTF8) {
return len(src)
}
toXEncoding := resolveXEncoding(nil, enc)
encoded, _ := toXEncoding.NewEncoder().String(src)
return len(encoded)
}
// decodeText decodes src from "from" encoding to UTF-8.
func decodeText(src []byte, from Encoding) string {
if from.Equals(EncodingUTF8) {
return string(src)
}
fromXEncoding := resolveXEncoding(src, from)
dst, err := fromXEncoding.NewDecoder().Bytes(src)
if err != nil {
return string(src)
}
return string(dst)
}
// encodeWriteText encodes src from UTF-8 to "to" encoding and writes to bw.
func encodeWriteText(bw *bufio.Writer, src string, to Encoding) (n int, err error) {
if to.Equals(EncodingUTF8) {
return bw.WriteString(src)
}
toXEncoding := resolveXEncoding(nil, to)
encoded, err := toXEncoding.NewEncoder().String(src)
if err != nil {
return 0, err
}
return bw.WriteString(encoded)
}
// resolveXEncoding returns golang.org/x/text/encoding encoding
// from src and encoding.
func resolveXEncoding(src []byte, encoding Encoding) xencoding.Encoding {
switch encoding.Key {
case 0: // ISO-8859-1
return charmap.ISO8859_1
case 1: // UTF-16 With BOM
if len(src) < 2 {
return unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM)
} else if src[0] == 0xFE && src[1] == 0xFF {
return unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM)
} else if src[0] == 0xFF && src[1] == 0xFE {
return unicode.UTF16(unicode.LittleEndian, unicode.ExpectBOM)
}
return unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM)
case 2: // UTF-16BE without BOM
return unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
case 3: // UTF-8
return unicode.UTF8
}
return unicode.UTF8
}