shithub: purgatorio

ref: c116550e6a41572796e4db65e4f6acbcb3d9d6f8
dir: /appl/lib/csv.b/

View raw version
implement CSV;

include "sys.m";

include "bufio.m";
	bufio: Bufio;
	Iobuf: import bufio;

include "csv.m";

init(b: Bufio)
{
	bufio = b;
}

getline(fd: ref Iobuf): list of string
{
	rl: list of string;
	for(;;){
		(w, end) := getfield(fd);
		if(rl == nil && w == nil && end < 0)
			return nil;
		rl = w :: rl;
		if(end != ',')
			break;
	}
	l: list of string;
	for(; rl != nil; rl = tl rl)
		l = hd rl :: l;
	return l;
}

getfield(fd: ref Iobuf): (string, int)
{
	w := "";
	if((c := getcr(fd)) == '"'){	# quoted field
		while((c = getcr(fd)) >= 0){
			if(c == '"'){
				c = getcr(fd);
				if(c != '"')
					break;
			}
			w[len w] = c;
		}
	}
	# unquoted text, possibly following quoted text above
	for(; c >= 0 && c != ',' && c != '\n'; c = getcr(fd))
		w[len w] = c;
	return (w, c);
}

getcr(fd: ref Iobuf): int
{
	c := fd.getc();
	if(c == '\r'){
		nc := fd.getc();
		if(nc >= 0 && nc != '\n')
			fd.ungetc();
		c = '\n';
	}
	return c;
}

quote(s: string): string
{
	sep := 0;
	for(i := 0; i < len s; i++)
		if((c := s[i]) == '"')
			return innerquote(s);
		else if(c == ',' || c == '\n')
			sep = 1;
	if(sep)
		return "\""+s+"\"";
	return s;
}

innerquote(s: string): string
{
	w := "\"";
	for(i := j := 0; i < len s; i++)
		if(s[i] == '"'){
			w += s[j: i+1];	# including "
			j = i;		# including " again
		}
	return w+s[j:i]+"\"";
}