1 76193d7c 2003-09-30 devnull #include "sam.h"
5 76193d7c 2003-09-30 devnull Slop = 100, /* room to grow with reallocation */
10 76193d7c 2003-09-30 devnull sizecache(Buffer *b, uint n)
12 76193d7c 2003-09-30 devnull if(n <= b->cmax)
14 76193d7c 2003-09-30 devnull b->cmax = n+Slop;
15 76193d7c 2003-09-30 devnull b->c = runerealloc(b->c, b->cmax);
20 76193d7c 2003-09-30 devnull addblock(Buffer *b, uint i, uint n)
22 76193d7c 2003-09-30 devnull if(i > b->nbl)
23 76193d7c 2003-09-30 devnull panic("internal error: addblock");
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++;
35 76193d7c 2003-09-30 devnull delblock(Buffer *b, uint i)
37 76193d7c 2003-09-30 devnull if(i >= b->nbl)
38 76193d7c 2003-09-30 devnull panic("internal error: delblock");
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]);
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.
54 76193d7c 2003-09-30 devnull flush(Buffer *b)
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);
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;
67 76193d7c 2003-09-30 devnull setcache(Buffer *b, uint q0)
69 76193d7c 2003-09-30 devnull Block **blp, *bl;
70 76193d7c 2003-09-30 devnull uint i, q;
72 76193d7c 2003-09-30 devnull if(q0 > b->nc)
73 76193d7c 2003-09-30 devnull panic("internal error: setcache");
75 76193d7c 2003-09-30 devnull * flush and reload if q0 is not in cache.
77 76193d7c 2003-09-30 devnull if(b->nc == 0 || (b->cq<=q0 && q0<b->cq+b->cnc))
80 76193d7c 2003-09-30 devnull * if q0 is at end of file and end of cache, continue to grow this block
82 76193d7c 2003-09-30 devnull if(q0==b->nc && q0==b->cq+b->cnc && b->cnc<=Maxblock)
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){
90 76193d7c 2003-09-30 devnull q = b->cq;
91 76193d7c 2003-09-30 devnull i = b->cbi;
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;
98 76193d7c 2003-09-30 devnull if(i >= b->nbl)
99 76193d7c 2003-09-30 devnull panic("block not found");
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);
112 76193d7c 2003-09-30 devnull bufinsert(Buffer *b, uint q0, Rune *s, uint n)
114 76193d7c 2003-09-30 devnull uint i, m, t, off;
116 76193d7c 2003-09-30 devnull if(q0 > b->nc)
117 76193d7c 2003-09-30 devnull panic("internal error: bufinsert");
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;
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;
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;
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.
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");
152 76193d7c 2003-09-30 devnull i = b->cbi;
153 76193d7c 2003-09-30 devnull if(q0 > b->cq)
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;
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.
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;
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.
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;
184 76193d7c 2003-09-30 devnull b->nc += m;
185 76193d7c 2003-09-30 devnull q0 += m;
188 76193d7c 2003-09-30 devnull b->cdirty = TRUE;
193 76193d7c 2003-09-30 devnull bufdelete(Buffer *b, uint q0, uint q1)
195 76193d7c 2003-09-30 devnull uint m, n, off;
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;
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;
217 76193d7c 2003-09-30 devnull bufload(Buffer *b, uint q0, int fd, int *nulls)
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;
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);
232 76193d7c 2003-09-30 devnull q1 = q0;
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.
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);
244 76193d7c 2003-09-30 devnull p[m] = 0;
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;
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;
260 76193d7c 2003-09-30 devnull bufread(Buffer *b, uint q0, Rune *s, uint n)
264 76193d7c 2003-09-30 devnull if(!(q0<=b->nc && q0+n<=b->nc))
265 76193d7c 2003-09-30 devnull panic("bufread: internal error");
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;
278 76193d7c 2003-09-30 devnull bufreset(Buffer *b)
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);
293 76193d7c 2003-09-30 devnull bufclose(Buffer *b)
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;