#line 154 "/home/travis/build/felix-lang/felix/src/packages/codecs.fdoc"
  
  Comma Separated Values (CSV) reader
  Splits a string like 1,2,"hell" up into three strings.
  class Csv {
    open List;
  
    Fetch a value string res from position i of string s.
    Update i past the comma ready to fetch another value.
    proc get_csv_value(s:string, i:&int,res:&string) {
      var r = "";
      proc add(j:int) { r += s.[j]; }
      n := s.len.int;
      enum state_t = skip,collect,quote;
      fun eq(a:state_t, b:state_t)=> caseno a == caseno b;
  
      var state = skip;
      ech:for var j in *i upto n - 1 do
        ch := s.[j];
        if ch == char "," do
          match state with
          | #quote => add j;
          | _ => break ech;
          endmatch;
        elif ch == char " " do
          match state with
          | #skip => continue ech;
          | #quote => add j;
          | #collect => state = skip;
          endmatch;
        elif ch == char '"' do
          match state with
          | #quote => state = skip;
          | _ => state = quote;
          endmatch;
        else
          add j;
        done;
      done;
      i <- j+1;
      res <- r;
    }
  
    Fetch all the values in a CSV string
    and return them as list.
    fun get_csv_values(s:string): list[string] = {
      var v: list[string] = Empty[string];
      var res = "";
      var pos = 0;
      n := s.len.int;
      while pos < n do
        get_csv_value (s, &pos, &res);
        if res.len.int >0 do v += res; done;
      done;
      return v;
    }
  }