Botan 3.11.0
Crypto and TLS for C&
Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY > Class Template Reference

Alignment buffer helper. More...

#include <alignment_buffer.h>

Public Member Functions

std::tuple< std::span< const uint8_t >, size_t > aligned_data_to_process (BufferSlicer &slicer) const
 AlignmentBuffer ()=default
 AlignmentBuffer (AlignmentBuffer &&other) noexcept=default
 AlignmentBuffer (const AlignmentBuffer &other)=default
void append (std::span< const T > elements)
void clear ()
std::span< const T > consume ()
std::span< const T > consume_partial ()
constexpr bool defers_final_block () const
std::span< T > directly_modify_first (size_t elements)
std::span< T > directly_modify_last (size_t elements)
size_t elements_in_buffer () const
size_t elements_until_alignment () const
void fill_up_with_zeros ()
std::optional< std::span< const T > > handle_unaligned_data (BufferSlicer &slicer)
bool in_alignment () const
std::optional< std::span< const uint8_t > > next_aligned_block_to_process (BufferSlicer &slicer) const
AlignmentBufferoperator= (AlignmentBuffer &&other) noexcept=default
AlignmentBufferoperator= (const AlignmentBuffer &other)=default
bool ready_to_consume () const
constexpr size_t size () const
 ~AlignmentBuffer ()

Detailed Description

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
requires (BLOCK_SIZE > 0)
class Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >

Alignment buffer helper.

Many algorithms have an intrinsic block size in which they consume input data. When streaming arbitrary data chunks to such algorithms we must store some data intermittently to honor the algorithm's alignment requirements.

This helper encapsulates such an alignment buffer. The API of this class is designed to minimize user errors in the algorithm implementations. Therefore, it is strongly opinionated on its use case. Don't try to use it for anything but the described circumstance.

Template Parameters
Tthe element type of the internal buffer
BLOCK_SIZEthe buffer size to use for the alignment buffer
FINAL_BLOCK_STRATEGYdefines whether the final input data block is retained in handle_unaligned_data() and must be manually consumed

Definition at line 60 of file alignment_buffer.h.

Constructor & Destructor Documentation

◆ AlignmentBuffer() [1/3]

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::AlignmentBuffer ( )
default

◆ ~AlignmentBuffer()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::~AlignmentBuffer ( )
inline

Definition at line 64 of file alignment_buffer.h.

64{ secure_zeroize_buffer(m_buffer.data(), sizeof(T) * m_buffer.size()); }
Alignment buffer helper.
void secure_zeroize_buffer(void *ptr, size_t n)
Definition mem_utils.cpp:29

References Botan::secure_zeroize_buffer().

◆ AlignmentBuffer() [2/3]

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::AlignmentBuffer ( const AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY > & other)
default

References AlignmentBuffer().

◆ AlignmentBuffer() [3/3]

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::AlignmentBuffer ( AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY > && other)
defaultnoexcept

References AlignmentBuffer().

Member Function Documentation

◆ aligned_data_to_process()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
std::tuple< std::span< const uint8_t >, size_t > Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::aligned_data_to_process ( BufferSlicer & slicer) const
inlinenodiscard

Once the buffer reached alignment, this can be used to consume as many input bytes from the given slider as possible. The output always contains data elements that are a multiple of the intrinsic block size.

Returns
a view onto the aligned data from slicer and the number of full blocks that are represented by this view.

Definition at line 126 of file alignment_buffer.h.

126 {
128
129 // When the final block is to be deferred, the last block must not be
130 // selected for processing if there is no (unaligned) extra input data.
131 const size_t defer = (defers_final_block()) ? 1 : 0;
132 const size_t full_blocks_to_process = (slicer.remaining() - defer) / m_buffer.size();
133 return {slicer.take(full_blocks_to_process * m_buffer.size()), full_blocks_to_process};
134 }
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
constexpr size_t size() const
constexpr bool defers_final_block() const

References BOTAN_ASSERT_NOMSG, defers_final_block(), in_alignment(), Botan::BufferSlicer::remaining(), and Botan::BufferSlicer::take().

