-
Notifications
You must be signed in to change notification settings - Fork 0
/
chunkwriter.go
78 lines (68 loc) · 2.23 KB
/
chunkwriter.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
package gochunks
import (
"io"
"github.com/chasingcarrots/gobinary"
)
type ChunkWriter struct {
stream *gobinary.StreamWriter
writer gobinary.HighLevelWriter
header chunkFileHeader
atChunk int
initialOffset int64
chunkAvailable bool
lastChunkOffset int64
}
func NewChunkWriter(stream *gobinary.StreamWriter, version uint16) *ChunkWriter {
return &ChunkWriter{
lastChunkOffset: -1,
stream: stream,
header: chunkFileHeader{version: version},
writer: gobinary.MakeHighLevelWriter(stream),
}
}
func (cw *ChunkWriter) Init() {
cw.header.numChunks = 0
cw.initialOffset = cw.stream.Offset()
cw.writer.WriteUInt16(cw.header.version)
// dummy value for the length, will be overwritten when all chunks have been
// written.
cw.writer.WriteUInt16(cw.header.numChunks)
}
func (cw *ChunkWriter) BeginChunk(name string, version uint16) ChunkHandle {
if cw.lastChunkOffset >= 0 {
panic("Cannot begin new chunk! You need to finish the chunk you started earlier!")
}
cw.stream.SeekCurrent()
cw.writer.WriteUInt16(uint16(len(name)))
cw.writer.WriteString(name)
cw.writer.WriteUInt16(version)
// length dummy value, will be overwritten when chunk is finished
cw.writer.WriteUInt32(0)
cw.lastChunkOffset = cw.stream.Offset()
cw.header.numChunks++
streamCopy := *cw.stream
handle := ChunkHandle{
stream: gobinary.MakeStreamWriterView(&streamCopy),
writer: gobinary.MakeHighLevelWriter(&streamCopy),
}
handle.stream.ViewHere()
return handle
}
func (cw *ChunkWriter) EndChunk(handle ChunkHandle) {
if cw.lastChunkOffset < 0 {
panic("No chunk has been started; there is no way to end one!")
}
if handle.stream.Base() != cw.lastChunkOffset {
panic("Cannot end this chunk! This is not the last chunk that was started!")
}
currentOffset := handle.stream.GlobalOffset()
cw.stream.Seek(cw.lastChunkOffset-4, io.SeekStart)
chunkSize := currentOffset - cw.lastChunkOffset
cw.writer.WriteUInt32(uint32(chunkSize))
cw.stream.Seek(currentOffset, io.SeekStart)
cw.lastChunkOffset = -1
}
func (cw *ChunkWriter) Finish() {
cw.stream.Seek(cw.initialOffset+2, io.SeekStart)
cw.writer.WriteUInt16(cw.header.numChunks)
}