static_string.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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_IMPL_STATIC_STRING_HPP
  10. #define BOOST_BEAST_IMPL_STATIC_STRING_HPP
  11. #include <boost/beast/core/detail/static_string.hpp>
  12. #include <boost/throw_exception.hpp>
  13. namespace boost {
  14. namespace beast {
  15. //
  16. // (constructor)
  17. //
  18. template<std::size_t N, class CharT, class Traits>
  19. static_string<N, CharT, Traits>::
  20. static_string()
  21. {
  22. n_ = 0;
  23. term();
  24. }
  25. template<std::size_t N, class CharT, class Traits>
  26. static_string<N, CharT, Traits>::
  27. static_string(size_type count, CharT ch)
  28. {
  29. assign(count, ch);
  30. }
  31. template<std::size_t N, class CharT, class Traits>
  32. template<std::size_t M>
  33. static_string<N, CharT, Traits>::
  34. static_string(static_string<M, CharT, Traits> const& other,
  35. size_type pos)
  36. {
  37. assign(other, pos);
  38. }
  39. template<std::size_t N, class CharT, class Traits>
  40. template<std::size_t M>
  41. static_string<N, CharT, Traits>::
  42. static_string(static_string<M, CharT, Traits> const& other,
  43. size_type pos, size_type count)
  44. {
  45. assign(other, pos, count);
  46. }
  47. template<std::size_t N, class CharT, class Traits>
  48. static_string<N, CharT, Traits>::
  49. static_string(CharT const* s, size_type count)
  50. {
  51. assign(s, count);
  52. }
  53. template<std::size_t N, class CharT, class Traits>
  54. static_string<N, CharT, Traits>::
  55. static_string(CharT const* s)
  56. {
  57. auto const count = Traits::length(s);
  58. if(count > max_size())
  59. BOOST_THROW_EXCEPTION(std::length_error{
  60. "count > max_size()"});
  61. n_ = count;
  62. Traits::copy(&s_[0], s, n_ + 1);
  63. }
  64. template<std::size_t N, class CharT, class Traits>
  65. template<class InputIt>
  66. static_string<N, CharT, Traits>::
  67. static_string(InputIt first, InputIt last)
  68. {
  69. assign(first, last);
  70. }
  71. template<std::size_t N, class CharT, class Traits>
  72. static_string<N, CharT, Traits>::
  73. static_string(static_string const& s)
  74. {
  75. assign(s);
  76. }
  77. template<std::size_t N, class CharT, class Traits>
  78. template<std::size_t M>
  79. static_string<N, CharT, Traits>::
  80. static_string(static_string<M, CharT, Traits> const& s)
  81. {
  82. assign(s);
  83. }
  84. template<std::size_t N, class CharT, class Traits>
  85. static_string<N, CharT, Traits>::
  86. static_string(std::initializer_list<CharT> init)
  87. {
  88. assign(init.begin(), init.end());
  89. }
  90. template<std::size_t N, class CharT, class Traits>
  91. static_string<N, CharT, Traits>::
  92. static_string(string_view_type sv)
  93. {
  94. assign(sv);
  95. }
  96. template<std::size_t N, class CharT, class Traits>
  97. template<class T, class>
  98. static_string<N, CharT, Traits>::
  99. static_string(T const& t, size_type pos, size_type n)
  100. {
  101. assign(t, pos, n);
  102. }
  103. //
  104. // (assignment)
  105. //
  106. template<std::size_t N, class CharT, class Traits>
  107. auto
  108. static_string<N, CharT, Traits>::
  109. operator=(CharT const* s) ->
  110. static_string&
  111. {
  112. auto const count = Traits::length(s);
  113. if(count > max_size())
  114. BOOST_THROW_EXCEPTION(std::length_error{
  115. "count > max_size()"});
  116. n_ = count;
  117. Traits::copy(&s_[0], s, n_ + 1);
  118. return *this;
  119. }
  120. template<std::size_t N, class CharT, class Traits>
  121. auto
  122. static_string<N, CharT, Traits>::
  123. assign(size_type count, CharT ch) ->
  124. static_string&
  125. {
  126. if(count > max_size())
  127. BOOST_THROW_EXCEPTION(std::length_error{
  128. "count > max_size()"});
  129. n_ = count;
  130. Traits::assign(&s_[0], n_, ch);
  131. term();
  132. return *this;
  133. }
  134. template<std::size_t N, class CharT, class Traits>
  135. auto
  136. static_string<N, CharT, Traits>::
  137. assign(static_string const& str) ->
  138. static_string&
  139. {
  140. n_ = str.n_;
  141. auto const n = n_ + 1;
  142. BOOST_BEAST_ASSUME(n != 0);
  143. Traits::copy(&s_[0], &str.s_[0], n);
  144. return *this;
  145. }
  146. template<std::size_t N, class CharT, class Traits>
  147. template<std::size_t M>
  148. auto
  149. static_string<N, CharT, Traits>::
  150. assign(static_string<M, CharT, Traits> const& str,
  151. size_type pos, size_type count) ->
  152. static_string&
  153. {
  154. auto const ss = str.substr(pos, count);
  155. return assign(ss.data(), ss.size());
  156. }
  157. template<std::size_t N, class CharT, class Traits>
  158. auto
  159. static_string<N, CharT, Traits>::
  160. assign(CharT const* s, size_type count) ->
  161. static_string&
  162. {
  163. if(count > max_size())
  164. BOOST_THROW_EXCEPTION(std::length_error{
  165. "count > max_size()"});
  166. n_ = count;
  167. Traits::copy(&s_[0], s, n_);
  168. term();
  169. return *this;
  170. }
  171. template<std::size_t N, class CharT, class Traits>
  172. template<class InputIt>
  173. auto
  174. static_string<N, CharT, Traits>::
  175. assign(InputIt first, InputIt last) ->
  176. static_string&
  177. {
  178. std::size_t const n = std::distance(first, last);
  179. if(n > max_size())
  180. BOOST_THROW_EXCEPTION(std::length_error{
  181. "n > max_size()"});
  182. n_ = n;
  183. for(auto it = &s_[0]; first != last; ++it, ++first)
  184. Traits::assign(*it, *first);
  185. term();
  186. return *this;
  187. }
  188. template<std::size_t N, class CharT, class Traits>
  189. template<class T>
  190. auto
  191. static_string<N, CharT, Traits>::
  192. assign(T const& t, size_type pos, size_type count) ->
  193. typename std::enable_if<std::is_convertible<T,
  194. string_view_type>::value, static_string&>::type
  195. {
  196. auto const sv = string_view_type(t).substr(pos, count);
  197. if(sv.size() > max_size())
  198. BOOST_THROW_EXCEPTION(std::length_error{
  199. "sv.size() > max_size()"});
  200. n_ = sv.size();
  201. Traits::copy(&s_[0], &sv[0], n_);
  202. term();
  203. return *this;
  204. }
  205. //
  206. // Element access
  207. //
  208. template<std::size_t N, class CharT, class Traits>
  209. auto
  210. static_string<N, CharT, Traits>::
  211. at(size_type pos) ->
  212. reference
  213. {
  214. if(pos >= size())
  215. BOOST_THROW_EXCEPTION(std::out_of_range{
  216. "pos >= size()"});
  217. return s_[pos];
  218. }
  219. template<std::size_t N, class CharT, class Traits>
  220. auto
  221. static_string<N, CharT, Traits>::
  222. at(size_type pos) const ->
  223. const_reference
  224. {
  225. if(pos >= size())
  226. BOOST_THROW_EXCEPTION(std::out_of_range{
  227. "pos >= size()"});
  228. return s_[pos];
  229. }
  230. //
  231. // Capacity
  232. //
  233. template<std::size_t N, class CharT, class Traits>
  234. void
  235. static_string<N, CharT, Traits>::
  236. reserve(std::size_t n)
  237. {
  238. if(n > max_size())
  239. BOOST_THROW_EXCEPTION(std::length_error{
  240. "n > max_size()"});
  241. }
  242. //
  243. // Operations
  244. //
  245. template<std::size_t N, class CharT, class Traits>
  246. void
  247. static_string<N, CharT, Traits>::
  248. clear()
  249. {
  250. n_ = 0;
  251. term();
  252. }
  253. template<std::size_t N, class CharT, class Traits>
  254. auto
  255. static_string<N, CharT, Traits>::
  256. insert(size_type index, size_type count, CharT ch) ->
  257. static_string&
  258. {
  259. if(index > size())
  260. BOOST_THROW_EXCEPTION(std::out_of_range{
  261. "index > size()"});
  262. insert(begin() + index, count, ch);
  263. return *this;
  264. }
  265. template<std::size_t N, class CharT, class Traits>
  266. auto
  267. static_string<N, CharT, Traits>::
  268. insert(size_type index, CharT const* s, size_type count) ->
  269. static_string&
  270. {
  271. if(index > size())
  272. BOOST_THROW_EXCEPTION(std::out_of_range{
  273. "index > size()"});
  274. if(size() + count > max_size())
  275. BOOST_THROW_EXCEPTION(std::length_error{
  276. "size() + count > max_size()"});
  277. Traits::move(
  278. &s_[index + count], &s_[index], size() - index);
  279. n_ += count;
  280. Traits::copy(&s_[index], s, count);
  281. term();
  282. return *this;
  283. }
  284. template<std::size_t N, class CharT, class Traits>
  285. template<std::size_t M>
  286. auto
  287. static_string<N, CharT, Traits>::
  288. insert(size_type index,
  289. static_string<M, CharT, Traits> const& str,
  290. size_type index_str, size_type count) ->
  291. static_string&
  292. {
  293. auto const ss = str.substr(index_str, count);
  294. return insert(index, ss.data(), ss.size());
  295. }
  296. template<std::size_t N, class CharT, class Traits>
  297. auto
  298. static_string<N, CharT, Traits>::
  299. insert(const_iterator pos, size_type count, CharT ch) ->
  300. iterator
  301. {
  302. if(size() + count > max_size())
  303. BOOST_THROW_EXCEPTION(std::length_error{
  304. "size() + count() > max_size()"});
  305. auto const index = pos - &s_[0];
  306. Traits::move(
  307. &s_[index + count], &s_[index], size() - index);
  308. n_ += count;
  309. Traits::assign(&s_[index], count, ch);
  310. term();
  311. return &s_[index];
  312. }
  313. template<std::size_t N, class CharT, class Traits>
  314. template<class InputIt>
  315. auto
  316. static_string<N, CharT, Traits>::
  317. insert(const_iterator pos, InputIt first, InputIt last) ->
  318. typename std::enable_if<
  319. detail::is_input_iterator<InputIt>::value,
  320. iterator>::type
  321. {
  322. std::size_t const count = std::distance(first, last);
  323. if(size() + count > max_size())
  324. BOOST_THROW_EXCEPTION(std::length_error{
  325. "size() + count > max_size()"});
  326. std::size_t const index = pos - begin();
  327. Traits::move(
  328. &s_[index + count], &s_[index], size() - index);
  329. n_ += count;
  330. for(auto it = begin() + index;
  331. first != last; ++it, ++first)
  332. Traits::assign(*it, *first);
  333. term();
  334. return begin() + index;
  335. }
  336. template<std::size_t N, class CharT, class Traits>
  337. template<class T>
  338. auto
  339. static_string<N, CharT, Traits>::
  340. insert(size_type index, const T& t,
  341. size_type index_str, size_type count) ->
  342. typename std::enable_if<std::is_convertible<
  343. T const&, string_view_type>::value &&
  344. ! std::is_convertible<T const&, CharT const*>::value,
  345. static_string&>::type
  346. {
  347. auto const str =
  348. string_view_type(t).substr(index_str, count);
  349. return insert(index, str.data(), str.size());
  350. }
  351. template<std::size_t N, class CharT, class Traits>
  352. auto
  353. static_string<N, CharT, Traits>::
  354. erase(size_type index, size_type count) ->
  355. static_string&
  356. {
  357. if(index > size())
  358. BOOST_THROW_EXCEPTION(std::out_of_range{
  359. "index > size()"});
  360. auto const n = (std::min)(count, size() - index);
  361. Traits::move(
  362. &s_[index], &s_[index + n], size() - (index + n) + 1);
  363. n_ -= n;
  364. return *this;
  365. }
  366. template<std::size_t N, class CharT, class Traits>
  367. auto
  368. static_string<N, CharT, Traits>::
  369. erase(const_iterator pos) ->
  370. iterator
  371. {
  372. erase(pos - begin(), 1);
  373. return begin() + (pos - begin());
  374. }
  375. template<std::size_t N, class CharT, class Traits>
  376. auto
  377. static_string<N, CharT, Traits>::
  378. erase(const_iterator first, const_iterator last) ->
  379. iterator
  380. {
  381. erase(first - begin(),
  382. std::distance(first, last));
  383. return begin() + (first - begin());
  384. }
  385. template<std::size_t N, class CharT, class Traits>
  386. void
  387. static_string<N, CharT, Traits>::
  388. push_back(CharT ch)
  389. {
  390. if(size() >= max_size())
  391. BOOST_THROW_EXCEPTION(std::length_error{
  392. "size() >= max_size()"});
  393. Traits::assign(s_[n_++], ch);
  394. term();
  395. }
  396. template<std::size_t N, class CharT, class Traits>
  397. template<std::size_t M>
  398. auto
  399. static_string<N, CharT, Traits>::
  400. append(static_string<M, CharT, Traits> const& str,
  401. size_type pos, size_type count) ->
  402. static_string&
  403. {
  404. // Valid range is [0, size)
  405. if(pos >= str.size())
  406. BOOST_THROW_EXCEPTION(std::out_of_range{
  407. "pos > str.size()"});
  408. string_view_type const ss{&str.s_[pos],
  409. (std::min)(count, str.size() - pos)};
  410. insert(size(), ss.data(), ss.size());
  411. return *this;
  412. }
  413. template<std::size_t N, class CharT, class Traits>
  414. auto
  415. static_string<N, CharT, Traits>::
  416. substr(size_type pos, size_type count) const ->
  417. string_view_type
  418. {
  419. if(pos > size())
  420. BOOST_THROW_EXCEPTION(std::out_of_range{
  421. "pos > size()"});
  422. return{&s_[pos], (std::min)(count, size() - pos)};
  423. }
  424. template<std::size_t N, class CharT, class Traits>
  425. auto
  426. static_string<N, CharT, Traits>::
  427. copy(CharT* dest, size_type count, size_type pos) const ->
  428. size_type
  429. {
  430. auto const str = substr(pos, count);
  431. Traits::copy(dest, str.data(), str.size());
  432. return str.size();
  433. }
  434. template<std::size_t N, class CharT, class Traits>
  435. void
  436. static_string<N, CharT, Traits>::
  437. resize(std::size_t n)
  438. {
  439. if(n > max_size())
  440. BOOST_THROW_EXCEPTION(std::length_error{
  441. "n > max_size()"});
  442. if(n > n_)
  443. Traits::assign(&s_[n_], n - n_, CharT{});
  444. n_ = n;
  445. term();
  446. }
  447. template<std::size_t N, class CharT, class Traits>
  448. void
  449. static_string<N, CharT, Traits>::
  450. resize(std::size_t n, CharT c)
  451. {
  452. if(n > max_size())
  453. BOOST_THROW_EXCEPTION(std::length_error{
  454. "n > max_size()"});
  455. if(n > n_)
  456. Traits::assign(&s_[n_], n - n_, c);
  457. n_ = n;
  458. term();
  459. }
  460. template<std::size_t N, class CharT, class Traits>
  461. void
  462. static_string<N, CharT, Traits>::
  463. swap(static_string& str)
  464. {
  465. static_string tmp(str);
  466. str.n_ = n_;
  467. Traits::copy(&str.s_[0], &s_[0], n_ + 1);
  468. n_ = tmp.n_;
  469. Traits::copy(&s_[0], &tmp.s_[0], n_ + 1);
  470. }
  471. template<std::size_t N, class CharT, class Traits>
  472. template<std::size_t M>
  473. void
  474. static_string<N, CharT, Traits>::
  475. swap(static_string<M, CharT, Traits>& str)
  476. {
  477. if(size() > str.max_size())
  478. BOOST_THROW_EXCEPTION(std::length_error{
  479. "size() > str.max_size()"});
  480. if(str.size() > max_size())
  481. BOOST_THROW_EXCEPTION(std::length_error{
  482. "str.size() > max_size()"});
  483. static_string tmp(str);
  484. str.n_ = n_;
  485. Traits::copy(&str.s_[0], &s_[0], n_ + 1);
  486. n_ = tmp.n_;
  487. Traits::copy(&s_[0], &tmp.s_[0], n_ + 1);
  488. }
  489. template<std::size_t N, class CharT, class Traits>
  490. auto
  491. static_string<N, CharT, Traits>::
  492. assign_char(CharT ch, std::true_type) ->
  493. static_string&
  494. {
  495. n_ = 1;
  496. Traits::assign(s_[0], ch);
  497. term();
  498. return *this;
  499. }
  500. template<std::size_t N, class CharT, class Traits>
  501. auto
  502. static_string<N, CharT, Traits>::
  503. assign_char(CharT, std::false_type) ->
  504. static_string&
  505. {
  506. BOOST_THROW_EXCEPTION(std::length_error{
  507. "max_size() == 0"});
  508. }
  509. template<class Integer, class>
  510. static_string<detail::max_digits(sizeof(Integer))>
  511. to_static_string(Integer x)
  512. {
  513. using CharT = char;
  514. using Traits = std::char_traits<CharT>;
  515. BOOST_STATIC_ASSERT(std::is_integral<Integer>::value);
  516. char buf[detail::max_digits(sizeof(Integer))];
  517. auto last = buf + sizeof(buf);
  518. auto it = detail::raw_to_string<
  519. CharT, Integer, Traits>(last, sizeof(buf), x);
  520. static_string<detail::max_digits(sizeof(Integer))> s;
  521. s.resize(static_cast<std::size_t>(last - it));
  522. auto p = s.data();
  523. while(it < last)
  524. Traits::assign(*p++, *it++);
  525. return s;
  526. }
  527. } // beast
  528. } // boost
  529. #endif