diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-22 14:44:47 +0200 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-22 14:44:47 +0200 |
commit | 8c0562c8ef37cd5e80c58609f7bc7ae352365f65 (patch) | |
tree | 42e9906c5ddf1b0e719ee3eb7b965a444be64c38 | |
parent | bc02054d56118110a36aea72d21f9d5e73d07d1f (diff) |
refactor parser factory
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | CSVParser.cpp | 14 | ||||
-rw-r--r-- | CSVParser.h | 10 | ||||
-rw-r--r-- | LoadFilesCommand.cpp | 12 | ||||
-rw-r--r-- | Parser.cpp | 13 | ||||
-rw-r--r-- | Parser.h | 12 | ||||
-rw-r--r-- | ParserFactory.cpp | 35 | ||||
-rw-r--r-- | ParserFactory.h | 14 | ||||
-rw-r--r-- | TXTParser.cpp | 10 | ||||
-rw-r--r-- | TXTParser.h | 10 | ||||
-rw-r--r-- | XMLParser.cpp | 15 | ||||
-rw-r--r-- | XMLParser.h | 10 | ||||
-rw-r--r-- | docs/class-diag.puml | 53 |
13 files changed, 108 insertions, 103 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 15f889b..cf2f157 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,10 +23,11 @@ add_executable(main Exception.cpp FileReaderFactory.cpp Canvas.cpp + Parser.cpp ParserFactory.cpp CSVParser.cpp XMLParser.cpp - # TXTParser.cpp + TXTParser.cpp MuseumDeserializer.cpp Tile.cpp TileColorFactory.cpp diff --git a/CSVParser.cpp b/CSVParser.cpp index 824d5f4..8afce80 100644 --- a/CSVParser.cpp +++ b/CSVParser.cpp @@ -6,17 +6,11 @@ #include "CSVParser.h" #include "Exception.h" -#include "ParserFactory.h" using namespace std; -CSVParser CSVParser::instance {}; -CSVParser::CSVParser() { - ParserFactory::register_strategy(this); -} - -unsigned int CSVParser::heuristic(FileReader & f) { - const string content = f.read(); +unsigned int CSVParser::heuristic() { + const string content = this->get_file().read(); int global_columns = 0; int columns = 1; int rows = 0; @@ -41,10 +35,10 @@ static size_t header_idx(vector<string> header, string field) { return iter - header.begin(); } -void CSVParser::parse(FileReader & f, MuseumDeserializer & d) { +void CSVParser::parse(MuseumDeserializer & d) { vector<vector<string>> table = {}; - istringstream rows(f.read()); + istringstream rows(this->get_file().read()); string row; while (getline(rows, row)) { // ignore windows line endings diff --git a/CSVParser.h b/CSVParser.h index 660cc18..2e3231b 100644 --- a/CSVParser.h +++ b/CSVParser.h @@ -3,12 +3,10 @@ #include "Parser.h" class CSVParser : public Parser { -public: - virtual void parse(FileReader & f, MuseumDeserializer & d); - virtual unsigned int heuristic(FileReader & f); + friend class ParserFactory; -private: - static CSVParser instance; - CSVParser(); +public: + virtual void parse(MuseumDeserializer & d); + virtual unsigned int heuristic(); }; diff --git a/LoadFilesCommand.cpp b/LoadFilesCommand.cpp index 3fb4978..76cd197 100644 --- a/LoadFilesCommand.cpp +++ b/LoadFilesCommand.cpp @@ -1,3 +1,4 @@ +#include <memory> #include <vector> #include <string> @@ -27,12 +28,15 @@ void LoadFilesCommand::load_files() { ToggleMuseumPauseCommand(this->museum, true).execute(); MuseumDeserializer deserializer { this->museum }; + ParserFactory factory {}; + for (string url : files) { - unique_ptr<FileReader> file = FileReaderFactory().create(url); try { - ParserFactory::parse(*file, deserializer); + unique_ptr<FileReader> file = FileReaderFactory().create(url); + Parser & parser = factory.get_parser(*file); + parser.parse(deserializer); } catch (Exception & e) { - throw Exception("parser error: %s (%s)", e.what(), url.c_str()); + throw Exception("%s (%s)", e.what(), url.c_str()); } } } @@ -41,7 +45,7 @@ void LoadFilesCommand::execute() { try { this->load_files(); } catch (Exception & e) { - throw Exception("LoadFilesCommand error: %s", e.what()); + throw Exception("LoadFilesCommand: %s", e.what()); } } diff --git a/Parser.cpp b/Parser.cpp new file mode 100644 index 0000000..9b07089 --- /dev/null +++ b/Parser.cpp @@ -0,0 +1,13 @@ +#include "Parser.h" +#include "Exception.h" + +void Parser::set_file(FileReader & file) { + this->file = &file; +} + +FileReader & Parser::get_file() { + if (this->file == nullptr) + throw Exception("Parser: no file to read"); + return *this->file; +} + @@ -5,7 +5,15 @@ class Parser { public: - virtual void parse(FileReader & f, MuseumDeserializer & d) = 0; - virtual unsigned int heuristic(FileReader & f) = 0; + virtual void parse(MuseumDeserializer & d) = 0; + virtual unsigned int heuristic() = 0; + +protected: + friend class ParserFactory; + void set_file(FileReader & f); + FileReader & get_file(); + +private: + FileReader * file = nullptr; }; diff --git a/ParserFactory.cpp b/ParserFactory.cpp index 49c4d00..53bfbc5 100644 --- a/ParserFactory.cpp +++ b/ParserFactory.cpp @@ -1,32 +1,33 @@ -#include <algorithm> - #include "ParserFactory.h" #include "Exception.h" -void ParserFactory::parse(FileReader & file, MuseumDeserializer & deserializer) { - auto & col = ParserFactory::get_collection(); - if (col.size() < 1) - throw Exception("no parsers registered"); +#include "XMLParser.h" +#include "TXTParser.h" +#include "CSVParser.h" + +using namespace std; + +ParserFactory::ParserFactory() { + this->parsers.push_back(unique_ptr<Parser>(new XMLParser())); + this->parsers.push_back(unique_ptr<Parser>(new TXTParser())); + this->parsers.push_back(unique_ptr<Parser>(new CSVParser())); +} +Parser & ParserFactory::get_parser(FileReader & file) { unsigned int best_score = 0; Parser * best_strategy = nullptr; - for (Parser * strategy : col) { - unsigned int score = strategy->heuristic(file); + for (auto & parser : this->parsers) { + parser->set_file(file); + unsigned int score = parser->heuristic(); if (score <= best_score) continue; best_score = score; - best_strategy = strategy; + best_strategy = parser.get(); } if (best_strategy == nullptr) - throw Exception("unknown file type"); - - best_strategy->parse(file, deserializer); -} + throw Exception("ParserFactory: unknown file type"); -void ParserFactory::register_strategy(Parser * ps) { - auto & col = ParserFactory::get_collection(); - if (std::find(col.begin(), col.end(), ps) != col.end()) return; - col.push_back(ps); + return *best_strategy; } diff --git a/ParserFactory.h b/ParserFactory.h index 5430366..cb8cb99 100644 --- a/ParserFactory.h +++ b/ParserFactory.h @@ -1,20 +1,16 @@ #pragma once +#include <memory> + #include "FileReader.h" -#include "MuseumDeserializer.h" #include "Parser.h" class ParserFactory { - typedef std::vector<Parser*> ParserCollection; - public: - static void parse(FileReader & f, MuseumDeserializer & d); - static void register_strategy(Parser * p); + ParserFactory(); + Parser & get_parser(FileReader & f); private: - static ParserCollection & get_collection() { - static ParserCollection c = {}; - return c; - } + std::vector<std::unique_ptr<Parser>> parsers; }; diff --git a/TXTParser.cpp b/TXTParser.cpp index e19f343..17890e0 100644 --- a/TXTParser.cpp +++ b/TXTParser.cpp @@ -1,16 +1,10 @@ #include "TXTParser.h" -#include "ParserFactory.h" -TXTParser TXTParser::instance {}; -TXTParser::TXTParser() { - ParserFactory::register_strategy(this); -} - -unsigned int TXTParser::heuristic(FileReader & f) { +unsigned int TXTParser::heuristic() { return 0; } -void TXTParser::parse(FileReader & f, MuseumDeserializer & d) { +void TXTParser::parse(MuseumDeserializer & d) { printf("%s\n", __PRETTY_FUNCTION__); } diff --git a/TXTParser.h b/TXTParser.h index 064a0cf..cfb485a 100644 --- a/TXTParser.h +++ b/TXTParser.h @@ -3,12 +3,10 @@ #include "Parser.h" class TXTParser : public Parser { -public: - virtual void parse(FileReader & f, MuseumDeserializer & d); - virtual unsigned int heuristic(FileReader & f); + friend class ParserFactory; -private: - static TXTParser instance; - TXTParser(); +public: + virtual void parse(MuseumDeserializer & d); + virtual unsigned int heuristic(); }; diff --git a/XMLParser.cpp b/XMLParser.cpp index 4bfde46..6252be8 100644 --- a/XMLParser.cpp +++ b/XMLParser.cpp @@ -4,18 +4,11 @@ #include "XMLParser.h" #include "Exception.h" -#include "ParserFactory.h" -#include "TileData.h" using namespace std; -XMLParser XMLParser::instance {}; -XMLParser::XMLParser() { - ParserFactory::register_strategy(this); -} - -unsigned int XMLParser::heuristic(FileReader & f) { - const string content = f.read(); +unsigned int XMLParser::heuristic() { + const string content = this->get_file().read(); int open_backets = 0; int close_brackets = 0; for (char c : content) { @@ -27,10 +20,10 @@ unsigned int XMLParser::heuristic(FileReader & f) { return (open_backets + close_brackets) / penalty; } -void XMLParser::parse(FileReader & f, MuseumDeserializer & d) { +void XMLParser::parse(MuseumDeserializer & d) { using namespace pugi; - const string content = f.read(); + const string content = this->get_file().read(); xml_document doc; xml_parse_result result = doc.load_string(content.c_str()); if (!result) diff --git a/XMLParser.h b/XMLParser.h index 16f8749..8a36f44 100644 --- a/XMLParser.h +++ b/XMLParser.h @@ -3,12 +3,10 @@ #include "Parser.h" class XMLParser : public Parser { -public: - virtual void parse(FileReader & f, MuseumDeserializer & d); - virtual unsigned int heuristic(FileReader & f); + friend class ParserFactory; -private: - static XMLParser instance; - XMLParser(); +public: + virtual void parse(MuseumDeserializer & d); + virtual unsigned int heuristic(); }; diff --git a/docs/class-diag.puml b/docs/class-diag.puml index 6c38d9c..58ed950 100644 --- a/docs/class-diag.puml +++ b/docs/class-diag.puml @@ -50,15 +50,20 @@ rectangle Group_FileReading as "File reading" <<group>> { HTTPFileReader -r[hidden] LocalFileReader } rectangle Group_ParsingDeserialization as "Parsing & deserialization" <<group>> { - class ParserFactory { - + parse(FileReader &, MuseumDeserializer &) <<static>> - + register_strategy(Parser *) <<static>> + class ParserFactory <<factory>> { + + ParserFactory() + + get_parser(FileReader &) : Parser & -- - - get_collection() : ParserCollection <<static>> + - parsers : vec<uniq<Parser>> } - interface Parser { - + parse(FileReader &, MuseumDeserializer &) <<static>> - + heuristic(FileReader &) : unsigned int <<static>> + interface Parser { + + parse(FileReader &, MuseumDeserializer &) + + heuristic(FileReader &) : unsigned int + -- + # set_file(FileReader &) + # get_file() : FileReader & + -- + file : FileReader * } class XMLParser @@ -86,9 +91,7 @@ rectangle Group_ParsingDeserialization as "Parsing & deserialization" <<group>> + add_type(type : string, Color, weight : unsigned int) } - CSVParser -up-> MuseumDeserializer - XMLParser -up-> MuseumDeserializer - TXTParser -up-> MuseumDeserializer + Parser .> MuseumDeserializer ' LAYOUT CSVParser -r[hidden] TXTParser @@ -103,9 +106,10 @@ rectangle Group_Algorithms as "Algorithms" <<group>> { class CollisionContext { + CollisionContext(Museum &) } - class CollisionChecker { + class CollisionChecker <<abstract>> { + CollisionChecker(Museum &) - + check(Artist & a, Artist & b) + + compare(Artist & a, Artist & b) + + check() <<pure virtual>> } class QuadTreeCollisionChecker { + QuadTree(Museum &) @@ -208,7 +212,7 @@ rectangle Group_Model as "Model" <<group>> { green : unsigned int blue : unsigned int } - class TileColorFactory <<singleton>> { + class TileColorFactory <<factory>> <<singleton>> { + get_color(string) : Color <<static>> + register_color(string, Color) <<static>> } @@ -224,7 +228,7 @@ rectangle Group_Model as "Model" <<group>> { # interactions : unsigned int # museum : Museum & } - class TileBehaviorFactory { + class TileBehaviorFactory <<factory>> { + TileBehaviorFactory(Museum &) + create(string) : uniq<TileBehavior> -- @@ -322,9 +326,9 @@ rectangle Group_Visualization as "Visualization" <<group>> { } class ViewController { + update() - + ev_keydown(KeyboardCode); - + ev_mousedown(MouseCode); - + ev_mousemove(x, y); + + ev_keydown(KeyboardCode) + + ev_mousedown(MouseCode) + + ev_mousemove(x, y) -- - draw_artists : bool <<+get>> <<+set>> } @@ -355,11 +359,6 @@ rectangle Group_Commands as "Commands" <<group>> { - museum : Museum & - view : View & } - class ToggleArtistVisibilityCommand { - + constructor(ViewController &) - -- - - controller : ViewController & - } class LoadFilesCommand { + constructor(Museum &, files : vec<string>) + constructor(Museum &, argc, argv) @@ -381,10 +380,18 @@ rectangle Group_Commands as "Commands" <<group>> { - museum : Museum & - forwards : bool } + class ControlBooleanCommand { + + constructor(target : bool &) + + constructor(target : bool &, set : bool) + -- + - toggle : bool + - value : bool + - target : bool & + } Command <|-d- ToggleMuseumPauseCommand Command <|-u- OpenFileGUICommand - Command <|-u- ToggleArtistVisibilityCommand + Command <|-u- ControlBooleanCommand Command <|-d- StepTileCommand Command <|-d- LoadFilesCommand Command <|-d- TimeTravelCommand |