Blame


1 76193d7c 2003-09-30 devnull #include "sam.h"
2 76193d7c 2003-09-30 devnull
3 76193d7c 2003-09-30 devnull enum
4 76193d7c 2003-09-30 devnull {
5 cbeb0b26 2006-04-01 devnull Slop = 100 /* room to grow with reallocation */
6 76193d7c 2003-09-30 devnull };
7 76193d7c 2003-09-30 devnull
8 76193d7c 2003-09-30 devnull static
9 76193d7c 2003-09-30 devnull void
10 76193d7c 2003-09-30 devnull sizecache(Buffer *b, uint n)
11 76193d7c 2003-09-30 devnull {
12 76193d7c 2003-09-30 devnull if(n <= b->cmax)
13 76193d7c 2003-09-30 devnull return;
14 76193d7c 2003-09-30 devnull b->cmax = n+Slop;
15 76193d7c 2003-09-30 devnull b->c = runerealloc(b->c, b->cmax);
16 76193d7c 2003-09-30 devnull }
17 76193d7c 2003-09-30 devnull
18 76193d7c 2003-09-30 devnull static
19 76193d7c 2003-09-30 devnull void
20 76193d7c 2003-09-30 devnull addblock(Buffer *b, uint i, uint n)
21 76193d7c 2003-09-30 devnull {
22 76193d7c 2003-09-30 devnull if(i > b->nbl)
23 76193d7c 2003-09-30 devnull panic("internal error: addblock");
24 76193d7c 2003-09-30 devnull
25 76193d7c 2003-09-30 devnull b->bl = realloc(b->bl, (b->nbl+1)*sizeof b->bl[0]);
26 76193d7c 2003-09-30 devnull if(i < b->nbl)
27 76193d7c 2003-09-30 devnull memmove(b->bl+i+1, b->bl+i, (b->nbl-i)*sizeof(Block*));
28 76193d7c 2003-09-30 devnull b->bl[i] = disknewblock(disk, n);
29 76193d7c 2003-09-30 devnull b->nbl++;
30 76193d7c 2003-09-30 devnull }
31 76193d7c 2003-09-30 devnull
32 76193d7c 2003-09-30 devnull
33 76193d7c 2003-09-30 devnull static
34 76193d7c 2003-09-30 devnull void
35 76193d7c 2003-09-30 devnull delblock(Buffer *b, uint i)
36 76193d7c 2003-09-30 devnull {
37 76193d7c 2003-09-30 devnull if(i >= b->nbl)
38 76193d7c 2003-09-30 devnull panic("internal error: delblock");
39 76193d7c 2003-09-30 devnull
40 76193d7c 2003-09-30 devnull diskrelease(disk, b->bl[i]);
41 76193d7c 2003-09-30 devnull b->nbl--;
42 76193d7c 2003-09-30 devnull if(i < b->nbl)
43 76193d7c 2003-09-30 devnull memmove(b->bl+i, b->bl+i+1, (b->nbl-i)*sizeof(Block*));
44 76193d7c 2003-09-30 devnull b->bl = realloc(b->bl, b->nbl*sizeof b->bl[0]);
45 76193d7c 2003-09-30 devnull }
46 76193d7c 2003-09-30 devnull
47 76193d7c 2003-09-30 devnull /*
48 76193d7c 2003-09-30 devnull * Move cache so b->cq <= q0 < b->cq+b->cnc.
49 76193d7c 2003-09-30 devnull * If at very end, q0 will fall on end of cache block.
50 76193d7c 2003-09-30 devnull */
51 76193d7c 2003-09-30 devnull
52 76193d7c 2003-09-30 devnull static
53 76193d7c 2003-09-30 devnull void
54 76193d7c 2003-09-30 devnull flush(Buffer *b)
55 76193d7c 2003-09-30 devnull {
56 76193d7c 2003-09-30 devnull if(b->cdirty || b->cnc==0){
57 76193d7c 2003-09-30 devnull if(b->cnc == 0)
58 76193d7c 2003-09-30 devnull delblock(b, b->cbi);
59 76193d7c 2003-09-30 devnull else
60 76193d7c 2003-09-30 devnull diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc);
61 76193d7c 2003-09-30 devnull b->cdirty = FALSE;
62 76193d7c 2003-09-30 devnull }
63 76193d7c 2003-09-30 devnull }
64 76193d7c 2003-09-30 devnull
65 76193d7c 2003-09-30 devnull static
66 76193d7c 2003-09-30 devnull void
67 76193d7c 2003-09-30 devnull setcache(Buffer *b, uint q0)
68 76193d7c 2003-09-30 devnull {
69 76193d7c 2003-09-30 devnull Block **blp, *bl;
70 76193d7c 2003-09-30 devnull uint i, q;
71 76193d7c 2003-09-30 devnull
72 76193d7c 2003-09-30 devnull if(q0 > b->nc)
73 76193d7c 2003-09-30 devnull panic("internal error: setcache");
74 76193d7c 2003-09-30 devnull /*
75 76193d7c 2003-09-30 devnull * flush and reload if q0 is not in cache.
76 76193d7c 2003-09-30 devnull */
77 76193d7c 2003-09-30 devnull if(b->nc == 0 || (b->cq<=q0 && q0<b->cq+b->cnc))
78 76193d7c 2003-09-30 devnull return;
79 76193d7c 2003-09-30 devnull /*
80 76193d7c 2003-09-30 devnull * if q0 is at end of file and end of cache, continue to grow this block
81 76193d7c 2003-09-30 devnull */
82 76193d7c 2003-09-30 devnull if(q0==b->nc && q0==b->cq+b->cnc && b->cnc<=Maxblock)
83 76193d7c 2003-09-30 devnull return;
84 76193d7c 2003-09-30 devnull flush(b);
85 76193d7c 2003-09-30 devnull /* find block */
86 76193d7c 2003-09-30 devnull if(q0 < b->cq){
87 76193d7c 2003-09-30 devnull q = 0;
88 76193d7c 2003-09-30 devnull i = 0;
89 76193d7c 2003-09-30 devnull }else{
90 76193d7c 2003-09-30 devnull q = b->cq;
91 76193d7c 2003-09-30 devnull i = b->cbi;
92 76193d7c 2003-09-30 devnull }
93 76193d7c 2003-09-30 devnull blp = &b->bl[i];
94 522b0689 2003-09-30 devnull while(q+(*blp)->u.n <= q0 && q+(*blp)->u.n < b->nc){
95 522b0689 2003-09-30 devnull q += (*blp)->u.n;
96 76193d7c 2003-09-30 devnull i++;
97 76193d7c 2003-09-30 devnull blp++;
98 76193d7c 2003-09-30 devnull if(i >= b->nbl)
99 76193d7c 2003-09-30 devnull panic("block not found");
100 76193d7c 2003-09-30 devnull }
101 76193d7c 2003-09-30 devnull bl = *blp;
102 76193d7c 2003-09-30 devnull /* remember position */
103 76193d7c 2003-09-30 devnull b->cbi = i;
104 76193d7c 2003-09-30 devnull b->cq = q;
105 522b0689 2003-09-30 devnull sizecache(b, bl->u.n);
106 522b0689 2003-09-30 devnull b->cnc = bl->u.n;
107 76193d7c 2003-09-30 devnull /*read block*/
108 76193d7c 2003-09-30 devnull diskread(disk, bl, b->c, b->cnc);
109 76193d7c 2003-09-30 devnull }
110 76193d7c 2003-09-30 devnull
111 76193d7c 2003-09-30 devnull void
112 76193d7c 2003-09-30 devnull bufinsert(Buffer *b, uint q0, Rune *s, uint n)
113 76193d7c 2003-09-30 devnull {
114 76193d7c 2003-09-30 devnull uint i, m, t, off;
115 76193d7c 2003-09-30 devnull
116 76193d7c 2003-09-30 devnull if(q0 > b->nc)
117 76193d7c 2003-09-30 devnull panic("internal error: bufinsert");
118 76193d7c 2003-09-30 devnull
119 76193d7c 2003-09-30 devnull while(n > 0){
120 76193d7c 2003-09-30 devnull setcache(b, q0);
121 76193d7c 2003-09-30 devnull off = q0-b->cq;
122 76193d7c 2003-09-30 devnull if(b->cnc+n <= Maxblock){
123 76193d7c 2003-09-30 devnull /* Everything fits in one block. */
124 76193d7c 2003-09-30 devnull t = b->cnc+n;
125 76193d7c 2003-09-30 devnull m = n;
126 76193d7c 2003-09-30 devnull if(b->bl == nil){ /* allocate */
127 76193d7c 2003-09-30 devnull if(b->cnc != 0)
128 76193d7c 2003-09-30 devnull panic("internal error: bufinsert1 cnc!=0");
129 76193d7c 2003-09-30 devnull addblock(b, 0, t);
130 76193d7c 2003-09-30 devnull b->cbi = 0;
131 76193d7c 2003-09-30 devnull }
132 76193d7c 2003-09-30 devnull sizecache(b, t);
133 76193d7c 2003-09-30 devnull runemove(b->c+off+m, b->c+off, b->cnc-off);
134 76193d7c 2003-09-30 devnull runemove(b->c+off, s, m);
135 76193d7c 2003-09-30 devnull b->cnc = t;
136 76193d7c 2003-09-30 devnull goto Tail;
137 76193d7c 2003-09-30 devnull }
138 76193d7c 2003-09-30 devnull /*
139 76193d7c 2003-09-30 devnull * We must make a new block. If q0 is at
140 76193d7c 2003-09-30 devnull * the very beginning or end of this block,
141 76193d7c 2003-09-30 devnull * just make a new block and fill it.
142 76193d7c 2003-09-30 devnull */
143 76193d7c 2003-09-30 devnull if(q0==b->cq || q0==b->cq+b->cnc){
144 76193d7c 2003-09-30 devnull if(b->cdirty)
145 76193d7c 2003-09-30 devnull flush(b);
146 76193d7c 2003-09-30 devnull m = min(n, Maxblock);
147 76193d7c 2003-09-30 devnull if(b->bl == nil){ /* allocate */
148 76193d7c 2003-09-30 devnull if(b->cnc != 0)
149 76193d7c 2003-09-30 devnull panic("internal error: bufinsert2 cnc!=0");
150 76193d7c 2003-09-30 devnull i = 0;
151 76193d7c 2003-09-30 devnull }else{
152 76193d7c 2003-09-30 devnull i = b->cbi;
153 76193d7c 2003-09-30 devnull if(q0 > b->cq)
154 76193d7c 2003-09-30 devnull i++;
155 76193d7c 2003-09-30 devnull }
156 76193d7c 2003-09-30 devnull addblock(b, i, m);
157 76193d7c 2003-09-30 devnull sizecache(b, m);
158 76193d7c 2003-09-30 devnull runemove(b->c, s, m);
159 76193d7c 2003-09-30 devnull b->cq = q0;
160 76193d7c 2003-09-30 devnull b->cbi = i;
161 76193d7c 2003-09-30 devnull b->cnc = m;
162 76193d7c 2003-09-30 devnull goto Tail;
163 76193d7c 2003-09-30 devnull }
164 76193d7c 2003-09-30 devnull /*
165 76193d7c 2003-09-30 devnull * Split the block; cut off the right side and
166 76193d7c 2003-09-30 devnull * let go of it.
167 76193d7c 2003-09-30 devnull */
168 76193d7c 2003-09-30 devnull m = b->cnc-off;
169 76193d7c 2003-09-30 devnull if(m > 0){
170 76193d7c 2003-09-30 devnull i = b->cbi+1;
171 76193d7c 2003-09-30 devnull addblock(b, i, m);
172 76193d7c 2003-09-30 devnull diskwrite(disk, &b->bl[i], b->c+off, m);
173 76193d7c 2003-09-30 devnull b->cnc -= m;
174 76193d7c 2003-09-30 devnull }
175 76193d7c 2003-09-30 devnull /*
176 76193d7c 2003-09-30 devnull * Now at end of block. Take as much input
177 76193d7c 2003-09-30 devnull * as possible and tack it on end of block.
178 76193d7c 2003-09-30 devnull */
179 76193d7c 2003-09-30 devnull m = min(n, Maxblock-b->cnc);
180 76193d7c 2003-09-30 devnull sizecache(b, b->cnc+m);
181 76193d7c 2003-09-30 devnull runemove(b->c+b->cnc, s, m);
182 76193d7c 2003-09-30 devnull b->cnc += m;
183 76193d7c 2003-09-30 devnull Tail:
184 76193d7c 2003-09-30 devnull b->nc += m;
185 76193d7c 2003-09-30 devnull q0 += m;
186 76193d7c 2003-09-30 devnull s += m;
187 76193d7c 2003-09-30 devnull n -= m;
188 76193d7c 2003-09-30 devnull b->cdirty = TRUE;
189 76193d7c 2003-09-30 devnull }
190 76193d7c 2003-09-30 devnull }
191 76193d7c 2003-09-30 devnull
192 76193d7c 2003-09-30 devnull void
193 76193d7c 2003-09-30 devnull bufdelete(Buffer *b, uint q0, uint q1)
194 76193d7c 2003-09-30 devnull {
195 76193d7c 2003-09-30 devnull uint m, n, off;
196 76193d7c 2003-09-30 devnull
197 76193d7c 2003-09-30 devnull if(!(q0<=q1 && q0<=b->nc && q1<=b->nc))
198 76193d7c 2003-09-30 devnull panic("internal error: bufdelete");
199 76193d7c 2003-09-30 devnull while(q1 > q0){
200 76193d7c 2003-09-30 devnull setcache(b, q0);
201 76193d7c 2003-09-30 devnull off = q0-b->cq;
202 76193d7c 2003-09-30 devnull if(q1 > b->cq+b->cnc)
203 76193d7c 2003-09-30 devnull n = b->cnc - off;
204 76193d7c 2003-09-30 devnull else
205 76193d7c 2003-09-30 devnull n = q1-q0;
206 76193d7c 2003-09-30 devnull m = b->cnc - (off+n);
207 76193d7c 2003-09-30 devnull if(m > 0)
208 76193d7c 2003-09-30 devnull runemove(b->c+off, b->c+off+n, m);
209 76193d7c 2003-09-30 devnull b->cnc -= n;
210 76193d7c 2003-09-30 devnull b->cdirty = TRUE;
211 76193d7c 2003-09-30 devnull q1 -= n;
212 76193d7c 2003-09-30 devnull b->nc -= n;
213 76193d7c 2003-09-30 devnull }
214 76193d7c 2003-09-30 devnull }
215 76193d7c 2003-09-30 devnull
216 76193d7c 2003-09-30 devnull uint
217 76193d7c 2003-09-30 devnull bufload(Buffer *b, uint q0, int fd, int *nulls)
218 76193d7c 2003-09-30 devnull {
219 76193d7c 2003-09-30 devnull char *p;
220 76193d7c 2003-09-30 devnull Rune *r;
221 76193d7c 2003-09-30 devnull int l, m, n, nb, nr;
222 76193d7c 2003-09-30 devnull uint q1;
223 76193d7c 2003-09-30 devnull
224 76193d7c 2003-09-30 devnull if(q0 > b->nc)
225 76193d7c 2003-09-30 devnull panic("internal error: bufload");
226 76193d7c 2003-09-30 devnull p = malloc((Maxblock+UTFmax+1)*sizeof p[0]);
227 76193d7c 2003-09-30 devnull if(p == nil)
228 76193d7c 2003-09-30 devnull panic("bufload: malloc failed");
229 76193d7c 2003-09-30 devnull r = runemalloc(Maxblock);
230 76193d7c 2003-09-30 devnull m = 0;
231 76193d7c 2003-09-30 devnull n = 1;
232 76193d7c 2003-09-30 devnull q1 = q0;
233 76193d7c 2003-09-30 devnull /*
234 76193d7c 2003-09-30 devnull * At top of loop, may have m bytes left over from
235 76193d7c 2003-09-30 devnull * last pass, possibly representing a partial rune.
236 76193d7c 2003-09-30 devnull */
237 76193d7c 2003-09-30 devnull while(n > 0){
238 76193d7c 2003-09-30 devnull n = read(fd, p+m, Maxblock);
239 76193d7c 2003-09-30 devnull if(n < 0){
240 76193d7c 2003-09-30 devnull error(Ebufload);
241 76193d7c 2003-09-30 devnull break;
242 76193d7c 2003-09-30 devnull }
243 76193d7c 2003-09-30 devnull m += n;
244 76193d7c 2003-09-30 devnull p[m] = 0;
245 76193d7c 2003-09-30 devnull l = m;
246 76193d7c 2003-09-30 devnull if(n > 0)
247 76193d7c 2003-09-30 devnull l -= UTFmax;
248 76193d7c 2003-09-30 devnull cvttorunes(p, l, r, &nb, &nr, nulls);
249 76193d7c 2003-09-30 devnull memmove(p, p+nb, m-nb);
250 76193d7c 2003-09-30 devnull m -= nb;
251 76193d7c 2003-09-30 devnull bufinsert(b, q1, r, nr);
252 76193d7c 2003-09-30 devnull q1 += nr;
253 76193d7c 2003-09-30 devnull }
254 76193d7c 2003-09-30 devnull free(p);
255 76193d7c 2003-09-30 devnull free(r);
256 76193d7c 2003-09-30 devnull return q1-q0;
257 76193d7c 2003-09-30 devnull }
258 76193d7c 2003-09-30 devnull
259 76193d7c 2003-09-30 devnull void
260 76193d7c 2003-09-30 devnull bufread(Buffer *b, uint q0, Rune *s, uint n)
261 76193d7c 2003-09-30 devnull {
262 76193d7c 2003-09-30 devnull uint m;
263 76193d7c 2003-09-30 devnull
264 76193d7c 2003-09-30 devnull if(!(q0<=b->nc && q0+n<=b->nc))
265 76193d7c 2003-09-30 devnull panic("bufread: internal error");
266 76193d7c 2003-09-30 devnull
267 76193d7c 2003-09-30 devnull while(n > 0){
268 76193d7c 2003-09-30 devnull setcache(b, q0);
269 76193d7c 2003-09-30 devnull m = min(n, b->cnc-(q0-b->cq));
270 76193d7c 2003-09-30 devnull runemove(s, b->c+(q0-b->cq), m);
271 76193d7c 2003-09-30 devnull q0 += m;
272 76193d7c 2003-09-30 devnull s += m;
273 76193d7c 2003-09-30 devnull n -= m;
274 76193d7c 2003-09-30 devnull }
275 76193d7c 2003-09-30 devnull }
276 76193d7c 2003-09-30 devnull
277 76193d7c 2003-09-30 devnull void
278 76193d7c 2003-09-30 devnull bufreset(Buffer *b)
279 76193d7c 2003-09-30 devnull {
280 76193d7c 2003-09-30 devnull int i;
281 76193d7c 2003-09-30 devnull
282 76193d7c 2003-09-30 devnull b->nc = 0;
283 76193d7c 2003-09-30 devnull b->cnc = 0;
284 76193d7c 2003-09-30 devnull b->cq = 0;
285 76193d7c 2003-09-30 devnull b->cdirty = 0;
286 76193d7c 2003-09-30 devnull b->cbi = 0;
287 76193d7c 2003-09-30 devnull /* delete backwards to avoid n² behavior */
288 76193d7c 2003-09-30 devnull for(i=b->nbl-1; --i>=0; )
289 76193d7c 2003-09-30 devnull delblock(b, i);
290 76193d7c 2003-09-30 devnull }
291 76193d7c 2003-09-30 devnull
292 76193d7c 2003-09-30 devnull void
293 76193d7c 2003-09-30 devnull bufclose(Buffer *b)
294 76193d7c 2003-09-30 devnull {
295 76193d7c 2003-09-30 devnull bufreset(b);
296 76193d7c 2003-09-30 devnull free(b->c);
297 76193d7c 2003-09-30 devnull b->c = nil;
298 76193d7c 2003-09-30 devnull b->cnc = 0;
299 76193d7c 2003-09-30 devnull free(b->bl);
300 76193d7c 2003-09-30 devnull b->bl = nil;
301 76193d7c 2003-09-30 devnull b->nbl = 0;
302 76193d7c 2003-09-30 devnull }