⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buff.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include <fcall.h>#include <plumb.h>#include "dat.h"#include "fns.h"enum{	Slop = 100,	/* room to grow with reallocation */};staticvoidsizecache(Buffer *b, uint n){	if(n <= b->cmax)		return;	b->cmax = n+Slop;	b->c = runerealloc(b->c, b->cmax);}staticvoidaddblock(Buffer *b, uint i, uint n){	if(i > b->nbl)		error("internal error: addblock");	b->bl = realloc(b->bl, (b->nbl+1)*sizeof b->bl[0]);	if(i < b->nbl)		memmove(b->bl+i+1, b->bl+i, (b->nbl-i)*sizeof(Block*));	b->bl[i] = disknewblock(disk, n);	b->nbl++;}staticvoiddelblock(Buffer *b, uint i){	if(i >= b->nbl)		error("internal error: delblock");	diskrelease(disk, b->bl[i]);	b->nbl--;	if(i < b->nbl)		memmove(b->bl+i, b->bl+i+1, (b->nbl-i)*sizeof(Block*));	b->bl = realloc(b->bl, b->nbl*sizeof b->bl[0]);}/* * Move cache so b->cq <= q0 < b->cq+b->cnc. * If at very end, q0 will fall on end of cache block. */staticvoidflush(Buffer *b){	if(b->cdirty || b->cnc==0){		if(b->cnc == 0)			delblock(b, b->cbi);		else			diskwrite(disk, &b->bl[b->cbi], b->c, b->cnc);		b->cdirty = FALSE;	}}staticvoidsetcache(Buffer *b, uint q0){	Block **blp, *bl;	uint i, q;	if(q0 > b->nc)		error("internal error: setcache");	/*	 * flush and reload if q0 is not in cache.	 */	if(b->nc == 0 || (b->cq<=q0 && q0<b->cq+b->cnc))		return;	/*	 * if q0 is at end of file and end of cache, continue to grow this block	 */	if(q0==b->nc && q0==b->cq+b->cnc && b->cnc<Maxblock)		return;	flush(b);	/* find block */	if(q0 < b->cq){		q = 0;		i = 0;	}else{		q = b->cq;		i = b->cbi;	}	blp = &b->bl[i];	while(q+(*blp)->n <= q0 && q+(*blp)->n < b->nc){		q += (*blp)->n;		i++;		blp++;		if(i >= b->nbl)			error("block not found");	}	bl = *blp;	/* remember position */	b->cbi = i;	b->cq = q;	sizecache(b, bl->n);	b->cnc = bl->n;	/*read block*/	diskread(disk, bl, b->c, b->cnc);}voidbufinsert(Buffer *b, uint q0, Rune *s, uint n){	uint i, m, t, off;	if(q0 > b->nc)		error("internal error: bufinsert");	while(n > 0){		setcache(b, q0);		off = q0-b->cq;		if(b->cnc+n <= Maxblock){			/* Everything fits in one block. */			t = b->cnc+n;			m = n;			if(b->bl == nil){	/* allocate */				if(b->cnc != 0)					error("internal error: bufinsert1 cnc!=0");				addblock(b, 0, t);				b->cbi = 0;			}			sizecache(b, t);			runemove(b->c+off+m, b->c+off, b->cnc-off);			runemove(b->c+off, s, m);			b->cnc = t;			goto Tail;		}		/*		 * We must make a new block.  If q0 is at		 * the very beginning or end of this block,		 * just make a new block and fill it.		 */		if(q0==b->cq || q0==b->cq+b->cnc){			if(b->cdirty)				flush(b);			m = min(n, Maxblock);			if(b->bl == nil){	/* allocate */				if(b->cnc != 0)					error("internal error: bufinsert2 cnc!=0");				i = 0;			}else{				i = b->cbi;				if(q0 > b->cq)					i++;			}			addblock(b, i, m);			sizecache(b, m);			runemove(b->c, s, m);			b->cq = q0;			b->cbi = i;			b->cnc = m;			goto Tail;		}		/*		 * Split the block; cut off the right side and		 * let go of it.		 */		m = b->cnc-off;		if(m > 0){			i = b->cbi+1;			addblock(b, i, m);			diskwrite(disk, &b->bl[i], b->c+off, m);			b->cnc -= m;		}		/*		 * Now at end of block.  Take as much input		 * as possible and tack it on end of block.		 */		m = min(n, Maxblock-b->cnc);		sizecache(b, b->cnc+m);		runemove(b->c+b->cnc, s, m);		b->cnc += m;  Tail:		b->nc += m;		q0 += m;		s += m;		n -= m;		b->cdirty = TRUE;	}}voidbufdelete(Buffer *b, uint q0, uint q1){	uint m, n, off;	if(!(q0<=q1 && q0<=b->nc && q1<=b->nc))		error("internal error: bufdelete");	while(q1 > q0){		setcache(b, q0);		off = q0-b->cq;		if(q1 > b->cq+b->cnc)			n = b->cnc - off;		else			n = q1-q0;		m = b->cnc - (off+n);		if(m > 0)			runemove(b->c+off, b->c+off+n, m);		b->cnc -= n;		b->cdirty = TRUE;		q1 -= n;		b->nc -= n;	}}static intbufloader(void *v, uint q0, Rune *r, int nr){	bufinsert(v, q0, r, nr);	return nr;}uintloadfile(int fd, uint q0, int *nulls, int(*f)(void*, uint, Rune*, int), void *arg){	char *p;	Rune *r;	int l, m, n, nb, nr;	uint q1;	p = emalloc((Maxblock+UTFmax+1)*sizeof p[0]);	r = runemalloc(Maxblock);	m = 0;	n = 1;	q1 = q0;	/*	 * At top of loop, may have m bytes left over from	 * last pass, possibly representing a partial rune.	 */	while(n > 0){		n = read(fd, p+m, Maxblock);		if(n < 0){			warning(nil, "read error in Buffer.load");			break;		}		m += n;		p[m] = 0;		l = m;		if(n > 0)			l -= UTFmax;		cvttorunes(p, l, r, &nb, &nr, nulls);		memmove(p, p+nb, m-nb);		m -= nb;		q1 += (*f)(arg, q1, r, nr);	}	free(p);	free(r);	return q1-q0;}uintbufload(Buffer *b, uint q0, int fd, int *nulls){	if(q0 > b->nc)		error("internal error: bufload");	return loadfile(fd, q0, nulls, bufloader, b);}voidbufread(Buffer *b, uint q0, Rune *s, uint n){	uint m;	if(!(q0<=b->nc && q0+n<=b->nc))		error("bufread: internal error");	while(n > 0){		setcache(b, q0);		m = min(n, b->cnc-(q0-b->cq));		runemove(s, b->c+(q0-b->cq), m);		q0 += m;		s += m;		n -= m;	}}voidbufreset(Buffer *b){	int i;	b->nc = 0;	b->cnc = 0;	b->cq = 0;	b->cdirty = 0;	b->cbi = 0;	/* delete backwards to avoid n² behavior */	for(i=b->nbl-1; --i>=0; )		delblock(b, i);}voidbufclose(Buffer *b){	bufreset(b);	free(b->c);	b->c = nil;	b->cnc = 0;	free(b->bl);	b->bl = nil;	b->nbl = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -