Array.h 5.0 KB

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