diff options
author | Maksim Denisov <denisov.maksim@huawei.com> | 2025-02-20 10:17:18 +0100 |
---|---|---|
committer | Maksim Denisov <denisov.maksim@huawei.com> | 2025-02-21 14:46:30 +0100 |
commit | 86eb98393ab87989cc9752506adba9786c635c5a (patch) | |
tree | 0066a0e10f95a4cdf0c72e3aaa46137df7d7e5b5 | |
parent | 4ab55fc98ce14cf61af6527c81a0ff2fc6216e62 (diff) | |
download | justbuild-86eb98393ab87989cc9752506adba9786c635c5a.tar.gz |
IncrementalReader: Support reading from memory
-rw-r--r-- | src/utils/cpp/incremental_reader.cpp | 38 | ||||
-rw-r--r-- | src/utils/cpp/incremental_reader.hpp | 17 |
2 files changed, 54 insertions, 1 deletions
diff --git a/src/utils/cpp/incremental_reader.cpp b/src/utils/cpp/incremental_reader.cpp index c1b5bc3a..a7bcc184 100644 --- a/src/utils/cpp/incremental_reader.cpp +++ b/src/utils/cpp/incremental_reader.cpp @@ -72,6 +72,29 @@ auto IncrementalReader::FromFile(std::size_t chunk_size, } } +auto IncrementalReader::FromMemory( + std::size_t chunk_size, + gsl::not_null<std::string const*> const& data) noexcept + -> expected<IncrementalReader, std::string> { + if (chunk_size == 0) { + return unexpected<std::string>{ + "IncrementalReader: the chunk size cannot be 0"}; + } + + try { + // Reading from memory doesn't require a buffer. The resulting chunks + // point at the content_ directly. + return IncrementalReader{chunk_size, + /*content_size=*/data->size(), + data, + /*buffer=*/std::string{}}; + } catch (...) { + return unexpected<std::string>{ + "IncrementalReader: Got an unknown exception during creation from " + "a string"}; + } +} + auto IncrementalReader::ReadChunk(std::size_t offset) const noexcept -> expected<std::string_view, std::string> { using Result = expected<std::string_view, std::string>; @@ -79,6 +102,9 @@ auto IncrementalReader::ReadChunk(std::size_t offset) const noexcept [this, offset](FileSource const& file) -> Result { return ReadFromFile(file, offset); }, + [this, offset](MemorySource const& data) -> Result { + return ReadFromMemory(data, offset); + }, }; try { @@ -119,6 +145,18 @@ auto IncrementalReader::ReadFromFile(FileSource const& file, std::size_t offset) return std::string_view{buffer_.data(), read}; } +auto IncrementalReader::ReadFromMemory(MemorySource const& data, + std::size_t offset) const + -> expected<std::string_view, std::string> { + if (data->empty()) { + // NOLINTNEXTLINE(bugprone-string-constructor,-warnings-as-errors) + return std::string_view{data->data(), 0}; + } + + std::size_t const read = std::min(chunk_size_, data->size() - offset); + return std::string_view{&data->at(offset), read}; +} + IncrementalReader::Iterator::Iterator( gsl::not_null<IncrementalReader const*> const& owner, std::size_t offset) noexcept diff --git a/src/utils/cpp/incremental_reader.hpp b/src/utils/cpp/incremental_reader.hpp index f8f6d32b..31c3cc96 100644 --- a/src/utils/cpp/incremental_reader.hpp +++ b/src/utils/cpp/incremental_reader.hpp @@ -79,6 +79,16 @@ class IncrementalReader final { std::filesystem::path const& path) noexcept -> expected<IncrementalReader, std::string>; + /// \brief Create IncrementalReader that uses the given string as the source + /// of data. + /// \param chunk_size Size of chunk, must be greater than 0. + /// \param data String to read. + /// \return Configured reader on success or an error message on failure. + [[nodiscard]] static auto FromMemory( + std::size_t chunk_size, + gsl::not_null<std::string const*> const& data) noexcept + -> expected<IncrementalReader, std::string>; + [[nodiscard]] auto GetContentSize() const noexcept -> std::size_t { return content_size_; } @@ -100,7 +110,8 @@ class IncrementalReader final { private: using FileSource = std::shared_ptr<std::FILE>; - using ContentSource = std::variant<FileSource>; + using MemorySource = gsl::not_null<std::string const*>; + using ContentSource = std::variant<FileSource, MemorySource>; std::size_t chunk_size_; std::size_t content_size_; @@ -122,6 +133,10 @@ class IncrementalReader final { [[nodiscard]] auto ReadFromFile(FileSource const& file, std::size_t offset) const -> expected<std::string_view, std::string>; + [[nodiscard]] auto ReadFromMemory(MemorySource const& data, + std::size_t offset) const + -> expected<std::string_view, std::string>; + /// \brief Obtain offset corresponding to the end of content. The content /// size is shifted by 1 character to properly handle empty sources. [[nodiscard]] auto GetEndOffset() const noexcept -> std::size_t { |