Simplified unsynchroniser and added tests

This commit is contained in:
David Howden 2015-05-02 09:58:05 +10:00
parent 5ddbd701bc
commit 5989e00ece
2 changed files with 142 additions and 33 deletions

View File

@ -238,44 +238,28 @@ func readID3v2Frames(r io.Reader, h *ID3v2Header) (map[string]interface{}, error
return result, nil
}
type Unsynchroniser struct {
orig io.Reader
prevWasFF bool
type unsynchroniser struct {
io.Reader
ff bool
}
// filter io.Reader which skip the Unsynchronisation bytes
func (r *Unsynchroniser) Read(p []byte) (int, error) {
for i := 0; i < len(p); i++ {
// there is only one byte to read.
if i == len(p)-1 {
if n, err := r.orig.Read(p[i : i+1]); n == 0 || err != nil {
return i, err
}
// we need to read this last byte once more
if r.prevWasFF && p[i] == 0 {
i--
r.prevWasFF = false
}
r.prevWasFF = (p[i] == 255)
continue
}
if n, err := r.orig.Read(p[i : i+2]); n == 0 || err != nil {
func (r *unsynchroniser) Read(p []byte) (i int, err error) {
b := make([]byte, 1)
for i < len(p) {
x, err := r.Reader.Read(b)
if err != nil || x == 0 {
return i, err
}
if r.prevWasFF && p[i] == 0 {
p[i] = p[i+1]
r.prevWasFF = (p[i+1] == 255)
if r.ff && b[0] == 0x00 {
r.ff = false
continue
}
if p[i] == 255 && p[i+1] == 0 {
r.prevWasFF = false
continue
}
r.prevWasFF = (p[i+1] == 255)
// these 2 bytes are fine, we skip none
p[i] = b[0]
i++
r.ff = (b[0] == 0xFF)
}
return len(p), nil
return
}
// ReadID3v2Tags parses ID3v2.{2,3,4} tags from the io.ReadSeeker into a Metadata, returning
@ -292,11 +276,9 @@ func ReadID3v2Tags(r io.ReadSeeker) (Metadata, error) {
}
var ur io.Reader
ur = r
if h.Unsynchronisation {
ur = &Unsynchroniser{orig: r}
} else {
ur = r
ur = &unsynchroniser{Reader: r}
}
f, err := readID3v2Frames(ur, h)

127
id3v2_test.go Normal file
View File

@ -0,0 +1,127 @@
package tag
import (
"bytes"
"reflect"
"testing"
)
func TestUnsynchroniser(t *testing.T) {
tests := []struct {
input []byte
output []byte
}{
{
input: []byte{},
output: []byte{},
},
{
input: []byte{0x00},
output: []byte{0x00},
},
{
input: []byte{0xFF},
output: []byte{0xFF},
},
{
input: []byte{0xFF, 0x00},
output: []byte{0xFF},
},
{
input: []byte{0xFF, 0x00, 0x00},
output: []byte{0xFF, 0x00},
},
{
input: []byte{0xFF, 0x00, 0x01},
output: []byte{0xFF, 0x01},
},
{
input: []byte{0xFF, 0x00, 0xFF, 0x00},
output: []byte{0xFF, 0xFF},
},
{
input: []byte{0xFF, 0x00, 0xFF, 0xFF, 0x00},
output: []byte{0xFF, 0xFF, 0xFF},
},
{
input: []byte{0x00, 0x01, 0x02},
output: []byte{0x00, 0x01, 0x02},
},
}
for ii, tt := range tests {
r := bytes.NewReader(tt.input)
ur := unsynchroniser{Reader: r}
got := make([]byte, len(tt.output))
n, err := ur.Read(got)
if n != len(got) || err != nil {
t.Errorf("[%d] got: n = %d, err = %v, expected: n = %d, err = nil", ii, n, err, len(got))
}
if !reflect.DeepEqual(got, tt.output) {
t.Errorf("[%d] got: %v, expected %v", ii, got, tt.output)
}
}
}
func TestUnsynchroniserSplitReads(t *testing.T) {
tests := []struct {
input []byte
output []byte
split []int
}{
{
input: []byte{0x00, 0xFF, 0x00},
output: []byte{0x00, 0xFF},
split: []int{1, 1},
},
{
input: []byte{0xFF, 0x00, 0x01},
output: []byte{0xFF, 0x01},
split: []int{1, 1},
},
{
input: []byte{0xFF, 0x00, 0x01, 0x02},
output: []byte{0xFF, 0x01, 0x02},
split: []int{1, 1, 1},
},
{
input: []byte{0xFF, 0x00, 0x01, 0x02},
output: []byte{0xFF, 0x01, 0x02},
split: []int{2, 1},
},
{
input: []byte{0xFF, 0x00, 0x01, 0x02},
output: []byte{0xFF, 0x01, 0x02},
split: []int{1, 2},
},
}
for ii, tt := range tests {
r := bytes.NewReader(tt.input)
ur := unsynchroniser{Reader: r}
var got []byte
for i, l := range tt.split {
chunk := make([]byte, l)
n, err := ur.Read(chunk)
if n != len(chunk) || err != nil {
t.Errorf("[%d : %d] got: n = %d, err = %v, expected: n = %d, err = nil", ii, i, n, err, l)
}
got = append(got, chunk...)
}
if !reflect.DeepEqual(got, tt.output) {
t.Errorf("[%d] got: %v, expected %v", ii, got, tt.output)
}
}
}