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

📄 hio.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <httpd.h>static	char	hstates[] = "nrewE";static	char	hxfers[] = " x";inthinit(Hio *h, int fd, int mode){	if(fd == -1 || mode != Hread && mode != Hwrite)		return -1;	h->hh = nil;	h->fd = fd;	h->seek = 0;	h->state = mode;	h->start = h->buf + 16;		/* leave space for chunk length */	h->stop = h->pos = h->start;	if(mode == Hread){		h->bodylen = ~0UL;		*h->pos = '\0';	}else		h->stop = h->start + Hsize;	return 0;}inthiserror(Hio *h){	return h->state == Herr;}inthgetc(Hio *h){	uchar *p;	p = h->pos;	if(p < h->stop){		h->pos = p + 1;		return *p;	}	p -= UTFmax;	if(p < h->start)		p = h->start;	if(!hreadbuf(h, p) || h->pos == h->stop)		return -1;	return *h->pos++;}inthungetc(Hio *h){	if(h->state == Hend)		h->state = Hread;	else if(h->state == Hread)		h->pos--;	if(h->pos < h->start || h->state != Hread){		h->state = Herr;		h->pos = h->stop;		return -1;	}	return 0;}/* * fill the buffer, saving contents from vsave onwards. * nothing is saved if vsave is nil. * returns the beginning of the buffer. * * understands message body sizes and chunked transfer encoding */void *hreadbuf(Hio *h, void *vsave){	Hio *hh;	uchar *save;	int c, in, cpy, dpos;	save = vsave;	if(save && (save < h->start || save > h->stop)	|| h->state != Hread && h->state != Hend){		h->state = Herr;		h->pos = h->stop;		return nil;	}	dpos = 0;	if(save && h->pos > save)		dpos = h->pos - save;	cpy = 0;	if(save){		cpy = h->stop - save;		memmove(h->start, save, cpy);	}	h->seek += h->stop - h->start - cpy;	h->pos = h->start + dpos;	in = Hsize - cpy;	if(h->state == Hend)		in = 0;	else if(in > h->bodylen)		in = h->bodylen;	/*	 * for chunked encoding, fill buffer,	 * then read in new chunk length and wipe out that line	 */	hh = h->hh;	if(hh != nil){		if(!in && h->xferenc && h->state != Hend){			if(h->xferenc == 2){				c = hgetc(hh);				if(c == '\r')					c = hgetc(hh);				if(c != '\n'){					h->pos = h->stop;					h->state = Herr;					return nil;				}			}			h->xferenc = 2;			in = 0;			while((c = hgetc(hh)) != '\n'){				if(c >= '0' && c <= '9')					c -= '0';				else if(c >= 'a' && c <= 'f')					c -= 'a' - 10;				else if(c >= 'A' && c <= 'F')					c -= 'A' - 10;				else					break;				in = in * 16 + c;			}			while(c != '\n'){				if(c < 0){					h->pos = h->stop;					h->state = Herr;					return nil;				}				c = hgetc(hh);			}			h->bodylen = in;			in = Hsize - cpy;			if(in > h->bodylen)				in = h->bodylen;		}		if(in){			while(hh->pos + in > hh->stop){				if(hreadbuf(hh, hh->pos) == nil){					h->pos = h->stop;					h->state = Herr;					return nil;				}			}			memmove(h->start + cpy, hh->pos, in);			hh->pos += in;		}	}else if(in && (in = read(h->fd, h->start + cpy, in)) < 0){		h->state = Herr;		h->pos = h->stop;		return nil;	}	if(in == 0)		h->state = Hend;	h->bodylen -= in;	h->stop = h->start + cpy + in;	*h->stop = '\0';	if(h->pos == h->stop)		return nil;	return h->start;}inthbuflen(Hio *h, void *p){	return h->stop - (uchar*)p;}/* * prepare to receive a message body * len is the content length (~0 => unspecified) * te is the transfer encoding * returns < 0 if setup failed */Hio*hbodypush(Hio *hh, ulong len, HFields *te){	Hio *h;	int xe;	if(hh->state != Hread)		return nil;	xe = 0;	if(te != nil){		if(te->params != nil || te->next != nil)			return nil;		if(cistrcmp(te->s, "chunked") == 0){			xe = 1;			len = 0;		}else if(cistrcmp(te->s, "identity") == 0){			;		}else			return nil;	}	h = malloc(sizeof *h);	if(h == nil)		return nil;	h->hh = hh;	h->fd = -1;	h->seek = 0;	h->state = Hread;	h->xferenc = xe;	h->start = h->buf + 16;		/* leave space for chunk length */	h->stop = h->pos = h->start;	*h->pos = '\0';	h->bodylen = len;	return h;}/* * dump the state of the io buffer into a string */char *hunload(Hio *h){	uchar *p, *t, *stop, *buf;	int ne, n, c;	stop = h->stop;	ne = 0;	for(p = h->pos; p < stop; p++){		c = *p;		if(c == 0x80)			ne++;	}	p = h->pos;	n = (stop - p) + ne + 3;	buf = mallocz(n, 1);	if(buf == nil)		return nil;	buf[0] = hstates[h->state];	buf[1] = hxfers[h->xferenc];	t = &buf[2];	for(; p < stop; p++){		c = *p;		if(c == 0 || c == 0x80){			*t++ = 0x80;			if(c == 0x80)				*t++ = 0x80;		}else			*t++ = c;	}	*t++ = '\0';	if(t != buf + n)		return nil;	return (char*)buf;}/* * read the io buffer state from a string */inthload(Hio *h, char *buf){	uchar *p, *t, *stop;	char *s;	int c;	s = strchr(hstates, buf[0]);	if(s == nil)		return 0;	h->state = s - hstates;	s = strchr(hxfers, buf[1]);	if(s == nil)		return 0;	h->xferenc = s - hxfers;	t = h->start;	stop = t + Hsize;	for(p = (uchar*)&buf[2]; c = *p; p++){		if(c == 0x80){			if(p[1] != 0x80)				c = 0;			else				p++;		}		*t++ = c;		if(t >= stop)			return 0;	}	*t = '\0';	h->pos = h->start;	h->stop = t;	h->seek = 0;	return 1;}voidhclose(Hio *h){	if(h->fd >= 0){		if(h->state == Hwrite)			hxferenc(h, 0);		close(h->fd);	}	h->stop = h->pos = nil;	h->fd = -1;}/* * flush the buffer and possibly change encoding modes */inthxferenc(Hio *h, int on){	if(h->xferenc && !on && h->pos != h->start)		hflush(h);	if(hflush(h) < 0)		return -1;	h->xferenc = !!on;	return 0;}inthputc(Hio *h, int c){	uchar *p;	p = h->pos;	if(p < h->stop){		h->pos = p + 1;		return *p = c;	}	if(hflush(h) < 0)		return -1;	return *h->pos++ = c;}static intfmthflush(Fmt *f){	Hio *h;	h = f->farg;	h->pos = f->to;	if(hflush(h) < 0)		return 0;	f->stop = h->stop;	f->to = h->pos;	f->start = h->pos;	return 1;}inthvprint(Hio *h, char *fmt, va_list args){	int n;	Fmt f;	f.runes = 0;	f.stop = h->stop;	f.to = h->pos;	f.start = h->pos;	f.flush = fmthflush;	f.farg = h;	f.nfmt = 0;	f.args = args;	n = dofmt(&f, fmt);	h->pos = f.to;	return n;}inthprint(Hio *h, char *fmt, ...){	int n;	va_list arg;	va_start(arg, fmt);	n = hvprint(h, fmt, arg);	va_end(arg);	return n;}static int_hflush(Hio* h, int dolength){	uchar *s;	int w;	if(h->state != Hwrite){		h->state = Herr;		h->stop = h->pos;		return -1;	}	s = h->start;	w = h->pos - s;	if(h->xferenc){		*--s = '\n';		*--s = '\r';		do{			*--s = "0123456789abcdef"[w & 0xf];			w >>= 4;		}while(w);		h->pos[0] = '\r';		h->pos[1] = '\n';		w = &h->pos[2] - s;	}	if (dolength)		fprint(h->fd, "Content-Length: %d\r\n\r\n", w);	if(write(h->fd, s, w) != w){		h->state = Herr;		h->stop = h->pos;		return -1;	}	h->seek += w;	h->pos = h->start;	return 0;}inthflush(Hio *h){	return _hflush(h, 0);}inthlflush(Hio* h){	return _hflush(h, 1);}inthwrite(Hio *h, void *vbuf, int len){	uchar *pos, *buf;	int n, m;	buf = vbuf;	n = len;	if(n < 0 || h->state != Hwrite){		h->state = Herr;		h->stop = h->pos;		return -1;	}	pos = h->pos;	if(pos + n >= h->stop){		m = pos - h->start;		if(m){			m = Hsize - m;			if(m){				memmove(pos, buf, m);				buf += m;				n -= m;			}			if(write(h->fd, h->start, Hsize) != Hsize){				h->state = Herr;				h->stop = h->pos;				return -1;			}			h->seek += Hsize;		}		m = n % Hsize;		n -= m;		if(n != 0 && write(h->fd, buf, n) != n){			h->state = Herr;			h->stop = h->pos;			return -1;		}		h->seek += n;		buf += n;		pos = h->pos = h->start;		n = m;	}	memmove(pos, buf, n);	h->pos = pos + n;	return len;}

⌨️ 快捷键说明

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