diff options
Diffstat (limited to 'appl/lib/csv.b')
-rw-r--r-- | appl/lib/csv.b | 86 |
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]+"\""; +} |