using System.IO using System.Text using Nemerle.Utility using Nemerle.Imperative set namespace Fx7 public module CSV public WriteFile (filename : string, data : list [list [string]], append = false) : void def sb = StringBuilder () def quote (x) if (x.IndexOf (",") != -1) _ = sb.Append ('"').Append (x).Append ('"') else _ = sb.Append (x) foreach (line in data) NString.SeparatedCalls (",", line, quote, sb) _ = sb.Append ('\n') if (append) File.AppendAllText (filename, sb.ToString ()) else File.WriteAllText (filename, sb.ToString ()) public ReadFile (filename : string) : list [list [string]] def s = File.OpenText (filename) def buf = s.ReadToEnd () mutable ptr = 0 mutable eol = false def read_word () while (ptr < buf.Length && (buf [ptr] == ' ' || buf [ptr] == '\t')) ptr++ def beg = ptr if (ptr < buf.Length) match (buf [ptr]) | '"' => ptr++ while (ptr < buf.Length) if (buf [ptr] == '"') if (ptr + 1 >= buf.Length || buf [ptr + 1] != '"') break else ptr += 2 else ptr++ def res = buf.Substring (beg + 1, ptr - beg - 1).Replace ("\"\"", "\"") ptr++ while (ptr < buf.Length) match (buf [ptr]) | ' ' | '\t' | '\r' => ptr++ | '\n' => eol = true break | ',' => break | _ => ptr++ ptr++ res | _ => while (ptr < buf.Length) match (buf [ptr]) | ',' => break | '\n' => eol = true break | _ => ptr++ ptr++ buf.Substring (beg, ptr - beg - 1).Trim () else null def read_line () eol = false def w = read_word () if (w == null) null else if (eol) [w] else mutable line = [w] while (true) eol = false def w = read_word () when (w != null) line ::= w when (eol) break line.Rev () mutable lines = [] while (true) def line = read_line () if (line == null) break else lines ::= line lines.Rev () public Line (params objects : array [object]) : list [string] $[o.ToString () | o in objects]