#pragma once #include namespace nall { template struct array_span : array_view { using type = array_span; using super = array_view; inline array_span() { super::_data = nullptr; super::_size = 0; } inline array_span(nullptr_t) { super::_data = nullptr; super::_size = 0; } inline array_span(void* data, uint64_t size) { super::_data = (T*)data; super::_size = (int)size; } inline operator T*() { return (T*)super::operator const T*(); } inline auto operator[](uint index) -> T& { return (T&)super::operator[](index); } template inline auto data() -> U* { return (U*)super::_data; } inline auto begin() -> iterator { return {(T*)super::_data, (uint)0}; } inline auto end() -> iterator { return {(T*)super::_data, (uint)super::_size}; } inline auto rbegin() -> reverse_iterator { return {(T*)super::_data, (uint)super::_size - 1}; } inline auto rend() -> reverse_iterator { return {(T*)super::_data, (uint)-1}; } auto write(T value) -> void { operator[](0) = value; super::_data++; super::_size--; } auto span(uint offset, uint length) const -> type { #ifdef DEBUG struct out_of_bounds {}; if(offset + length >= super::_size) throw out_of_bounds{}; #endif return {super::_data + offset, length}; } //array_span specializations template auto writel(U value, uint size) -> void; template auto writem(U value, uint size) -> void; template auto writevn(U value, uint size) -> void; template auto writevi(U value, uint size) -> void; }; //array_span template<> inline auto array_span::write(uint8_t value) -> void { operator[](0) = value; _data++; _size--; } template<> template inline auto array_span::writel(U value, uint size) -> void { for(uint byte : range(size)) write(value >> byte * 8); } template<> template inline auto array_span::writem(U value, uint size) -> void { for(uint byte : reverse(range(size))) write(value >> byte * 8); } template<> template inline auto array_span::writevn(U value, uint size) -> void { while(true) { auto byte = value & 0x7f; value >>= 7; if(value == 0) return write(0x80 | byte); write(byte); value--; } } template<> template inline auto array_span::writevi(U value, uint size) -> void { bool negate = value < 0; if(negate) value = ~value; value = value << 1 | negate; writevn(value); } }