range_rule.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  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/url
  8. //
  9. #ifndef BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
  10. #define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
  11. #include <boost/url/detail/except.hpp>
  12. #include <boost/url/grammar/error.hpp>
  13. #include <boost/url/grammar/recycled.hpp>
  14. #include <boost/core/empty_value.hpp>
  15. #include <boost/assert.hpp>
  16. #include <boost/static_assert.hpp>
  17. #include <exception>
  18. #include <iterator>
  19. #include <new>
  20. #include <stddef.h> // ::max_align_t
  21. namespace boost {
  22. namespace urls {
  23. namespace grammar {
  24. // VFALCO This could be reused for
  25. // other things that need to type-erase
  26. //------------------------------------------------
  27. //
  28. // any_rule
  29. //
  30. //------------------------------------------------
  31. // base class for the type-erased rule pair
  32. template<class T>
  33. struct range<T>::
  34. any_rule
  35. {
  36. virtual
  37. ~any_rule() = default;
  38. virtual
  39. void
  40. move(void* dest) noexcept
  41. {
  42. ::new(dest) any_rule(
  43. std::move(*this));
  44. }
  45. virtual
  46. void
  47. copy(void* dest) const noexcept
  48. {
  49. ::new(dest) any_rule(*this);
  50. }
  51. virtual
  52. system::result<T>
  53. first(
  54. char const*&,
  55. char const*) const noexcept
  56. {
  57. return system::error_code{};
  58. }
  59. virtual
  60. system::result<T>
  61. next(
  62. char const*&,
  63. char const*) const noexcept
  64. {
  65. return system::error_code{};
  66. }
  67. };
  68. //------------------------------------------------
  69. // small
  70. template<class T>
  71. template<class R, bool Small>
  72. struct range<T>::impl1
  73. : any_rule
  74. , private empty_value<R>
  75. {
  76. explicit
  77. impl1(R const& next) noexcept
  78. : empty_value<R>(
  79. empty_init,
  80. next)
  81. {
  82. }
  83. private:
  84. impl1(impl1&&) noexcept = default;
  85. impl1(impl1 const&) noexcept = default;
  86. void
  87. move(void* dest
  88. ) noexcept override
  89. {
  90. ::new(dest) impl1(
  91. std::move(*this));
  92. }
  93. void
  94. copy(void* dest
  95. ) const noexcept override
  96. {
  97. ::new(dest) impl1(*this);
  98. }
  99. system::result<T>
  100. first(
  101. char const*& it,
  102. char const* end)
  103. const noexcept override
  104. {
  105. return grammar::parse(
  106. it, end, this->get());
  107. }
  108. system::result<T>
  109. next(
  110. char const*& it,
  111. char const* end)
  112. const noexcept override
  113. {
  114. return grammar::parse(
  115. it, end, this->get());
  116. }
  117. };
  118. //------------------------------------------------
  119. // big
  120. template<class T>
  121. template<class R>
  122. struct range<T>::impl1<R, false>
  123. : any_rule
  124. {
  125. explicit
  126. impl1(R const& next) noexcept
  127. {
  128. ::new(p_->addr()) impl{next};
  129. }
  130. private:
  131. struct impl
  132. {
  133. R r;
  134. };
  135. recycled_ptr<
  136. aligned_storage<impl>> p_;
  137. impl1(impl1&&) noexcept = default;
  138. impl1(impl1 const&) noexcept = default;
  139. impl const&
  140. get() const noexcept
  141. {
  142. return *reinterpret_cast<
  143. impl const*>(p_->addr());
  144. }
  145. ~impl1()
  146. {
  147. if(p_)
  148. get().~impl();
  149. }
  150. void
  151. move(void* dest
  152. ) noexcept override
  153. {
  154. ::new(dest) impl1(
  155. std::move(*this));
  156. }
  157. void
  158. copy(void* dest
  159. ) const noexcept override
  160. {
  161. ::new(dest) impl1(*this);
  162. }
  163. system::result<T>
  164. first(
  165. char const*& it,
  166. char const* end)
  167. const noexcept override
  168. {
  169. return grammar::parse(
  170. it, end, this->get().r);
  171. }
  172. system::result<T>
  173. next(
  174. char const*& it,
  175. char const* end)
  176. const noexcept override
  177. {
  178. return grammar::parse(
  179. it, end, this->get().r);
  180. }
  181. };
  182. //------------------------------------------------
  183. // small
  184. template<class T>
  185. template<
  186. class R0, class R1, bool Small>
  187. struct range<T>::impl2
  188. : any_rule
  189. , private empty_value<R0, 0>
  190. , private empty_value<R1, 1>
  191. {
  192. impl2(
  193. R0 const& first,
  194. R1 const& next) noexcept
  195. : empty_value<R0,0>(
  196. empty_init, first)
  197. , empty_value<R1,1>(
  198. empty_init, next)
  199. {
  200. }
  201. private:
  202. impl2(impl2&&) noexcept = default;
  203. impl2(impl2 const&) noexcept = default;
  204. void
  205. move(void* dest
  206. ) noexcept override
  207. {
  208. ::new(dest) impl2(
  209. std::move(*this));
  210. }
  211. void
  212. copy(void* dest
  213. ) const noexcept override
  214. {
  215. ::new(dest) impl2(*this);
  216. }
  217. system::result<T>
  218. first(
  219. char const*& it,
  220. char const* end)
  221. const noexcept override
  222. {
  223. return grammar::parse(it, end,
  224. empty_value<
  225. R0,0>::get());
  226. }
  227. system::result<T>
  228. next(
  229. char const*& it,
  230. char const* end)
  231. const noexcept override
  232. {
  233. return grammar::parse(it, end,
  234. empty_value<
  235. R1,1>::get());
  236. }
  237. };
  238. //------------------------------------------------
  239. // big
  240. template<class T>
  241. template<
  242. class R0, class R1>
  243. struct range<T>::impl2<R0, R1, false>
  244. : any_rule
  245. {
  246. impl2(
  247. R0 const& first,
  248. R1 const& next) noexcept
  249. {
  250. ::new(p_->addr()) impl{
  251. first, next};
  252. }
  253. private:
  254. struct impl
  255. {
  256. R0 first;
  257. R1 next;
  258. };
  259. recycled_ptr<
  260. aligned_storage<impl>> p_;
  261. impl2(impl2&&) noexcept = default;
  262. impl2(impl2 const&) noexcept = default;
  263. impl const&
  264. get() const noexcept
  265. {
  266. return *reinterpret_cast<
  267. impl const*>(p_->addr());
  268. }
  269. ~impl2()
  270. {
  271. if(p_)
  272. get().~impl();
  273. }
  274. void
  275. move(void* dest
  276. ) noexcept override
  277. {
  278. ::new(dest) impl2(
  279. std::move(*this));
  280. }
  281. void
  282. copy(void* dest
  283. ) const noexcept override
  284. {
  285. ::new(dest) impl2(*this);
  286. }
  287. system::result<T>
  288. first(
  289. char const*& it,
  290. char const* end)
  291. const noexcept override
  292. {
  293. return grammar::parse(
  294. it, end, get().first);
  295. }
  296. system::result<T>
  297. next(
  298. char const*& it,
  299. char const* end)
  300. const noexcept override
  301. {
  302. return grammar::parse(
  303. it, end, get().next);
  304. }
  305. };
  306. //------------------------------------------------
  307. //
  308. // iterator
  309. //
  310. //------------------------------------------------
  311. template<class T>
  312. class range<T>::
  313. iterator
  314. {
  315. public:
  316. using value_type = T;
  317. using reference = T const&;
  318. using pointer = void const*;
  319. using difference_type =
  320. std::ptrdiff_t;
  321. using iterator_category =
  322. std::forward_iterator_tag;
  323. iterator() = default;
  324. iterator(
  325. iterator const&) = default;
  326. iterator& operator=(
  327. iterator const&) = default;
  328. reference
  329. operator*() const noexcept
  330. {
  331. return *rv_;
  332. }
  333. bool
  334. operator==(
  335. iterator const& other) const noexcept
  336. {
  337. // can't compare iterators
  338. // from different containers!
  339. BOOST_ASSERT(r_ == other.r_);
  340. return p_ == other.p_;
  341. }
  342. bool
  343. operator!=(
  344. iterator const& other) const noexcept
  345. {
  346. return !(*this == other);
  347. }
  348. iterator&
  349. operator++() noexcept
  350. {
  351. BOOST_ASSERT(
  352. p_ != nullptr);
  353. auto const end =
  354. r_->s_.data() +
  355. r_->s_.size();
  356. rv_ = r_->get().next(p_, end);
  357. if( !rv_ )
  358. p_ = nullptr;
  359. return *this;
  360. }
  361. iterator
  362. operator++(int) noexcept
  363. {
  364. auto tmp = *this;
  365. ++*this;
  366. return tmp;
  367. }
  368. private:
  369. friend class range<T>;
  370. range<T> const* r_ = nullptr;
  371. char const* p_ = nullptr;
  372. system::result<T> rv_;
  373. iterator(
  374. range<T> const& r) noexcept
  375. : r_(&r)
  376. , p_(r.s_.data())
  377. {
  378. auto const end =
  379. r_->s_.data() +
  380. r_->s_.size();
  381. rv_ = r_->get().first(p_, end);
  382. if( !rv_ )
  383. p_ = nullptr;
  384. }
  385. constexpr
  386. iterator(
  387. range<T> const& r,
  388. int) noexcept
  389. : r_(&r)
  390. , p_(nullptr)
  391. {
  392. }
  393. };
  394. //------------------------------------------------
  395. template<class T>
  396. template<class R>
  397. range<T>::
  398. range(
  399. core::string_view s,
  400. std::size_t n,
  401. R const& next)
  402. : s_(s)
  403. , n_(n)
  404. {
  405. BOOST_STATIC_ASSERT(
  406. sizeof(impl1<R, false>) <=
  407. BufferSize);
  408. ::new(&get()) impl1<R,
  409. sizeof(impl1<R, true>) <=
  410. BufferSize>(next);
  411. }
  412. //------------------------------------------------
  413. template<class T>
  414. template<
  415. class R0, class R1>
  416. range<T>::
  417. range(
  418. core::string_view s,
  419. std::size_t n,
  420. R0 const& first,
  421. R1 const& next)
  422. : s_(s)
  423. , n_(n)
  424. {
  425. BOOST_STATIC_ASSERT(
  426. sizeof(impl2<R0, R1, false>) <=
  427. BufferSize);
  428. ::new(&get()) impl2<R0, R1,
  429. sizeof(impl2<R0, R1, true>
  430. ) <= BufferSize>(
  431. first, next);
  432. }
  433. //------------------------------------------------
  434. template<class T>
  435. range<T>::
  436. ~range()
  437. {
  438. get().~any_rule();
  439. }
  440. template<class T>
  441. range<T>::
  442. range() noexcept
  443. {
  444. ::new(&get()) any_rule{};
  445. char const* it = nullptr;
  446. get().first(it, nullptr);
  447. get().next(it, nullptr);
  448. }
  449. template<class T>
  450. range<T>::
  451. range(
  452. range&& other) noexcept
  453. : s_(other.s_)
  454. , n_(other.n_)
  455. {
  456. other.s_ = {};
  457. other.n_ = {};
  458. other.get().move(&get());
  459. other.get().~any_rule();
  460. ::new(&other.get()) any_rule{};
  461. }
  462. template<class T>
  463. range<T>::
  464. range(
  465. range const& other) noexcept
  466. : s_(other.s_)
  467. , n_(other.n_)
  468. {
  469. other.get().copy(&get());
  470. }
  471. template<class T>
  472. auto
  473. range<T>::
  474. operator=(
  475. range&& other) noexcept ->
  476. range&
  477. {
  478. s_ = other.s_;
  479. n_ = other.n_;
  480. other.s_ = {};
  481. other.n_ = 0;
  482. // VFALCO we rely on nothrow move
  483. // construction here, but if necessary we
  484. // could move to a local buffer first.
  485. get().~any_rule();
  486. other.get().move(&get());
  487. other.get().~any_rule();
  488. ::new(&other.get()) any_rule{};
  489. return *this;
  490. }
  491. template<class T>
  492. auto
  493. range<T>::
  494. operator=(
  495. range const& other) noexcept ->
  496. range&
  497. {
  498. s_ = other.s_;
  499. n_ = other.n_;
  500. // VFALCO we rely on nothrow copy
  501. // construction here, but if necessary we
  502. // could construct to a local buffer first.
  503. get().~any_rule();
  504. other.get().copy(&get());
  505. return *this;
  506. }
  507. template<class T>
  508. auto
  509. range<T>::
  510. begin() const noexcept ->
  511. iterator
  512. {
  513. return { *this };
  514. }
  515. template<class T>
  516. auto
  517. range<T>::
  518. end() const noexcept ->
  519. iterator
  520. {
  521. return { *this, 0 };
  522. }
  523. //------------------------------------------------
  524. template<class R>
  525. auto
  526. range_rule_t<R>::
  527. parse(
  528. char const*& it,
  529. char const* end) const ->
  530. system::result<value_type>
  531. {
  532. using T = typename R::value_type;
  533. std::size_t n = 0;
  534. auto const it0 = it;
  535. auto it1 = it;
  536. auto rv = (grammar::parse)(
  537. it, end, next_);
  538. if( !rv )
  539. {
  540. if(rv.error() != error::end_of_range)
  541. {
  542. // rewind unless error::end_of_range
  543. it = it1;
  544. }
  545. if(n < N_)
  546. {
  547. // too few
  548. BOOST_URL_RETURN_EC(
  549. error::mismatch);
  550. }
  551. // good
  552. return range<T>(
  553. core::string_view(it0, it - it0),
  554. n, next_);
  555. }
  556. for(;;)
  557. {
  558. ++n;
  559. it1 = it;
  560. rv = (grammar::parse)(
  561. it, end, next_);
  562. if( !rv )
  563. {
  564. if(rv.error() != error::end_of_range)
  565. {
  566. // rewind unless error::end_of_range
  567. it = it1;
  568. }
  569. break;
  570. }
  571. if(n >= M_)
  572. {
  573. // too many
  574. BOOST_URL_RETURN_EC(
  575. error::mismatch);
  576. }
  577. }
  578. if(n < N_)
  579. {
  580. // too few
  581. BOOST_URL_RETURN_EC(
  582. error::mismatch);
  583. }
  584. // good
  585. return range<T>(
  586. core::string_view(it0, it - it0),
  587. n, next_);
  588. }
  589. //------------------------------------------------
  590. template<class R0, class R1>
  591. auto
  592. range_rule_t<R0, R1>::
  593. parse(
  594. char const*& it,
  595. char const* end) const ->
  596. system::result<range<typename
  597. R0::value_type>>
  598. {
  599. using T = typename R0::value_type;
  600. std::size_t n = 0;
  601. auto const it0 = it;
  602. auto it1 = it;
  603. auto rv = (grammar::parse)(
  604. it, end, first_);
  605. if( !rv )
  606. {
  607. if(rv.error() != error::end_of_range)
  608. {
  609. // rewind unless error::end_of_range
  610. it = it1;
  611. }
  612. if(n < N_)
  613. {
  614. // too few
  615. BOOST_URL_RETURN_EC(
  616. error::mismatch);
  617. }
  618. // good
  619. return range<T>(
  620. core::string_view(it0, it - it0),
  621. n, first_, next_);
  622. }
  623. for(;;)
  624. {
  625. ++n;
  626. it1 = it;
  627. rv = (grammar::parse)(
  628. it, end, next_);
  629. if( !rv )
  630. {
  631. if(rv.error() != error::end_of_range)
  632. {
  633. // rewind unless error::end_of_range
  634. it = it1;
  635. }
  636. break;
  637. }
  638. if(n >= M_)
  639. {
  640. // too many
  641. BOOST_URL_RETURN_EC(
  642. error::mismatch);
  643. }
  644. }
  645. if(n < N_)
  646. {
  647. // too few
  648. BOOST_URL_RETURN_EC(
  649. error::mismatch);
  650. }
  651. // good
  652. return range<T>(
  653. core::string_view(it0, it - it0),
  654. n, first_, next_);
  655. }
  656. } // grammar
  657. } // urls
  658. } // boost
  659. #endif