xref: /inferno-os/appl/lib/csv.b (revision 0e96539ff7cff23233d3f0a64bb285b385a3a1f4)
1implement CSV;
2
3include "sys.m";
4
5include "bufio.m";
6	bufio: Bufio;
7	Iobuf: import bufio;
8
9include "csv.m";
10
11init(b: Bufio)
12{
13	bufio = b;
14}
15
16getline(fd: ref Iobuf): list of string
17{
18	rl: list of string;
19	for(;;){
20		(w, end) := getfield(fd);
21		if(rl == nil && w == nil && end < 0)
22			return nil;
23		rl = w :: rl;
24		if(end != ',')
25			break;
26	}
27	l: list of string;
28	for(; rl != nil; rl = tl rl)
29		l = hd rl :: l;
30	return l;
31}
32
33getfield(fd: ref Iobuf): (string, int)
34{
35	w := "";
36	if((c := getcr(fd)) == '"'){	# quoted field
37		while((c = getcr(fd)) >= 0){
38			if(c == '"'){
39				c = getcr(fd);
40				if(c != '"')
41					break;
42			}
43			w[len w] = c;
44		}
45	}
46	# unquoted text, possibly following quoted text above
47	for(; c >= 0 && c != ',' && c != '\n'; c = getcr(fd))
48		w[len w] = c;
49	return (w, c);
50}
51
52getcr(fd: ref Iobuf): int
53{
54	c := fd.getc();
55	if(c == '\r'){
56		nc := fd.getc();
57		if(nc >= 0 && nc != '\n')
58			fd.ungetc();
59		c = '\n';
60	}
61	return c;
62}
63
64quote(s: string): string
65{
66	sep := 0;
67	for(i := 0; i < len s; i++)
68		if((c := s[i]) == '"')
69			return innerquote(s);
70		else if(c == ',' || c == '\n')
71			sep = 1;
72	if(sep)
73		return "\""+s+"\"";
74	return s;
75}
76
77innerquote(s: string): string
78{
79	w := "\"";
80	for(i := j := 0; i < len s; i++)
81		if(s[i] == '"'){
82			w += s[j: i+1];	# including "
83			j = i;		# including " again
84		}
85	return w+s[j:i]+"\"";
86}
87