module twoda; import std.string; import std.conv : to; import std.regex; class TwoDA{ import std.regex; import std.file; class ParseException : Exception{ this(in string s){super(s);} } this(string filepath){ lastLine = 0; foreach(index, line ; readText(filepath).splitLines){ string data[]; auto results = matchAll(line, rgxField); if(results.empty) throw new ParseException("Could not parse fields in line: "~filepath~":"~index.to!string); foreach(res ; results){ string s; if(res[0][0]=='"') data~= res[2]; else data~= res[1]; } if(index==0){ header = data; } else{ if(data.length != header.length) throw new ParseException("Incorrect number of fields: "~filepath~":"~index.to!string); int nLine = data[0].to!int; values[nLine] = data[1..$]; //writeln(values[nLine]); if(nLine > lastLine) lastLine = nLine; } } } string[] header; string[][uint] values; uint lastLine; enum rgxField = ctRegex!"(?:\\b([^\\s]+?)\\b|\"([^\"]+?)\")"; }