array-span.hpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #pragma once
  2. #include <nall/array-view.hpp>
  3. namespace nall {
  4. template<typename T> struct array_span : array_view<T> {
  5. using type = array_span;
  6. using super = array_view<T>;
  7. inline array_span() {
  8. super::_data = nullptr;
  9. super::_size = 0;
  10. }
  11. inline array_span(nullptr_t) {
  12. super::_data = nullptr;
  13. super::_size = 0;
  14. }
  15. inline array_span(void* data, uint64_t size) {
  16. super::_data = (T*)data;
  17. super::_size = (int)size;
  18. }
  19. inline operator T*() { return (T*)super::operator const T*(); }
  20. inline auto operator[](uint index) -> T& { return (T&)super::operator[](index); }
  21. template<typename U = T> inline auto data() -> U* { return (U*)super::_data; }
  22. inline auto begin() -> iterator<T> { return {(T*)super::_data, (uint)0}; }
  23. inline auto end() -> iterator<T> { return {(T*)super::_data, (uint)super::_size}; }
  24. inline auto rbegin() -> reverse_iterator<T> { return {(T*)super::_data, (uint)super::_size - 1}; }
  25. inline auto rend() -> reverse_iterator<T> { return {(T*)super::_data, (uint)-1}; }
  26. auto write(T value) -> void {
  27. operator[](0) = value;
  28. super::_data++;
  29. super::_size--;
  30. }
  31. auto span(uint offset, uint length) const -> type {
  32. #ifdef DEBUG
  33. struct out_of_bounds {};
  34. if(offset + length >= super::_size) throw out_of_bounds{};
  35. #endif
  36. return {super::_data + offset, length};
  37. }
  38. //array_span<uint8_t> specializations
  39. template<typename U> auto writel(U value, uint size) -> void;
  40. template<typename U> auto writem(U value, uint size) -> void;
  41. template<typename U> auto writevn(U value, uint size) -> void;
  42. template<typename U> auto writevi(U value, uint size) -> void;
  43. };
  44. //array_span<uint8_t>
  45. template<> inline auto array_span<uint8_t>::write(uint8_t value) -> void {
  46. operator[](0) = value;
  47. _data++;
  48. _size--;
  49. }
  50. template<> template<typename U> inline auto array_span<uint8_t>::writel(U value, uint size) -> void {
  51. for(uint byte : range(size)) write(value >> byte * 8);
  52. }
  53. template<> template<typename U> inline auto array_span<uint8_t>::writem(U value, uint size) -> void {
  54. for(uint byte : reverse(range(size))) write(value >> byte * 8);
  55. }
  56. template<> template<typename U> inline auto array_span<uint8_t>::writevn(U value, uint size) -> void {
  57. while(true) {
  58. auto byte = value & 0x7f;
  59. value >>= 7;
  60. if(value == 0) return write(0x80 | byte);
  61. write(byte);
  62. value--;
  63. }
  64. }
  65. template<> template<typename U> inline auto array_span<uint8_t>::writevi(U value, uint size) -> void {
  66. bool negate = value < 0;
  67. if(negate) value = ~value;
  68. value = value << 1 | negate;
  69. writevn(value);
  70. }
  71. }