diff options
Diffstat (limited to 'TXTParser.cpp')
-rw-r--r-- | TXTParser.cpp | 165 |
1 files changed, 163 insertions, 2 deletions
diff --git a/TXTParser.cpp b/TXTParser.cpp index 17890e0..5d0820f 100644 --- a/TXTParser.cpp +++ b/TXTParser.cpp @@ -1,10 +1,171 @@ +#include <sstream> + #include "TXTParser.h" +#include "Color.h" +#include "Exception.h" + +using namespace std; unsigned int TXTParser::heuristic() { - return 0; + bool grid = false; + int columns = 0; + int rows = 0; + int penalty = 1; + + istringstream lines(this->get_file().read()); + string line; + while (getline(lines, line)) { + if (line.back() == '\r') line.pop_back(); + + if (line.size() == 0) { + grid = true; + continue; + } + if (!grid) continue; + + rows++; + if (columns == 0) columns = line.size(); + penalty += abs(columns - static_cast<int>(line.size())); + } + + if (grid == false) return 0; + + if (columns == 1) penalty += 1000; + return (rows + columns) / penalty; +} + + +static void parse_header_def(MuseumDeserializer & d, const std::string & line) { + CanvasData data; + + istringstream defs(line); + string def; + while (getline(defs, def, ',')) { + size_t equals = def.find("="); + if (equals == string::npos) + throw Exception("TXTParser: invalid def \"%s\"", def.c_str()); + + string key = def.substr(0, equals); + + if (key == "rows") { + data.rows = stoi(def.substr(equals + 1)); + continue; + } + + if (key == "cols") { + data.columns = stoi(def.substr(equals + 1)); + continue; + } + + throw Exception("TXTParser: invalid key \"%s\"", key.c_str()); + } + + d.set_canvas(data); +} + +static size_t header_idx(vector<string> header, string field) { + auto iter = find(header.begin(), header.end(), field); + if (iter == header.end()) + throw Exception("header table is missing \"%s\" column", field.c_str()); + return iter - header.begin(); +} + +static Color stocolor(const string & str) { + istringstream ss(str); + string red, green, blue; + getline(ss, red, ','); + getline(ss, green, ','); + getline(ss, blue, ','); + return { + .red = static_cast<unsigned int>(stoi(red)), + .green = static_cast<unsigned int>(stoi(green)), + .blue = static_cast<unsigned int>(stoi(blue)), + }; +} + +static void parse_header_table(MuseumDeserializer & d, const std::string & header, std::istringstream & rows) { + vector<string> table_header; + istringstream header_row(header); + string column; + while (getline(header_row, column, ',')) + table_header.push_back(column); + + size_t type_idx = header_idx(table_header, "letter"); + size_t color_idx = header_idx(table_header, "rgb"); + size_t weight_idx = header_idx(table_header, "weight"); + + string row; + while (getline(rows, row)) { + if (row.back() == '\r') row.pop_back(); + if (row.size() == 0) break; + + unsigned int col_idx = 0; + string col = ""; + string stack = ""; + vector<string> cols = {}; + + for (char c : row) { + if (c == stack.back()) { + stack.pop_back(); + continue; + } + if (c == '[') { + stack.push_back(']'); + continue; + } + if (stack.size() == 0 && c == ',') { + cols.push_back(col); + col.clear(); + continue; + } + col.push_back(c); + } + if (col.size() > 0) cols.push_back(col); + + if (cols.size() != 3) + throw Exception("invalid header table row"); + + d.add_type( + cols[type_idx], + stocolor(cols[color_idx]), + stoi(cols[weight_idx]) + ); + } +} + +static void parse_header(MuseumDeserializer & d, istringstream & input) { + string line; + while (getline(input, line)) { + if (line.back() == '\r') line.pop_back(); + if (line.size() == 0) break; + + if (line.find("=") != string::npos) { + parse_header_def(d, line); + } else { + parse_header_table(d, line, input); + break; + } + } +} + +static void parse_canvas(MuseumDeserializer & d, istringstream & input) { + unsigned int x = 0, y = 0; + char c; + while (input >> c) { + if (c == '\r') continue; + if (c == '\n') { + x = 0; + y += 1; + } + d.set_tile({ .x = x, .y = y, .type = string(1, c), }); + x += 1; + } } void TXTParser::parse(MuseumDeserializer & d) { - printf("%s\n", __PRETTY_FUNCTION__); + istringstream input(this->get_file().read()); + + parse_header(d, input); + parse_canvas(d, input); } |