/src/contrib/boost/spirit/home/classic/iterator/multi_pass.hpp

http://pythonocc.googlecode.com/ · C++ Header · 1307 lines · 990 code · 169 blank · 148 comment · 47 complexity · 01432647f5e63b2da8cfb687a13608b2 MD5 · raw file

  1. /*=============================================================================
  2. Copyright (c) 2001, Daniel C. Nuffer
  3. http://spirit.sourceforge.net/
  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. #ifndef BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
  8. #define BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP
  9. #include <boost/config.hpp>
  10. #include <boost/throw_exception.hpp>
  11. #include <deque>
  12. #include <iterator>
  13. #include <iostream>
  14. #include <algorithm> // for std::swap
  15. #include <exception> // for std::exception
  16. #include <boost/limits.hpp>
  17. #include <boost/iterator.hpp>
  18. #include <boost/spirit/home/classic/namespace.hpp>
  19. #include <boost/spirit/home/classic/core/assert.hpp> // for BOOST_SPIRIT_ASSERT
  20. #include <boost/spirit/home/classic/iterator/fixed_size_queue.hpp>
  21. #include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
  22. #include <boost/spirit/home/classic/iterator/multi_pass_fwd.hpp>
  23. namespace boost { namespace spirit {
  24. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  25. namespace impl {
  26. template <typename T>
  27. inline void mp_swap(T& t1, T& t2);
  28. }
  29. namespace multi_pass_policies
  30. {
  31. ///////////////////////////////////////////////////////////////////////////////
  32. // class ref_counted
  33. // Implementation of an OwnershipPolicy used by multi_pass.
  34. //
  35. // Implementation modified from RefCounted class from the Loki library by
  36. // Andrei Alexandrescu
  37. ///////////////////////////////////////////////////////////////////////////////
  38. class ref_counted
  39. {
  40. protected:
  41. ref_counted()
  42. : count(new std::size_t(1))
  43. {}
  44. ref_counted(ref_counted const& x)
  45. : count(x.count)
  46. {}
  47. // clone is called when a copy of the iterator is made, so increment
  48. // the ref-count.
  49. void clone()
  50. {
  51. ++*count;
  52. }
  53. // called when a copy is deleted. Decrement the ref-count. Return
  54. // value of true indicates that the last copy has been released.
  55. bool release()
  56. {
  57. if (!--*count)
  58. {
  59. delete count;
  60. count = 0;
  61. return true;
  62. }
  63. return false;
  64. }
  65. void swap(ref_counted& x)
  66. {
  67. impl::mp_swap(count, x.count);
  68. }
  69. public:
  70. // returns true if there is only one iterator in existence.
  71. // std_deque StoragePolicy will free it's buffered data if this
  72. // returns true.
  73. bool unique() const
  74. {
  75. return *count == 1;
  76. }
  77. private:
  78. std::size_t* count;
  79. };
  80. ///////////////////////////////////////////////////////////////////////////////
  81. // class first_owner
  82. // Implementation of an OwnershipPolicy used by multi_pass
  83. // This ownership policy dictates that the first iterator created will
  84. // determine the lifespan of the shared components. This works well for
  85. // spirit, since no dynamic allocation of iterators is done, and all copies
  86. // are make on the stack.
  87. //
  88. // There is a caveat about using this policy together with the std_deque
  89. // StoragePolicy. Since first_owner always returns false from unique(),
  90. // std_deque will only release the queued data if clear_queue() is called.
  91. ///////////////////////////////////////////////////////////////////////////////
  92. class first_owner
  93. {
  94. protected:
  95. first_owner()
  96. : first(true)
  97. {}
  98. first_owner(first_owner const&)
  99. : first(false)
  100. {}
  101. void clone()
  102. {
  103. }
  104. // return true to indicate deletion of resources
  105. bool release()
  106. {
  107. return first;
  108. }
  109. void swap(first_owner&)
  110. {
  111. // if we're the first, we still remain the first, even if assigned
  112. // to, so don't swap first_. swap is only called from operator=
  113. }
  114. public:
  115. bool unique() const
  116. {
  117. return false; // no way to know, so always return false
  118. }
  119. private:
  120. bool first;
  121. };
  122. ///////////////////////////////////////////////////////////////////////////////
  123. // class illegal_backtracking
  124. // thrown by buf_id_check CheckingPolicy if an instance of an iterator is
  125. // used after another one has invalidated the queue
  126. ///////////////////////////////////////////////////////////////////////////////
  127. class illegal_backtracking : public std::exception
  128. {
  129. public:
  130. illegal_backtracking() throw() {}
  131. ~illegal_backtracking() throw() {}
  132. virtual const char*
  133. what() const throw()
  134. { return "BOOST_SPIRIT_CLASSIC_NS::illegal_backtracking"; }
  135. };
  136. ///////////////////////////////////////////////////////////////////////////////
  137. // class buf_id_check
  138. // Implementation of the CheckingPolicy used by multi_pass
  139. // This policy is most effective when used together with the std_deque
  140. // StoragePolicy.
  141. // If used with the fixed_size_queue StoragePolicy, it will not detect
  142. // iterator derefereces that are out of the range of the queue.
  143. ///////////////////////////////////////////////////////////////////////////////
  144. class buf_id_check
  145. {
  146. protected:
  147. buf_id_check()
  148. : shared_buf_id(new unsigned long(0))
  149. , buf_id(0)
  150. {}
  151. buf_id_check(buf_id_check const& x)
  152. : shared_buf_id(x.shared_buf_id)
  153. , buf_id(x.buf_id)
  154. {}
  155. // will be called from the destructor of the last iterator.
  156. void destroy()
  157. {
  158. delete shared_buf_id;
  159. shared_buf_id = 0;
  160. }
  161. void swap(buf_id_check& x)
  162. {
  163. impl::mp_swap(shared_buf_id, x.shared_buf_id);
  164. impl::mp_swap(buf_id, x.buf_id);
  165. }
  166. // called to verify that everything is okay.
  167. void check() const
  168. {
  169. if (buf_id != *shared_buf_id)
  170. {
  171. boost::throw_exception(illegal_backtracking());
  172. }
  173. }
  174. // called from multi_pass::clear_queue, so we can increment the count
  175. void clear_queue()
  176. {
  177. ++*shared_buf_id;
  178. ++buf_id;
  179. }
  180. private:
  181. unsigned long* shared_buf_id;
  182. unsigned long buf_id;
  183. };
  184. ///////////////////////////////////////////////////////////////////////////////
  185. // class no_check
  186. // Implementation of the CheckingPolicy used by multi_pass
  187. // It does not do anything :-)
  188. ///////////////////////////////////////////////////////////////////////////////
  189. class no_check
  190. {
  191. protected:
  192. no_check() {}
  193. no_check(no_check const&) {}
  194. void destroy() {}
  195. void swap(no_check&) {}
  196. void check() const {}
  197. void clear_queue() {}
  198. };
  199. ///////////////////////////////////////////////////////////////////////////////
  200. // class std_deque
  201. // Implementation of the StoragePolicy used by multi_pass
  202. // This stores all data in a std::deque, and keeps an offset to the current
  203. // position. It stores all the data unless there is only one
  204. // iterator using the queue.
  205. // Note: a position is used instead of an iterator, because a push_back on
  206. // a deque can invalidate any iterators.
  207. ///////////////////////////////////////////////////////////////////////////////
  208. class std_deque
  209. {
  210. public:
  211. template <typename ValueT>
  212. class inner
  213. {
  214. private:
  215. typedef std::deque<ValueT> queue_type;
  216. queue_type* queuedElements;
  217. mutable typename queue_type::size_type queuePosition;
  218. protected:
  219. inner()
  220. : queuedElements(new queue_type)
  221. , queuePosition(0)
  222. {}
  223. inner(inner const& x)
  224. : queuedElements(x.queuedElements)
  225. , queuePosition(x.queuePosition)
  226. {}
  227. // will be called from the destructor of the last iterator.
  228. void destroy()
  229. {
  230. BOOST_SPIRIT_ASSERT(NULL != queuedElements);
  231. delete queuedElements;
  232. queuedElements = 0;
  233. }
  234. void swap(inner& x)
  235. {
  236. impl::mp_swap(queuedElements, x.queuedElements);
  237. impl::mp_swap(queuePosition, x.queuePosition);
  238. }
  239. // This is called when the iterator is dereferenced. It's a template
  240. // method so we can recover the type of the multi_pass iterator
  241. // and call unique and access the m_input data member.
  242. template <typename MultiPassT>
  243. static typename MultiPassT::reference dereference(MultiPassT const& mp)
  244. {
  245. if (mp.queuePosition == mp.queuedElements->size())
  246. {
  247. // check if this is the only iterator
  248. if (mp.unique())
  249. {
  250. // free up the memory used by the queue.
  251. if (mp.queuedElements->size() > 0)
  252. {
  253. mp.queuedElements->clear();
  254. mp.queuePosition = 0;
  255. }
  256. }
  257. return mp.get_input();
  258. }
  259. else
  260. {
  261. return (*mp.queuedElements)[mp.queuePosition];
  262. }
  263. }
  264. // This is called when the iterator is incremented. It's a template
  265. // method so we can recover the type of the multi_pass iterator
  266. // and call unique and access the m_input data member.
  267. template <typename MultiPassT>
  268. static void increment(MultiPassT& mp)
  269. {
  270. if (mp.queuePosition == mp.queuedElements->size())
  271. {
  272. // check if this is the only iterator
  273. if (mp.unique())
  274. {
  275. // free up the memory used by the queue.
  276. if (mp.queuedElements->size() > 0)
  277. {
  278. mp.queuedElements->clear();
  279. mp.queuePosition = 0;
  280. }
  281. }
  282. else
  283. {
  284. mp.queuedElements->push_back(mp.get_input());
  285. ++mp.queuePosition;
  286. }
  287. mp.advance_input();
  288. }
  289. else
  290. {
  291. ++mp.queuePosition;
  292. }
  293. }
  294. // called to forcibly clear the queue
  295. void clear_queue()
  296. {
  297. queuedElements->clear();
  298. queuePosition = 0;
  299. }
  300. // called to determine whether the iterator is an eof iterator
  301. template <typename MultiPassT>
  302. static bool is_eof(MultiPassT const& mp)
  303. {
  304. return mp.queuePosition == mp.queuedElements->size() &&
  305. mp.input_at_eof();
  306. }
  307. // called by operator==
  308. bool equal_to(inner const& x) const
  309. {
  310. return queuePosition == x.queuePosition;
  311. }
  312. // called by operator<
  313. bool less_than(inner const& x) const
  314. {
  315. return queuePosition < x.queuePosition;
  316. }
  317. }; // class inner
  318. }; // class std_deque
  319. ///////////////////////////////////////////////////////////////////////////////
  320. // class fixed_size_queue
  321. // Implementation of the StoragePolicy used by multi_pass
  322. // fixed_size_queue keeps a circular buffer (implemented by
  323. // BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue class) that is size N+1 and stores N elements.
  324. // It is up to the user to ensure that there is enough look ahead for their
  325. // grammar. Currently there is no way to tell if an iterator is pointing
  326. // to forgotten data. The leading iterator will put an item in the queue
  327. // and remove one when it is incremented. No dynamic allocation is done,
  328. // except on creation of the queue (fixed_size_queue constructor).
  329. ///////////////////////////////////////////////////////////////////////////////
  330. template < std::size_t N>
  331. class fixed_size_queue
  332. {
  333. public:
  334. template <typename ValueT>
  335. class inner
  336. {
  337. private:
  338. typedef BOOST_SPIRIT_CLASSIC_NS::fixed_size_queue<ValueT, N> queue_type;
  339. queue_type * queuedElements;
  340. mutable typename queue_type::iterator queuePosition;
  341. protected:
  342. inner()
  343. : queuedElements(new queue_type)
  344. , queuePosition(queuedElements->begin())
  345. {}
  346. inner(inner const& x)
  347. : queuedElements(x.queuedElements)
  348. , queuePosition(x.queuePosition)
  349. {}
  350. // will be called from the destructor of the last iterator.
  351. void destroy()
  352. {
  353. BOOST_SPIRIT_ASSERT(NULL != queuedElements);
  354. delete queuedElements;
  355. queuedElements = 0;
  356. }
  357. void swap(inner& x)
  358. {
  359. impl::mp_swap(queuedElements, x.queuedElements);
  360. impl::mp_swap(queuePosition, x.queuePosition);
  361. }
  362. // This is called when the iterator is dereferenced. It's a template
  363. // method so we can recover the type of the multi_pass iterator
  364. // and access the m_input data member.
  365. template <typename MultiPassT>
  366. static typename MultiPassT::reference dereference(MultiPassT const& mp)
  367. {
  368. if (mp.queuePosition == mp.queuedElements->end())
  369. {
  370. return mp.get_input();
  371. }
  372. else
  373. {
  374. return *mp.queuePosition;
  375. }
  376. }
  377. // This is called when the iterator is incremented. It's a template
  378. // method so we can recover the type of the multi_pass iterator
  379. // and access the m_input data member.
  380. template <typename MultiPassT>
  381. static void increment(MultiPassT& mp)
  382. {
  383. if (mp.queuePosition == mp.queuedElements->end())
  384. {
  385. // don't let the queue get larger than N
  386. if (mp.queuedElements->size() >= N)
  387. mp.queuedElements->pop_front();
  388. mp.queuedElements->push_back(mp.get_input());
  389. mp.advance_input();
  390. }
  391. ++mp.queuePosition;
  392. }
  393. // no-op
  394. void clear_queue()
  395. {}
  396. // called to determine whether the iterator is an eof iterator
  397. template <typename MultiPassT>
  398. static bool is_eof(MultiPassT const& mp)
  399. {
  400. return mp.queuePosition == mp.queuedElements->end() &&
  401. mp.input_at_eof();
  402. }
  403. // called by operator==
  404. bool equal_to(inner const& x) const
  405. {
  406. return queuePosition == x.queuePosition;
  407. }
  408. // called by operator<
  409. bool less_than(inner const& x) const
  410. {
  411. return queuePosition < x.queuePosition;
  412. }
  413. }; // class inner
  414. }; // class fixed_size_queue
  415. ///////////////////////////////////////////////////////////////////////////////
  416. // class input_iterator
  417. // Implementation of the InputPolicy used by multi_pass
  418. // input_iterator encapsulates an input iterator of type InputT
  419. ///////////////////////////////////////////////////////////////////////////////
  420. class input_iterator
  421. {
  422. public:
  423. template <typename InputT>
  424. class inner
  425. {
  426. private:
  427. typedef
  428. typename boost::detail::iterator_traits<InputT>::value_type
  429. result_type;
  430. public:
  431. typedef result_type value_type;
  432. private:
  433. struct Data {
  434. Data(InputT const &input_)
  435. : input(input_), was_initialized(false)
  436. {}
  437. InputT input;
  438. value_type curtok;
  439. bool was_initialized;
  440. };
  441. // Needed by compilers not implementing the resolution to DR45. For
  442. // reference, see
  443. // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
  444. friend struct Data;
  445. public:
  446. typedef
  447. typename boost::detail::iterator_traits<InputT>::difference_type
  448. difference_type;
  449. typedef
  450. typename boost::detail::iterator_traits<InputT>::pointer
  451. pointer;
  452. typedef
  453. typename boost::detail::iterator_traits<InputT>::reference
  454. reference;
  455. protected:
  456. inner()
  457. : data(0)
  458. {}
  459. inner(InputT x)
  460. : data(new Data(x))
  461. {}
  462. inner(inner const& x)
  463. : data(x.data)
  464. {}
  465. void destroy()
  466. {
  467. delete data;
  468. data = 0;
  469. }
  470. bool same_input(inner const& x) const
  471. {
  472. return data == x.data;
  473. }
  474. typedef
  475. typename boost::detail::iterator_traits<InputT>::value_type
  476. value_t;
  477. void swap(inner& x)
  478. {
  479. impl::mp_swap(data, x.data);
  480. }
  481. void ensure_initialized() const
  482. {
  483. if (data && !data->was_initialized) {
  484. data->curtok = *data->input; // get the first token
  485. data->was_initialized = true;
  486. }
  487. }
  488. public:
  489. reference get_input() const
  490. {
  491. BOOST_SPIRIT_ASSERT(NULL != data);
  492. ensure_initialized();
  493. return data->curtok;
  494. }
  495. void advance_input()
  496. {
  497. BOOST_SPIRIT_ASSERT(NULL != data);
  498. data->was_initialized = false; // should get the next token
  499. ++data->input;
  500. }
  501. bool input_at_eof() const
  502. {
  503. return !data || data->input == InputT();
  504. }
  505. private:
  506. Data *data;
  507. };
  508. };
  509. ///////////////////////////////////////////////////////////////////////////////
  510. // class lex_input
  511. // Implementation of the InputPolicy used by multi_pass
  512. // lex_input gets tokens (ints) from yylex()
  513. ///////////////////////////////////////////////////////////////////////////////
  514. class lex_input
  515. {
  516. public:
  517. template <typename InputT>
  518. class inner
  519. {
  520. public:
  521. typedef int value_type;
  522. typedef std::ptrdiff_t difference_type;
  523. typedef int* pointer;
  524. typedef int& reference;
  525. protected:
  526. inner()
  527. : curtok(new int(0))
  528. {}
  529. inner(InputT x)
  530. : curtok(new int(x))
  531. {}
  532. inner(inner const& x)
  533. : curtok(x.curtok)
  534. {}
  535. void destroy()
  536. {
  537. delete curtok;
  538. curtok = 0;
  539. }
  540. bool same_input(inner const& x) const
  541. {
  542. return curtok == x.curtok;
  543. }
  544. void swap(inner& x)
  545. {
  546. impl::mp_swap(curtok, x.curtok);
  547. }
  548. public:
  549. reference get_input() const
  550. {
  551. return *curtok;
  552. }
  553. void advance_input()
  554. {
  555. extern int yylex();
  556. *curtok = yylex();
  557. }
  558. bool input_at_eof() const
  559. {
  560. return *curtok == 0;
  561. }
  562. private:
  563. int* curtok;
  564. };
  565. };
  566. ///////////////////////////////////////////////////////////////////////////////
  567. // class functor_input
  568. // Implementation of the InputPolicy used by multi_pass
  569. // functor_input gets tokens from a functor
  570. // Note: the functor must have a typedef for result_type
  571. // It also must have a static variable of type result_type defined to
  572. // represent eof that is called eof.
  573. ///////////////////////////////////////////////////////////////////////////////
  574. class functor_input
  575. {
  576. public:
  577. template <typename FunctorT>
  578. class inner
  579. {
  580. typedef typename FunctorT::result_type result_type;
  581. public:
  582. typedef result_type value_type;
  583. typedef std::ptrdiff_t difference_type;
  584. typedef result_type* pointer;
  585. typedef result_type& reference;
  586. protected:
  587. inner()
  588. : ftor(0)
  589. , curtok(0)
  590. {}
  591. inner(FunctorT const& x)
  592. : ftor(new FunctorT(x))
  593. , curtok(new result_type((*ftor)()))
  594. {}
  595. inner(inner const& x)
  596. : ftor(x.ftor)
  597. , curtok(x.curtok)
  598. {}
  599. void destroy()
  600. {
  601. delete ftor;
  602. ftor = 0;
  603. delete curtok;
  604. curtok = 0;
  605. }
  606. bool same_input(inner const& x) const
  607. {
  608. return ftor == x.ftor;
  609. }
  610. void swap(inner& x)
  611. {
  612. impl::mp_swap(curtok, x.curtok);
  613. impl::mp_swap(ftor, x.ftor);
  614. }
  615. public:
  616. reference get_input() const
  617. {
  618. return *curtok;
  619. }
  620. void advance_input()
  621. {
  622. if (curtok) {
  623. *curtok = (*ftor)();
  624. }
  625. }
  626. bool input_at_eof() const
  627. {
  628. return !curtok || *curtok == ftor->eof;
  629. }
  630. FunctorT& get_functor() const
  631. {
  632. return *ftor;
  633. }
  634. private:
  635. FunctorT* ftor;
  636. result_type* curtok;
  637. };
  638. };
  639. } // namespace multi_pass_policies
  640. ///////////////////////////////////////////////////////////////////////////////
  641. // iterator_base_creator
  642. ///////////////////////////////////////////////////////////////////////////////
  643. namespace iterator_ { namespace impl {
  644. // Meta-function to generate a std::iterator<> base class for multi_pass. This
  645. // is used mainly to improve conformance of compilers not supporting PTS
  646. // and thus relying on inheritance to recognize an iterator.
  647. // We are using boost::iterator<> because it offers an automatic workaround
  648. // for broken std::iterator<> implementations.
  649. template <typename InputPolicyT, typename InputT>
  650. struct iterator_base_creator
  651. {
  652. typedef typename InputPolicyT::BOOST_NESTED_TEMPLATE inner<InputT> input_t;
  653. typedef boost::iterator
  654. <
  655. std::forward_iterator_tag,
  656. typename input_t::value_type,
  657. typename input_t::difference_type,
  658. typename input_t::pointer,
  659. typename input_t::reference
  660. > type;
  661. };
  662. }}
  663. ///////////////////////////////////////////////////////////////////////////////
  664. // class template multi_pass
  665. ///////////////////////////////////////////////////////////////////////////////
  666. // The default multi_pass instantiation uses a ref-counted std_deque scheme.
  667. template
  668. <
  669. typename InputT,
  670. typename InputPolicy,
  671. typename OwnershipPolicy,
  672. typename CheckingPolicy,
  673. typename StoragePolicy
  674. >
  675. class multi_pass
  676. : public OwnershipPolicy
  677. , public CheckingPolicy
  678. , public StoragePolicy::template inner<
  679. typename InputPolicy::template inner<InputT>::value_type>
  680. , public InputPolicy::template inner<InputT>
  681. , public iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
  682. {
  683. typedef OwnershipPolicy OP;
  684. typedef CheckingPolicy CHP;
  685. typedef typename StoragePolicy::template inner<
  686. typename InputPolicy::template inner<InputT>::value_type> SP;
  687. typedef typename InputPolicy::template inner<InputT> IP;
  688. typedef typename
  689. iterator_::impl::iterator_base_creator<InputPolicy, InputT>::type
  690. IB;
  691. public:
  692. typedef typename IB::value_type value_type;
  693. typedef typename IB::difference_type difference_type;
  694. typedef typename IB::reference reference;
  695. typedef typename IB::pointer pointer;
  696. typedef InputT iterator_type;
  697. multi_pass();
  698. explicit multi_pass(InputT input);
  699. #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  700. multi_pass(int);
  701. #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  702. ~multi_pass();
  703. multi_pass(multi_pass const&);
  704. multi_pass& operator=(multi_pass const&);
  705. void swap(multi_pass& x);
  706. reference operator*() const;
  707. pointer operator->() const;
  708. multi_pass& operator++();
  709. multi_pass operator++(int);
  710. void clear_queue();
  711. bool operator==(const multi_pass& y) const;
  712. bool operator<(const multi_pass& y) const;
  713. private: // helper functions
  714. bool is_eof() const;
  715. };
  716. template
  717. <
  718. typename InputT,
  719. typename InputPolicy,
  720. typename OwnershipPolicy,
  721. typename CheckingPolicy,
  722. typename StoragePolicy
  723. >
  724. inline
  725. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  726. multi_pass()
  727. : OP()
  728. , CHP()
  729. , SP()
  730. , IP()
  731. {
  732. }
  733. template
  734. <
  735. typename InputT,
  736. typename InputPolicy,
  737. typename OwnershipPolicy,
  738. typename CheckingPolicy,
  739. typename StoragePolicy
  740. >
  741. inline
  742. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  743. multi_pass(InputT input)
  744. : OP()
  745. , CHP()
  746. , SP()
  747. , IP(input)
  748. {
  749. }
  750. #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  751. // The standard library shipped with gcc-3.1 has a bug in
  752. // bits/basic_string.tcc. It tries to use iter::iter(0) to
  753. // construct an iterator. Ironically, this happens in sanity
  754. // checking code that isn't required by the standard.
  755. // The workaround is to provide an additional constructor that
  756. // ignores its int argument and behaves like the default constructor.
  757. template
  758. <
  759. typename InputT,
  760. typename InputPolicy,
  761. typename OwnershipPolicy,
  762. typename CheckingPolicy,
  763. typename StoragePolicy
  764. >
  765. inline
  766. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  767. multi_pass(int)
  768. : OP()
  769. , CHP()
  770. , SP()
  771. , IP()
  772. {
  773. }
  774. #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  775. template
  776. <
  777. typename InputT,
  778. typename InputPolicy,
  779. typename OwnershipPolicy,
  780. typename CheckingPolicy,
  781. typename StoragePolicy
  782. >
  783. inline
  784. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  785. ~multi_pass()
  786. {
  787. if (OP::release())
  788. {
  789. CHP::destroy();
  790. SP::destroy();
  791. IP::destroy();
  792. }
  793. }
  794. template
  795. <
  796. typename InputT,
  797. typename InputPolicy,
  798. typename OwnershipPolicy,
  799. typename CheckingPolicy,
  800. typename StoragePolicy
  801. >
  802. inline
  803. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  804. multi_pass(
  805. multi_pass const& x)
  806. : OP(x)
  807. , CHP(x)
  808. , SP(x)
  809. , IP(x)
  810. {
  811. OP::clone();
  812. }
  813. template
  814. <
  815. typename InputT,
  816. typename InputPolicy,
  817. typename OwnershipPolicy,
  818. typename CheckingPolicy,
  819. typename StoragePolicy
  820. >
  821. inline
  822. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
  823. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  824. operator=(
  825. multi_pass const& x)
  826. {
  827. multi_pass temp(x);
  828. temp.swap(*this);
  829. return *this;
  830. }
  831. template
  832. <
  833. typename InputT,
  834. typename InputPolicy,
  835. typename OwnershipPolicy,
  836. typename CheckingPolicy,
  837. typename StoragePolicy
  838. >
  839. inline void
  840. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  841. swap(multi_pass& x)
  842. {
  843. OP::swap(x);
  844. CHP::swap(x);
  845. SP::swap(x);
  846. IP::swap(x);
  847. }
  848. template
  849. <
  850. typename InputT,
  851. typename InputPolicy,
  852. typename OwnershipPolicy,
  853. typename CheckingPolicy,
  854. typename StoragePolicy
  855. >
  856. inline
  857. typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  858. reference
  859. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  860. operator*() const
  861. {
  862. CHP::check();
  863. return SP::dereference(*this);
  864. }
  865. template
  866. <
  867. typename InputT,
  868. typename InputPolicy,
  869. typename OwnershipPolicy,
  870. typename CheckingPolicy,
  871. typename StoragePolicy
  872. >
  873. inline
  874. typename multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  875. pointer
  876. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  877. operator->() const
  878. {
  879. return &(operator*());
  880. }
  881. template
  882. <
  883. typename InputT,
  884. typename InputPolicy,
  885. typename OwnershipPolicy,
  886. typename CheckingPolicy,
  887. typename StoragePolicy
  888. >
  889. inline
  890. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>&
  891. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  892. operator++()
  893. {
  894. CHP::check();
  895. SP::increment(*this);
  896. return *this;
  897. }
  898. template
  899. <
  900. typename InputT,
  901. typename InputPolicy,
  902. typename OwnershipPolicy,
  903. typename CheckingPolicy,
  904. typename StoragePolicy
  905. >
  906. inline
  907. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>
  908. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  909. operator++(int)
  910. {
  911. multi_pass
  912. <
  913. InputT,
  914. InputPolicy,
  915. OwnershipPolicy,
  916. CheckingPolicy,
  917. StoragePolicy
  918. > tmp(*this);
  919. ++*this;
  920. return tmp;
  921. }
  922. template
  923. <
  924. typename InputT,
  925. typename InputPolicy,
  926. typename OwnershipPolicy,
  927. typename CheckingPolicy,
  928. typename StoragePolicy
  929. >
  930. inline void
  931. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  932. clear_queue()
  933. {
  934. SP::clear_queue();
  935. CHP::clear_queue();
  936. }
  937. template
  938. <
  939. typename InputT,
  940. typename InputPolicy,
  941. typename OwnershipPolicy,
  942. typename CheckingPolicy,
  943. typename StoragePolicy
  944. >
  945. inline bool
  946. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  947. is_eof() const
  948. {
  949. return SP::is_eof(*this);
  950. }
  951. ///// Comparisons
  952. template
  953. <
  954. typename InputT,
  955. typename InputPolicy,
  956. typename OwnershipPolicy,
  957. typename CheckingPolicy,
  958. typename StoragePolicy
  959. >
  960. inline bool
  961. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  962. operator==(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  963. StoragePolicy>& y) const
  964. {
  965. bool is_eof_ = SP::is_eof(*this);
  966. bool y_is_eof_ = SP::is_eof(y);
  967. if (is_eof_ && y_is_eof_)
  968. {
  969. return true; // both are EOF
  970. }
  971. else if (is_eof_ ^ y_is_eof_)
  972. {
  973. return false; // one is EOF, one isn't
  974. }
  975. else if (!IP::same_input(y))
  976. {
  977. return false;
  978. }
  979. else
  980. {
  981. return SP::equal_to(y);
  982. }
  983. }
  984. template
  985. <
  986. typename InputT,
  987. typename InputPolicy,
  988. typename OwnershipPolicy,
  989. typename CheckingPolicy,
  990. typename StoragePolicy
  991. >
  992. inline bool
  993. multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy>::
  994. operator<(const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  995. StoragePolicy>& y) const
  996. {
  997. return SP::less_than(y);
  998. }
  999. template
  1000. <
  1001. typename InputT,
  1002. typename InputPolicy,
  1003. typename OwnershipPolicy,
  1004. typename CheckingPolicy,
  1005. typename StoragePolicy
  1006. >
  1007. inline
  1008. bool operator!=(
  1009. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1010. StoragePolicy>& x,
  1011. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1012. StoragePolicy>& y)
  1013. {
  1014. return !(x == y);
  1015. }
  1016. template
  1017. <
  1018. typename InputT,
  1019. typename InputPolicy,
  1020. typename OwnershipPolicy,
  1021. typename CheckingPolicy,
  1022. typename StoragePolicy
  1023. >
  1024. inline
  1025. bool operator>(
  1026. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1027. StoragePolicy>& x,
  1028. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1029. StoragePolicy>& y)
  1030. {
  1031. return y < x;
  1032. }
  1033. template
  1034. <
  1035. typename InputT,
  1036. typename InputPolicy,
  1037. typename OwnershipPolicy,
  1038. typename CheckingPolicy,
  1039. typename StoragePolicy
  1040. >
  1041. inline
  1042. bool operator>=(
  1043. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1044. StoragePolicy>& x,
  1045. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1046. StoragePolicy>& y)
  1047. {
  1048. return !(x < y);
  1049. }
  1050. template
  1051. <
  1052. typename InputT,
  1053. typename InputPolicy,
  1054. typename OwnershipPolicy,
  1055. typename CheckingPolicy,
  1056. typename StoragePolicy
  1057. >
  1058. inline
  1059. bool operator<=(
  1060. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1061. StoragePolicy>& x,
  1062. const multi_pass<InputT, InputPolicy, OwnershipPolicy, CheckingPolicy,
  1063. StoragePolicy>& y)
  1064. {
  1065. return !(y < x);
  1066. }
  1067. ///// Generator function
  1068. template <typename InputT>
  1069. inline multi_pass<InputT,
  1070. multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
  1071. multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>
  1072. make_multi_pass(InputT i)
  1073. {
  1074. return multi_pass<InputT,
  1075. multi_pass_policies::input_iterator, multi_pass_policies::ref_counted,
  1076. multi_pass_policies::buf_id_check, multi_pass_policies::std_deque>(i);
  1077. }
  1078. // this could be a template typedef, since such a thing doesn't
  1079. // exist in C++, we'll use inheritance to accomplish the same thing.
  1080. template <typename InputT, std::size_t N>
  1081. class look_ahead :
  1082. public multi_pass<
  1083. InputT,
  1084. multi_pass_policies::input_iterator,
  1085. multi_pass_policies::first_owner,
  1086. multi_pass_policies::no_check,
  1087. multi_pass_policies::fixed_size_queue<N> >
  1088. {
  1089. typedef multi_pass<
  1090. InputT,
  1091. multi_pass_policies::input_iterator,
  1092. multi_pass_policies::first_owner,
  1093. multi_pass_policies::no_check,
  1094. multi_pass_policies::fixed_size_queue<N> > base_t;
  1095. public:
  1096. look_ahead()
  1097. : base_t() {}
  1098. explicit look_ahead(InputT x)
  1099. : base_t(x) {}
  1100. look_ahead(look_ahead const& x)
  1101. : base_t(x) {}
  1102. #if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  1103. look_ahead(int) // workaround for a bug in the library
  1104. : base_t() {} // shipped with gcc 3.1
  1105. #endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
  1106. // default generated operators destructor and assignment operator are okay.
  1107. };
  1108. template
  1109. <
  1110. typename InputT,
  1111. typename InputPolicy,
  1112. typename OwnershipPolicy,
  1113. typename CheckingPolicy,
  1114. typename StoragePolicy
  1115. >
  1116. void swap(
  1117. multi_pass<
  1118. InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
  1119. > &x,
  1120. multi_pass<
  1121. InputT, InputPolicy, OwnershipPolicy, CheckingPolicy, StoragePolicy
  1122. > &y)
  1123. {
  1124. x.swap(y);
  1125. }
  1126. namespace impl {
  1127. template <typename T>
  1128. inline void mp_swap(T& t1, T& t2)
  1129. {
  1130. using std::swap;
  1131. using BOOST_SPIRIT_CLASSIC_NS::swap;
  1132. swap(t1, t2);
  1133. }
  1134. }
  1135. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  1136. }} // namespace BOOST_SPIRIT_CLASSIC_NS
  1137. #endif // BOOST_SPIRIT_ITERATOR_MULTI_PASS_HPP