Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/sam/buff.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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