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_;
159template <std::size_t N>
161 : data_(sv.begin(), sv.end())
164template <std::size_t N>
166 return std::string_view{data_.data(), data_.size()};
169template <std::size_t N>
170SmallString<N>& SmallString<N>::
operator=(std::string_view sv) {
171 data_ = {sv.begin(), sv.end()};
175template <std::size_t N>
176bool operator==(
const SmallString<N>& str, std::string_view sv) {
177 return std::string_view{str} == sv;
180template <std::size_t N>
181bool operator==(std::string_view sv,
const SmallString<N>& str) {
182 return std::string_view{str} == sv;
185template <std::size_t N>
186bool operator==(
const SmallString<N>& str1,
const SmallString<N>& str2) {
187 return std::string_view{str1} == std::string_view{str2};
190template <std::size_t N>
191bool operator!=(
const SmallString<N>& str1,
const SmallString<N>& str2) {
192 return !(str1 == str2);
195template <std::size_t N>
196const char& SmallString<N>::
operator[](std::size_t pos)
const {
200template <std::size_t N>
205template <std::size_t N>
206const char& SmallString<N>::
at(std::size_t pos)
const {
208 throw std::out_of_range(
"at");
213template <std::size_t N>
214char& SmallString<N>::
at(std::size_t pos) {
216 throw std::out_of_range(
"at");
221template <std::size_t N>
222typename SmallString<N>::iterator SmallString<N>::begin()
noexcept {
223 return {data_.begin()};
226template <std::size_t N>
227typename SmallString<N>::const_iterator SmallString<N>::begin()
const noexcept {
228 return {data_.begin()};
231template <std::size_t N>
232typename SmallString<N>::iterator SmallString<N>::end()
noexcept {
233 return {data_.end()};
236template <std::size_t N>
237typename SmallString<N>::const_iterator SmallString<N>::end()
const noexcept {
238 return {data_.end()};
241template <std::size_t N>
242std::size_t SmallString<N>::
size()
const noexcept {
246template <std::size_t N>
247const char* SmallString<N>::
data()
const noexcept {
251template <std::size_t N>
252char* SmallString<N>::
data()
noexcept {
256template <std::size_t N>
257bool SmallString<N>::
empty()
const noexcept {
258 return data_.empty();
261template <std::size_t N>
263 return data_.front();
266template <std::size_t N>
267const char& SmallString<N>::
front()
const {
268 return data_.front();
271template <std::size_t N>
276template <std::size_t N>
277const char& SmallString<N>::
back()
const {
281template <std::size_t N>
286template <std::size_t N>
287void SmallString<N>::
append(std::string_view str) {
288 const std::size_t old_size = data_.size();
289 data_.insert(data_.begin() + old_size, str.begin(), str.end());
292template <std::size_t N>
293void SmallString<N>::
append(
const char* begin,
const char* end) {
294 append(std::string_view{begin,
static_cast<std::size_t>(end - begin)});
297template <std::size_t N>
298template <
class InputIt>
299void SmallString<N>::
insert(SmallString::const_iterator pos, InputIt begin, InputIt end) {
300 data_.insert(pos, begin, end);
303template <std::size_t N>
308template <std::size_t N>
309void SmallString<N>::
resize(std::size_t n,
char c) {
313template <std::size_t N>
314void SmallString<N>::
resize(std::size_t n) {
318template <std::size_t N>
319template <
class Operation>
321 data_.resize(size, boost::container::default_init);
322 data_.resize(std::move(op)(data_.data(), size), boost::container::default_init);
326template <std::size_t N>
328 data_.shrink_to_fit();
331template <std::size_t N>
332std::size_t SmallString<N>::
capacity()
const noexcept {
333 return data_.capacity();
336template <std::size_t N>
338 return data_.reserve(n);
341template <std::size_t N>
342void SmallString<N>::
clear()
noexcept {
350template <std::size_t N>
351struct std::hash<USERVER_NAMESPACE::utils::SmallString<N>> {
352 std::size_t operator()(
const USERVER_NAMESPACE::utils::SmallString<N>& s)
const noexcept {
353 return std::hash<std::string_view>{}(std::string_view{s});