[WIP] Buffers interface
This commit is contained in:
1 parent
7fd475c9a9
commit
9a5b56729b
11 files changed
+348
No files matched your search
@@ -0,0 +1,20 @@
|
||||
#include <cstdint>
|
||||
#include <acrux/memory/Endian.hpp>
|
||||
#include "acrux/format/Print.hpp"
|
||||
using namespace acrux::memory;
|
||||
using namespace acrux::fmt;
|
||||
|
||||
int main()
|
||||
{
|
||||
uint32_t number = 10;
|
||||
println(number);
|
||||
|
||||
Endian newEndian = !hostEndianness();
|
||||
fromHostEndianness(number, newEndian);
|
||||
println(number);
|
||||
|
||||
toHostEndianness(number, newEndian);
|
||||
println(number);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "BufferBase.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
template<typename TWriter, typename TReader>
|
||||
class Buffer : public IBuffer
|
||||
{
|
||||
public:
|
||||
virtual TWriter* getWriter() = 0;
|
||||
virtual std::unique_ptr<TReader> makeReader() = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
#include "acrux/memory/Endian.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
class IBuffer
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] virtual size_t byteLength() const = 0;
|
||||
[[nodiscard]] virtual size_t bitLength() const = 0;
|
||||
|
||||
[[nodiscard]] virtual size_t byteCapacity() const = 0;
|
||||
[[nodiscard]] virtual size_t bitCapacity() const = 0;
|
||||
|
||||
virtual bool copyTo(std::ostream& stream) const = 0;
|
||||
virtual bool copyFrom(std::istream& stream) = 0;
|
||||
|
||||
[[nodiscard]] virtual bool hasBytesLeft(size_t count) const = 0;
|
||||
[[nodiscard]] virtual bool hasBitsLeft(size_t count) const = 0;
|
||||
|
||||
void setendianness(acrux::memory::Endian endianness);
|
||||
acrux::memory::Endian endianness();
|
||||
|
||||
~IBuffer() = default;
|
||||
|
||||
IBuffer(const IBuffer&) = default;
|
||||
IBuffer(IBuffer&&) noexcept = default;
|
||||
|
||||
IBuffer& operator=(IBuffer&&) noexcept = default;
|
||||
IBuffer& operator=(const IBuffer&) = default;
|
||||
|
||||
private:
|
||||
acrux::memory::Endian m_endianness{acrux::memory::Endian::None};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
|
||||
#include "BufferBase.hpp"
|
||||
#include "acrux/memory/Endian.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
class BufferReader : public IBuffer
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] virtual bool read(void* s, size_t bitCount) = 0;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] bool read(T& value, acrux::memory::Endian endianness);
|
||||
|
||||
[[nodiscard]] const IBuffer* getBuffer() const;
|
||||
IBuffer* getBuffer();
|
||||
|
||||
BufferReader(IBuffer* buffer);
|
||||
~BufferReader() = default;
|
||||
|
||||
BufferReader(const BufferReader&) = default;
|
||||
BufferReader(BufferReader&&) noexcept = default;
|
||||
|
||||
BufferReader& operator=(BufferReader&&) noexcept = default;
|
||||
BufferReader& operator=(const BufferReader&) = default;
|
||||
|
||||
private:
|
||||
IBuffer* m_buffer{nullptr};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
|
||||
#include "BufferBase.hpp"
|
||||
#include "acrux/memory/Endian.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
class BufferWriter : public IBuffer
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] virtual bool write(const void* s, size_t bitCount) = 0;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] bool write(const T& value, acrux::memory::Endian endianness);
|
||||
|
||||
[[nodiscard]] const IBuffer* getBuffer() const;
|
||||
IBuffer* getBuffer();
|
||||
|
||||
BufferWriter(IBuffer* buffer);
|
||||
~BufferWriter() = default;
|
||||
|
||||
BufferWriter(const BufferWriter&) = default;
|
||||
BufferWriter(BufferWriter&&) noexcept = default;
|
||||
|
||||
BufferWriter& operator=(BufferWriter&&) noexcept = default;
|
||||
BufferWriter& operator=(const BufferWriter&) = default;
|
||||
|
||||
private:
|
||||
IBuffer* m_buffer{nullptr};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "acrux/buffers/fixed/FixedBufferBase.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
template <size_t ByteCapacity> class FixedBuffer : FixedBufferBase
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] const uint8_t* data() const override;
|
||||
|
||||
private:
|
||||
uint8_t* data() override;
|
||||
std::array<uint8_t, ByteCapacity> m_data{0};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include "acrux/buffers/Buffer.hpp"
|
||||
#include "acrux/buffers/fixed/FixedBufferReader.hpp"
|
||||
#include "acrux/buffers/fixed/FixedBufferWriter.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
class FixedBufferBase : Buffer<FixedBufferWriter, FixedBufferReader>
|
||||
{
|
||||
public:
|
||||
FixedBufferWriter* getWriter() override;
|
||||
std::unique_ptr<FixedBufferReader> makeReader() override;
|
||||
|
||||
~FixedBufferBase() = default;
|
||||
|
||||
FixedBufferBase(const FixedBufferBase&) = default;
|
||||
FixedBufferBase(FixedBufferBase&&) noexcept = default;
|
||||
|
||||
FixedBufferBase& operator=(FixedBufferBase&&) noexcept = default;
|
||||
FixedBufferBase& operator=(const FixedBufferBase&) = default;
|
||||
|
||||
[[nodiscard]] virtual const uint8_t* data() const = 0;
|
||||
|
||||
private:
|
||||
virtual uint8_t* data() = 0;
|
||||
size_t m_byteCursor{0};
|
||||
uint8_t m_bitCursor{0};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "acrux/buffers/BufferBase.hpp"
|
||||
#include "acrux/buffers/BufferReader.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
class FixedBufferReader final : public BufferReader
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] bool read(void* s, size_t bitCount) override;
|
||||
|
||||
FixedBufferReader(IBuffer* buffer);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "acrux/buffers/BufferBase.hpp"
|
||||
#include "acrux/buffers/BufferWriter.hpp"
|
||||
|
||||
namespace acrux::buffers
|
||||
{
|
||||
class FixedBufferWriter final : public BufferWriter
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] bool write(const void* s, size_t bitCount) override;
|
||||
|
||||
FixedBufferWriter(IBuffer* buffer);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace acrux::memory
|
||||
{
|
||||
enum class Endian : uint8_t
|
||||
{
|
||||
None,
|
||||
Little,
|
||||
Big
|
||||
};
|
||||
|
||||
/**
|
||||
* @param endian The endianness to get the opposite of.
|
||||
* @return Gets the opposite endiannes, unchanged if `endian` is `None`.
|
||||
*/
|
||||
Endian operator!(const Endian& endian);
|
||||
|
||||
/**
|
||||
* @return The host's endianness
|
||||
*/
|
||||
Endian hostEndianness();
|
||||
|
||||
/**
|
||||
* @brief Swaps the bytes of `value` if `source` and `target` are different,
|
||||
* results in a no-op if `source` or `target` is `None`.
|
||||
*
|
||||
* @tparam T The type of the value to modify.
|
||||
* @param value The value to modify.
|
||||
* @param source The value's source endianness.
|
||||
* @param target The value's target endianness.
|
||||
*/
|
||||
template <typename T> void convertEndianness(T& value, Endian source, Endian target);
|
||||
|
||||
/**
|
||||
* @brief Swaps the bytes of `value` if `source` is different than the host's endianness.
|
||||
* results in a no-op if `source` is `None`
|
||||
*
|
||||
* @tparam T The type of the value to convert.
|
||||
* @param value The value to convert.
|
||||
* @param source The value's source endianness
|
||||
*/
|
||||
template <typename T> void toHostEndianness(T& value, Endian source);
|
||||
|
||||
/**
|
||||
* @brief Swaps the bytes of `value` if `target` is different than the host's endianness.
|
||||
* results in a no-op if `target` is `None`
|
||||
*
|
||||
* @tparam T The type of the value to convert.
|
||||
* @param value The value to convert.
|
||||
* @param target The value's target endianness
|
||||
*/
|
||||
template <typename T> void fromHostEndianness(T& value, Endian target);
|
||||
|
||||
/**
|
||||
* @brief Swaps the bytes of a given value.
|
||||
*
|
||||
* @tparam T The type of the value.
|
||||
* @param value The value to modify.
|
||||
*/
|
||||
template <typename T> void swapBytes(T& value);
|
||||
|
||||
template <typename T> void convertEndianness(T& value, Endian source, Endian target)
|
||||
{
|
||||
// Cannot operate on an unknown or invariant endianness
|
||||
if (source == Endian::None || target == Endian::None)
|
||||
return;
|
||||
|
||||
// Already in target order
|
||||
if (source == target)
|
||||
return;
|
||||
|
||||
swapBytes(value);
|
||||
}
|
||||
|
||||
template <typename T> void toHostEndianness(T& value, Endian source)
|
||||
{
|
||||
convertEndianness(value, source, hostEndianness());
|
||||
}
|
||||
|
||||
template <typename T> void fromHostEndianness(T& value, Endian target)
|
||||
{
|
||||
convertEndianness(value, hostEndianness(), target);
|
||||
}
|
||||
|
||||
template <typename T> void swapBytes(T& value)
|
||||
{
|
||||
static_assert(std::is_trivially_copyable<T>::value, "Type must be trivially copyable");
|
||||
|
||||
uint8_t* bytes = reinterpret_cast<uint8_t*>(&value);
|
||||
uint8_t temp;
|
||||
|
||||
for (std::size_t i = 0; i < sizeof(T) / 2; ++i)
|
||||
{
|
||||
temp = bytes[i];
|
||||
bytes[i] = bytes[sizeof(T) - 1 - i];
|
||||
bytes[sizeof(T) - 1 - i] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "acrux/memory/Endian.hpp"
|
||||
|
||||
namespace acrux::memory
|
||||
{
|
||||
Endian operator!(const Endian& endian)
|
||||
{
|
||||
switch (endian)
|
||||
{
|
||||
case Endian::Little:
|
||||
return Endian::Big;
|
||||
|
||||
case Endian::Big:
|
||||
return Endian::Little;
|
||||
|
||||
default:
|
||||
return Endian::None;
|
||||
}
|
||||
}
|
||||
|
||||
Endian hostEndianness()
|
||||
{
|
||||
const uint16_t number = 0x1;
|
||||
const uint8_t* firstByte = reinterpret_cast<const uint8_t*>(&number);
|
||||
return (*firstByte == 1) ? Endian::Little : Endian::Big;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user