userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
small_string.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/utils/small_string.hpp
4
/// @brief @copybrief utils::SmallString
5
6
#
include
<
cstddef
>
7
#
include
<
functional
>
8
#
include
<
stdexcept
>
9
#
include
<
string
>
10
11
#
include
<
boost
/
container
/
small_vector
.
hpp
>
12
13
#
include
<
userver
/
compiler
/
impl
/
lifetime
.
hpp
>
14
#
include
<
userver
/
utils
/
assert
.
hpp
>
15
16
USERVER_NAMESPACE_BEGIN
17
18
namespace
utils
{
19
20
/// @ingroup userver_universal userver_containers
21
///
22
/// @brief An alternative to std::string with a custom SSO (small string
23
/// optimization) container size. Unlike std::string, SmallString is not
24
/// null-terminated thus it has no c_str(), data() returns a not null-terminated
25
/// buffer.
26
template
<std::size_t N>
27
class
SmallString final {
28
using
Container = boost::container::small_vector<
char
, N>;
29
30
public
:
31
using
value_type =
char
;
32
33
/// @brief Create empty string.
34
SmallString
() =
default
;
35
36
/// @brief Create a string from another one.
37
SmallString
(
const
SmallString<N>&) =
default
;
38
39
/// @brief Create a string from another one.
40
explicit
SmallString
(SmallString<N>&&)
noexcept
=
default
;
41
42
/// @brief Create a string from std::string_view.
43
explicit
SmallString
(std::string_view sv);
44
45
/// @brief Assign the value of other string_view to this string.
46
SmallString&
operator
=(std::string_view sv);
47
48
/// @brief Assign the value of other string to this string.
49
SmallString&
operator
=(
const
SmallString&) =
default
;
50
51
/// @brief Assign the value of other string to this string.
52
SmallString&
operator
=(SmallString&&)
noexcept
=
default
;
53
54
SmallString& operator+=(std::string_view sv) {
55
append(sv);
56
return
*
this
;
57
}
58
59
SmallString& operator+=(
char
c) {
60
push_back
(
c
)
;
61
return
*
this
;
62
}
63
64
/// @brief Convert string to a std::string_view.
65
operator
std::string_view()
const
USERVER_IMPL_LIFETIME_BOUND;
66
67
/// @brief Read-only subscript access to the data contained in the string.
68
const
char
&
operator
[](std::size_t pos)
const
USERVER_IMPL_LIFETIME_BOUND;
69
70
/// @brief Subscript access to the data contained in the string.
71
char
&
operator
[](std::size_t pos) USERVER_IMPL_LIFETIME_BOUND;
72
73
/// @brief Provides access to the data contained in the string.
74
const
char
&
at
(std::size_t pos)
const
USERVER_IMPL_LIFETIME_BOUND;
75
76
/// @brief Provides access to the data contained in the string.
77
char
&
at
(std::size_t pos) USERVER_IMPL_LIFETIME_BOUND;
78
79
using
iterator =
typename
Container::iterator;
80
81
using
const_iterator =
typename
Container::const_iterator;
82
83
iterator begin()
noexcept
USERVER_IMPL_LIFETIME_BOUND;
84
const_iterator begin()
const
noexcept
USERVER_IMPL_LIFETIME_BOUND;
85
86
iterator end()
noexcept
USERVER_IMPL_LIFETIME_BOUND;
87
const_iterator end()
const
noexcept
USERVER_IMPL_LIFETIME_BOUND;
88
89
/// @brief Get string size.
90
std::size_t
size
()
const
noexcept
;
91
92
/// @brief Get pointer to data.
93
/// @warning The buffer is not null-terminated.
94
const
char
*
data
()
const
noexcept
USERVER_IMPL_LIFETIME_BOUND;
95
96
/// @brief Get pointer to data.
97
/// @warning The buffer is not null-terminated.
98
char
*
data
()
noexcept
USERVER_IMPL_LIFETIME_BOUND;
99
100
/// @brief Resize the string. If its length is increased,
101
/// fill new chars with %c.
102
void
resize
(std::size_t n,
char
c);
103
104
/// @brief Resize the string. If its length is increased,
105
/// fill new chars with \0.
106
void
resize
(std::size_t n);
107
108
/// @brief Resize the string. Use op to write into the string and replace a
109
/// sequence of characters
110
template
<
class
Operation>
111
void
resize_and_overwrite
(std::size_t size, Operation op);
112
113
/// @brief Shrink the string's size to fit all contents
114
void
shrink_to_fit
();
115
116
/// @brief Get current capacity.
117
std::size_t
capacity
()
const
noexcept
;
118
119
/// @brief Reserve to %n bytes.
120
void
reserve
(std::size_t n);
121
122
/// @brief Clear the string.
123
void
clear
()
noexcept
;
124
125
/// @brief Is the string empty?
126
bool
empty
()
const
noexcept
;
127
128
/// @brief Get a reference to the first character.
129
char
&
front
() USERVER_IMPL_LIFETIME_BOUND;
130
131
/// @brief Get a reference to the first character.
132
const
char
&
front
()
const
USERVER_IMPL_LIFETIME_BOUND;
133
134
/// @brief Get a reference to the last character.
135
char
&
back
() USERVER_IMPL_LIFETIME_BOUND;
136
137
/// @brief Get a reference to the last character.
138
const
char
&
back
()
const
USERVER_IMPL_LIFETIME_BOUND;
139
140
/// @brief Append a character to the string.
141
void
push_back
(
char
c);
142
143
/// @brief Append contents of a string_view to the string.
144
void
append
(std::string_view str);
145
146
/// @brief Append contents of a begin...end to the string.
147
void
append
(
const
char
* begin,
const
char
* end);
148
149
/// @brief Inserts elements from range [begin, end) before pos.
150
template
<
class
InputIt>
151
void
insert
(const_iterator pos, InputIt begin, InputIt end);
152
153
/// @brief Remove the last character from the string.
154
void
pop_back
();
155
156
private
:
157
boost::container::small_vector<
char
, N> data_;
158
};
159
160
template
<std::size_t N>
161
SmallString<N>::
SmallString
(std::string_view sv)
162
: data_(sv.begin(), sv.end())
163
{}
164
165
template
<std::size_t N>
166
SmallString
<
N
>::
operator
std::string_view()
const
USERVER_IMPL_LIFETIME_BOUND {
167
return
std::string_view{data_.data(), data_.size()};
168
}
169
170
template
<std::size_t N>
171
SmallString<N>& SmallString<N>::
operator
=(std::string_view sv) {
172
data_ = {sv.begin(), sv.end()};
173
return
*
this
;
174
}
175
176
template
<std::size_t N>
177
bool
operator==(
const
SmallString<N>& str, std::string_view sv) {
178
return
std::string_view{str} == sv;
179
}
180
181
template
<std::size_t N>
182
bool
operator==(std::string_view sv,
const
SmallString<N>& str) {
183
return
std::string_view{str} == sv;
184
}
185
186
template
<std::size_t N>
187
bool
operator==(
const
SmallString<N>& str1,
const
SmallString<N>& str2) {
188
return
std::string_view{str1} == std::string_view{str2};
189
}
190
191
template
<std::size_t N>
192
bool
operator!=(
const
SmallString<N>& str1,
const
SmallString<N>& str2) {
193
return
!(str1 == str2);
194
}
195
196
template
<std::size_t N>
197
const
char
&
SmallString
<
N
>::
operator
[](std::size_t pos)
const
USERVER_IMPL_LIFETIME_BOUND {
198
return
data_[pos];
199
}
200
201
template
<std::size_t N>
202
char
&
SmallString
<
N
>::
operator
[](std::size_t pos) USERVER_IMPL_LIFETIME_BOUND {
203
return
data_[pos];
204
}
205
206
template
<std::size_t N>
207
const
char
&
SmallString
<
N
>::
at
(std::size_t pos)
const
USERVER_IMPL_LIFETIME_BOUND {
208
if
(
size
(
)
<= pos) {
209
throw
std::out_of_range(
"at"
);
210
}
211
return
data_[pos];
212
}
213
214
template
<std::size_t N>
215
char
&
SmallString
<
N
>::
at
(std::size_t pos) USERVER_IMPL_LIFETIME_BOUND {
216
if
(
size
(
)
<= pos) {
217
throw
std::out_of_range(
"at"
);
218
}
219
return
data_[pos];
220
}
221
222
template
<std::size_t N>
223
typename
SmallString<N>::iterator SmallString<N>::begin()
noexcept
USERVER_IMPL_LIFETIME_BOUND {
224
return
{data_.begin()};
225
}
226
227
template
<std::size_t N>
228
typename
SmallString<N>::const_iterator SmallString<N>::begin()
const
noexcept
USERVER_IMPL_LIFETIME_BOUND {
229
return
{data_.begin()};
230
}
231
232
template
<std::size_t N>
233
typename
SmallString<N>::iterator SmallString<N>::end()
noexcept
USERVER_IMPL_LIFETIME_BOUND {
234
return
{data_.end()};
235
}
236
237
template
<std::size_t N>
238
typename
SmallString<N>::const_iterator SmallString<N>::end()
const
noexcept
USERVER_IMPL_LIFETIME_BOUND {
239
return
{data_.end()};
240
}
241
242
template
<std::size_t N>
243
std::size_t SmallString<N>::
size
()
const
noexcept
{
244
return
data_.size();
245
}
246
247
template
<std::size_t N>
248
const
char
* SmallString<N>::
data
()
const
noexcept
USERVER_IMPL_LIFETIME_BOUND {
249
return
data_.data();
250
}
251
252
template
<std::size_t N>
253
char
* SmallString<N>::
data
()
noexcept
USERVER_IMPL_LIFETIME_BOUND {
254
return
data_.data();
255
}
256
257
template
<std::size_t N>
258
bool
SmallString<N>::
empty
()
const
noexcept
{
259
return
data_.empty();
260
}
261
262
template
<std::size_t N>
263
char
& SmallString<N>::
front
() USERVER_IMPL_LIFETIME_BOUND {
264
return
data_.front();
265
}
266
267
template
<std::size_t N>
268
const
char
& SmallString<N>::
front
()
const
USERVER_IMPL_LIFETIME_BOUND {
269
return
data_.front();
270
}
271
272
template
<std::size_t N>
273
char
& SmallString<N>::
back
() USERVER_IMPL_LIFETIME_BOUND {
274
return
data_.back();
275
}
276
277
template
<std::size_t N>
278
const
char
& SmallString<N>::
back
()
const
USERVER_IMPL_LIFETIME_BOUND {
279
return
data_.back();
280
}
281
282
template
<std::size_t N>
283
void
SmallString<N>::
push_back
(
char
c) {
284
data_.push_back(c);
285
}
286
287
template
<std::size_t N>
288
void
SmallString<N>::
append
(std::string_view str) {
289
const
std::size_t old_size = data_.size();
290
data_.insert(data_.begin() + old_size, str.begin(), str.end());
291
}
292
293
template
<std::size_t N>
294
void
SmallString<N>::
append
(
const
char
* begin,
const
char
* end) {
295
append(std::string_view{begin,
static_cast
<std::size_t>(end - begin)});
296
}
297
298
template
<
std
::
size_t
N
>
299
template
<
class
InputIt>
300
void
SmallString<N>::
insert
(SmallString::const_iterator pos, InputIt begin, InputIt end) {
301
data_.insert(pos, begin, end);
302
}
303
304
template
<std::size_t N>
305
void
SmallString<N>::
pop_back
() {
306
data_.pop_back();
307
}
308
309
template
<std::size_t N>
310
void
SmallString<N>::
resize
(std::size_t n,
char
c) {
311
data_.resize(n, c);
312
}
313
314
template
<std::size_t N>
315
void
SmallString<N>::
resize
(std::size_t n) {
316
resize(n,
'\0'
);
317
}
318
319
template
<
std
::
size_t
N
>
320
template
<
class
Operation>
321
void
SmallString<N>::
resize_and_overwrite
(std::size_t size, Operation op) {
322
data_.resize(size, boost::container::default_init);
323
data_.resize(std::move(op)(data_.data(), size), boost::container::default_init);
324
UASSERT
(data_.size() <= size);
325
}
326
327
template
<std::size_t N>
328
void
SmallString<N>::
shrink_to_fit
() {
329
data_.shrink_to_fit();
330
}
331
332
template
<std::size_t N>
333
std::size_t SmallString<N>::
capacity
()
const
noexcept
{
334
return
data_.capacity();
335
}
336
337
template
<std::size_t N>
338
void
SmallString<N>::
reserve
(std::size_t n) {
339
return
data_.reserve(n);
340
}
341
342
template
<std::size_t N>
343
void
SmallString<N>::
clear
()
noexcept
{
344
data_.clear();
345
}
346
347
}
// namespace utils
348
349
USERVER_NAMESPACE_END
350
351
template
<std::size_t N>
352
struct
std
::
hash
<USERVER_NAMESPACE::
utils
::SmallString<N>> {
353
std::size_t operator()(
const
USERVER_NAMESPACE::
utils
::SmallString<N>& s)
const
noexcept
{
354
return
std::hash<std::string_view>{}(std::string_view{s});
355
}
356
};
userver
utils
small_string.hpp
Generated on
for userver by
Doxygen
1.17.0