userver: userver/utils/small_string.hpp Source File
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
13USERVER_NAMESPACE_BEGIN
14
15namespace utils {
16
17/// @ingroup userver_universal userver_containers
18///
19/// @brief An alternative to std::string with a custom SSO (small string
20/// optimization) container size. Unlike std::string, SmallString is not
21/// null-terminated thus it has no c_str(), data() returns a not null-terminated
22/// buffer.
23template <std::size_t N>
24class SmallString final {
25 using Container = boost::container::small_vector<char, N>;
26
27 public:
28 /// @brief Create empty string.
29 SmallString() = default;
30
31 /// @brief Create a string from another one.
32 explicit SmallString(const SmallString<N>&) = default;
33
34 /// @brief Create a string from another one.
35 explicit SmallString(SmallString<N>&&) noexcept = default;
36
37 /// @brief Create a string from std::string_view.
38 explicit SmallString(std::string_view sv);
39
40 /// @brief Assign the value of other string_view to this string.
41 SmallString& operator=(std::string_view sv);
42
43 /// @brief Assign the value of other string to this string.
44 SmallString& operator=(const SmallString&) = default;
45
46 /// @brief Assign the value of other string to this string.
47 SmallString& operator=(SmallString&&) noexcept = default;
48
49 /// @brief Convert string to a std::string_view.
50 operator std::string_view() const;
51
52 /// @brief Read-only subscript access to the data contained in the string.
53 const char& operator[](std::size_t pos) const;
54
55 /// @brief Subscript access to the data contained in the string.
56 char& operator[](std::size_t pos);
57
58 /// @brief Provides access to the data contained in the string.
59 const char& at(std::size_t pos) const;
60
61 /// @brief Provides access to the data contained in the string.
62 char& at(std::size_t pos);
63
64 using iterator = typename Container::iterator;
65
66 using const_iterator = typename Container::const_iterator;
67
68 iterator begin() noexcept;
69 const_iterator begin() const noexcept;
70
71 iterator end() noexcept;
72 const_iterator end() const noexcept;
73
74 /// @brief Get string size.
75 std::size_t size() const noexcept;
76
77 /// @brief Get pointer to data.
78 /// @warning The buffer is not null-terminated.
79 const char* data() const noexcept;
80
81 /// @brief Get pointer to data.
82 /// @warning The buffer is not null-terminated.
83 char* data() noexcept;
84
85 /// @brief Resize the string. If its length is increased,
86 /// fill new chars with %c.
87 void resize(std::size_t n, char c);
88
89 /// @brief Get current capacity.
90 std::size_t capacity() const noexcept;
91
92 /// @brief Reserve to %n bytes.
93 void reserve(std::size_t n);
94
95 /// @brief Clear the string.
96 void clear() noexcept;
97
98 /// @brief Is the string empty?
99 bool empty() const noexcept;
100
101 /// @brief Get a reference to the first character.
102 char& front();
103
104 /// @brief Get a reference to the first character.
105 const char& front() const;
106
107 /// @brief Get a reference to the last character.
108 char& back();
109
110 /// @brief Get a reference to the last character.
111 const char& back() const;
112
113 /// @brief Append a character to the string.
114 void push_back(char c);
115
116 /// @brief Remove the last character from the string.
117 void pop_back();
118
119 private:
120 boost::container::small_vector<char, N> data_;
121};
122
123template <std::size_t N>
124SmallString<N>::SmallString(std::string_view sv)
125 : data_(sv.begin(), sv.end()) {}
126
127template <std::size_t N>
129 return std::string_view{data_.data(), data_.size()};
130}
131
132template <std::size_t N>
134 data_ = {sv.begin(), sv.end()};
135 return *this;
136}
137
138template <std::size_t N>
139bool operator==(const SmallString<N>& str, std::string_view sv) {
140 return std::string_view{str} == sv;
141}
142
143template <std::size_t N>
144bool operator==(std::string_view sv, const SmallString<N>& str) {
145 return std::string_view{str} == sv;
146}
147
148template <std::size_t N>
149bool operator==(const SmallString<N>& str1, const SmallString<N>& str2) {
150 return std::string_view{str1} == std::string_view{str2};
151}
152
153template <std::size_t N>
154bool operator!=(const SmallString<N>& str1, const SmallString<N>& str2) {
155 return !(str1 == str2);
156}
157
158template <std::size_t N>
159const char& SmallString<N>::operator[](std::size_t pos) const {
160 return data_[pos];
161}
162
163template <std::size_t N>
165 return data_[pos];
166}
167
168template <std::size_t N>
169const char& SmallString<N>::at(std::size_t pos) const {
170 if (size() <= pos) throw std::out_of_range("at");
171 return data_[pos];
172}
173
174template <std::size_t N>
176 if (size() <= pos) throw std::out_of_range("at");
177 return data_[pos];
178}
179
180template <std::size_t N>
181typename SmallString<N>::iterator SmallString<N>::begin() noexcept {
182 return {data_.begin()};
183}
184
185template <std::size_t N>
186typename SmallString<N>::const_iterator SmallString<N>::begin() const noexcept {
187 return {data_.begin()};
188}
189
190template <std::size_t N>
191typename SmallString<N>::iterator SmallString<N>::end() noexcept {
192 return {data_.end()};
193}
194
195template <std::size_t N>
196typename SmallString<N>::const_iterator SmallString<N>::end() const noexcept {
197 return {data_.end()};
198}
199
200template <std::size_t N>
201std::size_t SmallString<N>::size() const noexcept {
202 return data_.size();
203}
204
205template <std::size_t N>
206const char* SmallString<N>::data() const noexcept {
207 return data_.data();
208}
209
210template <std::size_t N>
211char* SmallString<N>::data() noexcept {
212 return data_.data();
213}
214
215template <std::size_t N>
216bool SmallString<N>::empty() const noexcept {
217 return data_.empty();
218}
219
220template <std::size_t N>
221char& SmallString<N>::front() {
222 return data_.front();
223}
224
225template <std::size_t N>
226const char& SmallString<N>::front() const {
227 return data_.front();
228}
229
230template <std::size_t N>
231char& SmallString<N>::back() {
232 return data_.back();
233}
234
235template <std::size_t N>
236const char& SmallString<N>::back() const {
237 return data_.back();
238}
239
240template <std::size_t N>
241void SmallString<N>::push_back(char c) {
243}
244
245template <std::size_t N>
247 data_.pop_back();
248}
249
250template <std::size_t N>
251void SmallString<N>::resize(std::size_t n, char c) {
252 data_.resize(n, c);
253}
254
255template <std::size_t N>
256std::size_t SmallString<N>::capacity() const noexcept {
257 return data_.capacity();
258}
259
260template <std::size_t N>
262 return data_.reserve(n);
263}
264
265} // namespace utils
266
267USERVER_NAMESPACE_END
268
269template <std::size_t N>
270struct std::hash<USERVER_NAMESPACE::utils::SmallString<N>> {
271 std::size_t operator()(
272 const USERVER_NAMESPACE::utils::SmallString<N>& s) const noexcept {
273 return std::hash<std::string_view>{}(std::string_view{s});
274 }
275};