Array.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/Functions.h>
  7. namespace anki
  8. {
  9. /// @addtogroup util_containers
  10. /// @{
  11. /// Like std::array but with some additions
  12. template<typename T, PtrSize N>
  13. class Array
  14. {
  15. public:
  16. using Value = T;
  17. using Iterator = Value*;
  18. using ConstIterator = const Value*;
  19. using Reference = Value&;
  20. using ConstReference = const Value&;
  21. // STL compatible
  22. using iterator = Iterator;
  23. using const_iterator = ConstIterator;
  24. using reference = Reference;
  25. using const_reference = ConstReference;
  26. Value m_data[N];
  27. /// Access an element using an integer.
  28. template<typename TInt, ANKI_ENABLE(!std::is_enum<TInt>::value)>
  29. Reference operator[](const TInt n)
  30. {
  31. ANKI_ASSERT(!(std::is_signed<TInt>::value && n < 0));
  32. ANKI_ASSERT(PtrSize(n) < N);
  33. return m_data[n];
  34. }
  35. /// Access an element using an integer.
  36. template<typename TInt, ANKI_ENABLE(!std::is_enum<TInt>::value)>
  37. ConstReference operator[](const TInt n) const
  38. {
  39. ANKI_ASSERT(!(std::is_signed<TInt>::value && n < 0));
  40. ANKI_ASSERT(PtrSize(n) < N);
  41. return m_data[n];
  42. }
  43. /// Access an element using an enumerant. It's a little bit special and separate from operator[] that accepts
  44. /// integer. This to avoid any short of arbitrary integer type casting.
  45. template<typename TEnum, ANKI_ENABLE(std::is_enum<TEnum>::value)>
  46. Reference operator[](const TEnum n)
  47. {
  48. return operator[](typename std::underlying_type<TEnum>::type(n));
  49. }
  50. /// Access an element using an enumerant. It's a little bit special and separate from operator[] that accepts
  51. /// integer. This to avoid any short of arbitrary integer type casting.
  52. template<typename TEnum, ANKI_ENABLE(std::is_enum<TEnum>::value)>
  53. ConstReference operator[](const TEnum n) const
  54. {
  55. return operator[](typename std::underlying_type<TEnum>::type(n));
  56. }
  57. Iterator getBegin()
  58. {
  59. return &m_data[0];
  60. }
  61. ConstIterator getBegin() const
  62. {
  63. return &m_data[0];
  64. }
  65. Iterator getEnd()
  66. {
  67. return &m_data[0] + N;
  68. }
  69. ConstIterator getEnd() const
  70. {
  71. return &m_data[0] + N;
  72. }
  73. Reference getFront()
  74. {
  75. return m_data[0];
  76. }
  77. ConstReference getFront() const
  78. {
  79. return m_data[0];
  80. }
  81. Reference getBack()
  82. {
  83. return m_data[N - 1];
  84. }
  85. ConstReference getBack() const
  86. {
  87. return m_data[N - 1];
  88. }
  89. /// Make it compatible with the C++11 range based for loop
  90. Iterator begin()
  91. {
  92. return getBegin();
  93. }
  94. /// Make it compatible with the C++11 range based for loop
  95. ConstIterator begin() const
  96. {
  97. return getBegin();
  98. }
  99. /// Make it compatible with the C++11 range based for loop
  100. Iterator end()
  101. {
  102. return getEnd();
  103. }
  104. /// Make it compatible with the C++11 range based for loop
  105. ConstIterator end() const
  106. {
  107. return getEnd();
  108. }
  109. /// Make it compatible with STL
  110. Reference front()
  111. {
  112. return getFront();
  113. }
  114. /// Make it compatible with STL
  115. ConstReference front() const
  116. {
  117. return getFront();
  118. }
  119. /// Make it compatible with STL
  120. Reference back()
  121. {
  122. return getBack;
  123. }
  124. /// Make it compatible with STL
  125. ConstReference back() const
  126. {
  127. return getBack();
  128. }
  129. // Get size
  130. #define ANKI_ARRAY_SIZE_METHOD(type, condition) \
  131. ANKI_ENABLE_METHOD(condition) \
  132. static constexpr type getSize() \
  133. { \
  134. return type(N); \
  135. }
  136. ANKI_ARRAY_SIZE_METHOD(U8, N <= MAX_U8)
  137. ANKI_ARRAY_SIZE_METHOD(U16, N > MAX_U8 && N <= MAX_U16)
  138. ANKI_ARRAY_SIZE_METHOD(U32, N > MAX_U16 && N <= MAX_U32)
  139. ANKI_ARRAY_SIZE_METHOD(U64, N > MAX_U32)
  140. #undef ANKI_ARRAY_SIZE_METHOD
  141. /// Make it compatible with STL
  142. static constexpr size_t size()
  143. {
  144. return N;
  145. }
  146. // Get size in bytes
  147. #define ANKI_ARRAY_SIZE_IN_BYTES_METHOD(type, condition) \
  148. ANKI_ENABLE_METHOD(condition) \
  149. static constexpr type getSizeInBytes() \
  150. { \
  151. return type(N * sizeof(Value)); \
  152. }
  153. ANKI_ARRAY_SIZE_IN_BYTES_METHOD(U8, N * sizeof(Value) <= MAX_U8)
  154. ANKI_ARRAY_SIZE_IN_BYTES_METHOD(U16, N * sizeof(Value) > MAX_U8 && N * sizeof(Value) <= MAX_U16)
  155. ANKI_ARRAY_SIZE_IN_BYTES_METHOD(U32, N * sizeof(Value) > MAX_U16 && N * sizeof(Value) <= MAX_U32)
  156. ANKI_ARRAY_SIZE_IN_BYTES_METHOD(U64, N * sizeof(Value) > MAX_U32)
  157. #undef ANKI_ARRAY_SIZE_IN_BYTES_METHOD
  158. };
  159. /// 2D Array. @code Array2d<X, 10, 2> a; @endcode is equivelent to @code X a[10][2]; @endcode
  160. template<typename T, PtrSize I, PtrSize J>
  161. using Array2d = Array<Array<T, J>, I>;
  162. /// 3D Array. @code Array3d<X, 10, 2, 3> a; @endcode is equivelent to @code X a[10][2][3]; @endcode
  163. template<typename T, PtrSize I, PtrSize J, PtrSize K>
  164. using Array3d = Array<Array<Array<T, K>, J>, I>;
  165. /// 4D Array. @code Array4d<X, 10, 2, 3, 4> a; @endcode is equivelent to @code X a[10][2][3][4]; @endcode
  166. template<typename T, PtrSize I, PtrSize J, PtrSize K, PtrSize L>
  167. using Array4d = Array<Array<Array<Array<T, L>, K>, J>, I>;
  168. /// 5D Array. @code Array5d<X, 10, 2, 3, 4, 5> a; @endcode is equivelent to @code X a[10][2][3][4][5]; @endcode
  169. template<typename T, PtrSize I, PtrSize J, PtrSize K, PtrSize L, PtrSize M>
  170. using Array5d = Array<Array<Array<Array<Array<T, M>, L>, K>, J>, I>;
  171. /// @}
  172. } // end namespace anki