-
Notifications
You must be signed in to change notification settings - Fork 0
/
container.go
93 lines (70 loc) · 2.34 KB
/
container.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
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
package chunk
import (
"encoding/binary"
"io"
)
// Container describes a chunked data structure by name, container chunk header, contained chunk headers and byte order.
type Container struct {
Name string
Header *ContainerHeader
Headers []*Header
ByteOrder binary.ByteOrder
}
// FindHeader returns headers with provided ID.
func (c *Container) FindHeaders(id string) []*Header {
var headers []*Header
for _, header := range c.Headers {
if header.ID() == id {
headers = append(headers, header)
}
}
return headers
}
// ReadAiff reads a AIFF / AIFF-C file from provided byte stream and assigns provided name.
func ReadAiff(name string, reader io.ReadSeeker) (*Container, error) {
return read(name, reader, binary.BigEndian)
}
// ReadRiff reads a RIFF file from provided byte stream and assigns provided name.
func ReadRiff(name string, reader io.ReadSeeker) (*Container, error) {
return read(name, reader, binary.LittleEndian)
}
// Read
func read(name string, reader io.ReadSeeker, byteOrder binary.ByteOrder) (*Container, error) {
containerHeader, err := readContainerHeader(reader, byteOrder)
if err != nil {
return nil, err
}
headers := readChunkHeaders(reader, ContainerHeaderSizeBytes, byteOrder)
container := &Container{Name: name, Header: containerHeader, Headers: headers, ByteOrder: byteOrder}
return container, nil
}
func readChunkHeaders(reader io.ReadSeeker, offset uint32, byteOrder binary.ByteOrder) []*Header {
var headers []*Header
for {
var chunkHeaderBytes [HeaderSizeBytes]byte
_, err := io.ReadFull(reader, chunkHeaderBytes[:])
if err != nil {
break
}
chunkHeader := DecodeChunkHeader(chunkHeaderBytes, offset, byteOrder)
headers = append(headers, chunkHeader)
offset += chunkHeader.FullSize()
seek := int64(chunkHeader.Size())
// For compatibility with EA IFF (Electronic Arts Interchange File Format)
// chunks must be even sized and always start at an even position.
if chunkHeader.HasPadding() {
seek++
}
reader.Seek(seek, io.SeekCurrent)
}
return headers
}
func readContainerHeader(reader io.ReadSeeker, byteOrder binary.ByteOrder) (*ContainerHeader, error) {
var headerBytes [ContainerHeaderSizeBytes]byte
_, err := io.ReadFull(reader, headerBytes[:])
if err != nil {
return nil, err
}
header, err := DecodeContainerHeader(headerBytes[:], byteOrder)
return header, err
}