From 2aa26759e12da36d68641ea3abda9b53292a2cbd Mon Sep 17 00:00:00 2001 From: Aki Date: Mon, 18 Mar 2024 00:39:44 +0100 Subject: Bulk busy work towards Reader replacement to inject into DataLoader --- FoundationEx/CMakeLists.txt | 10 +- .../include/starshatter/foundation/reader.h | 83 ++++++++++++ FoundationEx/src/Reader.cpp | 89 ------------- FoundationEx/src/Reader_.cpp | 89 +++++++++++++ FoundationEx/src/reader.cpp | 82 ++++++++++++ FoundationEx/src/reader/buffer.h | 51 ++++++++ FoundationEx/src/reader/buffer.inl.h | 141 +++++++++++++++++++++ FoundationEx/test/reader.cpp | 65 ++++++++++ 8 files changed, 519 insertions(+), 91 deletions(-) create mode 100644 FoundationEx/include/starshatter/foundation/reader.h delete mode 100644 FoundationEx/src/Reader.cpp create mode 100644 FoundationEx/src/Reader_.cpp create mode 100644 FoundationEx/src/reader.cpp create mode 100644 FoundationEx/src/reader/buffer.h create mode 100644 FoundationEx/src/reader/buffer.inl.h create mode 100644 FoundationEx/test/reader.cpp diff --git a/FoundationEx/CMakeLists.txt b/FoundationEx/CMakeLists.txt index 045b44e..646ee58 100644 --- a/FoundationEx/CMakeLists.txt +++ b/FoundationEx/CMakeLists.txt @@ -1,7 +1,13 @@ project(FoundationEx) -add_library(${PROJECT_NAME} STATIC src/Reader.cpp src/Text.cpp src/Utils.cpp) +add_library( + ${PROJECT_NAME} STATIC + src/Reader_.cpp + src/Text.cpp + src/Utils.cpp + src/reader.cpp + ) target_include_directories(${PROJECT_NAME} PUBLIC include) -add_executable(${PROJECT_NAME}_test test/Text.cpp) +add_executable(${PROJECT_NAME}_test test/Text.cpp test/reader.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/reader.h b/FoundationEx/include/starshatter/foundation/reader.h new file mode 100644 index 0000000..7ec81b4 --- /dev/null +++ b/FoundationEx/include/starshatter/foundation/reader.h @@ -0,0 +1,83 @@ +/* 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 + + +namespace starshatter +{ +namespace foundation +{ + + +using Count = std::size_t; +using Offset = std::ptrdiff_t; + + +enum class Direction +{ + Start, + End, + Current, +}; + + +template +struct BaseReader +{ + virtual ~BaseReader() = default; + virtual bool valid() const = 0; + virtual Count available() const = 0; + virtual Count seek(Count pos) = 0; + virtual Count seek(Offset offset, Direction dir) = 0; + virtual Count read(Char* dest) = 0; + 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; +}; + + +struct Reader : public BaseReader +{ + using Base = std::unique_ptr; + using Chars = std::unique_ptr; + + Reader(); + + Reader(const Reader&) = delete; + Reader& operator=(const Reader&) = delete; + + Reader(Reader&& other); + Reader& operator=(Reader&& other); + + Reader(Base src); + Reader(Chars src); + Reader(Chars src, Count bytes); + Reader(const char* src); + Reader(const char* src, Count bytes); + + ~Reader() 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; + const char* data() const override; +private: + Base actual; +}; + + +} // namespace foundation +} // namespace starshatter diff --git a/FoundationEx/src/Reader.cpp b/FoundationEx/src/Reader.cpp deleted file mode 100644 index c3e33d5..0000000 --- a/FoundationEx/src/Reader.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* 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. - - AUTHOR: John DiCamillo - - - OVERVIEW - ======== - Implementation of the Reader class -*/ - -#include - -#include -#include - -#include - - -FileReader::FileReader(const char* fname) : - filename(fname), - done(0) -{ -} - - -Text -FileReader::more() -{ - if (done) return Text(); - - std::fstream fin(filename, std::fstream::in); - - if (!fin) { - Print("ERROR(Parse): Could not open file '%s'\n", filename.data()); - return Text(); - } - - Text result; - char buf[1000], newline; - - while (fin.get(buf, 1000)) { - result.append(buf); - fin.get(newline); - result.append(newline); - } - - done = 1; - return result; -} - - -BlockReader::BlockReader(const char* block) : - data((char*) block), - done(0), - length(0) -{ -} - - -BlockReader::BlockReader(const char* block, int len) : - data((char*) block), - done(0), - length(len) -{ -} - - -Text -BlockReader::more() -{ - if (done) return Text(); - - if (length) { - Text result(data, length); - done = 1; - return result; - } - else if (data) { - Text result(data); - done = 1; - return result; - } - - done = 1; - return Text(); -} diff --git a/FoundationEx/src/Reader_.cpp b/FoundationEx/src/Reader_.cpp new file mode 100644 index 0000000..c3e33d5 --- /dev/null +++ b/FoundationEx/src/Reader_.cpp @@ -0,0 +1,89 @@ +/* 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. + + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the Reader class +*/ + +#include + +#include +#include + +#include + + +FileReader::FileReader(const char* fname) : + filename(fname), + done(0) +{ +} + + +Text +FileReader::more() +{ + if (done) return Text(); + + std::fstream fin(filename, std::fstream::in); + + if (!fin) { + Print("ERROR(Parse): Could not open file '%s'\n", filename.data()); + return Text(); + } + + Text result; + char buf[1000], newline; + + while (fin.get(buf, 1000)) { + result.append(buf); + fin.get(newline); + result.append(newline); + } + + done = 1; + return result; +} + + +BlockReader::BlockReader(const char* block) : + data((char*) block), + done(0), + length(0) +{ +} + + +BlockReader::BlockReader(const char* block, int len) : + data((char*) block), + done(0), + length(len) +{ +} + + +Text +BlockReader::more() +{ + if (done) return Text(); + + if (length) { + Text result(data, length); + done = 1; + return result; + } + else if (data) { + Text result(data); + done = 1; + return result; + } + + done = 1; + return Text(); +} diff --git a/FoundationEx/src/reader.cpp b/FoundationEx/src/reader.cpp new file mode 100644 index 0000000..7bce34d --- /dev/null +++ b/FoundationEx/src/reader.cpp @@ -0,0 +1,82 @@ +/* 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 "reader/buffer.h" + + +namespace starshatter +{ +namespace foundation +{ + + +Reader::Reader() +{ +} + + +Reader::Reader(Reader&& other) : + actual {std::move(other.actual)} +{ +} + + +Reader& +Reader::operator=(Reader&& other) +{ + actual = std::move(other.actual); + return *this; +} + + +Reader::Reader(Base src) : + actual {std::move(src)} +{ +} + + +Reader::Reader(Chars src) : + actual {std::make_unique>(std::move(src))} +{ +} + + +Reader::Reader(Chars src, Count bytes) : + actual {std::make_unique>(std::move(src), bytes)} +{ +} + + +Reader::Reader(const char* src) : + actual {std::make_unique>(src)} +{ +} + + +Reader::Reader(const char* src, Count bytes) : + actual {std::make_unique>(src, bytes)} +{ +} + + +bool Reader::valid() const { return static_cast(actual); } +Count Reader::available() const { return actual->available(); } +Count Reader::seek(Count pos) { return actual->seek(pos); } +Count Reader::seek(Offset offset, Direction dir) { return actual->seek(offset, dir); } +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(); } + + +} // namespace foundation +} // namespace starshatter diff --git a/FoundationEx/src/reader/buffer.h b/FoundationEx/src/reader/buffer.h new file mode 100644 index 0000000..c36310a --- /dev/null +++ b/FoundationEx/src/reader/buffer.h @@ -0,0 +1,51 @@ +/* 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 + + +namespace starshatter +{ +namespace foundation +{ + + +template +struct BufferReader : public BaseReader +{ + BufferReader(); + BufferReader(Source src); + BufferReader(Source src, Count bytes); + BufferReader(const BufferReader& other) = default; + BufferReader& operator=(const BufferReader& other) = default; + BufferReader(BufferReader&& other) = default; + BufferReader& operator=(BufferReader&& other) = default; + ~BufferReader() 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; + const char* data() const override; + +private: + Source buffer; + Count size; + Count position; +}; + + +} // namespace foundation +} // namespace starshatter + + +#include "buffer.inl.h" diff --git a/FoundationEx/src/reader/buffer.inl.h b/FoundationEx/src/reader/buffer.inl.h new file mode 100644 index 0000000..3b739e4 --- /dev/null +++ b/FoundationEx/src/reader/buffer.inl.h @@ -0,0 +1,141 @@ +/* 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 + + +namespace starshatter +{ +namespace foundation +{ + + +// If extension is needed, use type_traits or update to C++20 and use concepts +inline bool ok(const char* data) { return data != nullptr; } +inline bool ok(const std::unique_ptr& data) { return static_cast(data); } +inline const char* at(const char* data) { return data; } +inline const char* at(const std::unique_ptr& data) { return data.get(); } + + +template +BufferReader::BufferReader() +{ +} + + +template +BufferReader::BufferReader(Source src) : + buffer {std::move(src)}, + size {std::strlen(at(buffer)) + 1} +{ +} + + +template +BufferReader::BufferReader(Source src, Count bytes) : + buffer {std::move(src)}, + size {bytes} +{ +} + + +template +bool +BufferReader::valid() const +{ + return ok(buffer); +} + + +template +Count +BufferReader::available() const +{ + return size - position; +} + + +template +Count +BufferReader::seek(Count pos) +{ + position = pos; + if (position > size) + position = size; + return position; +} + + +template +Count +BufferReader::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; + } + position = static_cast(std::clamp(offset, 0, size)); + return position; +} + + +template +Count +BufferReader::read(char* dest) +{ + return read(dest, available()); +} + + +template +Count +BufferReader::read(char* dest, Count bytes) +{ + bytes = peek(dest, bytes); + position += bytes; + return bytes; +} + + +template +Count +BufferReader::peek(char* dest) const +{ + return peek(dest, available()); +} + + +template +Count +BufferReader::peek(char* dest, Count bytes) const +{ + bytes = std::min(bytes, available()); + std::copy(data(), data() + bytes, dest); + return bytes; +} + + +template +const char* +BufferReader::data() const +{ + return at(buffer) + position; +} + + +} // namespace foundation +} // namespace starshatter diff --git a/FoundationEx/test/reader.cpp b/FoundationEx/test/reader.cpp new file mode 100644 index 0000000..395ad81 --- /dev/null +++ b/FoundationEx/test/reader.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include + +#include + +#include +#include + + +using starshatter::foundation::Direction; +using starshatter::foundation::Reader; + + +TEST(FoundationEx, ReadFromView) +{ + Reader reader("Hello, World!"); + ASSERT_TRUE(reader.valid()); + std::vector buffer(reader.available()); + ASSERT_EQ(14, buffer.size()); + const auto bytes = reader.read(buffer.data()); + ASSERT_EQ(14, bytes); + ASSERT_EQ(0, reader.available()); + ASSERT_STREQ("Hello, World!", buffer.data()); +} + + +TEST(FoundationEx, PeekIntoView) +{ + Reader reader("Hello, World!"); + ASSERT_TRUE(reader.valid()); + reader.seek(7); + std::vector buffer(reader.available()); + ASSERT_EQ(7, buffer.size()); + const auto bytes = reader.peek(buffer.data()); + ASSERT_EQ(7, bytes); + ASSERT_EQ(7, reader.available()); + ASSERT_STREQ("World!", buffer.data()); +} + + +TEST(FoundationEx, RelativeSeek) +{ + Reader reader("Hello, World!"); + ASSERT_TRUE(reader.valid()); + ASSERT_EQ(11, reader.seek(-3, Direction::End)); + EXPECT_EQ(8, reader.seek(-3, Direction::Current)); + ASSERT_EQ(5, reader.seek(5, Direction::Start)); + EXPECT_EQ(7, reader.seek(2, Direction::Current)); +} + + +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]; + Reader reader(std::move(ptr)); + ASSERT_TRUE(reader.valid()); + Text text(reader.data()); + ASSERT_EQ("Hello!", text); +} -- cgit v1.1