...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package comdoc
18
19 import (
20 "errors"
21 "io"
22 )
23
24 type streamReader struct {
25 remaining uint32
26 nextSector SecID
27 sat []SecID
28 sectorSize int
29 readSector func(SecID, []byte) error
30 buf, saved []byte
31 }
32
33
34 func (r *ComDoc) ReadStream(e *DirEnt) (io.Reader, error) {
35 if e.Type != DirStream {
36 return nil, errors.New("not a stream")
37 }
38 sr := &streamReader{
39 remaining: e.StreamSize,
40 nextSector: e.NextSector,
41 }
42 if e.StreamSize < r.Header.MinStdStreamSize {
43 sr.sectorSize = r.ShortSectorSize
44 sr.sat = r.SSAT
45 sr.readSector = r.readShortSector
46 } else {
47 sr.sectorSize = r.SectorSize
48 sr.sat = r.SAT
49 sr.readSector = r.readSector
50 }
51 sr.buf = make([]byte, sr.sectorSize)
52 return sr, nil
53 }
54
55 func (sr *streamReader) Read(d []byte) (copied int, err error) {
56 if sr.remaining == 0 {
57 return 0, io.EOF
58 } else if len(d) == 0 {
59 return 0, nil
60 }
61 if int64(len(d)) > int64(sr.remaining) {
62 d = d[:int(sr.remaining)]
63 }
64
65 if len(sr.saved) > 0 {
66 n := len(sr.saved)
67 if n > len(d) {
68 n = len(d)
69 }
70 copy(d[:n], sr.saved[:n])
71 d = d[n:]
72 sr.saved = sr.saved[n:]
73 copied += n
74 sr.remaining -= uint32(n)
75 }
76
77 n := sr.sectorSize
78 for len(d) >= n {
79 if sr.nextSector < 0 {
80 return copied, errors.New("unexpected end to stream")
81 }
82 if err := sr.readSector(sr.nextSector, d[:n]); err != nil {
83 return copied, err
84 }
85 d = d[n:]
86 copied += n
87 sr.remaining -= uint32(n)
88 sr.nextSector = sr.sat[sr.nextSector]
89 }
90
91 if len(d) > 0 {
92 n = len(d)
93 if sr.nextSector < 0 {
94 return copied, errors.New("unexpected end to stream")
95 }
96 if err := sr.readSector(sr.nextSector, sr.buf); err != nil {
97 return copied, err
98 }
99 copy(d, sr.buf)
100 copied += n
101 sr.remaining -= uint32(n)
102 sr.saved = sr.buf[n:]
103 sr.nextSector = sr.sat[sr.nextSector]
104 }
105 return copied, nil
106 }
107
108
109
110 func (r *ComDoc) addStream(contents []byte, short bool) (SecID, error) {
111 var sectorSize int
112 var sat, freeList []SecID
113 if short {
114 sectorSize = int(r.ShortSectorSize)
115 needSectors := (len(contents) + sectorSize - 1) / sectorSize
116 freeList = r.makeFreeSectors(needSectors, true)
117 sat = r.SSAT
118 } else {
119 sectorSize = int(r.SectorSize)
120 needSectors := (len(contents) + sectorSize - 1) / sectorSize
121 freeList = r.makeFreeSectors(needSectors, false)
122 sat = r.SAT
123 }
124 first := SecIDEndOfChain
125 previous := first
126 for _, i := range freeList {
127 if previous == SecIDEndOfChain {
128 first = i
129 } else {
130 sat[previous] = i
131 }
132 previous = i
133
134 n := sectorSize
135 if n > len(contents) {
136 n = len(contents)
137 }
138 var err error
139 if short {
140 err = r.writeShortSector(i, contents[:n])
141 } else {
142 err = r.writeSector(i, contents[:n])
143 }
144 if err != nil {
145 return 0, err
146 }
147 contents = contents[n:]
148 }
149 sat[previous] = SecIDEndOfChain
150 if len(contents) > 0 {
151 panic("didn't allocate enough sectors")
152 }
153 return first, nil
154 }
155
View as plain text