/** * @file Buffer.h * @author apio (cloudapio.eu) * @brief A managed wrapper around a resizable buffer of arbitrary memory. * * @copyright Copyright (c) 2023, the Luna authors. * */ #pragma once #include #include /** * @brief A managed wrapper around a resizable buffer of arbitrary memory. */ class Buffer { public: Buffer(); ~Buffer(); Buffer(Buffer&& other); Buffer(const Buffer& other) = delete; // For now. /** * @brief Create a Buffer object, allocating a specific amount of memory for it. * * @param size The number of bytes to allocate. * @return Result An error, or the newly created buffer. */ static Result create_sized(usize size); /** * @brief Resize the buffer. * * The existing data is kept, unless the new size is smaller than the old size, in which case only the first * new_size bytes are kept. * * @param new_size The new size of the buffer, in bytes. * @return Result Whether the operation succeeded. */ Result try_resize(usize new_size); /** * @brief Expand the buffer and return a pointer to the beginning of this new expanded area. * * @param size The amount of bytes to expand the buffer by. * @return Result An error, or a pointer to the new area of the buffer. */ Result slice_at_end(usize size); /** * @brief Return a pointer to an area of the buffer, expanding it if necessary. * * @param offset The offset inside the buffer to start at. * @param size The amount of bytes to reserve. * @return Result An error, or a pointer to the requested area. */ Result slice(usize offset, usize size); /** * @brief Add data to the end of the buffer. * * @param data A pointer to the data to add. * @param size The amount of bytes to add. * @return Result Whether the operation succeeded. */ Result append_data(const u8* data, usize size); /** * @brief Remove data from the beginning of the buffer and return it. * * @param data A pointer to store the removed data in. * @param size The amount of bytes to remove. * @return usize The amount of bytes actually removed (may be less if the buffer was smaller than the requested * size). */ usize dequeue_data(u8* data, usize size); /** * @brief Return a pointer to the data contained in the buffer. * * This pointer may be invalid after the buffer is resized. * * @return u8* The contained data. */ u8* data() { return m_data; } /** * @brief Return a pointer to the data contained in the buffer. * * This pointer may be invalid after the buffer is resized. * * @return const u8* The contained data. */ const u8* data() const { return m_data; } /** * @brief Return a pointer to the data contained in the buffer, moving the data out of the buffer. * * This call will empty the buffer, making it the caller's responsibility to manage the data, including freeing it * when no longer used. * * @return u8* The released data. */ u8* release_data(); /** * @brief Return a pointer to the end of the data contained in the buffer. * * This pointer points past the data; as such, dereferencing it directly is undefined behavior. * * @return u8* The end of the data. */ u8* end() { return m_data + m_size; } /** * @brief Return a pointer to the end of the data contained in the buffer. * * This pointer points past the data; as such, dereferencing it directly is undefined behavior. * * @return const u8* The end of the data. */ const u8* end() const { return m_data + m_size; } /** * @brief Return the size of the buffer in bytes. * * @return usize The buffer's size. */ usize size() const { return m_size; } /** * @brief Check whether the buffer is empty. * * @return true The buffer is empty. * @return false The buffer is not empty. */ bool is_empty() const { return m_size == 0; } private: Buffer(u8* data, usize size); u8* m_data { nullptr }; usize m_size { 0 }; };