summaryrefslogtreecommitdiff
path: root/appl/lib/csv.b
blob: 336e2cde2d9bd0ffdc4e1995ae2afce86089ab2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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]+"\"";
}