forsyth20121205-174063a80cc13 years agoHistory
249 lines · 4.9 KB · Brainfuck
RawDownload
implement Message; include "sys.m";	sys: Sys; include "string.m";	S : String; include "bufio.m";	B : Bufio;	Iobuf: import B; include "message.m";	msg: Message; msglog: ref Sys->FD; init(bufio: Bufio, smod: String){	sys = load Sys Sys->PATH;	S = smod;	B = bufio;} sptab : con " \t";crlf : con "\r\n"; Msg.newmsg() : ref Msg{	return ref Msg("", nil, nil, nil, 0);} # Read a message header from fd and return a Msg# the header fields.# If withprefix is true, read one line first and put it# in the prefixline field of the Msg (without terminating \r\n)# Return nil if there is a read error or eof before the# header is completely read.Msg.readhdr(io: ref Iobuf, withprefix: int) : (ref Msg, string){	m := Msg.newmsg();	l : list of Nameval = nil;	needprefix := withprefix;	for(;;) {		line := getline(io);		n := len line;		if(n == 0) {			if(withprefix && m.prefixline != "")				break;			return(nil, "msg read hdr error: no header");		}		if(line[n-1] != '\n')			return (m, "msg read hdr error: incomplete header");		if(n >= 2 && line[n-2] == '\r')			line = line[0:n-2];		else			line = line[0:n-1];		if(needprefix) {			m.prefixline = line;			needprefix = 0;		}		else {			if(line == "")				break;			if(S->in(line[0], sptab)) {				if(l == nil)					continue;				nv := hd l;				l = Nameval(nv.name, nv.value + " " + S->drop(line, sptab)) :: tl l;			}			else {				(nam, val) := S->splitl(line, ":");				if(val == nil)					continue;  # no colon				l = Nameval(S->tolower(nam), S->drop(val[1:], sptab)) :: l;			}		}	}	nh := len l;	if(nh > 0) {		m.fields = array[nh] of Nameval;		for(i := nh-1; i >= 0; i--) {			m.fields[i] = hd l;			l = tl l;		}	}	return (m, "");} glbuf := array[300] of byte; # Like io.gets('\n'), but assume Latin-1 instead of UTF encodinggetline(io: ref Iobuf): string{	imax := len glbuf - 1;	for(i := 0; i < imax; ) {		c := io.getb();		if(c < 0)			break;		if(c < 128)			glbuf[i++] = byte c;		else			i += sys->char2byte(c, glbuf, i);		if(c == '\n')			break;		if(i == imax) {			imax += 100;			if(imax > 1000)				break;	# Header lines aren't supposed to be > 1000			newglbuf := array[imax] of byte;			newglbuf[0:] = glbuf[0:i];			glbuf = newglbuf;		}	}	ans := string glbuf[0:i];	return ans;} Bbufsize: con 8000; # Read the body of the message, assuming the header has been processed.# If content-length has been specified, read exactly that many bytes# or until eof; else read until done.# Return "" if all is OK, else return an error string.Msg.readbody(m: self ref Msg, io: ref Iobuf) : string{	(clfnd, cl) := m.fieldval("content-length");	if(clfnd) {		clen := int cl;		if(clen > 0) {			m.body = array[clen] of byte;			n := B->io.read(m.body, clen);			m.bodylen = n;			if(n != clen)				return "short read";		}	}	else {		m.body = array[Bbufsize] of byte;		curlen := 0;		for(;;) {			avail := len m.body - curlen;			if(avail <= 0) {				newa := array[len m.body + Bbufsize] of byte;				if(curlen > 0)					newa[0:] = m.body[0:curlen];				m.body = newa;				avail = Bbufsize;			}			n := B->io.read(m.body[curlen:], avail);			if(n < 0)				return sys->sprint("readbody error %r");			if(n == 0)				break;			else				curlen += n;		}		m.bodylen = curlen;	}	return "";} # Look for name (lowercase) in the fields of m# and (1, field value) if found, or (0,"") if not.# If multiple fields with the same name exist,# the value is defined as the comma separated list# of all such values.Msg.fieldval(m: self ref Msg, name: string) : (int, string){	n := len m.fields;	ans := "";	found := 0;	for(i := 0; i < n; i++) {		if(m.fields[i].name == name) {			v := m.fields[i].value;			if(found)				ans = ans + ", " + v;			else				ans = v;			found = 1;		}	}	return (found, ans);} Msg.addhdrs(m: self ref Msg, hdrs: list of Nameval){	nh := len hdrs;	if(nh == 0)		return;	onh := len m.fields;	newa := array[nh + onh] of Nameval;	newa[0:] = m.fields;	i := onh;	while(hdrs != nil) {		newa[i++] = hd hdrs;		hdrs = tl hdrs;	}	m.fields = newa;} Msg.update(m: self ref Msg, name, value: string){	for(i := 0; i < len m.fields; i++)		if(m.fields[i].name == name) {			m.fields[i] = Nameval(name, value);			return;		}	m.addhdrs(Nameval(name, value) :: nil);} Msg.header(m: self ref Msg) : string{	s := "";	for(i := 0; i < len m.fields; i++) {		nv := m.fields[i];		s += nv.name + ": " + nv.value + "\n";	}	return s;} Msg.writemsg(m: self ref Msg, io: ref Iobuf) : string{	n := 0;	if(m.prefixline != nil) {		n = B->io.puts(m.prefixline);		if(n >= 0)			n = B->io.puts(crlf);	}	for(i := 0; i < len m.fields; i++) {		nv := m.fields[i];		if(n >= 0)			n = B->io.puts(nv.name);		if(n >= 0)			n = B->io.puts(": ");		if(n >= 0)			n = B->io.puts(nv.value);		if(n >= 0)			n = B->io.puts(crlf);	}	if(n >= 0)		n = B->io.puts(crlf);	if(n >= 0 && m.bodylen > 0)		n = B->io.write(m.body, m.bodylen);	if(n < 0)		return sys->sprint("msg write error: %r");	B->io.flush();	return "";}