Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

237 lignes
8.1 KiB

  1. /*!
  2. * \file utl/container/id.h
  3. * \brief A container for device IDs
  4. *
  5. * Copyright (C) 2018 Christos Choutouridis
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation, either version 3
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. */
  21. #ifndef __utl_container_id_h__
  22. #define __utl_container_id_h__
  23. #include <utl/impl/impl.h>
  24. #include <utl/container/array.h>
  25. #include <algorithm>
  26. namespace utl {
  27. /*!
  28. * \ingroup containers
  29. * \brief
  30. * id container traits helper
  31. */
  32. //! @{
  33. template <typename _Tp, size_t _Nm>
  34. struct id_traits {
  35. typedef _Tp type[_Nm];
  36. static constexpr _Tp& Ref (const type& t, size_t n) noexcept {
  37. return const_cast<_Tp&> (t[n]);
  38. }
  39. static constexpr _Tp* Ptr(const type& t) noexcept {
  40. return const_cast<_Tp*> (t);
  41. }
  42. };
  43. template <typename _Tp>
  44. struct id_traits<_Tp, 0> {
  45. struct type { };
  46. static constexpr _Tp& Ref(const type& t, size_t n) noexcept {
  47. return *static_cast<_Tp*>(nullptr);
  48. }
  49. static constexpr _Tp* Ptr(const type& t) noexcept {
  50. return nullptr;
  51. }
  52. };
  53. //! @{
  54. /*!
  55. * \ingroup containers
  56. * \brief
  57. * A standard container for storing IDs as a fixed size
  58. * sequence of bytes. This type is based on etl::array
  59. * Meets the requirements of:
  60. * <a href="tables.html#65">container</a>,
  61. * <a href="tables.html#66">reversible container</a>,
  62. * <a href="tables.html#67">sequence</a>.
  63. * Sets support random access iterators.
  64. * \tparam _Tp The base type
  65. * \tparam _Nm Number of bytes.
  66. */
  67. template <typename _Tp, size_t _Nm>
  68. struct id_t {
  69. using value_type = _Tp;
  70. using pointer = value_type*;
  71. using const_pointer = const value_type*;
  72. using reference = value_type&;
  73. using const_reference = const value_type&;
  74. using iterator = value_type*;
  75. using const_iterator = const value_type*;
  76. using size_type = size_t;
  77. using difference_type = std::ptrdiff_t;
  78. using reverse_iterator = std::reverse_iterator <iterator>;
  79. using const_reverse_iterator
  80. = std::reverse_iterator <const_iterator>;
  81. // type and data
  82. using traits_t = id_traits<_Tp, _Nm>;
  83. typename traits_t::type _data;
  84. // No explicit construct/copy/destroy for aggregate type.
  85. // DR 776 (std::array)
  86. void fill (const value_type& v) { std::fill_n (begin(), size(), v); }
  87. void swap (id_t& other) noexcept {
  88. std::swap_ranges (begin(), end(), other.begin());
  89. }
  90. //! \name Iterators.
  91. //!@{
  92. iterator begin() noexcept { return iterator (data()); }
  93. const_iterator begin() const noexcept { return const_iterator (data()); }
  94. iterator end() noexcept { return iterator (data() + _Nm); }
  95. const_iterator end() const noexcept { return const_iterator (data() + _Nm); }
  96. const_iterator cbegin() const noexcept { return const_iterator (data()); }
  97. const_iterator cend() const noexcept { return const_iterator (data() + _Nm); }
  98. reverse_iterator rbegin() noexcept { return reverse_iterator (end()); }
  99. reverse_iterator rend() noexcept { return reverse_iterator (begin()); }
  100. const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator (end()); }
  101. const_reverse_iterator rend() const noexcept { return const_reverse_iterator (begin()); }
  102. const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator (end()); }
  103. const_reverse_iterator crend() const noexcept { return const_reverse_iterator (begin()); }
  104. //!@{
  105. //! \name Capacity.
  106. //!@{
  107. constexpr size_type size() const noexcept { return _Nm; }
  108. constexpr size_type max_size() const noexcept { return _Nm; }
  109. constexpr bool empty() const noexcept { return size() == 0; }
  110. //!@{
  111. //! \name Element access.
  112. //!@{
  113. //! Operator []
  114. reference operator[] (size_type n) noexcept {
  115. return traits_t::Ref (_data, n);
  116. }
  117. //! Operator [] for const
  118. constexpr const_reference operator[] (size_type n) const noexcept {
  119. return traits_t::Ref (_data, n);
  120. }
  121. /*!
  122. * Boundary check dereference operator.
  123. * If out of bounds, abort (for now).
  124. */
  125. reference at (size_type n) noexcept {
  126. if (n < _Nm)
  127. return traits_t::Ref (_data, n);
  128. else
  129. abort ();
  130. }
  131. //! Compile time boundary check dereference operator.
  132. constexpr const_reference at (size_type n) const noexcept {
  133. static_assert ((n < _Nm), "id_t::at: out of range");
  134. return traits_t::Ref (_data, n);
  135. }
  136. /*!
  137. * Read a bit position from a id
  138. * \param bit The bit location we want to read
  139. */
  140. constexpr bool bit (uint8_t bit) const noexcept {
  141. value_type one = 1;
  142. uint8_t den = 8*sizeof(_Tp)/sizeof(uint8_t);
  143. return traits_t::Ref (_data, bit/den) & (one << ((bit % den)-1));
  144. }
  145. /*!
  146. * Write/modify a bit position from a id
  147. * \param bit The bit location we want to set
  148. * \param v The value we want to set
  149. */
  150. void bit (uint8_t bit, bool v) noexcept {
  151. value_type one = 1;
  152. uint8_t den = 8*sizeof(_Tp)/sizeof(uint8_t);
  153. if (v) traits_t::Ref (_data, bit/den) |= one << ((bit % den)-1);
  154. else traits_t::Ref (_data, bit/den) &= ~one << ((bit % den)-1);
  155. }
  156. // first item
  157. reference front () noexcept {
  158. return *begin ();
  159. }
  160. constexpr const_reference front () const noexcept {
  161. return traits_t::Ref (_data, 0);
  162. }
  163. // Last item
  164. reference back () noexcept {
  165. return _Nm ? *(end() - 1) : *end();
  166. }
  167. constexpr const_reference back () const noexcept {
  168. return _Nm ? traits_t::Ref (_data, _Nm - 1)
  169. : traits_t::Ref (_data, 0);
  170. }
  171. // Pointer to data
  172. pointer data () noexcept { return traits_t::Ptr (_data); }
  173. const_pointer data () const noexcept { return traits_t::Ptr (_data); }
  174. //!<@}
  175. };
  176. //! \name device ID comparisons.
  177. //!@{
  178. template <typename _Tp, size_t _Nm>
  179. inline bool operator== (const id_t<_Tp, _Nm>& lhs, const id_t<_Tp, _Nm>& rhs) {
  180. return std::equal (lhs.begin(), lhs.end(), rhs.begin());
  181. }
  182. template <typename _Tp, size_t _Nm>
  183. inline bool operator!= (const id_t<_Tp, _Nm>& lhs, const id_t<_Tp, _Nm>& rhs) {
  184. return !(lhs == rhs);
  185. }
  186. template <typename _Tp, size_t _Nm>
  187. inline bool operator< (const id_t<_Tp, _Nm>& lhs, const id_t<_Tp, _Nm>& rhs) {
  188. // MSB plays bigger role in comparison
  189. return std::lexicographical_compare(lhs.rbegin(), lhs.rend(), rhs.rbegin(), rhs.rend());
  190. }
  191. template <typename _Tp, size_t _Nm>
  192. inline bool operator> (const id_t<_Tp, _Nm>& lhs, const id_t<_Tp, _Nm>& rhs) {
  193. return rhs < lhs;
  194. }
  195. template <typename _Tp, size_t _Nm>
  196. inline bool operator<= (const id_t<_Tp, _Nm>& lhs, const id_t<_Tp, _Nm>& rhs) {
  197. return !(lhs > rhs);
  198. }
  199. template <typename _Tp, size_t _Nm>
  200. inline bool operator>= (const id_t<_Tp, _Nm>& lhs, const id_t<_Tp, _Nm>& rhs) {
  201. return !(lhs < rhs);
  202. }
  203. //!@}
  204. } // namespace utl
  205. #endif /* __utl_container_id_h__ */