Unbewohnte
3 years ago
13 changed files with 263 additions and 198 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1,81 @@ |
|||||||
|
package util |
||||||
|
|
||||||
|
import ( |
||||||
|
"strings" |
||||||
|
"unicode" |
||||||
|
|
||||||
|
euni "golang.org/x/text/encoding/unicode" |
||||||
|
) |
||||||
|
|
||||||
|
// Checks if given characters are in ASCII range
|
||||||
|
func InASCII(chars string) bool { |
||||||
|
for i := 0; i < len(chars); i++ { |
||||||
|
if chars[i] > unicode.MaxASCII { |
||||||
|
return false |
||||||
|
} |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
// Converts given bytes into string, ignoring the first 31 non-printable ASCII characters.
|
||||||
|
// (LOSSY, if given bytes contain some nasty ones)
|
||||||
|
func ToStringLossy(gBytes []byte) string { |
||||||
|
var runes []rune |
||||||
|
for _, b := range gBytes { |
||||||
|
if b <= 31 { |
||||||
|
continue |
||||||
|
} |
||||||
|
runes = append(runes, rune(b)) |
||||||
|
} |
||||||
|
|
||||||
|
return strings.ToValidUTF8(string(runes), "") |
||||||
|
} |
||||||
|
|
||||||
|
const ( |
||||||
|
EncodingISO8859 byte = iota |
||||||
|
EncodingUTF16BOM |
||||||
|
EncodingUTF16 |
||||||
|
EncodingUTF8 |
||||||
|
) |
||||||
|
|
||||||
|
// Decodes the given frame`s contents
|
||||||
|
func DecodeText(fContents []byte) string { |
||||||
|
textEncoding := fContents[0] // the first byte is the encoding
|
||||||
|
|
||||||
|
switch textEncoding { |
||||||
|
case EncodingISO8859: |
||||||
|
// ISO-8859-1
|
||||||
|
return ToStringLossy(fContents[1:]) |
||||||
|
case EncodingUTF16BOM: |
||||||
|
// UTF-16 with BOM
|
||||||
|
encoding := euni.UTF16(euni.BigEndian, euni.ExpectBOM) |
||||||
|
decoder := encoding.NewDecoder() |
||||||
|
|
||||||
|
decodedBytes := make([]byte, len(fContents)*2) |
||||||
|
_, _, err := decoder.Transform(decodedBytes, fContents[1:], true) |
||||||
|
if err != nil { |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
return string(decodedBytes) |
||||||
|
|
||||||
|
case EncodingUTF16: |
||||||
|
// UTF-16
|
||||||
|
encoding := euni.UTF16(euni.BigEndian, euni.IgnoreBOM) |
||||||
|
decoder := encoding.NewDecoder() |
||||||
|
|
||||||
|
decodedBytes := make([]byte, len(fContents)*2) |
||||||
|
_, _, err := decoder.Transform(decodedBytes, fContents[1:], true) |
||||||
|
if err != nil { |
||||||
|
return "" |
||||||
|
} |
||||||
|
|
||||||
|
return string(decodedBytes) |
||||||
|
|
||||||
|
case EncodingUTF8: |
||||||
|
// UTF-8
|
||||||
|
return ToStringLossy(fContents[1:]) |
||||||
|
} |
||||||
|
|
||||||
|
return "" |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package util |
||||||
|
|
||||||
|
import "testing" |
||||||
|
|
||||||
|
func TestToStringLossy(t *testing.T) { |
||||||
|
someVeryNastyBytes := []byte{0, 1, 2, 3, 4, 5, 6, 50, 7, 8, 9, 10, 11, 50, 50} |
||||||
|
|
||||||
|
gString := ToStringLossy(someVeryNastyBytes) |
||||||
|
|
||||||
|
if gString != "222" { |
||||||
|
t.Errorf("ToString failed: expected output: %s; got %s", "222", gString) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func TestDecodeText(t *testing.T) { |
||||||
|
// 3 - UTF-8 encoding
|
||||||
|
someFrameContents := []byte{3, 50, 50, 50, 50, 0, 0, 0, 0, 50} |
||||||
|
|
||||||
|
decodedUtf8text := DecodeText(someFrameContents) |
||||||
|
|
||||||
|
if decodedUtf8text != "22222" { |
||||||
|
t.Errorf("DecodeText failed: expected text %s, got %s", "22222", decodedUtf8text) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func TestInASCII(t *testing.T) { |
||||||
|
asciiChars := "All these characters are in ASCII table ()^&$*!@$&%#" |
||||||
|
nonASCII := "These are not ᗜˬᗜ FUMO" |
||||||
|
|
||||||
|
if !InASCII(asciiChars) { |
||||||
|
t.Errorf("InASCII failed: expected %s to be in ASCII table", asciiChars) |
||||||
|
} |
||||||
|
|
||||||
|
if InASCII(nonASCII) { |
||||||
|
t.Errorf("InASCII failed: expected %s not to be in ASCII table", nonASCII) |
||||||
|
} |
||||||
|
} |
@ -1,12 +1,12 @@ |
|||||||
package v2 |
package v2 |
||||||
|
|
||||||
const HEADERIDENTIFIER string = "ID3" |
const HEADERIDENTIFIER string = "ID3" |
||||||
const HEADERSIZE int = 10 // bytes
|
const HEADERSIZE int = 10 |
||||||
const HEADERMAXSIZE int = 268435456 // bytes (256 MB)
|
|
||||||
const V2_2 string = "ID3v2.2" |
const V2_2 string = "ID3v2.2" |
||||||
const V2_3 string = "ID3v2.3" |
const V2_3 string = "ID3v2.3" |
||||||
const V2_4 string = "ID3v2.4" |
const V2_4 string = "ID3v2.4" |
||||||
|
|
||||||
const V2_2FrameIDSize uint = 3 |
const V2_2FrameHeaderSize uint = 6 |
||||||
const V2_3FrameIDSize uint = 4 |
const V2_3FrameHeaderSize uint = 10 |
||||||
const V2_4FrameIDSize uint = 4 |
const V2_4FrameHeaderSize uint = V2_3FrameHeaderSize |
||||||
|
@ -1,16 +1,41 @@ |
|||||||
package v2 |
package v2 |
||||||
|
|
||||||
// var TESTTAG = &ID3v2Tag{
|
|
||||||
// Frames: []Frame{
|
|
||||||
// Frame{
|
|
||||||
// Header: FrameHeader{
|
|
||||||
// ID: "COMM",
|
|
||||||
// },
|
|
||||||
// Contents: []byte("comment_here"),
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func TestWrite(t *testing.T) {
|
// func TestWrite(t *testing.T) {
|
||||||
// t.Errorf("%v", TESTTAG.Header.Version)
|
// f, err := os.Open(filepath.Join(TESTDATAPATH, "testreadv2.mp3"))
|
||||||
|
// if err != nil {
|
||||||
|
// t.Errorf("%s", err)
|
||||||
|
// }
|
||||||
|
// defer f.Close()
|
||||||
|
|
||||||
|
// testTag, err := ReadV2Tag(f)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Errorf("%s", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ff, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testwritev2.mp3"),
|
||||||
|
// os.O_CREATE|os.O_RDWR, os.ModePerm)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Errorf("%s", err)
|
||||||
|
// }
|
||||||
|
// defer ff.Close()
|
||||||
|
|
||||||
|
// err = testTag.write(ff)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Errorf("%s", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// wroteTag, err := ReadV2Tag(ff)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Errorf("%s", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // t.Errorf("ORIGINAL: %+v", testTag)
|
||||||
|
// // t.Errorf("WRITTEN: %+v", wroteTag)
|
||||||
|
// for _, origfr := range testTag.Frames {
|
||||||
|
// t.Errorf("ORIG Fr: %+v\n", origfr)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for _, wrtfr := range wroteTag.Frames {
|
||||||
|
// t.Errorf("WRITTEN Fr: %+v\n", wrtfr)
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
|
Loading…
Reference in new issue