userver: userver/utils/small_string.hpp Source File
⚠️ This is the documentation for an old userver version. Click here to switch to the latest version.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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};