|
| 1 | +#ifndef CLP_FFI_STRINGBLOB_HPP |
| 2 | +#define CLP_FFI_STRINGBLOB_HPP |
| 3 | + |
| 4 | +#include <cstddef> |
| 5 | +#include <optional> |
| 6 | +#include <string> |
| 7 | +#include <string_view> |
| 8 | +#include <vector> |
| 9 | + |
| 10 | +#include "../ErrorCode.hpp" |
| 11 | +#include "../ReaderInterface.hpp" |
| 12 | + |
| 13 | +namespace clp::ffi { |
| 14 | +// Stores a list of strings as an indexable blob. |
| 15 | +class StringBlob { |
| 16 | +public: |
| 17 | + // Constructors |
| 18 | + StringBlob() = default; |
| 19 | + |
| 20 | + // Methods |
| 21 | + [[nodiscard]] auto get_num_strings() const -> size_t { return m_offsets.size() - 1; } |
| 22 | + |
| 23 | + /** |
| 24 | + * @param index |
| 25 | + * @return A view of the string at the given `index` in the blob. |
| 26 | + * @return std::nullopt if `index` is out of bounds. |
| 27 | + */ |
| 28 | + [[nodiscard]] auto get_string(size_t index) const -> std::optional<std::string_view> { |
| 29 | + if (index >= get_num_strings()) { |
| 30 | + return std::nullopt; |
| 31 | + } |
| 32 | + size_t const start_offset{m_offsets[index]}; |
| 33 | + size_t const end_offset{m_offsets[index + 1]}; |
| 34 | + return std::string_view{m_data}.substr(start_offset, end_offset - start_offset); |
| 35 | + } |
| 36 | + |
| 37 | + /** |
| 38 | + * Reads a string of the given `length` from the `reader` and appends it to the blob. |
| 39 | + * @param reader |
| 40 | + * @param length The exact length of the string to read. |
| 41 | + * @return std::nullopt on success. |
| 42 | + * @return Forwards `ReaderInterface::try_read_exact_length`'s error code on failure. |
| 43 | + */ |
| 44 | + [[nodiscard]] auto read_from(ReaderInterface& reader, size_t length) |
| 45 | + -> std::optional<ErrorCode> { |
| 46 | + auto const start_offset{m_data.size()}; |
| 47 | + auto const end_offset{start_offset + length}; |
| 48 | + m_data.resize(static_cast<std::string::size_type>(end_offset)); |
| 49 | + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) |
| 50 | + if (auto const err{reader.try_read_exact_length(m_data.data() + start_offset, length)}; |
| 51 | + ErrorCode::ErrorCode_Success != err) |
| 52 | + { |
| 53 | + m_data.resize(start_offset); |
| 54 | + return err; |
| 55 | + } |
| 56 | + m_offsets.emplace_back(end_offset); |
| 57 | + return std::nullopt; |
| 58 | + } |
| 59 | + |
| 60 | +private: |
| 61 | + std::string m_data; |
| 62 | + std::vector<size_t> m_offsets{0}; |
| 63 | +}; |
| 64 | +} // namespace clp::ffi |
| 65 | + |
| 66 | +#endif // CLP_FFI_STRINGBLOB_HPP |
0 commit comments