/* * (C) 2023-2024 René Meusel - Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_BUFFER_STUFFER_H_ #define BOTAN_BUFFER_STUFFER_H_ #include #include #include #include namespace Botan { /** * @brief Helper class to ease in-place marshalling of concatenated fixed-length * values. * * The size of the final buffer must be known from the start, reallocations are * not performed. */ class BufferStuffer final { public: constexpr explicit BufferStuffer(std::span buffer) : m_buffer(buffer) {} /** * @returns a span for the next @p bytes bytes in the concatenated buffer. * Checks that the buffer is not exceeded. */ constexpr std::span next(size_t bytes) { BOTAN_STATE_CHECK(m_buffer.size() >= bytes); auto result = m_buffer.first(bytes); m_buffer = m_buffer.subspan(bytes); return result; } template constexpr std::span next() { BOTAN_STATE_CHECK(m_buffer.size() >= bytes); auto result = m_buffer.first(); m_buffer = m_buffer.subspan(bytes); return result; } template StrongSpan next(size_t bytes) { return StrongSpan(next(bytes)); } /** * @returns a reference to the next single byte in the buffer */ constexpr uint8_t& next_byte() { return next(1)[0]; } constexpr void append(std::span buffer) { auto sink = next(buffer.size()); std::copy(buffer.begin(), buffer.end(), sink.begin()); } constexpr void append(uint8_t b, size_t repeat = 1) { auto sink = next(repeat); std::fill(sink.begin(), sink.end(), b); } constexpr bool full() const { return m_buffer.empty(); } constexpr size_t remaining_capacity() const { return m_buffer.size(); } private: std::span m_buffer; }; } // namespace Botan #endif