diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-22 14:00:41 +0200 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-10-22 14:00:41 +0200 |
commit | bc02054d56118110a36aea72d21f9d5e73d07d1f (patch) | |
tree | 2fc49dd3f93307df6242b8e63bca0e26b2e62168 | |
parent | fab0fccc0aaa18e915bcd08e81e5a04177e435cd (diff) |
refactor file reading factory
-rw-r--r-- | FileReader.cpp | 9 | ||||
-rw-r--r-- | FileReader.h | 17 | ||||
-rw-r--r-- | FileReaderFactory.cpp | 40 | ||||
-rw-r--r-- | FileReaderFactory.h | 15 | ||||
-rw-r--r-- | HTTPFileReader.cpp | 16 | ||||
-rw-r--r-- | HTTPFileReader.h | 17 | ||||
-rw-r--r-- | LoadFilesCommand.cpp | 2 | ||||
-rw-r--r-- | LocalFileReader.cpp | 27 | ||||
-rw-r--r-- | LocalFileReader.h | 20 | ||||
-rw-r--r-- | docs/class-diag.puml | 69 |
10 files changed, 98 insertions, 134 deletions
diff --git a/FileReader.cpp b/FileReader.cpp index b76de50..89ebe17 100644 --- a/FileReader.cpp +++ b/FileReader.cpp @@ -1,9 +1,6 @@ -#include <string> - #include "FileReader.h" -#include "FileReaderFactory.h" -FileReader::FileReader(const std::string protocol) { - FileReaderFactory::register_strategy(protocol, this); -} +using namespace std; + +FileReader::FileReader(const string & url) : url(url) { } diff --git a/FileReader.h b/FileReader.h index f896ec8..ee6e550 100644 --- a/FileReader.h +++ b/FileReader.h @@ -5,21 +5,20 @@ class FileReaderFactory; #include <string> class FileReader { -protected: - virtual void open(const std::string url) = 0; -public: - virtual void close() = 0; - virtual const std::string read() = 0; + friend class FileReaderFactory; +protected: + FileReader(const std::string & url); public: virtual ~FileReader() = default; protected: - FileReader() = default; - virtual FileReader * clone() const = 0; + virtual void open() = 0; +public: + virtual void close() = 0; + virtual const std::string read() = 0; protected: - FileReader(const std::string protocol); - friend FileReaderFactory; + const std::string url = ""; }; diff --git a/FileReaderFactory.cpp b/FileReaderFactory.cpp index 4b72b11..e40dbb9 100644 --- a/FileReaderFactory.cpp +++ b/FileReaderFactory.cpp @@ -3,34 +3,28 @@ #include "FileReaderFactory.h" #include "FileReader.h" +#include "LocalFileReader.h" +#include "HTTPFileReader.h" + using namespace std; -unique_ptr<FileReader> FileReaderFactory::open(const std::string url) { - FileReader * reader = find_reader(url)->clone(); - reader->open(url); - return unique_ptr<FileReader>(reader); -} +unique_ptr<FileReader> FileReaderFactory::create(const string & url) { + FileReader * reader = nullptr; -void FileReaderFactory::register_strategy(const std::string type, const FileReader * node) { - static FactoryMap & map = get_map(); - map[type] = node; -} + // protocol handlers + if (url.starts_with("file://")) + reader = new LocalFileReader(url); + else if (url.starts_with("http://")) + reader = new HTTPFileReader(url); + else if (url.starts_with("https://")) + reader = new HTTPFileReader(url); -FactoryMap & FileReaderFactory::get_map() { - static FactoryMap map; - return map; -} - -const FileReader * FileReaderFactory::find_reader(const std::string type) { - static FactoryMap & map = get_map(); + // no protocol = treat as file:// + if (reader == nullptr) + reader = new LocalFileReader(url); - // try to find protocol by prefix - for (auto item : map) { - if (!type.starts_with(item.first)) continue; - return item.second; - } + reader->open(); - // fallback is local file - return map.find("file://")->second; + return unique_ptr<FileReader>(reader); } diff --git a/FileReaderFactory.h b/FileReaderFactory.h index 0829985..85521c0 100644 --- a/FileReaderFactory.h +++ b/FileReaderFactory.h @@ -1,27 +1,16 @@ #pragma once #include <string> -#include <map> #include <memory> #include "FileReader.h" -using FactoryMap = std::map<std::string, const FileReader *>; - class FileReaderFactory { public: - static std::unique_ptr<FileReader> open(const std::string url); + std::unique_ptr<FileReader> create(const std::string & url); -private: +public: FileReaderFactory() = default; virtual ~FileReaderFactory() = default; - -private: - static void register_strategy(const std::string type, const FileReader * node); - static FactoryMap & get_map(); - static const FileReader * find_reader(const std::string type); - -private: - friend FileReader; }; diff --git a/HTTPFileReader.cpp b/HTTPFileReader.cpp index d7f5dd4..191e212 100644 --- a/HTTPFileReader.cpp +++ b/HTTPFileReader.cpp @@ -2,10 +2,10 @@ #include "HTTPFileReader.h" -HTTPFileReader HTTPFileReader::instance(protocol); +using namespace std; -void HTTPFileReader::open(const std::string url) { - _res = cpr::Get(cpr::Url{url}); +void HTTPFileReader::open() { + _res = cpr::Get(cpr::Url{this->url}); } void HTTPFileReader::close() { } @@ -14,13 +14,3 @@ const std::string HTTPFileReader::read() { return _res.text.data(); } -HTTPFileReader::~HTTPFileReader() { - this->close(); -} - -HTTPFileReader * HTTPFileReader::clone() const { - return new HTTPFileReader(this); -} - -HTTPFileReader::HTTPFileReader(const HTTPFileReader *) : FileReader() { } - diff --git a/HTTPFileReader.h b/HTTPFileReader.h index 4b05e18..59a8599 100644 --- a/HTTPFileReader.h +++ b/HTTPFileReader.h @@ -5,24 +5,15 @@ #include "FileReader.h" class HTTPFileReader : FileReader { + friend class FileReaderFactory; + using FileReader::FileReader; + protected: - virtual void open(const std::string url); + virtual void open(); public: virtual void close(); virtual const std::string read(); -public: - virtual ~HTTPFileReader(); - -private: - HTTPFileReader(const HTTPFileReader *); - virtual HTTPFileReader * clone() const; - -private: - using FileReader::FileReader; - constexpr static const std::string protocol = "https://"; - static HTTPFileReader instance; - private: cpr::Response _res; }; diff --git a/LoadFilesCommand.cpp b/LoadFilesCommand.cpp index 82ede60..3fb4978 100644 --- a/LoadFilesCommand.cpp +++ b/LoadFilesCommand.cpp @@ -28,7 +28,7 @@ void LoadFilesCommand::load_files() { MuseumDeserializer deserializer { this->museum }; for (string url : files) { - unique_ptr<FileReader> file = FileReaderFactory::open(url); + unique_ptr<FileReader> file = FileReaderFactory().create(url); try { ParserFactory::parse(*file, deserializer); } catch (Exception & e) { diff --git a/LocalFileReader.cpp b/LocalFileReader.cpp index 1f9d574..a505616 100644 --- a/LocalFileReader.cpp +++ b/LocalFileReader.cpp @@ -1,17 +1,18 @@ #include <cstdio> +#include <cstring> #include <iterator> #include "LocalFileReader.h" #include "Exception.h" -LocalFileReader LocalFileReader::instance(protocol); +using namespace std; -void LocalFileReader::open(const std::string url) { - std::string path = url; - if (path.starts_with(protocol)) - path = path.substr(protocol.size()); +void LocalFileReader::open() { + string path = this->url; + if (path.starts_with("file://")) + path = path.substr(strlen("file://")); - this->file = new std::ifstream(path, std::ios::in); + this->file = new ifstream(path, ios::in); if (this->file->fail() || !this->file->is_open()) throw Exception("cannot open file://%s\n", path.c_str()); } @@ -23,7 +24,7 @@ void LocalFileReader::close() { this->file->close(); } -const std::string LocalFileReader::read() { +const string LocalFileReader::read() { if (this->content != nullptr) return *this->content; @@ -33,9 +34,9 @@ const std::string LocalFileReader::read() { if (!this->file->is_open()) throw Exception("FileReader read after close\n"); - this->content = new std::string( - std::istreambuf_iterator<char>(*this->file), - std::istreambuf_iterator<char>() + this->content = new string( + istreambuf_iterator<char>(*this->file), + istreambuf_iterator<char>() ); return *this->content; @@ -55,9 +56,3 @@ LocalFileReader::~LocalFileReader() { } } -LocalFileReader * LocalFileReader::clone() const { - return new LocalFileReader(this); -} - -LocalFileReader::LocalFileReader(const LocalFileReader *) : FileReader() { } - diff --git a/LocalFileReader.h b/LocalFileReader.h index 6ea4f84..b9daa55 100644 --- a/LocalFileReader.h +++ b/LocalFileReader.h @@ -5,23 +5,17 @@ #include "FileReader.h" class LocalFileReader : FileReader { -protected: - virtual void open(const std::string url); -public: - virtual void close(); - virtual const std::string read(); + friend class FileReaderFactory; + using FileReader::FileReader; public: virtual ~LocalFileReader(); -private: - LocalFileReader(const LocalFileReader *); - virtual LocalFileReader * clone() const; - -private: - using FileReader::FileReader; - constexpr static const std::string protocol = "file://"; - static LocalFileReader instance; +protected: + virtual void open(); +public: + virtual void close(); + virtual const std::string read(); private: std::ifstream * file = nullptr; diff --git a/docs/class-diag.puml b/docs/class-diag.puml index 8058e0a..6c38d9c 100644 --- a/docs/class-diag.puml +++ b/docs/class-diag.puml @@ -18,29 +18,31 @@ exception Exception { } rectangle Group_FileReading as "File reading" <<group>> { - class FileReaderFactory <<Factory>> { - + open(url) : FileReader& + class FileReaderFactory <<factory>> { + + create(url : const string &) : uniq<FileReader> } interface FileReader { - + read() : string + # FileReader(url : const string &) + + ~FileReader() + -- + # open() + + read() : const string + close() -- - # open(string url) - # clone() : FileReader* <<const>> + # url : const string } class LocalFileReader { - - instance : LocalFileReader <<static>> + + ~LocalFileReader() } class HTTPFileReader { - - instance : HTTPFileReader <<static>> } package CPR { } - FileReader <|.u. LocalFileReader - FileReader <|.u. HTTPFileReader + FileReader <|.d. LocalFileReader + FileReader <|.d. HTTPFileReader - FileReader .l> FileReaderFactory - FileReader <. FileReaderFactory + FileReaderFactory -u-> LocalFileReader + FileReaderFactory -u-> HTTPFileReader HTTPFileReader -l> CPR @@ -59,20 +61,21 @@ rectangle Group_ParsingDeserialization as "Parsing & deserialization" <<group>> + heuristic(FileReader &) : unsigned int <<static>> } - Parser .> ParserFactory - Parser <. ParserFactory - - class CSVParser class XMLParser class TXTParser + class CSVParser package pugixml { } - CSVParser ..|> Parser - TXTParser ..|> Parser - XMLParser ..|> Parser + Parser <|.d. XMLParser + Parser <|.d. TXTParser + Parser <|.d. CSVParser + + ParserFactory -u-> XMLParser + ParserFactory -u-> TXTParser + ParserFactory -u-> CSVParser - XMLParser -> pugixml + XMLParser -r> pugixml class MuseumDeserializer { + MuseumDeserializer(Museum &) @@ -135,6 +138,7 @@ rectangle Group_Model as "Model" <<group>> { - worker : thread * - work() } + together { class Canvas { + Canvas(Museum &) -- @@ -148,6 +152,10 @@ rectangle Group_Model as "Model" <<group>> { - tiles : vector<Tile *> - museum : Museum & } + struct CanvasData { + + rows : unsigned int + + columns : unsigned int + } class People { + People(Museum &) -- @@ -159,6 +167,8 @@ rectangle Group_Model as "Model" <<group>> { - artist_count : size_t - museum : Museum & } + } + together { class Tile { + data : TileData + color : Color @@ -190,11 +200,9 @@ rectangle Group_Model as "Model" <<group>> { + vx : float + vy : float } - struct CanvasData { - + rows : unsigned int - + columns : unsigned int } + together { struct Color { red : unsigned int green : unsigned int @@ -204,7 +212,9 @@ rectangle Group_Model as "Model" <<group>> { + get_color(string) : Color <<static>> + register_color(string, Color) <<static>> } + } + together { interface TileBehavior { + step(Artist *) + update(Tile &) @@ -214,13 +224,13 @@ rectangle Group_Model as "Model" <<group>> { # interactions : unsigned int # museum : Museum & } - class TileBehaviorFactory { + TileBehaviorFactory(Museum &) + create(string) : uniq<TileBehavior> -- - museum : Museum & } + } together { class NullTileBehavior { @@ -243,8 +253,15 @@ rectangle Group_Model as "Model" <<group>> { -- - last_interactions : unsigned int } + + NullTileBehavior -d[hidden]- StepTileBehavior + StepTileBehavior -d[hidden]- DeleteArtistTileBehavior + DeleteArtistTileBehavior -d[hidden]- SetNeighborTileBehavior + SetNeighborTileBehavior -d[hidden]- CreateArtistTileBehavior } + Canvas -l[hidden] People + Museum --> People Museum --> Canvas @@ -258,7 +275,7 @@ rectangle Group_Model as "Model" <<group>> { Tile --> "state" Color Tile .[norank].> TileColorFactory - TileColorFactory .> Color + TileColorFactory -> Color TileBehavior <|.. NullTileBehavior TileBehavior <|.. StepTileBehavior @@ -275,9 +292,6 @@ rectangle Group_Model as "Model" <<group>> { Tile --> "state" TileBehavior Tile .[norank].> TileBehaviorFactory - TileBehaviorFactory .l> TileBehavior - TileBehaviorFactory <. TileBehavior - ' LAYOUT Artist -r[hidden] Tile } @@ -378,6 +392,7 @@ rectangle Group_Commands as "Commands" <<group>> { } /' LAYOUT '/ Parser .l> FileReader +' Parser -l> FileReaderFactory MuseumDeserializer .l> Museum Museum --> PathfindingContext |