85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #pragma once
 | |
| 
 | |
| #if !defined(MIJIN_CONTAINER_MEMORY_VIEW_HPP_INCLUDED)
 | |
| #define MIJIN_CONTAINER_MEMORY_VIEW_HPP_INCLUDED 1
 | |
| 
 | |
| #include <bit>
 | |
| #include <cstddef>
 | |
| #include <span>
 | |
| #include "../debug/assert.hpp"
 | |
| #include "../util/traits.hpp"
 | |
| 
 | |
| namespace mijin
 | |
| {
 | |
| 
 | |
| //
 | |
| // public defines
 | |
| //
 | |
| 
 | |
| //
 | |
| // public constants
 | |
| //
 | |
| 
 | |
| //
 | |
| // public types
 | |
| //
 | |
| 
 | |
| template<typename TBytes>
 | |
| class MemoryViewBase
 | |
| {
 | |
| public:
 | |
|     using size_type = std::size_t;
 | |
| private:
 | |
|     std::span<TBytes> bytes_;
 | |
| public:
 | |
|     MemoryViewBase() noexcept = default;
 | |
|     MemoryViewBase(const MemoryViewBase&) noexcept = default;
 | |
|     MemoryViewBase(copy_const_t<TBytes, void>* data, std::size_t size) noexcept : bytes_(static_cast<TBytes*>(data), size) {}
 | |
| 
 | |
|     MemoryViewBase& operator=(const MemoryViewBase&) noexcept = default;
 | |
|     
 | |
|     [[nodiscard]] void* data() noexcept { return bytes_.data(); }
 | |
|     [[nodiscard]] const void* data() const noexcept { return bytes_.data(); }
 | |
|     [[nodiscard]] size_type byteSize() const noexcept { return bytes_.size(); }
 | |
|     [[nodiscard]] bool empty() const noexcept { return bytes_.empty(); }
 | |
| 
 | |
|     template<typename T>
 | |
|     [[nodiscard]] std::span<T> makeSpan();
 | |
| 
 | |
|     template<typename T>
 | |
|     [[nodiscard]] std::span<const T> makeSpan() const;
 | |
| };
 | |
| using MemoryView = MemoryViewBase<std::byte>;
 | |
| using ConstMemoryView = MemoryViewBase<const std::byte>;
 | |
| 
 | |
| //
 | |
| // public functions
 | |
| //
 | |
| 
 | |
| template<typename TBytes>
 | |
| template<typename T>
 | |
| std::span<T> MemoryViewBase<TBytes>::makeSpan()
 | |
| {
 | |
|     static_assert(!std::is_const_v<TBytes>, "Cannot create writable spans from const memory views.");
 | |
|     MIJIN_ASSERT(bytes_.size() % sizeof(T) == 0, "MemoryView cannot be divided into elements of this type.");
 | |
|     return {
 | |
|         std::bit_cast<T*>(bytes_.data()),
 | |
|         std::bit_cast<T*>(bytes_.data() + bytes_.size())
 | |
|     };
 | |
| }
 | |
| 
 | |
| template<typename TBytes>
 | |
| template<typename T>
 | |
| std::span<const T> MemoryViewBase<TBytes>::makeSpan() const
 | |
| {
 | |
|     MIJIN_ASSERT(bytes_.size() % sizeof(T) == 0, "MemoryView cannot be divided into elements of this type.");
 | |
|     return {
 | |
|         std::bit_cast<const T*>(bytes_.data()),
 | |
|         std::bit_cast<const T*>(bytes_.data() + bytes_.size())
 | |
|     };
 | |
| }
 | |
| } // namespace mijin
 | |
| 
 | |
| #endif // !defined(MIJIN_CONTAINER_MEMORY_VIEW_HPP_INCLUDED)
 |