limage - xcf/writer.go
1 package xcf
2
3 import (
4 "errors"
5 "io"
6
7 "vimagination.zapto.org/byteio"
8 )
9
10 type writer struct {
11 *byteio.StickyBigEndianWriter
12 *writerAtWriter
13 }
14
15 func newWriter(w io.WriterAt) writer {
16 wr := &writerAtWriter{
17 WriterAt: w,
18 }
19 return writer{
20 StickyBigEndianWriter: &byteio.StickyBigEndianWriter{Writer: wr},
21 writerAtWriter: wr,
22 }
23 }
24
25 func (w writer) WriteAt(p []byte, off int64) (int, error) {
26 if w.Err != nil {
27 return 0, w.Err
28 }
29 var n int
30 n, w.Err = w.WriterAt.WriteAt(p, off)
31 return n, w.Err
32 }
33
34 func (w writer) Write(p []byte) {
35 w.StickyBigEndianWriter.Write(p)
36 }
37
38 func (w writer) WriteString(str string) {
39 w.WriteUint32(uint32(len(str)) + 1)
40 w.Write([]byte(str))
41 w.WriteUint8(0)
42 }
43
44 type pointerWriter struct {
45 bw *byteio.StickyBigEndianWriter
46 toWrite uint32
47 obw *byteio.StickyBigEndianWriter
48 }
49
50 func (p *pointerWriter) WritePointer(ptr uint32) {
51 if p.toWrite > 0 {
52 p.bw.WriteUint32(ptr)
53 p.toWrite--
54 if p.bw.Err != nil {
55 p.obw.Err = p.bw.Err
56 }
57 }
58 }
59
60 func (w writer) ReservePointers(n uint32) *pointerWriter {
61 p := &pointerWriter{
62 bw: &byteio.StickyBigEndianWriter{
63 Writer: &writerAtWriter{
64 WriterAt: w.writerAtWriter.WriterAt,
65 pos: w.pos,
66 },
67 },
68 toWrite: n,
69 obw: w.StickyBigEndianWriter,
70 }
71 w.pos += int64(n) * 4
72 return p
73 }
74
75 func (w writer) ReservePointerList(n uint32) *pointerWriter {
76 pw := w.ReservePointers(n)
77 w.WriteUint32(0)
78 return pw
79 }
80
81 type writerAtWriter struct {
82 io.WriterAt
83 pos int64
84 }
85
86 func (w *writerAtWriter) Write(p []byte) (int, error) {
87 n, err := w.WriteAt(p, w.pos)
88 w.pos += int64(n)
89 return n, err
90 }
91
92 // Errors
93 var (
94 ErrTooBig = errors.New("write too big")
95 )
96