summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksim Denisov <denisov.maksim@huawei.com>2025-02-20 10:17:18 +0100
committerMaksim Denisov <denisov.maksim@huawei.com>2025-02-21 14:46:30 +0100
commit86eb98393ab87989cc9752506adba9786c635c5a (patch)
tree0066a0e10f95a4cdf0c72e3aaa46137df7d7e5b5
parent4ab55fc98ce14cf61af6527c81a0ff2fc6216e62 (diff)
downloadjustbuild-86eb98393ab87989cc9752506adba9786c635c5a.tar.gz
IncrementalReader: Support reading from memory
-rw-r--r--src/utils/cpp/incremental_reader.cpp38
-rw-r--r--src/utils/cpp/incremental_reader.hpp17
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 {