#include #include "TXTParser.h" #include "Color.h" #include "Exception.h" using namespace std; unsigned int TXTParser::heuristic() { 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(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 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(stoi(red)), .green = static_cast(stoi(green)), .blue = static_cast(stoi(blue)), }; } static void parse_header_table(MuseumDeserializer & d, const std::string & header, std::istringstream & rows) { vector 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 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.get(c)) { if (c == '\r') continue; if (c == '\n') { x = 0; y += 1; continue; } d.set_tile({ .x = x, .y = y, .type = string(1, c), }); x += 1; } } void TXTParser::parse(MuseumDeserializer & d) { istringstream input(this->get_file().read()); parse_header(d, input); parse_canvas(d, input); }