◆ append()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
void Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::append ( std::span< const T > elements)
inline

Appends the provided elements to the buffer. The user has to make sure that elements fits in the remaining capacity of the buffer.

Definition at line 90 of file alignment_buffer.h.

90 {
92 std::copy(elements.begin(), elements.end(), m_buffer.begin() + m_position);
93 m_position += elements.size();
94 }
size_t elements_until_alignment() const

References BOTAN_ASSERT_NOMSG, and elements_until_alignment().

Referenced by handle_unaligned_data().

◆ clear()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
void Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::clear ( )
inline

Definition at line 71 of file alignment_buffer.h.

71 {
72 zeroize_buffer(m_buffer.data(), m_buffer.size());
73 m_position = 0;
74 }
void zeroize_buffer(T buf[], size_t n)
Definition mem_utils.h:37

References Botan::zeroize_buffer().

◆ consume()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
std::span< const T > Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::consume ( )
inlinenodiscard

Explicitly consume the currently collected block. It is the caller's responsibility to ensure that the buffer is filled fully. After consumption, the buffer is cleared and ready to collect new data.

Definition at line 200 of file alignment_buffer.h.

200 {
202 m_position = 0;
203 return m_buffer;
204 }

References BOTAN_ASSERT_NOMSG, and ready_to_consume().

Referenced by handle_unaligned_data().

◆ consume_partial()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
std::span< const T > Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::consume_partial ( )
inlinenodiscard

Explicitly consumes however many bytes are currently stored in the buffer. After consumption, the buffer is cleared and ready to collect new data.

Definition at line 211 of file alignment_buffer.h.

211 {
212 const auto elements = elements_in_buffer();
213 m_position = 0;
214 return std::span(m_buffer).first(elements);
215 }
size_t elements_in_buffer() const

References elements_in_buffer().

◆ defers_final_block()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
bool Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::defers_final_block ( ) const
inlineconstexpr

◆ directly_modify_first()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
std::span< T > Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::directly_modify_first ( size_t elements)
inline

Allows direct modification of the first elements in the buffer. This is a low-level accessor that neither takes the buffer's current capacity into account nor does it change the internal cursor. Beware not to overwrite unconsumed bytes.

Definition at line 102 of file alignment_buffer.h.

102 {
104 return std::span(m_buffer).first(elements);
105 }

References BOTAN_ASSERT_NOMSG, and size().

◆ directly_modify_last()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
std::span< T > Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::directly_modify_last ( size_t elements)
inline

Allows direct modification of the last elements in the buffer. This is a low-level accessor that neither takes the buffer's current capacity into account nor does it change the internal cursor. Beware not to overwrite unconsumed bytes.

Definition at line 113 of file alignment_buffer.h.

113 {
115 return std::span(m_buffer).last(elements);
116 }

References BOTAN_ASSERT_NOMSG, and size().

◆ elements_in_buffer()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
size_t Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::elements_in_buffer ( ) const
inline

Definition at line 219 of file alignment_buffer.h.

219{ return m_position; }

Referenced by consume_partial().

◆ elements_until_alignment()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
size_t Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::elements_until_alignment ( ) const
inline

Definition at line 221 of file alignment_buffer.h.

221{ return m_buffer.size() - m_position; }

Referenced by append(), and fill_up_with_zeros().

◆ fill_up_with_zeros()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
void Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::fill_up_with_zeros ( )
inline

Fills the currently unused bytes of the buffer with zero bytes

Definition at line 79 of file alignment_buffer.h.

79 {
80 if(!ready_to_consume()) {
81 zeroize_buffer(&m_buffer[m_position], elements_until_alignment());
82 m_position = m_buffer.size();
83 }
84 }

References elements_until_alignment(), ready_to_consume(), and Botan::zeroize_buffer().

◆ handle_unaligned_data()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
std::optional< std::span< const T > > Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::handle_unaligned_data ( BufferSlicer & slicer)
inlinenodiscard

Intermittently buffers potentially unaligned data provided in slicer. If the internal buffer already contains some elements, data is appended. Once a full block is collected, it is returned to the caller for processing.

