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)
 |