]> git.proxmox.com Git - ceph.git/blame - ceph/src/Beast/include/beast/core/static_string.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / Beast / include / beast / core / static_string.hpp
CommitLineData
7c673cae
FG
1//
2// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8#ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP
9#define BEAST_WEBSOCKET_STATIC_STRING_HPP
10
11#include <beast/config.hpp>
12#include <beast/core/detail/type_traits.hpp>
13#include <array>
14#include <cstdint>
15#include <iterator>
16#include <stdexcept>
17#include <string>
18
19namespace beast {
20
21/** A string with a fixed-size storage area.
22
23 These objects behave like `std::string` except that the storage
24 is not dynamically allocated but rather fixed in size.
25
26 These strings offer performance advantages when a protocol
27 imposes a natural small upper limit on the size of a value.
28
29 @note The stored string is always null-terminated.
30*/
31template<
32 std::size_t N,
33 class CharT = char,
34 class Traits = std::char_traits<CharT>>
35class static_string
36{
37 template<std::size_t, class, class>
38 friend class static_string;
39
40 std::size_t n_;
41 std::array<CharT, N+1> s_;
42
43public:
44 using traits_type = Traits;
45 using value_type = typename Traits::char_type;
46 using size_type = std::size_t;
47 using difference_type = std::ptrdiff_t;
48 using pointer = value_type*;
49 using reference = value_type&;
50 using const_pointer = value_type const*;
51 using const_reference = value_type const&;
52 using iterator = value_type*;
53 using const_iterator = value_type const*;
54 using reverse_iterator =
55 std::reverse_iterator<iterator>;
56 using const_reverse_iterator =
57 std::reverse_iterator<const_iterator>;
58
59 /** Default constructor.
60
61 The string is initially empty, and null terminated.
62 */
63 static_string();
64
65 /// Copy constructor.
66 static_string(static_string const& s);
67
68 /// Copy constructor.
69 template<std::size_t M>
70 static_string(static_string<M, CharT, Traits> const& s);
71
72 /// Copy assignment.
73 static_string&
74 operator=(static_string const& s);
75
76 /// Copy assignment.
77 template<std::size_t M>
78 static_string&
79 operator=(static_string<M, CharT, Traits> const& s);
80
81 /// Construct from string literal.
82 template<std::size_t M>
83 static_string(const CharT (&s)[M]);
84
85 /// Assign from string literal.
86 template<std::size_t M>
87 static_string& operator=(const CharT (&s)[M]);
88
89 /// Access specified character with bounds checking.
90 reference
91 at(size_type pos);
92
93 /// Access specified character with bounds checking.
94 const_reference
95 at(size_type pos) const;
96
97 /// Access specified character.
98 reference
99 operator[](size_type pos)
100 {
101 return s_[pos];
102 }
103
104 /// Access specified character.
105 const_reference
106 operator[](size_type pos) const
107 {
108 return s_[pos];
109 }
110
111 /// Accesses the first character.
112 CharT&
113 front()
114 {
115 return s_[0];
116 }
117
118 /// Accesses the first character.
119 CharT const&
120 front() const
121 {
122 return s_[0];
123 }
124
125 /// Accesses the last character.
126 CharT&
127 back()
128 {
129 return s_[n_-1];
130 }
131
132 /// Accesses the last character.
133 CharT const&
134 back() const
135 {
136 return s_[n_-1];
137 }
138
139 /// Returns a pointer to the first character of a string.
140 CharT*
141 data()
142 {
143 return &s_[0];
144 }
145
146 /// Returns a pointer to the first character of a string.
147 CharT const*
148 data() const
149 {
150 return &s_[0];
151 }
152
153 /// Returns a non-modifiable standard C character array version of the string.
154 CharT const*
155 c_str() const
156 {
157 return &s_[0];
158 }
159
160 /// Returns an iterator to the beginning.
161 iterator
162 begin()
163 {
164 return &s_[0];
165 }
166
167 /// Returns an iterator to the beginning.
168 const_iterator
169 begin() const
170 {
171 return &s_[0];
172 }
173
174 /// Returns an iterator to the beginning.
175 const_iterator
176 cbegin() const
177 {
178 return &s_[0];
179 }
180
181 /// Returns an iterator to the end.
182 iterator
183 end()
184 {
185 return &s_[n_];
186 }
187
188 /// Returns an iterator to the end.
189 const_iterator
190 end() const
191 {
192 return &s_[n_];
193 }
194
195 /// Returns an iterator to the end.
196 const_iterator
197 cend() const
198 {
199 return &s_[n_];
200 }
201
202 /// Returns a reverse iterator to the beginning.
203 reverse_iterator
204 rbegin()
205 {
206 return reverse_iterator{end()};
207 }
208
209 /// Returns a reverse iterator to the beginning.
210 const_reverse_iterator
211 rbegin() const
212 {
213 return const_reverse_iterator{cend()};
214 }
215
216 /// Returns a reverse iterator to the beginning.
217 const_reverse_iterator
218 crbegin() const
219 {
220 return const_reverse_iterator{cend()};
221 }
222
223 /// Returns a reverse iterator to the end.
224 reverse_iterator
225 rend()
226 {
227 return reverse_iterator{begin()};
228 }
229
230 /// Returns a reverse iterator to the end.
231 const_reverse_iterator
232 rend() const
233 {
234 return const_reverse_iterator{cbegin()};
235 }
236
237 /// Returns a reverse iterator to the end.
238 const_reverse_iterator
239 crend() const
240 {
241 return const_reverse_iterator{cbegin()};
242 }
243
244 /// Returns `true` if the string is empty.
245 bool
246 empty() const
247 {
248 return n_ == 0;
249 }
250
251 /// Returns the number of characters, excluding the null terminator.
252 size_type
253 size() const
254 {
255 return n_;
256 }
257
258 /// Returns the maximum number of characters that can be stored, excluding the null terminator.
259 size_type constexpr
260 max_size() const
261 {
262 return N;
263 }
264
265 /// Returns the number of characters that can be held in currently allocated storage.
266 size_type
267 capacity() const
268 {
269 return N;
270 }
271
272 /// Clears the contents.
273 void
274 clear()
275 {
276 resize(0);
277 }
278
279 /** Changes the number of characters stored.
280
281 @note No value-initialization is performed.
282 */
283 void
284 resize(std::size_t n);
285
286 /** Changes the number of characters stored.
287
288 If the resulting string is larger, the new
289 characters are initialized to the value of `c`.
290 */
291 void
292 resize(std::size_t n, CharT c);
293
294 /// Compare two character sequences.
295 template<std::size_t M>
296 int
297 compare(static_string<M, CharT, Traits> const& rhs) const;
298
299 /// Return the characters as a `basic_string`.
300 std::basic_string<CharT, Traits>
301 to_string() const
302 {
303 return std::basic_string<
304 CharT, Traits>{&s_[0], n_};
305 }
306
307private:
308 void
309 assign(CharT const* s);
310};
311
312template<std::size_t N, class CharT, class Traits>
313static_string<N, CharT, Traits>::
314static_string()
315 : n_(0)
316{
317 s_[0] = 0;
318}
319
320template<std::size_t N, class CharT, class Traits>
321static_string<N, CharT, Traits>::
322static_string(static_string const& s)
323 : n_(s.n_)
324{
325 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
326}
327
328template<std::size_t N, class CharT, class Traits>
329template<std::size_t M>
330static_string<N, CharT, Traits>::
331static_string(static_string<M, CharT, Traits> const& s)
332{
333 if(s.size() > N)
334 throw detail::make_exception<std::length_error>(
335 "static_string overflow", __FILE__, __LINE__);
336 n_ = s.size();
337 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
338}
339
340template<std::size_t N, class CharT, class Traits>
341auto
342static_string<N, CharT, Traits>::
343operator=(static_string const& s) ->
344 static_string&
345{
346 n_ = s.n_;
347 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
348 return *this;
349}
350
351template<std::size_t N, class CharT, class Traits>
352template<std::size_t M>
353auto
354static_string<N, CharT, Traits>::
355operator=(static_string<M, CharT, Traits> const& s) ->
356 static_string&
357{
358 if(s.size() > N)
359 throw detail::make_exception<std::length_error>(
360 "static_string overflow", __FILE__, __LINE__);
361 n_ = s.size();
362 Traits::copy(&s_[0], &s.s_[0], n_ + 1);
363 return *this;
364}
365
366template<std::size_t N, class CharT, class Traits>
367template<std::size_t M>
368static_string<N, CharT, Traits>::
369static_string(const CharT (&s)[M])
370 : n_(M-1)
371{
372 static_assert(M-1 <= N,
373 "static_string overflow");
374 Traits::copy(&s_[0], &s[0], M);
375}
376
377template<std::size_t N, class CharT, class Traits>
378template<std::size_t M>
379auto
380static_string<N, CharT, Traits>::
381operator=(const CharT (&s)[M]) ->
382 static_string&
383{
384 static_assert(M-1 <= N,
385 "static_string overflow");
386 n_ = M-1;
387 Traits::copy(&s_[0], &s[0], M);
388 return *this;
389}
390
391template<std::size_t N, class CharT, class Traits>
392auto
393static_string<N, CharT, Traits>::
394at(size_type pos) ->
395 reference
396{
397 if(pos >= n_)
398 throw detail::make_exception<std::out_of_range>(
399 "invalid pos", __FILE__, __LINE__);
400 return s_[pos];
401}
402
403template<std::size_t N, class CharT, class Traits>
404auto
405static_string<N, CharT, Traits>::
406at(size_type pos) const ->
407 const_reference
408{
409 if(pos >= n_)
410 throw detail::make_exception<std::out_of_range>(
411 "static_string::at", __FILE__, __LINE__);
412 return s_[pos];
413}
414
415template<std::size_t N, class CharT, class Traits>
416void
417static_string<N, CharT, Traits>::
418resize(std::size_t n)
419{
420 if(n > N)
421 throw detail::make_exception<std::length_error>(
422 "static_string overflow", __FILE__, __LINE__);
423 n_ = n;
424 s_[n_] = 0;
425}
426
427template<std::size_t N, class CharT, class Traits>
428void
429static_string<N, CharT, Traits>::
430resize(std::size_t n, CharT c)
431{
432 if(n > N)
433 throw detail::make_exception<std::length_error>(
434 "static_string overflow", __FILE__, __LINE__);
435 if(n > n_)
436 Traits::assign(&s_[n_], n - n_, c);
437 n_ = n;
438 s_[n_] = 0;
439}
440
441template<std::size_t N, class CharT, class Traits>
442template<std::size_t M>
443int
444static_string<N, CharT, Traits>::
445compare(static_string<M, CharT, Traits> const& rhs) const
446{
447 if(size() < rhs.size())
448 {
449 auto const v = Traits::compare(
450 data(), rhs.data(), size());
451 if(v == 0)
452 return -1;
453 return v;
454 }
455 else if(size() > rhs.size())
456 {
457 auto const v = Traits::compare(
458 data(), rhs.data(), rhs.size());
459 if(v == 0)
460 return 1;
461 return v;
462 }
463 return Traits::compare(data(), rhs.data(), size());
464}
465
466template<std::size_t N, class CharT, class Traits>
467void
468static_string<N, CharT, Traits>::
469assign(CharT const* s)
470{
471 auto const n = Traits::length(s);
472 if(n > N)
473 throw detail::make_exception<std::out_of_range>(
474 "too large", __FILE__, __LINE__);
475 n_ = n;
476 Traits::copy(&s_[0], s, n_ + 1);
477}
478
479namespace detail {
480
481template<std::size_t N, std::size_t M, class CharT, class Traits>
482int
483compare(
484 static_string<N, CharT, Traits> const& lhs,
485 const CharT (&s)[M])
486{
487 if(lhs.size() < M-1)
488 {
489 auto const v = Traits::compare(
490 lhs.data(), &s[0], lhs.size());
491 if(v == 0)
492 return -1;
493 return v;
494 }
495 else if(lhs.size() > M-1)
496 {
497 auto const v = Traits::compare(
498 lhs.data(), &s[0], M-1);
499 if(v == 0)
500 return 1;
501 return v;
502 }
503 return Traits::compare(lhs.data(), &s[0], lhs.size());
504}
505
506template<std::size_t N, std::size_t M, class CharT, class Traits>
507inline
508int
509compare(
510 const CharT (&s)[M],
511 static_string<N, CharT, Traits> const& rhs)
512{
513 return -compare(rhs, s);
514}
515
516} // detail
517
518template<std::size_t N, std::size_t M, class CharT, class Traits>
519bool
520operator==(
521 static_string<N, CharT, Traits> const& lhs,
522 static_string<M, CharT, Traits> const& rhs)
523{
524 return lhs.compare(rhs) == 0;
525}
526
527template<std::size_t N, std::size_t M, class CharT, class Traits>
528bool
529operator!=(
530 static_string<N, CharT, Traits> const& lhs,
531 static_string<M, CharT, Traits> const& rhs)
532{
533 return lhs.compare(rhs) != 0;
534}
535
536template<std::size_t N, std::size_t M, class CharT, class Traits>
537bool
538operator<(
539 static_string<N, CharT, Traits> const& lhs,
540 static_string<M, CharT, Traits> const& rhs)
541{
542 return lhs.compare(rhs) < 0;
543}
544
545template<std::size_t N, std::size_t M, class CharT, class Traits>
546bool
547operator<=(
548 static_string<N, CharT, Traits> const& lhs,
549 static_string<M, CharT, Traits> const& rhs)
550{
551 return lhs.compare(rhs) <= 0;
552}
553
554template<std::size_t N, std::size_t M, class CharT, class Traits>
555bool
556operator>(
557 static_string<N, CharT, Traits> const& lhs,
558 static_string<M, CharT, Traits> const& rhs)
559{
560 return lhs.compare(rhs) > 0;
561}
562
563template<std::size_t N, std::size_t M, class CharT, class Traits>
564bool
565operator>=(
566 static_string<N, CharT, Traits> const& lhs,
567 static_string<M, CharT, Traits> const& rhs)
568{
569 return lhs.compare(rhs) >= 0;
570}
571
572//---
573
574template<std::size_t N, std::size_t M, class CharT, class Traits>
575bool
576operator==(
577 const CharT (&s)[N],
578 static_string<M, CharT, Traits> const& rhs)
579{
580 return detail::compare(s, rhs) == 0;
581}
582
583template<std::size_t N, class CharT, class Traits, std::size_t M>
584bool
585operator==(
586 static_string<N, CharT, Traits> const& lhs,
587 const CharT (&s)[M])
588{
589 return detail::compare(lhs, s) == 0;
590}
591
592template<std::size_t N, std::size_t M, class CharT, class Traits>
593bool
594operator!=(
595 const CharT (&s)[N],
596 static_string<M, CharT, Traits> const& rhs)
597{
598 return detail::compare(s, rhs) != 0;
599}
600
601template<std::size_t N, class CharT, class Traits, std::size_t M>
602bool
603operator!=(
604 static_string<N, CharT, Traits> const& lhs,
605 const CharT (&s)[M])
606{
607 return detail::compare(lhs, s) != 0;
608}
609
610template<std::size_t N, std::size_t M, class CharT, class Traits>
611bool
612operator<(
613 const CharT (&s)[N],
614 static_string<M, CharT, Traits> const& rhs)
615{
616 return detail::compare(s, rhs) < 0;
617}
618
619template<std::size_t N, class CharT, class Traits, std::size_t M>
620bool
621operator<(
622 static_string<N, CharT, Traits> const& lhs,
623 const CharT (&s)[M])
624{
625 return detail::compare(lhs, s) < 0;
626}
627
628template<std::size_t N, std::size_t M, class CharT, class Traits>
629bool
630operator<=(
631 const CharT (&s)[N],
632 static_string<M, CharT, Traits> const& rhs)
633{
634 return detail::compare(s, rhs) <= 0;
635}
636
637template<std::size_t N, class CharT, class Traits, std::size_t M>
638bool
639operator<=(
640 static_string<N, CharT, Traits> const& lhs,
641 const CharT (&s)[M])
642{
643 return detail::compare(lhs, s) <= 0;
644}
645
646template<std::size_t N, std::size_t M, class CharT, class Traits>
647bool
648operator>(
649 const CharT (&s)[N],
650 static_string<M, CharT, Traits> const& rhs)
651{
652 return detail::compare(s, rhs) > 0;
653}
654
655template<std::size_t N, class CharT, class Traits, std::size_t M>
656bool
657operator>(
658 static_string<N, CharT, Traits> const& lhs,
659 const CharT (&s)[M])
660{
661 return detail::compare(lhs, s) > 0;
662}
663
664template<std::size_t N, std::size_t M, class CharT, class Traits>
665bool
666operator>=(
667 const CharT (&s)[N],
668 static_string<M, CharT, Traits> const& rhs)
669{
670 return detail::compare(s, rhs) >= 0;
671}
672
673template<std::size_t N, class CharT, class Traits, std::size_t M>
674bool
675operator>=(
676 static_string<N, CharT, Traits> const& lhs,
677 const CharT (&s)[M])
678{
679 return detail::compare(lhs, s) >= 0;
680}
681
682} // beast
683
684#endif