static_string.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. //
  2. // Copyright (c) 2016-2019 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. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_STATIC_STRING_HPP
  10. #define BOOST_BEAST_STATIC_STRING_HPP
  11. #include <boost/beast/core/detail/config.hpp>
  12. #include <boost/beast/core/string.hpp>
  13. #include <boost/beast/core/detail/static_string.hpp>
  14. #include <algorithm>
  15. #include <cstdint>
  16. #include <initializer_list>
  17. #include <iosfwd>
  18. #include <stdexcept>
  19. #include <string>
  20. #include <type_traits>
  21. namespace boost {
  22. namespace beast {
  23. /** A modifiable string with a fixed-size storage area.
  24. These objects behave like `std::string` except that the storage
  25. is not dynamically allocated but rather fixed in size.
  26. These strings offer performance advantages when a protocol
  27. imposes a natural small upper limit on the size of a value.
  28. @note The stored string is always null-terminated.
  29. @see to_static_string
  30. */
  31. template<
  32. std::size_t N,
  33. class CharT = char,
  34. class Traits = std::char_traits<CharT>>
  35. class static_string
  36. {
  37. template<std::size_t, class, class>
  38. friend class static_string;
  39. void
  40. term()
  41. {
  42. Traits::assign(s_[n_], 0);
  43. }
  44. std::size_t n_;
  45. CharT s_[N+1];
  46. public:
  47. //
  48. // Member types
  49. //
  50. using traits_type = Traits;
  51. using value_type = typename Traits::char_type;
  52. using size_type = std::size_t;
  53. using difference_type = std::ptrdiff_t;
  54. using pointer = value_type*;
  55. using reference = value_type&;
  56. using const_pointer = value_type const*;
  57. using const_reference = value_type const&;
  58. using iterator = value_type*;
  59. using const_iterator = value_type const*;
  60. using reverse_iterator =
  61. std::reverse_iterator<iterator>;
  62. using const_reverse_iterator =
  63. std::reverse_iterator<const_iterator>;
  64. /// The type of `string_view` returned by the interface
  65. using string_view_type =
  66. basic_string_view<CharT, Traits>;
  67. //
  68. // Constants
  69. //
  70. /// Maximum size of the string excluding the null terminator
  71. static std::size_t constexpr max_size_n = N;
  72. /// A special index
  73. static constexpr size_type npos = size_type(-1);
  74. //
  75. // (constructor)
  76. //
  77. /// Default constructor (empty string).
  78. static_string();
  79. /** Construct with count copies of character `ch`.
  80. The behavior is undefined if `count >= npos`
  81. */
  82. static_string(size_type count, CharT ch);
  83. /// Construct with a substring (pos, other.size()) of `other`.
  84. template<std::size_t M>
  85. static_string(static_string<M, CharT, Traits> const& other,
  86. size_type pos);
  87. /// Construct with a substring (pos, count) of `other`.
  88. template<std::size_t M>
  89. static_string(static_string<M, CharT, Traits> const& other,
  90. size_type pos, size_type count);
  91. /// Construct with the first `count` characters of `s`, including nulls.
  92. static_string(CharT const* s, size_type count);
  93. /// Construct from a null terminated string.
  94. static_string(CharT const* s);
  95. /// Construct from a range of characters
  96. template<class InputIt>
  97. static_string(InputIt first, InputIt last);
  98. /// Copy constructor.
  99. static_string(static_string const& other);
  100. /// Copy constructor.
  101. template<std::size_t M>
  102. static_string(static_string<M, CharT, Traits> const& other);
  103. /// Construct from an initializer list
  104. static_string(std::initializer_list<CharT> init);
  105. /// Construct from a `string_view`
  106. explicit
  107. static_string(string_view_type sv);
  108. /** Construct from any object convertible to `string_view_type`.
  109. The range (pos, n) is extracted from the value
  110. obtained by converting `t` to `string_view_type`,
  111. and used to construct the string.
  112. */
  113. #if BOOST_BEAST_DOXYGEN
  114. template<class T>
  115. #else
  116. template<class T, class = typename std::enable_if<
  117. std::is_convertible<T, string_view_type>::value>::type>
  118. #endif
  119. static_string(T const& t, size_type pos, size_type n);
  120. //
  121. // (assignment)
  122. //
  123. /// Copy assignment.
  124. static_string&
  125. operator=(static_string const& str)
  126. {
  127. return assign(str);
  128. }
  129. /// Copy assignment.
  130. template<std::size_t M>
  131. static_string&
  132. operator=(static_string<M, CharT, Traits> const& str)
  133. {
  134. return assign(str);
  135. }
  136. /// Assign from null-terminated string.
  137. static_string&
  138. operator=(CharT const* s);
  139. /// Assign from single character.
  140. static_string&
  141. operator=(CharT ch)
  142. {
  143. return assign_char(ch,
  144. std::integral_constant<bool, (N>0)>{});
  145. }
  146. /// Assign from initializer list.
  147. static_string&
  148. operator=(std::initializer_list<CharT> init)
  149. {
  150. return assign(init);
  151. }
  152. /// Assign from `string_view_type`.
  153. static_string&
  154. operator=(string_view_type sv)
  155. {
  156. return assign(sv);
  157. }
  158. /// Assign `count` copies of `ch`.
  159. static_string&
  160. assign(size_type count, CharT ch);
  161. /// Assign from another `static_string`
  162. static_string&
  163. assign(static_string const& str);
  164. // VFALCO NOTE this could come in two flavors,
  165. // N>M and N<M, and skip the exception
  166. // check when N>M
  167. /// Assign from another `static_string`
  168. template<std::size_t M>
  169. static_string&
  170. assign(static_string<M, CharT, Traits> const& str)
  171. {
  172. return assign(str.data(), str.size());
  173. }
  174. /// Assign `count` characterss starting at `npos` from `other`.
  175. template<std::size_t M>
  176. static_string&
  177. assign(static_string<M, CharT, Traits> const& str,
  178. size_type pos, size_type count = npos);
  179. /// Assign the first `count` characters of `s`, including nulls.
  180. static_string&
  181. assign(CharT const* s, size_type count);
  182. /// Assign a null terminated string.
  183. static_string&
  184. assign(CharT const* s)
  185. {
  186. return assign(s, Traits::length(s));
  187. }
  188. /// Assign from an iterator range of characters.
  189. template<class InputIt>
  190. static_string&
  191. assign(InputIt first, InputIt last);
  192. /// Assign from initializer list.
  193. static_string&
  194. assign(std::initializer_list<CharT> init)
  195. {
  196. return assign(init.begin(), init.end());
  197. }
  198. /// Assign from `string_view_type`.
  199. static_string&
  200. assign(string_view_type str)
  201. {
  202. return assign(str.data(), str.size());
  203. }
  204. /** Assign from any object convertible to `string_view_type`.
  205. The range (pos, n) is extracted from the value
  206. obtained by converting `t` to `string_view_type`,
  207. and used to assign the string.
  208. */
  209. template<class T>
  210. #if BOOST_BEAST_DOXYGEN
  211. static_string&
  212. #else
  213. typename std::enable_if<std::is_convertible<T,
  214. string_view_type>::value, static_string&>::type
  215. #endif
  216. assign(T const& t,
  217. size_type pos, size_type count = npos);
  218. //
  219. // Element access
  220. //
  221. /// Access specified character with bounds checking.
  222. reference
  223. at(size_type pos);
  224. /// Access specified character with bounds checking.
  225. const_reference
  226. at(size_type pos) const;
  227. /// Access specified character.
  228. reference
  229. operator[](size_type pos)
  230. {
  231. return s_[pos];
  232. }
  233. /// Access specified character.
  234. const_reference
  235. operator[](size_type pos) const
  236. {
  237. return s_[pos];
  238. }
  239. /// Accesses the first character.
  240. CharT&
  241. front()
  242. {
  243. return s_[0];
  244. }
  245. /// Accesses the first character.
  246. CharT const&
  247. front() const
  248. {
  249. return s_[0];
  250. }
  251. /// Accesses the last character.
  252. CharT&
  253. back()
  254. {
  255. return s_[n_-1];
  256. }
  257. /// Accesses the last character.
  258. CharT const&
  259. back() const
  260. {
  261. return s_[n_-1];
  262. }
  263. /// Returns a pointer to the first character of a string.
  264. CharT*
  265. data()
  266. {
  267. return &s_[0];
  268. }
  269. /// Returns a pointer to the first character of a string.
  270. CharT const*
  271. data() const
  272. {
  273. return &s_[0];
  274. }
  275. /// Returns a non-modifiable standard C character array version of the string.
  276. CharT const*
  277. c_str() const
  278. {
  279. return data();
  280. }
  281. /// Convert a static string to a `string_view_type`
  282. operator string_view_type() const
  283. {
  284. return basic_string_view<
  285. CharT, Traits>{data(), size()};
  286. }
  287. //
  288. // Iterators
  289. //
  290. /// Returns an iterator to the beginning.
  291. iterator
  292. begin()
  293. {
  294. return &s_[0];
  295. }
  296. /// Returns an iterator to the beginning.
  297. const_iterator
  298. begin() const
  299. {
  300. return &s_[0];
  301. }
  302. /// Returns an iterator to the beginning.
  303. const_iterator
  304. cbegin() const
  305. {
  306. return &s_[0];
  307. }
  308. /// Returns an iterator to the end.
  309. iterator
  310. end()
  311. {
  312. return &s_[n_];
  313. }
  314. /// Returns an iterator to the end.
  315. const_iterator
  316. end() const
  317. {
  318. return &s_[n_];
  319. }
  320. /// Returns an iterator to the end.
  321. const_iterator
  322. cend() const
  323. {
  324. return &s_[n_];
  325. }
  326. /// Returns a reverse iterator to the beginning.
  327. reverse_iterator
  328. rbegin()
  329. {
  330. return reverse_iterator{end()};
  331. }
  332. /// Returns a reverse iterator to the beginning.
  333. const_reverse_iterator
  334. rbegin() const
  335. {
  336. return const_reverse_iterator{cend()};
  337. }
  338. /// Returns a reverse iterator to the beginning.
  339. const_reverse_iterator
  340. crbegin() const
  341. {
  342. return const_reverse_iterator{cend()};
  343. }
  344. /// Returns a reverse iterator to the end.
  345. reverse_iterator
  346. rend()
  347. {
  348. return reverse_iterator{begin()};
  349. }
  350. /// Returns a reverse iterator to the end.
  351. const_reverse_iterator
  352. rend() const
  353. {
  354. return const_reverse_iterator{cbegin()};
  355. }
  356. /// Returns a reverse iterator to the end.
  357. const_reverse_iterator
  358. crend() const
  359. {
  360. return const_reverse_iterator{cbegin()};
  361. }
  362. //
  363. // Capacity
  364. //
  365. /// Returns `true` if the string is empty.
  366. bool
  367. empty() const
  368. {
  369. return n_ == 0;
  370. }
  371. /// Returns the number of characters, excluding the null terminator.
  372. size_type
  373. size() const
  374. {
  375. return n_;
  376. }
  377. /// Returns the number of characters, excluding the null terminator.
  378. size_type
  379. length() const
  380. {
  381. return size();
  382. }
  383. /// Returns the maximum number of characters that can be stored, excluding the null terminator.
  384. size_type constexpr
  385. max_size() const
  386. {
  387. return N;
  388. }
  389. /** Reserves storage.
  390. This actually just throws an exception if `n > N`,
  391. otherwise does nothing since the storage is fixed.
  392. */
  393. void
  394. reserve(std::size_t n);
  395. /// Returns the number of characters that can be held in currently allocated storage.
  396. size_type constexpr
  397. capacity() const
  398. {
  399. return max_size();
  400. }
  401. /** Reduces memory usage by freeing unused memory.
  402. This actually does nothing, since the storage is fixed.
  403. */
  404. void
  405. shrink_to_fit()
  406. {
  407. }
  408. //
  409. // Operations
  410. //
  411. /// Clears the contents.
  412. void
  413. clear();
  414. static_string&
  415. insert(size_type index, size_type count, CharT ch);
  416. static_string&
  417. insert(size_type index, CharT const* s)
  418. {
  419. return insert(index, s, Traits::length(s));
  420. }
  421. static_string&
  422. insert(size_type index, CharT const* s, size_type count);
  423. template<std::size_t M>
  424. static_string&
  425. insert(size_type index,
  426. static_string<M, CharT, Traits> const& str)
  427. {
  428. return insert(index, str.data(), str.size());
  429. }
  430. template<std::size_t M>
  431. static_string&
  432. insert(size_type index,
  433. static_string<M, CharT, Traits> const& str,
  434. size_type index_str, size_type count = npos);
  435. iterator
  436. insert(const_iterator pos, CharT ch)
  437. {
  438. return insert(pos, 1, ch);
  439. }
  440. iterator
  441. insert(const_iterator pos, size_type count, CharT ch);
  442. template<class InputIt>
  443. #if BOOST_BEAST_DOXYGEN
  444. iterator
  445. #else
  446. typename std::enable_if<
  447. detail::is_input_iterator<InputIt>::value,
  448. iterator>::type
  449. #endif
  450. insert(const_iterator pos, InputIt first, InputIt last);
  451. iterator
  452. insert(const_iterator pos, std::initializer_list<CharT> init)
  453. {
  454. return insert(pos, init.begin(), init.end());
  455. }
  456. static_string&
  457. insert(size_type index, string_view_type str)
  458. {
  459. return insert(index, str.data(), str.size());
  460. }
  461. template<class T>
  462. #if BOOST_BEAST_DOXYGEN
  463. static_string&
  464. #else
  465. typename std::enable_if<
  466. std::is_convertible<T const&, string_view_type>::value &&
  467. ! std::is_convertible<T const&, CharT const*>::value,
  468. static_string&>::type
  469. #endif
  470. insert(size_type index, T const& t,
  471. size_type index_str, size_type count = npos);
  472. static_string&
  473. erase(size_type index = 0, size_type count = npos);
  474. iterator
  475. erase(const_iterator pos);
  476. iterator
  477. erase(const_iterator first, const_iterator last);
  478. void
  479. push_back(CharT ch);
  480. void
  481. pop_back()
  482. {
  483. Traits::assign(s_[--n_], 0);
  484. }
  485. static_string&
  486. append(size_type count, CharT ch)
  487. {
  488. insert(end(), count, ch);
  489. return *this;
  490. }
  491. template<std::size_t M>
  492. static_string&
  493. append(static_string<M, CharT, Traits> const& str)
  494. {
  495. insert(size(), str);
  496. return *this;
  497. }
  498. template<std::size_t M>
  499. static_string&
  500. append(static_string<M, CharT, Traits> const& str,
  501. size_type pos, size_type count = npos);
  502. static_string&
  503. append(CharT const* s, size_type count)
  504. {
  505. insert(size(), s, count);
  506. return *this;
  507. }
  508. static_string&
  509. append(CharT const* s)
  510. {
  511. insert(size(), s);
  512. return *this;
  513. }
  514. template<class InputIt>
  515. #if BOOST_BEAST_DOXYGEN
  516. static_string&
  517. #else
  518. typename std::enable_if<
  519. detail::is_input_iterator<InputIt>::value,
  520. static_string&>::type
  521. #endif
  522. append(InputIt first, InputIt last)
  523. {
  524. insert(end(), first, last);
  525. return *this;
  526. }
  527. static_string&
  528. append(std::initializer_list<CharT> init)
  529. {
  530. insert(end(), init);
  531. return *this;
  532. }
  533. static_string&
  534. append(string_view_type sv)
  535. {
  536. insert(size(), sv);
  537. return *this;
  538. }
  539. template<class T>
  540. typename std::enable_if<
  541. std::is_convertible<T const&, string_view_type>::value &&
  542. ! std::is_convertible<T const&, CharT const*>::value,
  543. static_string&>::type
  544. append(T const& t, size_type pos, size_type count = npos)
  545. {
  546. insert(size(), t, pos, count);
  547. return *this;
  548. }
  549. template<std::size_t M>
  550. static_string&
  551. operator+=(static_string<M, CharT, Traits> const& str)
  552. {
  553. return append(str.data(), str.size());
  554. }
  555. static_string&
  556. operator+=(CharT ch)
  557. {
  558. push_back(ch);
  559. return *this;
  560. }
  561. static_string&
  562. operator+=(CharT const* s)
  563. {
  564. return append(s);
  565. }
  566. static_string&
  567. operator+=(std::initializer_list<CharT> init)
  568. {
  569. return append(init);
  570. }
  571. static_string&
  572. operator+=(string_view_type const& str)
  573. {
  574. return append(str);
  575. }
  576. template<std::size_t M>
  577. int
  578. compare(static_string<M, CharT, Traits> const& str) const
  579. {
  580. return detail::lexicographical_compare<CharT, Traits>(
  581. &s_[0], n_, &str.s_[0], str.n_);
  582. }
  583. template<std::size_t M>
  584. int
  585. compare(size_type pos1, size_type count1,
  586. static_string<M, CharT, Traits> const& str) const
  587. {
  588. return detail::lexicographical_compare<CharT, Traits>(
  589. substr(pos1, count1), str.data(), str.size());
  590. }
  591. template<std::size_t M>
  592. int
  593. compare(size_type pos1, size_type count1,
  594. static_string<M, CharT, Traits> const& str,
  595. size_type pos2, size_type count2 = npos) const
  596. {
  597. return detail::lexicographical_compare(
  598. substr(pos1, count1), str.substr(pos2, count2));
  599. }
  600. int
  601. compare(CharT const* s) const
  602. {
  603. return detail::lexicographical_compare<CharT, Traits>(
  604. &s_[0], n_, s, Traits::length(s));
  605. }
  606. int
  607. compare(size_type pos1, size_type count1,
  608. CharT const* s) const
  609. {
  610. return detail::lexicographical_compare<CharT, Traits>(
  611. substr(pos1, count1), s, Traits::length(s));
  612. }
  613. int
  614. compare(size_type pos1, size_type count1,
  615. CharT const*s, size_type count2) const
  616. {
  617. return detail::lexicographical_compare<CharT, Traits>(
  618. substr(pos1, count1), s, count2);
  619. }
  620. int
  621. compare(string_view_type str) const
  622. {
  623. return detail::lexicographical_compare<CharT, Traits>(
  624. &s_[0], n_, str.data(), str.size());
  625. }
  626. int
  627. compare(size_type pos1, size_type count1,
  628. string_view_type str) const
  629. {
  630. return detail::lexicographical_compare<CharT, Traits>(
  631. substr(pos1, count1), str);
  632. }
  633. template<class T>
  634. #if BOOST_BEAST_DOXYGEN
  635. int
  636. #else
  637. typename std::enable_if<
  638. std::is_convertible<T const&, string_view_type>::value &&
  639. ! std::is_convertible<T const&, CharT const*>::value,
  640. int>::type
  641. #endif
  642. compare(size_type pos1, size_type count1,
  643. T const& t, size_type pos2,
  644. size_type count2 = npos) const
  645. {
  646. return compare(pos1, count1,
  647. string_view_type(t).substr(pos2, count2));
  648. }
  649. string_view_type
  650. substr(size_type pos = 0, size_type count = npos) const;
  651. /// Copy a substring (pos, pos+count) to character string pointed to by `dest`.
  652. size_type
  653. copy(CharT* dest, size_type count, size_type pos = 0) const;
  654. /** Changes the number of characters stored.
  655. If the resulting string is larger, the new
  656. characters are uninitialized.
  657. */
  658. void
  659. resize(std::size_t n);
  660. /** Changes the number of characters stored.
  661. If the resulting string is larger, the new
  662. characters are initialized to the value of `c`.
  663. */
  664. void
  665. resize(std::size_t n, CharT c);
  666. /// Exchange the contents of this string with another.
  667. void
  668. swap(static_string& str);
  669. /// Exchange the contents of this string with another.
  670. template<std::size_t M>
  671. void
  672. swap(static_string<M, CharT, Traits>& str);
  673. //
  674. // Search
  675. //
  676. private:
  677. static_string&
  678. assign_char(CharT ch, std::true_type);
  679. static_string&
  680. assign_char(CharT ch, std::false_type);
  681. };
  682. //
  683. // Disallowed operations
  684. //
  685. // These operations are explicitly deleted since
  686. // there is no reasonable implementation possible.
  687. template<std::size_t N, std::size_t M, class CharT, class Traits>
  688. void
  689. operator+(
  690. static_string<N, CharT, Traits>const&,
  691. static_string<M, CharT, Traits>const&) = delete;
  692. template<std::size_t N, class CharT, class Traits>
  693. void
  694. operator+(CharT const*,
  695. static_string<N, CharT, Traits>const&) = delete;
  696. template<std::size_t N, class CharT, class Traits>
  697. void
  698. operator+(CharT,
  699. static_string<N, CharT, Traits> const&) = delete;
  700. template<std::size_t N, class CharT, class Traits>
  701. void
  702. operator+(static_string<N, CharT, Traits> const&,
  703. CharT const*) = delete;
  704. template<std::size_t N, class CharT, class Traits>
  705. void
  706. operator+(static_string<N, CharT, Traits> const&, CharT) = delete;
  707. //
  708. // Non-member functions
  709. //
  710. template<std::size_t N, std::size_t M,
  711. class CharT, class Traits>
  712. bool
  713. operator==(
  714. static_string<N, CharT, Traits> const& lhs,
  715. static_string<M, CharT, Traits> const& rhs)
  716. {
  717. return lhs.compare(rhs) == 0;
  718. }
  719. template<std::size_t N, std::size_t M,
  720. class CharT, class Traits>
  721. bool
  722. operator!=(
  723. static_string<N, CharT, Traits> const& lhs,
  724. static_string<M, CharT, Traits> const& rhs)
  725. {
  726. return lhs.compare(rhs) != 0;
  727. }
  728. template<std::size_t N, std::size_t M,
  729. class CharT, class Traits>
  730. bool
  731. operator<(
  732. static_string<N, CharT, Traits> const& lhs,
  733. static_string<M, CharT, Traits> const& rhs)
  734. {
  735. return lhs.compare(rhs) < 0;
  736. }
  737. template<std::size_t N, std::size_t M,
  738. class CharT, class Traits>
  739. bool
  740. operator<=(
  741. static_string<N, CharT, Traits> const& lhs,
  742. static_string<M, CharT, Traits> const& rhs)
  743. {
  744. return lhs.compare(rhs) <= 0;
  745. }
  746. template<std::size_t N, std::size_t M,
  747. class CharT, class Traits>
  748. bool
  749. operator>(
  750. static_string<N, CharT, Traits> const& lhs,
  751. static_string<M, CharT, Traits> const& rhs)
  752. {
  753. return lhs.compare(rhs) > 0;
  754. }
  755. template<std::size_t N, std::size_t M,
  756. class CharT, class Traits>
  757. bool
  758. operator>=(
  759. static_string<N, CharT, Traits> const& lhs,
  760. static_string<M, CharT, Traits> const& rhs)
  761. {
  762. return lhs.compare(rhs) >= 0;
  763. }
  764. template<std::size_t N, class CharT, class Traits>
  765. bool
  766. operator==(
  767. CharT const* lhs,
  768. static_string<N, CharT, Traits> const& rhs)
  769. {
  770. return detail::lexicographical_compare<CharT, Traits>(
  771. lhs, Traits::length(lhs),
  772. rhs.data(), rhs.size()) == 0;
  773. }
  774. template<std::size_t N, class CharT, class Traits>
  775. bool
  776. operator==(
  777. static_string<N, CharT, Traits> const& lhs,
  778. CharT const* rhs)
  779. {
  780. return detail::lexicographical_compare<CharT, Traits>(
  781. lhs.data(), lhs.size(),
  782. rhs, Traits::length(rhs)) == 0;
  783. }
  784. template<std::size_t N, class CharT, class Traits>
  785. bool
  786. operator!=(
  787. CharT const* lhs,
  788. static_string<N, CharT, Traits> const& rhs)
  789. {
  790. return detail::lexicographical_compare<CharT, Traits>(
  791. lhs, Traits::length(lhs),
  792. rhs.data(), rhs.size()) != 0;
  793. }
  794. template<std::size_t N, class CharT, class Traits>
  795. bool
  796. operator!=(
  797. static_string<N, CharT, Traits> const& lhs,
  798. CharT const* rhs)
  799. {
  800. return detail::lexicographical_compare<CharT, Traits>(
  801. lhs.data(), lhs.size(),
  802. rhs, Traits::length(rhs)) != 0;
  803. }
  804. template<std::size_t N, class CharT, class Traits>
  805. bool
  806. operator<(
  807. CharT const* lhs,
  808. static_string<N, CharT, Traits> const& rhs)
  809. {
  810. return detail::lexicographical_compare<CharT, Traits>(
  811. lhs, Traits::length(lhs),
  812. rhs.data(), rhs.size()) < 0;
  813. }
  814. template<std::size_t N, class CharT, class Traits>
  815. bool
  816. operator<(
  817. static_string<N, CharT, Traits> const& lhs,
  818. CharT const* rhs)
  819. {
  820. return detail::lexicographical_compare<CharT, Traits>(
  821. lhs.data(), lhs.size(),
  822. rhs, Traits::length(rhs)) < 0;
  823. }
  824. template<std::size_t N, class CharT, class Traits>
  825. bool
  826. operator<=(
  827. CharT const* lhs,
  828. static_string<N, CharT, Traits> const& rhs)
  829. {
  830. return detail::lexicographical_compare<CharT, Traits>(
  831. lhs, Traits::length(lhs),
  832. rhs.data(), rhs.size()) <= 0;
  833. }
  834. template<std::size_t N, class CharT, class Traits>
  835. bool
  836. operator<=(
  837. static_string<N, CharT, Traits> const& lhs,
  838. CharT const* rhs)
  839. {
  840. return detail::lexicographical_compare<CharT, Traits>(
  841. lhs.data(), lhs.size(),
  842. rhs, Traits::length(rhs)) <= 0;
  843. }
  844. template<std::size_t N, class CharT, class Traits>
  845. bool
  846. operator>(
  847. CharT const* lhs,
  848. static_string<N, CharT, Traits> const& rhs)
  849. {
  850. return detail::lexicographical_compare<CharT, Traits>(
  851. lhs, Traits::length(lhs),
  852. rhs.data(), rhs.size()) > 0;
  853. }
  854. template<std::size_t N, class CharT, class Traits>
  855. bool
  856. operator>(
  857. static_string<N, CharT, Traits> const& lhs,
  858. CharT const* rhs)
  859. {
  860. return detail::lexicographical_compare<CharT, Traits>(
  861. lhs.data(), lhs.size(),
  862. rhs, Traits::length(rhs)) > 0;
  863. }
  864. template<std::size_t N, class CharT, class Traits>
  865. bool
  866. operator>=(
  867. CharT const* lhs,
  868. static_string<N, CharT, Traits> const& rhs)
  869. {
  870. return detail::lexicographical_compare<CharT, Traits>(
  871. lhs, Traits::length(lhs),
  872. rhs.data(), rhs.size()) >= 0;
  873. }
  874. template<std::size_t N, class CharT, class Traits>
  875. bool
  876. operator>=(
  877. static_string<N, CharT, Traits> const& lhs,
  878. CharT const* rhs)
  879. {
  880. return detail::lexicographical_compare<CharT, Traits>(
  881. lhs.data(), lhs.size(),
  882. rhs, Traits::length(rhs)) >= 0;
  883. }
  884. //
  885. // swap
  886. //
  887. template<std::size_t N, class CharT, class Traits>
  888. void
  889. swap(
  890. static_string<N, CharT, Traits>& lhs,
  891. static_string<N, CharT, Traits>& rhs)
  892. {
  893. lhs.swap(rhs);
  894. }
  895. template<std::size_t N, std::size_t M,
  896. class CharT, class Traits>
  897. void
  898. swap(
  899. static_string<N, CharT, Traits>& lhs,
  900. static_string<M, CharT, Traits>& rhs)
  901. {
  902. lhs.swap(rhs);
  903. }
  904. //
  905. // Input/Output
  906. //
  907. template<std::size_t N, class CharT, class Traits>
  908. std::basic_ostream<CharT, Traits>&
  909. operator<<(std::basic_ostream<CharT, Traits>& os,
  910. static_string<N, CharT, Traits> const& str)
  911. {
  912. return os << static_cast<
  913. beast::basic_string_view<CharT, Traits>>(str);
  914. }
  915. //
  916. // Numeric conversions
  917. //
  918. /** Returns a static string representing an integer as a decimal.
  919. @param x The signed or unsigned integer to convert.
  920. This must be an integral type.
  921. @return A @ref static_string with an implementation defined
  922. maximum size large enough to hold the longest possible decimal
  923. representation of any integer of the given type.
  924. */
  925. template<
  926. class Integer
  927. #ifndef BOOST_BEAST_DOXYGEN
  928. ,class = typename std::enable_if<
  929. std::is_integral<Integer>::value>::type
  930. #endif
  931. >
  932. static_string<detail::max_digits(sizeof(Integer))>
  933. to_static_string(Integer x);
  934. } // beast
  935. } // boost
  936. #include <boost/beast/core/impl/static_string.hpp>
  937. #endif