Commits

Robert Lowry committed f4dcb11

moved and renamed ID3v2 specific funcs from util.go into id3v2.go

Comments (0)

Files changed (5)

 	"bufio"
 	"fmt"
 	"io"
+	"strings"
+	"unicode/utf16"
 )
 
 // A parsed ID3v2 header as defined in Section 3 of
 	return string(data) == "ID3"
 }
 
+// Peeks at the buffer to see if there is a valid frame.
+func hasID3v2Frame(reader *bufio.Reader, frameSize int) bool {
+	data, err := reader.Peek(frameSize)
+	if err != nil {
+		return false
+	}
+
+	for _, c := range data {
+		if (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
+			return false
+		}
+	}
+	return true
+}
+
 func parseID3v2Header(reader *bufio.Reader) (*ID3v2Header, error) {
 	h := new(ID3v2Header)
 	data, err := readBytes(reader, 10)
 	h.Extended = data[5]&1<<6 != 0
 	h.Experimental = data[5]&1<<5 != 0
 	h.Footer = data[5]&1<<4 != 0
-	h.Size = parseSize(data[6:])
+	h.Size = parseID3v2Size(data[6:])
 
 	return h, nil
 }
 
+// Sizes are stored big endian but with the first bit set to 0 and always ignored.
+// Refer to section 3.1 of http://id3.org/id3v2.4.0-structure
+func parseID3v2Size(data []byte) int32 {
+	size := int32(0)
+	for i, b := range data {
+		if b&0x80 > 0 {
+			fmt.Println("Size byte had non-zero first bit")
+		}
+
+		shift := uint32(len(data)-i-1) * 7
+		size |= int32(b&0x7f) << shift
+	}
+	return size
+}
+
+// Parses a string from frame data. The first byte represents the encoding:
+//   0x01  ISO-8859-1
+//   0x02  UTF-16 w/ BOM
+//   0x03  UTF-16BE w/o BOM
+//   0x04  UTF-8
+//
+// Refer to section 4 of http://id3.org/id3v2.4.0-structure
+func parseID3v2String(data []byte) string {
+	var s string
+	switch data[0] {
+	case 0: // ISO-8859-1 text.
+		s = ISO8859_1ToUTF8(data[1:])
+		break
+	case 1: // UTF-16 with BOM.
+		s = string(utf16.Decode(toUTF16(data[1:])))
+		break
+	case 2: // UTF-16BE without BOM.
+		panic("Unsupported text encoding UTF-16BE.")
+	case 3: // UTF-8 text.
+		s = string(data[1:])
+		break
+	default:
+		// No encoding, assume ISO-8859-1 text.
+		s = ISO8859_1ToUTF8(data)
+	}
+	return strings.TrimRight(s, "\u0000")
+}
+
+func readID3v2String(reader *bufio.Reader, c int) string {
+	b, err := readBytes(reader, c)
+	if err != nil {
+		// FIXME: return an error
+		return ""
+	}
+	return parseID3v2String(b)
+}
+
+func readID3v2Genre(reader *bufio.Reader, c int) string {
+	b, err := readBytes(reader, c)
+	if err != nil {
+		// FIXME: return an error
+		return ""
+	}
+	genre := parseID3v2String(b)
+	return convertID3v1Genre(genre)
+}
+
 func parseID3v2File(reader *bufio.Reader) (*SimpleTags, error) {
 	var parseSize func(*bufio.Reader) (int, error)
 	var tagMap map[string]string
 
 	tags := new(SimpleTags)
 	lreader := bufio.NewReader(io.LimitReader(reader, int64(header.Size)))
-	for hasFrame(lreader, tagLen) {
+	for hasID3v2Frame(lreader, tagLen) {
 		b, err := readBytes(lreader, tagLen)
 		if err != nil {
 			return nil, fmt.Errorf("parseID3v2File: %s", err)
 
 		switch id {
 		case "album":
-			tags.Album = readString(lreader, size)
+			tags.Album = readID3v2String(lreader, size)
 		case "track":
-			tags.Track = readString(lreader, size)
+			tags.Track = readID3v2String(lreader, size)
 		case "artist":
-			tags.Artist = readString(lreader, size)
+			tags.Artist = readID3v2String(lreader, size)
 		case "name":
-			tags.Name = readString(lreader, size)
+			tags.Name = readID3v2String(lreader, size)
 		case "year":
-			tags.Year = readString(lreader, size)
+			tags.Year = readID3v2String(lreader, size)
 		case "disc":
-			tags.Disc = readString(lreader, size)
+			tags.Disc = readID3v2String(lreader, size)
 		case "genre":
-			tags.Genre = readGenre(lreader, size)
+			tags.Genre = readID3v2Genre(lreader, size)
 		case "length":
-			tags.Length = readString(lreader, size)
+			tags.Length = readID3v2String(lreader, size)
 		}
 	}
 	return tags, nil
 	}
 	return int(size[0])<<16 | int(size[1])<<8 | int(size[2]), nil
 }
-
 	binary.Read(reader, binary.BigEndian, &size)
 	return int(size), nil
 }
