row_view.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //
  2. // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_ROW_VIEW_HPP
  8. #define BOOST_MYSQL_ROW_VIEW_HPP
  9. #include <boost/mysql/field.hpp>
  10. #include <boost/mysql/field_view.hpp>
  11. #include <boost/mysql/detail/access.hpp>
  12. #include <boost/throw_exception.hpp>
  13. #include <cstddef>
  14. #include <stdexcept>
  15. #include <vector>
  16. namespace boost {
  17. namespace mysql {
  18. /**
  19. * \brief A non-owning read-only reference to a sequence of fields.
  20. * \details
  21. * A `row_view` points to memory owned by an external entity (like `string_view` does). The validity
  22. * of a `row_view` depends on how it was obtained:
  23. * \n
  24. * \li If it was constructed from a \ref row object (by calling \ref row::operator row_view()), the
  25. * view acts as a reference to the row's allocated memory, and is valid as long as references
  26. * to that row elements are valid.
  27. * \li If it was obtained by indexing a \ref rows object, the same applies.
  28. * \li If it was obtained by indexing a \ref rows_view object, it's valid as long as the
  29. * `rows_view` is valid.
  30. * \n
  31. * Calling any member function on an invalid view results in undefined behavior.
  32. * \n
  33. * When indexed (by using iterators, \ref row_view::at or \ref row_view::operator[]), it returns
  34. * \ref field_view elements that are valid as long as the underlying storage that `*this` points
  35. * to is valid. Destroying a `row_view` doesn't invalidate `field_view`s obtained from
  36. * it.
  37. * \n Instances of this class are usually created by the library, not by the user.
  38. */
  39. class row_view
  40. {
  41. public:
  42. /**
  43. * \brief Constructs an empty (but valid) view.
  44. * \par Exception safety
  45. * No-throw guarantee.
  46. */
  47. row_view() = default;
  48. #ifdef BOOST_MYSQL_DOXYGEN
  49. /**
  50. * \brief A random access iterator to an element.
  51. * \details The exact type of the iterator is unspecified.
  52. */
  53. using iterator = __see_below__;
  54. #else
  55. using iterator = const field_view*;
  56. #endif
  57. /// \copydoc iterator
  58. using const_iterator = iterator;
  59. /// A type that can hold elements in this collection with value semantics.
  60. using value_type = field;
  61. /// The reference type.
  62. using reference = field_view;
  63. /// \copydoc reference
  64. using const_reference = field_view;
  65. /// An unsigned integer type to represent sizes.
  66. using size_type = std::size_t;
  67. /// A signed integer type used to represent differences.
  68. using difference_type = std::ptrdiff_t;
  69. /**
  70. * \brief Returns an iterator to the first field in the row.
  71. * \par Exception safety
  72. * No-throw guarantee.
  73. *
  74. * \par Complexity
  75. * Constant.
  76. */
  77. iterator begin() const noexcept { return fields_; }
  78. /**
  79. * \brief Returns an iterator to one-past-the-last field in the row.
  80. * \par Exception safety
  81. * No-throw guarantee.
  82. *
  83. * \par Complexity
  84. * Constant.
  85. */
  86. iterator end() const noexcept { return fields_ + size_; }
  87. /**
  88. * \brief Returns the i-th element in the row or throws an exception.
  89. * \par Exception safety
  90. * Strong guranatee. Throws on invalid input.
  91. * \throws std::out_of_range `i >= this->size()`
  92. *
  93. * \par Complexity
  94. * Constant.
  95. */
  96. field_view at(std::size_t i) const
  97. {
  98. if (i >= size_)
  99. BOOST_THROW_EXCEPTION(std::out_of_range("row_view::at"));
  100. return fields_[i];
  101. }
  102. /**
  103. * \brief Returns the i-th element in the row (unchecked access).
  104. * \par Preconditions
  105. * `i < this->size()`
  106. *
  107. * \par Exception safety
  108. * No-throw guarantee.
  109. *
  110. * \par Complexity
  111. * Constant.
  112. */
  113. field_view operator[](std::size_t i) const noexcept { return fields_[i]; }
  114. /**
  115. * \brief Returns the first element in the row.
  116. * \par Preconditions
  117. * `this->size() > 0`
  118. *
  119. * \par Exception safety
  120. * No-throw guarantee.
  121. *
  122. * \par Complexity
  123. * Constant.
  124. */
  125. field_view front() const noexcept { return *fields_; }
  126. /**
  127. * \brief Returns the last element in the row.
  128. * \par Preconditions
  129. * `this->size() > 0`
  130. *
  131. * \par Exception safety
  132. * No-throw guarantee.
  133. *
  134. * \par Complexity
  135. * Constant.
  136. */
  137. field_view back() const noexcept { return fields_[size_ - 1]; }
  138. /**
  139. * \brief Returns true if there are no fields in the row (i.e. `this->size() == 0`).
  140. * \par Exception safety
  141. * No-throw guarantee.
  142. *
  143. * \par Complexity
  144. * Constant.
  145. */
  146. bool empty() const noexcept { return size_ == 0; }
  147. /**
  148. * \brief Returns the number of fields in the row.
  149. * \par Exception safety
  150. * No-throw guarantee.
  151. *
  152. * \par Complexity
  153. * Constant.
  154. */
  155. std::size_t size() const noexcept { return size_; }
  156. /**
  157. * \brief Converts the row into a `std::vector` of \ref field's.
  158. * \details As \ref row objects are read-only, you can use this function if you need to mutate
  159. * fields in a row.
  160. *
  161. * \par Exception safety
  162. * Basic guarantee. Allocations may throw.
  163. *
  164. * \par Complexity
  165. * Linear in `this->size()`.
  166. */
  167. template <class Allocator>
  168. void as_vector(std::vector<field, Allocator>& out) const
  169. {
  170. out.assign(begin(), end());
  171. }
  172. /// \copydoc as_vector
  173. std::vector<field> as_vector() const { return std::vector<field>(begin(), end()); }
  174. #ifndef BOOST_MYSQL_DOXYGEN
  175. // Required by iterators
  176. const row_view* operator->() const noexcept { return this; }
  177. #endif
  178. private:
  179. row_view(const field_view* f, std::size_t size) noexcept : fields_(f), size_(size) {}
  180. const field_view* fields_{};
  181. std::size_t size_{};
  182. #ifndef BOOST_MYSQL_DOXYGEN
  183. friend struct detail::access;
  184. friend class row;
  185. #endif
  186. };
  187. /**
  188. * \relates row_view
  189. * \brief Equality operator.
  190. * \details The containers are considered equal if they have the same number of elements and they
  191. * all compare equal, as defined by \ref field_view::operator==.
  192. *
  193. * \par Exception safety
  194. * No-throw guarantee.
  195. *
  196. * \par Complexity
  197. * Linear in `lhs.size()` and `rhs.size()`.
  198. */
  199. inline bool operator==(const row_view& lhs, const row_view& rhs) noexcept
  200. {
  201. if (lhs.size() != rhs.size())
  202. return false;
  203. for (std::size_t i = 0; i < lhs.size(); ++i)
  204. {
  205. if (lhs[i] != rhs[i])
  206. return false;
  207. }
  208. return true;
  209. }
  210. /**
  211. * \relates row_view
  212. * \brief Inequality operator.
  213. *
  214. * \par Exception safety
  215. * No-throw guarantee.
  216. *
  217. * \par Complexity
  218. * Linear in `lhs.size()` and `rhs.size()`.
  219. */
  220. inline bool operator!=(const row_view& lhs, const row_view& rhs) noexcept { return !(lhs == rhs); }
  221. } // namespace mysql
  222. } // namespace boost
  223. #endif