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