From 2066e4911948d11cac5a234d2f7773dc5f06ba96 Mon Sep 17 00:00:00 2001 From: Aki Date: Mon, 18 Mar 2024 23:41:20 +0100 Subject: Added filesystem-only starshatter::data DataLoader replacement Step by step. The intent is to find a good spot between current data representations and the standard library and put the intermediate stage there. After it matures a bit, we can move further away. --- FoundationEx/CMakeLists.txt | 4 +- FoundationEx/include/starshatter/foundation/data.h | 26 +++++ .../include/starshatter/foundation/reader.h | 6 +- FoundationEx/src/data.cpp | 42 +++++++ FoundationEx/src/reader.cpp | 4 +- FoundationEx/src/reader/buffer.h | 9 +- FoundationEx/src/reader/buffer.inl.h | 16 ++- FoundationEx/src/reader/file.cpp | 129 +++++++++++++++++++++ FoundationEx/src/reader/file.h | 49 ++++++++ FoundationEx/test/data.cpp | 26 +++++ FoundationEx/test/reader.cpp | 13 +-- 11 files changed, 304 insertions(+), 20 deletions(-) create mode 100644 FoundationEx/include/starshatter/foundation/data.h create mode 100644 FoundationEx/src/data.cpp create mode 100644 FoundationEx/src/reader/file.cpp create mode 100644 FoundationEx/src/reader/file.h create mode 100644 FoundationEx/test/data.cpp diff --git a/FoundationEx/CMakeLists.txt b/FoundationEx/CMakeLists.txt index 646ee58..972a242 100644 --- a/FoundationEx/CMakeLists.txt +++ b/FoundationEx/CMakeLists.txt @@ -5,9 +5,11 @@ add_library( src/Text.cpp src/Utils.cpp src/reader.cpp + src/data.cpp + src/reader/file.cpp ) target_include_directories(${PROJECT_NAME} PUBLIC include) -add_executable(${PROJECT_NAME}_test test/Text.cpp test/reader.cpp) +add_executable(${PROJECT_NAME}_test test/Text.cpp test/reader.cpp test/data.cpp) target_link_libraries(${PROJECT_NAME}_test PRIVATE ${PROJECT_NAME} GTest::gtest_main) generate_emulator(${PROJECT_NAME}_test) gtest_discover_tests(${PROJECT_NAME}_test DISCOVERY_TIMEOUT 60) diff --git a/FoundationEx/include/starshatter/foundation/data.h b/FoundationEx/include/starshatter/foundation/data.h new file mode 100644 index 0000000..20308a2 --- /dev/null +++ b/FoundationEx/include/starshatter/foundation/data.h @@ -0,0 +1,26 @@ +/* Starshatter: The Open Source Project + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors + Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors + Copyright (c) 1997-2006, Destroyer Studios LLC. +*/ + +#pragma once + +#include "reader.h" + + +namespace starshatter +{ +namespace foundation +{ +namespace data +{ + + +bool toggle_filesystem(bool enabled); +Reader open(const char* pathname); + + +} // namespace data +} // namespace foundation +} // namespace starshatter diff --git a/FoundationEx/include/starshatter/foundation/reader.h b/FoundationEx/include/starshatter/foundation/reader.h index 7ec81b4..69472c8 100644 --- a/FoundationEx/include/starshatter/foundation/reader.h +++ b/FoundationEx/include/starshatter/foundation/reader.h @@ -9,6 +9,8 @@ #include #include +#include + namespace starshatter { @@ -40,7 +42,7 @@ struct BaseReader virtual Count read(Char* dest, Count bytes) = 0; virtual Count peek(Char* dest) const = 0; virtual Count peek(Char* dest, Count bytes) const = 0; - virtual const Char* data() const = 0; + virtual Text more() = 0; }; @@ -73,7 +75,7 @@ struct Reader : public BaseReader Count read(char* dest, Count bytes) override; Count peek(char* dest) const override; Count peek(char* dest, Count bytes) const override; - const char* data() const override; + Text more() override; private: Base actual; }; diff --git a/FoundationEx/src/data.cpp b/FoundationEx/src/data.cpp new file mode 100644 index 0000000..643e823 --- /dev/null +++ b/FoundationEx/src/data.cpp @@ -0,0 +1,42 @@ +/* Starshatter: The Open Source Project + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors + Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors + Copyright (c) 1997-2006, Destroyer Studios LLC. +*/ + +#include + +#include +#include + +#include + +#include "reader/file.h" + + + +namespace starshatter +{ +namespace foundation +{ +namespace data +{ + + +bool +toggle_filesystem(bool) +{ + return true; +} + + +Reader +open(const char* pathname) +{ + return {std::make_unique(std::fstream(pathname, std::ios::binary | std::ios::in))}; +} + + +} // namespace data +} // namespace foundation +} // namespace starshatter diff --git a/FoundationEx/src/reader.cpp b/FoundationEx/src/reader.cpp index 7bce34d..0a3a2ba 100644 --- a/FoundationEx/src/reader.cpp +++ b/FoundationEx/src/reader.cpp @@ -9,6 +9,8 @@ #include #include +#include + #include "reader/buffer.h" @@ -75,7 +77,7 @@ Count Reader::read(char* dest) { return actual->read(dest); } Count Reader::read(char* dest, Count bytes) { return actual->read(dest, bytes); } Count Reader::peek(char* dest) const { return actual->peek(dest); } Count Reader::peek(char* dest, Count bytes) const { return actual->peek(dest, bytes); } -const char* Reader::data() const { return actual->data(); } +Text Reader::more() { return actual->more(); } } // namespace foundation diff --git a/FoundationEx/src/reader/buffer.h b/FoundationEx/src/reader/buffer.h index c36310a..532a8f9 100644 --- a/FoundationEx/src/reader/buffer.h +++ b/FoundationEx/src/reader/buffer.h @@ -7,6 +7,7 @@ #pragma once #include +#include namespace starshatter @@ -35,12 +36,12 @@ struct BufferReader : public BaseReader Count read(char* dest, Count bytes) override; Count peek(char* dest) const override; Count peek(char* dest, Count bytes) const override; - const char* data() const override; + Text more() override; private: - Source buffer; - Count size; - Count position; + Source buffer = {}; + Count size = {}; + Count position = {}; }; diff --git a/FoundationEx/src/reader/buffer.inl.h b/FoundationEx/src/reader/buffer.inl.h index 3b739e4..c452878 100644 --- a/FoundationEx/src/reader/buffer.inl.h +++ b/FoundationEx/src/reader/buffer.inl.h @@ -8,8 +8,9 @@ #include #include #include +#include -#include +#include namespace starshatter @@ -124,16 +125,21 @@ Count BufferReader::peek(char* dest, Count bytes) const { bytes = std::min(bytes, available()); - std::copy(data(), data() + bytes, dest); + std::copy(at(buffer) + position, at(buffer) + position + bytes, dest); return bytes; } template -const char* -BufferReader::data() const +Text +BufferReader::more() { - return at(buffer) + position; + const auto size = available(); + if (size < 1) + return Text(); + std::vector tmp(size); + read(tmp.data(), size); + return Text(tmp.data(), size); } diff --git a/FoundationEx/src/reader/file.cpp b/FoundationEx/src/reader/file.cpp new file mode 100644 index 0000000..f9e9ae2 --- /dev/null +++ b/FoundationEx/src/reader/file.cpp @@ -0,0 +1,129 @@ +/* Starshatter: The Open Source Project + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors + Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors + Copyright (c) 1997-2006, Destroyer Studios LLC. +*/ + +#include "file.h" + +#include +#include +#include +#include +#include +#include + +#include + + +namespace starshatter +{ +namespace foundation +{ + + +FileReader::FileReader(std::fstream src) : + file {std::move(src)} +{ + file.seekg(0); + file.ignore(std::numeric_limits::max()); + size = file.gcount(); + file.clear(); + file.seekg(0); + position = 0; +} + + +bool +FileReader::valid() const +{ + return static_cast(file) && file.is_open(); +} + + +Count +FileReader::available() const +{ + return size - position; +} + + +Count +FileReader::seek(Count pos) +{ + position = pos; + if (position > size) + position = size; + file.seekg(position); + return position; +} + + +Count +FileReader::seek(Offset offset, Direction dir) +{ + switch (dir) { + case Direction::Start: + break; // no-op + case Direction::End: + offset = size + offset; + break; + case Direction::Current: + offset = position + offset; + break; + } + if (offset < 0) + offset = 0; + return seek(static_cast(offset)); +} + + +Count +FileReader::read(char* dest) +{ + return read(dest, available()); +} + + +Count +FileReader::read(char* dest, Count bytes) +{ + bytes = std::min(bytes, available()); + file.read(dest, bytes); + position += bytes; + return bytes; +} + + +Count +FileReader::peek(char* dest) const +{ + return peek(dest, available()); +} + + +Count +FileReader::peek(char* dest, Count bytes) const +{ + bytes = std::min(bytes, available()); + const auto before = file.tellg(); + file.read(dest, bytes); + file.seekg(before); + return bytes; +} + + +Text +FileReader::more() +{ + const auto size = available(); + if (size < 1) + return Text(); + std::vector tmp(size); + read(tmp.data(), size); + return Text(tmp.data(), size); +} + + +} // namespace foundation +} // namespace starshatter diff --git a/FoundationEx/src/reader/file.h b/FoundationEx/src/reader/file.h new file mode 100644 index 0000000..22810b6 --- /dev/null +++ b/FoundationEx/src/reader/file.h @@ -0,0 +1,49 @@ +/* Starshatter: The Open Source Project + Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors + Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors + Copyright (c) 1997-2006, Destroyer Studios LLC. +*/ + +#pragma once + +#include + +#include +#include + + +namespace starshatter +{ +namespace foundation +{ + + +struct FileReader : public BaseReader +{ + FileReader() = default; + FileReader(std::fstream src); + FileReader(const FileReader& other) = delete; + FileReader& operator=(const FileReader& other) = delete; + FileReader(FileReader&& other) = default; + FileReader& operator=(FileReader&& other) = default; + ~FileReader() override = default; + + bool valid() const override; + Count available() const override; + Count seek(Count pos) override; + Count seek(Offset offset, Direction dir) override; + Count read(char* dest) override; + Count read(char* dest, Count bytes) override; + Count peek(char* dest) const override; + Count peek(char* dest, Count bytes) const override; + Text more() override; + +private: + mutable std::fstream file = {}; + Count size = {}; + Count position = {}; +}; + + +} // namespace foundation +} // namespace starshatter diff --git a/FoundationEx/test/data.cpp b/FoundationEx/test/data.cpp new file mode 100644 index 0000000..09ab49b --- /dev/null +++ b/FoundationEx/test/data.cpp @@ -0,0 +1,26 @@ +#include +#include + +#include + +#include + + +namespace data = starshatter::foundation::data; +namespace fs = std::filesystem; + + +TEST(FoundationEx, OpenRelativePathOnFilesystem) +{ + fs::current_path(fs::temp_directory_path()); + { + std::fstream tmp("sample", tmp.out | tmp.binary); + tmp << "Hello, there!\n"; + } + data::toggle_filesystem(true); + auto file = data::open("sample"); + ASSERT_TRUE(file.valid()); + ASSERT_LT(0, file.available()); + const auto text = file.more(); + ASSERT_STREQ("Hello, there!\n", text); +} diff --git a/FoundationEx/test/reader.cpp b/FoundationEx/test/reader.cpp index 395ad81..4bc4882 100644 --- a/FoundationEx/test/reader.cpp +++ b/FoundationEx/test/reader.cpp @@ -17,7 +17,8 @@ TEST(FoundationEx, ReadFromView) { Reader reader("Hello, World!"); ASSERT_TRUE(reader.valid()); - std::vector buffer(reader.available()); + const auto s = reader.available(); + std::vector buffer(s); ASSERT_EQ(14, buffer.size()); const auto bytes = reader.read(buffer.data()); ASSERT_EQ(14, bytes); @@ -54,12 +55,10 @@ TEST(FoundationEx, RelativeSeek) TEST(FoundationEx, CreateTextFromReader) { const char* ref = "Hello!"; - const auto size = 7; - auto ptr = std::make_unique(size); - for (auto i = 0; i < size; ++i) - ptr[i] = ref[i]; + auto ptr = std::make_unique(std::strlen(ref) + 1); + std::strcpy(ptr.get(), ref); Reader reader(std::move(ptr)); ASSERT_TRUE(reader.valid()); - Text text(reader.data()); - ASSERT_EQ("Hello!", text); + const auto text = reader.more(); + ASSERT_STREQ(ref, text); } -- cgit v1.1