aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-09-22 16:09:14 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-09-22 16:09:14 +0200
commitd90cecc758d3c348f3aedf9c6e45a13ba6a0b0c3 (patch)
tree1b24e7c0fac394ef5cf0d6538b5209b89e91f86e
parente185fe6bc6cbe9bc1e0694fc5b11650118eeef82 (diff)
-rw-r--r--.gitignore2
-rw-r--r--.gitmodules5
-rw-r--r--CMakeLists.txt13
-rw-r--r--Exception.cpp34
-rw-r--r--Exception.h17
-rw-r--r--File.cpp9
-rw-r--r--File.h25
-rw-r--r--FileReader.cpp32
-rw-r--r--FileReader.h26
-rw-r--r--HTTPFile.cpp28
-rw-r--r--HTTPFile.h29
-rw-r--r--LocalFile.cpp36
-rw-r--r--LocalFile.h29
-rw-r--r--docs/class-diag.puml26
-rw-r--r--lazy.mk33
m---------lib/cpr0
-rw-r--r--main.cpp12
17 files changed, 321 insertions, 35 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7194ea7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.cache
+build
diff --git a/.gitmodules b/.gitmodules
index 8c7dbb0..b260b07 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,5 +1,8 @@
[submodule "lib/SDL"]
path = lib/SDL
url = https://github.com/libsdl-org/SDL
- branch = release-2.30.x
+ shallow = true
+[submodule "lib/cpr"]
+ path = lib/cpr
+ url = https://github.com/libcpr/cpr
shallow = true
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4f76a5..67c5607 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,9 +5,22 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
set(CMAKE_BUILD_TYPE Debug)
+find_package(SDL2 REQUIRED)
+find_package(cpr REQUIRED)
+
project(main C CXX)
add_executable(main
main.cpp
+ File.cpp
+ HTTPFile.cpp
+ LocalFile.cpp
+ Exception.cpp
+ FileReader.cpp
+)
+
+target_link_libraries(main
+ SDL2
+ cpr
)
diff --git a/Exception.cpp b/Exception.cpp
new file mode 100644
index 0000000..d9765da
--- /dev/null
+++ b/Exception.cpp
@@ -0,0 +1,34 @@
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+
+#include "Exception.h"
+
+Exception::~Exception() {
+ if (error != NULL)
+ free(error);
+}
+
+const char * Exception::what() {
+ return error;
+}
+
+void Exception::va_format(va_list args, const char * fmt) {
+ va_list args_copy;
+ va_copy(args_copy, args);
+
+ size_t sz = vsnprintf(NULL, 0, fmt, args_copy) + 1;
+ if (error != NULL) free(error);
+ error = (char *) malloc(sz);
+ va_end(args_copy);
+
+ vsnprintf(error, sz, fmt, args);
+}
+
+Exception::Exception(const char * fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ va_format(args, fmt);
+ va_end(args);
+}
+
diff --git a/Exception.h b/Exception.h
new file mode 100644
index 0000000..31c517b
--- /dev/null
+++ b/Exception.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <cstdarg>
+#include <exception>
+
+class Exception : public std::exception {
+public:
+ Exception(const char * fmt, ...);
+ virtual ~Exception();
+ virtual const char * what();
+
+protected:
+ Exception() = default;
+ void va_format(va_list args, const char * fmt);
+ char * error = NULL;
+};
+
diff --git a/File.cpp b/File.cpp
new file mode 100644
index 0000000..bc31b1c
--- /dev/null
+++ b/File.cpp
@@ -0,0 +1,9 @@
+#include <string>
+
+#include "File.h"
+#include "FileReader.h"
+
+File::File(const std::string protocol) {
+ FileReader::assign(protocol, this);
+}
+
diff --git a/File.h b/File.h
new file mode 100644
index 0000000..71a96e0
--- /dev/null
+++ b/File.h
@@ -0,0 +1,25 @@
+#pragma once
+
+class FileReader;
+
+#include <string>
+
+class File {
+protected:
+ virtual void open(const std::string url) = 0;
+public:
+ virtual void close() = 0;
+ virtual const std::string read() = 0;
+
+public:
+ virtual ~File() = default;
+
+protected:
+ File() = default;
+ virtual File * clone() const = 0;
+
+protected:
+ File(const std::string protocol);
+ friend FileReader;
+};
+
diff --git a/FileReader.cpp b/FileReader.cpp
new file mode 100644
index 0000000..503aee5
--- /dev/null
+++ b/FileReader.cpp
@@ -0,0 +1,32 @@
+#include "FileReader.h"
+#include "File.h"
+
+File & FileReader::open(const std::string url) {
+ File * reader = find_reader(url)->clone();
+ reader->open(url);
+ return *reader;
+}
+
+void FileReader::assign(const std::string type, const File * node) {
+ static FactoryMap & map = get_map();
+ map[type] = node;
+}
+
+FactoryMap & FileReader::get_map() {
+ static FactoryMap map;
+ return map;
+}
+
+const File * FileReader::find_reader(const std::string type) {
+ static FactoryMap & map = get_map();
+
+ // try to find protocol by prefix
+ for (auto item : map) {
+ if (!type.starts_with(item.first)) continue;
+ return item.second;
+ }
+
+ // fallback is local file
+ return map.find("file://")->second;
+}
+
diff --git a/FileReader.h b/FileReader.h
new file mode 100644
index 0000000..b2d8b37
--- /dev/null
+++ b/FileReader.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <string>
+#include <map>
+
+#include "File.h"
+
+using FactoryMap = std::map<std::string, const File *>;
+
+class FileReader {
+public:
+ static File & open(const std::string url);
+
+private:
+ FileReader() = default;
+ virtual ~FileReader() = default;
+
+private:
+ static void assign(const std::string type, const File * node);
+ static FactoryMap & get_map();
+ static const File * find_reader(const std::string type);
+
+private:
+ friend File;
+};
+
diff --git a/HTTPFile.cpp b/HTTPFile.cpp
new file mode 100644
index 0000000..a1d9185
--- /dev/null
+++ b/HTTPFile.cpp
@@ -0,0 +1,28 @@
+#include <cpr/cpr.h>
+
+#include "HTTPFile.h"
+#include "Exception.h"
+
+HTTPFile HTTPFile::instance(protocol);
+
+void HTTPFile::open(const std::string url) {
+ _res = cpr::Get(cpr::Url{url});
+
+}
+
+void HTTPFile::close() { }
+
+const std::string HTTPFile::read() {
+ return _res.text.data();
+}
+
+HTTPFile::~HTTPFile() {
+ close();
+}
+
+HTTPFile * HTTPFile::clone() const {
+ return new HTTPFile(this);
+}
+
+HTTPFile::HTTPFile(const HTTPFile *) : File() { }
+
diff --git a/HTTPFile.h b/HTTPFile.h
new file mode 100644
index 0000000..94207f2
--- /dev/null
+++ b/HTTPFile.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <cpr/cpr.h>
+
+#include "File.h"
+
+class HTTPFile : File {
+protected:
+ virtual void open(const std::string url);
+public:
+ virtual void close();
+ virtual const std::string read();
+
+public:
+ virtual ~HTTPFile();
+
+private:
+ HTTPFile(const HTTPFile *);
+ virtual HTTPFile * clone() const;
+
+private:
+ using File::File;
+ constexpr static const std::string protocol = "https://";
+ static HTTPFile instance;
+
+private:
+ cpr::Response _res;
+};
+
diff --git a/LocalFile.cpp b/LocalFile.cpp
new file mode 100644
index 0000000..2f4140d
--- /dev/null
+++ b/LocalFile.cpp
@@ -0,0 +1,36 @@
+#include <cstdio>
+#include <iterator>
+
+#include "LocalFile.h"
+#include "Exception.h"
+
+LocalFile LocalFile::instance(protocol);
+
+void LocalFile::open(const std::string url) {
+ std::string path = url;
+ if (path.starts_with(protocol))
+ path = path.substr(protocol.size());
+
+ std::ifstream _file(path);
+ if (!_file.is_open())
+ throw Exception("Cannot open file://%s\n", path.c_str());
+}
+
+void LocalFile::close() {
+ if (_file.is_open()) _file.close();
+}
+
+const std::string LocalFile::read() {
+ return std::string(std::istreambuf_iterator<char>(_file), std::istreambuf_iterator<char>());
+}
+
+LocalFile::~LocalFile() {
+ close();
+}
+
+LocalFile * LocalFile::clone() const {
+ return new LocalFile(this);
+}
+
+LocalFile::LocalFile(const LocalFile *) : File() { }
+
diff --git a/LocalFile.h b/LocalFile.h
new file mode 100644
index 0000000..9529053
--- /dev/null
+++ b/LocalFile.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <fstream>
+
+#include "File.h"
+
+class LocalFile : File {
+protected:
+ virtual void open(const std::string url);
+public:
+ virtual void close();
+ virtual const std::string read();
+
+public:
+ virtual ~LocalFile();
+
+private:
+ LocalFile(const LocalFile *);
+ virtual LocalFile * clone() const;
+
+private:
+ using File::File;
+ constexpr static const std::string protocol = "file://";
+ static LocalFile instance;
+
+private:
+ std::ifstream _file;
+};
+
diff --git a/docs/class-diag.puml b/docs/class-diag.puml
index 17e2b59..6de5851 100644
--- a/docs/class-diag.puml
+++ b/docs/class-diag.puml
@@ -3,11 +3,17 @@
!theme plain
skinparam linetype ortho
skinparam classAttributeIconSize 0
+' skinparam packageStyle rectangle
+
+class main as "main()"
+hide main circle
+hide main members
class FileReader {
+ open(path)
+ read()
+ close()
+ - protocol
}
class LocalFile
@@ -31,6 +37,20 @@ class YellowTileBehavior
class Artist
+class ArtistDeserializer
+class CanvasDeserializer
+
+package CPR { }
+package SDL2 { }
+
+interface Parser {
+ + parse(f: FileReader)
+}
+
+class CSVParser
+class XMLParser
+class TXTParser
+
FileReader <|-- LocalFile
FileReader <|-- HTTPFile
Canvas "1" -> "*" Tile
@@ -39,6 +59,12 @@ TileBehavior <|-- RedTileBehavior
TileBehavior <|-- BlueTileBehavior
TileBehavior <|-- YellowTileBehavior
+Parser <|-- CSVParser
+Parser <|-- TXTParser
+Parser <|-- XMLParser
+
+HTTPFile ..> CPR
+
TileFactory --> Tile : create
diff --git a/lazy.mk b/lazy.mk
deleted file mode 100644
index a591fd5..0000000
--- a/lazy.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# NOTE: CMAKE IS THE PRIMARY BUILD SYSTEM FOR THIS PROJECT. THIS FILE IS
-# PROVIDED PURELY FOR CONVENIENCE, AND SHOULD NOT BECOME AN ESSENTIAL PART OF
-# THE BUILD SYSTEM!
-
-BUILD_DIR ?= build
-TARGET ?= $(BUILD_DIR)/main
-
-# always generate fresh build rules when cmake is re-run
-CMFLAGS += --fresh
-# make cmake shut up
-CMFLAGS += --log-level WARNING
-CMFLAGS += -Wno-deprecated
-
-.PHONY: FORCE
-
-all: FORCE $(TARGET)
-
-$(BUILD_DIR)/build.ninja: CMakeLists.txt
- @mkdir -p $(BUILD_DIR)
- @cmake -B $(BUILD_DIR) -G Ninja $(CMFLAGS)
-
-$(TARGET): $(BUILD_DIR)/build.ninja FORCE
- @ninja -C $(BUILD_DIR)
-
-clean: FORCE
- $(RM) -r $(BUILD_DIR)
-
-# Forward any unknown targets to Ninja
-ifneq ($(MAKECMDGOALS),)
-%::
- @ninja -C $(BUILD_DIR) $@
-endif
-
diff --git a/lib/cpr b/lib/cpr
new file mode 160000
+Subproject 99f044e386115194485ce77e326c31e9bd80bb0
diff --git a/main.cpp b/main.cpp
index 1846bfb..3ee5b4c 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,4 +1,14 @@
-int main() {
+#include <cstdio>
+
+#include "FileReader.h"
+
+int main(int argc, char** argv) {
+ for (int i = 1; i < argc; i++) {
+ File & r = FileReader::open(argv[i]);
+ printf("-- %s --\n%s\n", argv[i], r.read().c_str());
+ r.close();
+ }
+
return 0;
}