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