-
 	if err != nil {
 		return -1, err
 	}
-	return int(parseSize(size)), nil
+	return int(parseID3v2Size(size)), nil
 }
 import (
 	"bufio"
 	"fmt"
-	"strings"
-	"unicode/utf16"
 )
 
 var skipBuffer []byte = make([]byte, 1024*4)
 	return s
 }
 
-// Peeks at the buffer to see if there is a valid frame.
-func hasFrame(reader *bufio.Reader, frameSize int) bool {
-	data, err := reader.Peek(frameSize)
-	if err != nil {
-		return false
-	}
-
-	for _, c := range data {
-		if (c < 'A' || c > 'Z') && (c < '0' || c > '9') {
-			return false
-		}
-	}
-	return true
-}
-
-// Sizes are stored big endian but with the first bit set to 0 and always ignored.
-//
-// Refer to section 3.1 of http://id3.org/id3v2.4.0-structure
-func parseSize(data []byte) int32 {
-	size := int32(0)
-	for i, b := range data {
-		if b&0x80 > 0 {
-			fmt.Println("Size byte had non-zero first bit")
-		}
-
-		shift := uint32(len(data)-i-1) * 7
-		size |= int32(b&0x7f) << shift
-	}
-	return size
-}
-
-// Parses a string from frame data. The first byte represents the encoding:
-//   0x01  ISO-8859-1
-//   0x02  UTF-16 w/ BOM
-//   0x03  UTF-16BE w/o BOM
-//   0x04  UTF-8
-//
-// Refer to section 4 of http://id3.org/id3v2.4.0-structure
-func parseString(data []byte) string {
-	var s string
-	switch data[0] {
-	case 0: // ISO-8859-1 text.
-		s = ISO8859_1ToUTF8(data[1:])
-		break
-	case 1: // UTF-16 with BOM.
-		s = string(utf16.Decode(toUTF16(data[1:])))
-		break
-	case 2: // UTF-16BE without BOM.
-		panic("Unsupported text encoding UTF-16BE.")
-	case 3: // UTF-8 text.
-		s = string(data[1:])
-		break
-	default:
-		// No encoding, assume ISO-8859-1 text.
-		s = ISO8859_1ToUTF8(data)
-	}
-	return strings.TrimRight(s, "\u0000")
-}
-
 func readBytes(reader *bufio.Reader, c int) ([]byte, error) {
 	b := make([]byte, c)
 
 	return b, nil
 }
 
-func readString(reader *bufio.Reader, c int) string {
-	b, err := readBytes(reader, c)
-	if err != nil {
-		// FIXME: return an error
-		return ""
-	}
-	return parseString(b)
-}
-
-func readGenre(reader *bufio.Reader, c int) string {
-	b, err := readBytes(reader, c)
-	if err != nil {
-		// FIXME: return an error
-		return ""
-	}
-	genre := parseString(b)
-	return convertID3v1Genre(genre)
-}
-
 func skipBytes(reader *bufio.Reader, c int) {
 	pos := 0
 	for pos < c {