Parameters
slicerthe input data source to be (partially) consumed
Returns
a view onto a full block once enough data was collected, or std::nullopt if no full block is available yet

Definition at line 166 of file alignment_buffer.h.

166 {
167 // When the final block is to be deferred, we would need to store and
168 // hold a buffer that contains exactly one block until more data is
169 // passed or it is explicitly consumed.
170 const size_t defer = (defers_final_block()) ? 1 : 0;
171
172 if(in_alignment() && slicer.remaining() >= m_buffer.size() + defer) {
173 // We are currently in alignment and the passed-in data source
174 // contains enough data to benefit from aligned processing.
175 // Therefore, we don't copy anything into the intermittent buffer.
176 return std::nullopt;
177 }
178
179 // Fill the buffer with as much input data as needed to reach alignment
180 // or until the input source is depleted.
181 const auto elements_to_consume = std::min(m_buffer.size() - m_position, slicer.remaining());
183
184 // If we collected enough data, we push out one full block. When
185 // deferring the final block is enabled, we additionally check that
186 // more input data is available to continue processing a consecutive
187 // block.
188 if(ready_to_consume() && (!defers_final_block() || !slicer.empty())) {
189 return consume();
190 } else {
191 return std::nullopt;
192 }
193 }
void append(std::span< const T > elements)
std::span< const T > consume()

References append(), consume(), defers_final_block(), Botan::BufferSlicer::empty(), in_alignment(), ready_to_consume(), Botan::BufferSlicer::remaining(), and Botan::BufferSlicer::take().

◆ in_alignment()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
bool Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::in_alignment ( ) const
inline
Returns
true if the buffer is empty (i.e. contains no unaligned data)

Definition at line 226 of file alignment_buffer.h.

226{ return m_position == 0; }

Referenced by aligned_data_to_process(), handle_unaligned_data(), and next_aligned_block_to_process().

◆ next_aligned_block_to_process()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
std::optional< std::span< const uint8_t > > Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::next_aligned_block_to_process ( BufferSlicer & slicer) const
inlinenodiscard

Once the buffer reached alignment, this can be used to consume full blocks from the input data represented by slicer.

Returns
a view onto the next full block from slicer or std::nullopt if not enough data is available in slicer.

Definition at line 143 of file alignment_buffer.h.

143 {
145
146 // When the final block is to be deferred, the last block must not be
147 // selected for processing if there is no (unaligned) extra input data.
148 const size_t defer = (defers_final_block()) ? 1 : 0;
149 if(slicer.remaining() < m_buffer.size() + defer) {
150 return std::nullopt;
151 }
152
153 return slicer.take(m_buffer.size());
154 }

References BOTAN_ASSERT_NOMSG, defers_final_block(), in_alignment(), Botan::BufferSlicer::remaining(), and Botan::BufferSlicer::take().

◆ operator=() [1/2]

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
AlignmentBuffer & Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::operator= ( AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY > && other)
defaultnoexcept

References AlignmentBuffer().

◆ operator=() [2/2]

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
AlignmentBuffer & Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::operator= ( const AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY > & other)
default

References AlignmentBuffer().

◆ ready_to_consume()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
bool Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::ready_to_consume ( ) const
inline
Returns
true if the buffer is full (i.e. a block is ready to be consumed)

Definition at line 231 of file alignment_buffer.h.

231{ return m_position == m_buffer.size(); }

Referenced by consume(), fill_up_with_zeros(), and handle_unaligned_data().

◆ size()

template<typename T, size_t BLOCK_SIZE, AlignmentBufferFinalBlock FINAL_BLOCK_STRATEGY = AlignmentBufferFinalBlock::is_not_special>
size_t Botan::AlignmentBuffer< T, BLOCK_SIZE, FINAL_BLOCK_STRATEGY >::size ( ) const
inlineconstexpr

Definition at line 217 of file alignment_buffer.h.

217{ return m_buffer.size(); }

Referenced by directly_modify_first(), and directly_modify_last().


The documentation for this class was generated from the following file: