11#include <boost/container/small_vector.hpp>
13#include <userver/utils/assert.hpp>
15USERVER_NAMESPACE_BEGIN
25template <std::size_t N>
26class SmallString final {
27 using Container = boost::container::small_vector<
char, N>;
30 using value_type =
char;
48 SmallString&
operator=(
const SmallString&) =
default;
51 SmallString&
operator=(SmallString&&)
noexcept =
default;
53 SmallString& operator+=(std::string_view sv) {
58 SmallString& operator+=(
char c) {
73 const char&
at(std::size_t pos)
const;
76 char&
at(std::size_t pos);
78 using iterator =
typename Container::iterator;
80 using const_iterator =
typename Container::const_iterator;
82 iterator begin()
noexcept;
83 const_iterator begin()
const noexcept;
85 iterator end()
noexcept;
86 const_iterator end()
const noexcept;
89 std::size_t
size()
const noexcept;
93 const char*
data()
const noexcept;
109 template <
class Operation>
146 void append(
const char* begin,
const char* end);
149 template <
class InputIt>
150 void insert(const_iterator pos, InputIt begin, InputIt end);
156 boost::container::small_vector<
char, N> data_;
26class SmallString final {
…};
159template <std::size_t N>
160SmallString<N>::
SmallString(std::string_view sv) : data_(sv.begin(), sv.end()) {}
162template <std::size_t N>
164 return std::string_view{data_.data(), data_.size()};
167template <std::size_t N>
168SmallString<N>& SmallString<N>::
operator=(std::string_view sv) {
169 data_ = {sv.begin(), sv.end()};
168SmallString<N>& SmallString<N>::
operator=(std::string_view sv) {
…}
173template <std::size_t N>
174bool operator==(
const SmallString<N>& str, std::string_view sv) {
175 return std::string_view{str} == sv;
178template <std::size_t N>
179bool operator==(std::string_view sv,
const SmallString<N>& str) {
180 return std::string_view{str} == sv;
183template <std::size_t N>
184bool operator==(
const SmallString<N>& str1,
const SmallString<N>& str2) {
185 return std::string_view{str1} == std::string_view{str2};
188template <std::size_t N>
189bool operator!=(
const SmallString<N>& str1,
const SmallString<N>& str2) {
190 return !(str1 == str2);
193template <std::size_t N>
194const char& SmallString<N>::
operator[](std::size_t pos)
const {
194const char& SmallString<N>::
operator[](std::size_t pos)
const {
…}
198template <std::size_t N>
203template <std::size_t N>
204const char& SmallString<N>::
at(std::size_t pos)
const {
205 if (
size() <= pos)
throw std::out_of_range(
"at");
204const char& SmallString<N>::
at(std::size_t pos)
const {
…}
209template <std::size_t N>
210char& SmallString<N>::
at(std::size_t pos) {
211 if (
size() <= pos)
throw std::out_of_range(
"at");
210char& SmallString<N>::
at(std::size_t pos) {
…}
215template <std::size_t N>
216typename SmallString<N>::iterator SmallString<N>::begin()
noexcept {
217 return {data_.begin()};
220template <std::size_t N>
221typename SmallString<N>::const_iterator SmallString<N>::begin()
const noexcept {
222 return {data_.begin()};
225template <std::size_t N>
226typename SmallString<N>::iterator SmallString<N>::end()
noexcept {
227 return {data_.end()};
230template <std::size_t N>
231typename SmallString<N>::const_iterator SmallString<N>::end()
const noexcept {
232 return {data_.end()};
235template <std::size_t N>
236std::size_t SmallString<N>::
size()
const noexcept {
236std::size_t SmallString<N>::
size()
const noexcept {
…}
240template <std::size_t N>
241const char* SmallString<N>::
data()
const noexcept {
241const char* SmallString<N>::
data()
const noexcept {
…}
245template <std::size_t N>
246char* SmallString<N>::
data()
noexcept {
246char* SmallString<N>::
data()
noexcept {
…}
250template <std::size_t N>
251bool SmallString<N>::
empty()
const noexcept {
252 return data_.empty();
251bool SmallString<N>::
empty()
const noexcept {
…}
255template <std::size_t N>
257 return data_.front();
260template <std::size_t N>
261const char& SmallString<N>::
front()
const {
262 return data_.front();
261const char& SmallString<N>::
front()
const {
…}
265template <std::size_t N>
270template <std::size_t N>
271const char& SmallString<N>::
back()
const {
271const char& SmallString<N>::
back()
const {
…}
275template <std::size_t N>
280template <std::size_t N>
281void SmallString<N>::
append(std::string_view str) {
282 std::size_t old_size = data_.size();
283 data_.insert(data_.begin() + old_size, str.begin(), str.end());
281void SmallString<N>::
append(std::string_view str) {
…}
286template <std::size_t N>
287void SmallString<N>::
append(
const char* begin,
const char* end) {
288 append(std::string_view{begin,
static_cast<std::size_t>(end - begin)});
287void SmallString<N>::
append(
const char* begin,
const char* end) {
…}
292template <
class InputIt>
293void SmallString<N>::
insert(SmallString::const_iterator pos, InputIt begin, InputIt end) {
294 data_.insert(pos, begin, end);
293void SmallString<N>::
insert(SmallString::const_iterator pos, InputIt begin, InputIt end) {
…}
297template <std::size_t N>
302template <std::size_t N>
303void SmallString<N>::
resize(std::size_t n,
char c) {
303void SmallString<N>::
resize(std::size_t n,
char c) {
…}
307template <std::size_t N>
308void SmallString<N>::
resize(std::size_t n) {
313template <
class Operation>
315 data_.resize(size, boost::container::default_init);
316 data_.resize(std::move(op)(data_.data(), size), boost::container::default_init);
320template <std::size_t N>
322 data_.shrink_to_fit();
325template <std::size_t N>
326std::size_t SmallString<N>::
capacity()
const noexcept {
327 return data_.capacity();
326std::size_t SmallString<N>::
capacity()
const noexcept {
…}
330template <std::size_t N>
332 return data_.reserve(n);
335template <std::size_t N>
336void SmallString<N>::
clear()
noexcept {
344template <std::size_t N>
345struct std::hash<USERVER_NAMESPACE::
utils::SmallString<N>> {
346 std::size_t operator()(
const USERVER_NAMESPACE::
utils::SmallString<N>& s)
const noexcept {
347 return std::hash<std::string_view>{}(std::string_view{s});
345struct std::hash<USERVER_NAMESPACE::
utils::SmallString<N>> {
…};