diff options
| author | Stefan Boberg <[email protected]> | 2021-05-24 13:16:46 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-05-24 13:16:46 +0200 |
| commit | 4d5daa5ab598d0389890894cb713ddb4b366c3ca (patch) | |
| tree | 8fa3c0bd6027a105d06b1fa1a803a28fd508846c /zencore/include | |
| parent | Added RefPtr::IsNull() (diff) | |
| download | zen-4d5daa5ab598d0389890894cb713ddb4b366c3ca.tar.xz zen-4d5daa5ab598d0389890894cb713ddb4b366c3ca.zip | |
Added some functionality to support CompositeBuffer implementation
Diffstat (limited to 'zencore/include')
| -rw-r--r-- | zencore/include/zencore/memory.h | 146 |
1 files changed, 138 insertions, 8 deletions
diff --git a/zencore/include/zencore/memory.h b/zencore/include/zencore/memory.h index 5851ed137..1c681872b 100644 --- a/zencore/include/zencore/memory.h +++ b/zencore/include/zencore/memory.h @@ -8,10 +8,13 @@ #include <zencore/thread.h> #include <algorithm> +#include <span> #include <vector> namespace zen { +struct MemoryView; + class MemoryArena { public: @@ -81,8 +84,25 @@ struct MutableMemoryView return Size == InView.GetSize() && (memcmp(m_Data, InView.m_Data, Size) == 0); } + /** Modifies the view to be the given number of bytes from the right. */ + inline void RightInline(uint64_t InSize) + { + const uint64_t OldSize = GetSize(); + const uint64_t NewSize = zen::Min(OldSize, InSize); + m_Data = GetDataAtOffsetNoCheck(OldSize - NewSize); + m_DataEnd = m_Data + NewSize; + } + + /** Returns the right-most part of the view by taking the given number of bytes from the right. */ + [[nodiscard]] inline MutableMemoryView Right(uint64_t InSize) const + { + MutableMemoryView View(*this); + View.RightChopInline(InSize); + return View; + } + /** Modifies the view by chopping the given number of bytes from the left. */ - inline void RightChopInline(uint64_t InSize) + inline constexpr void RightChopInline(uint64_t InSize) { const uint64_t Offset = zen::Min(GetSize(), InSize); m_Data = GetDataAtOffsetNoCheck(Offset); @@ -99,12 +119,29 @@ struct MutableMemoryView /** Modifies the view to be the given number of bytes from the left. */ constexpr inline void LeftInline(uint64_t InSize) { m_DataEnd = std::min(m_DataEnd, m_Data + InSize); } + /** Returns the right-most part of the view by chopping the given number of bytes from the left. */ + [[nodiscard]] inline MutableMemoryView RightChop(uint64_t InSize) const + { + MutableMemoryView View(*this); + View.RightChopInline(InSize); + return View; + } + + inline constexpr MutableMemoryView& operator+=(size_t InSize) + { + RightChopInline(InSize); + return *this; + } + + /** Copies bytes from the input view into this view, and returns the remainder of this view. */ + inline MutableMemoryView CopyFrom(MemoryView InView) const; + private: uint8_t* m_Data = nullptr; uint8_t* m_DataEnd = nullptr; /** Returns the data pointer advanced by an offset in bytes. */ - inline uint8_t* GetDataAtOffsetNoCheck(uint64_t InOffset) const { return m_Data + InOffset; } + inline constexpr uint8_t* GetDataAtOffsetNoCheck(uint64_t InOffset) const { return m_Data + InOffset; } }; struct MemoryView @@ -143,14 +180,14 @@ struct MemoryView return Size == InView.GetSize() && (memcmp(m_Data, InView.GetData(), Size) == 0); } - inline MemoryView& operator+=(size_t InSize) + inline constexpr MemoryView& operator+=(size_t InSize) { RightChopInline(InSize); return *this; } /** Modifies the view by chopping the given number of bytes from the left. */ - inline void RightChopInline(uint64_t InSize) + inline constexpr void RightChopInline(uint64_t InSize) { const uint64_t Offset = std::min(GetSize(), InSize); m_Data = GetDataAtOffsetNoCheck(Offset); @@ -163,6 +200,23 @@ struct MemoryView return View; } + /** Returns the right-most part of the view by taking the given number of bytes from the right. */ + [[nodiscard]] inline MemoryView Right(uint64_t InSize) const + { + MemoryView View(*this); + View.RightInline(InSize); + return View; + } + + /** Modifies the view to be the given number of bytes from the right. */ + inline void RightInline(uint64_t InSize) + { + const uint64_t OldSize = GetSize(); + const uint64_t NewSize = zen::Min(OldSize, InSize); + m_Data = GetDataAtOffsetNoCheck(OldSize - NewSize); + m_DataEnd = m_Data + NewSize; + } + /** Returns the left-most part of the view by taking the given number of bytes from the left. */ constexpr inline MemoryView Left(uint64_t InSize) const { @@ -172,7 +226,26 @@ struct MemoryView } /** Modifies the view to be the given number of bytes from the left. */ - constexpr inline void LeftInline(uint64_t InSize) { m_DataEnd = std::min(m_DataEnd, m_Data + InSize); } + constexpr inline void LeftInline(uint64_t InSize) + { + InSize = zen::Min(GetSize(), InSize); + m_DataEnd = std::min(m_DataEnd, m_Data + InSize); + } + + /** Modifies the view to be the middle part by taking up to the given number of bytes from the given offset. */ + inline void MidInline(uint64_t InOffset, uint64_t InSize = ~uint64_t(0)) + { + RightChopInline(InOffset); + LeftInline(InSize); + } + + /** Returns the middle part of the view by taking up to the given number of bytes from the given position. */ + [[nodiscard]] inline MemoryView Mid(uint64_t InOffset, uint64_t InSize = ~uint64_t(0)) const + { + MemoryView View(*this); + View.MidInline(InOffset, InSize); + return View; + } constexpr void Reset() { @@ -185,9 +258,45 @@ private: const uint8_t* m_DataEnd = nullptr; /** Returns the data pointer advanced by an offset in bytes. */ - inline const uint8_t* GetDataAtOffsetNoCheck(uint64_t InOffset) const { return m_Data + InOffset; } + inline constexpr const uint8_t* GetDataAtOffsetNoCheck(uint64_t InOffset) const { return m_Data + InOffset; } }; +inline MutableMemoryView +MutableMemoryView::CopyFrom(MemoryView InView) const +{ + ZEN_ASSERT(InView.GetSize() <= GetSize()); + memcpy(m_Data, InView.GetData(), InView.GetSize()); + return RightChop(InView.GetSize()); +} + +/** Advances the start of the view by an offset, which is clamped to stay within the view. */ +constexpr inline MemoryView +operator+(const MemoryView& View, uint64_t Offset) +{ + return MemoryView(View) += Offset; +} + +/** Advances the start of the view by an offset, which is clamped to stay within the view. */ +constexpr inline MemoryView +operator+(uint64_t Offset, const MemoryView& View) +{ + return MemoryView(View) += Offset; +} + +/** Advances the start of the view by an offset, which is clamped to stay within the view. */ +constexpr inline MutableMemoryView +operator+(const MutableMemoryView& View, uint64_t Offset) +{ + return MutableMemoryView(View) += Offset; +} + +/** Advances the start of the view by an offset, which is clamped to stay within the view. */ +constexpr inline MutableMemoryView +operator+(uint64_t Offset, const MutableMemoryView& View) +{ + return MutableMemoryView(View) += Offset; +} + /** * Make a non-owning view of the memory of the initializer list. * @@ -205,8 +314,29 @@ template<std::ranges::contiguous_range R> [[nodiscard]] constexpr inline MemoryView MakeMemoryView(const R& Container) { - const auto& Front = *std::begin(Container); - return MemoryView(std::addressof(Front), std::size(Container) * sizeof(Front)); + std::span Span = Container; + return MemoryView(Span.data(), Span.size() * sizeof(decltype(Span)::element_type)); +} + +/** + * Make a non-owning view of the memory of the initializer list. + * + * This overload is only available when the element type does not need to be deduced. + */ +template<typename T> +[[nodiscard]] inline MutableMemoryView +MakeMutableMemoryView(std::initializer_list<typename std::type_identity<T>::type> List) +{ + return MutableMemoryView(List.begin(), List.size() * sizeof(T)); +} + +/** Make a non-owning view of the memory of the contiguous container. */ +template<std::ranges::contiguous_range R> +[[nodiscard]] constexpr inline MutableMemoryView +MakeMutableMemoryView(R& Container) +{ + std::span Span = Container; + return MutableMemoryView(Span.data(), Span.size() * sizeof(decltype(Span)::element_type)); } void memory_forcelink(); // internal |