summaryrefslogtreecommitdiff
path: root/appl/lib/csv.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/lib/csv.b')
-rw-r--r--appl/lib/csv.b86
1 files changed, 86 insertions, 0 deletions
diff --git a/appl/lib/csv.b b/appl/lib/csv.b
new file mode 100644
index 00000000..336e2cde
--- /dev/null
+++ b/appl/lib/csv.b
@@ -0,0 +1,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]+"\"";
+}