1 // Copyright (c) 2001, Daniel C. Nuffer 2 // Copyright (c) 2001-2011 Hartmut Kaiser 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 #if !defined(BOOST_SPIRIT_ITERATOR_BUF_ID_CHECK_POLICY_MAR_16_2007_1108AM) 8 #define BOOST_SPIRIT_ITERATOR_BUF_ID_CHECK_POLICY_MAR_16_2007_1108AM 9 10 #include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp> 11 #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp> 12 #include <boost/config.hpp> 13 #include <boost/throw_exception.hpp> 14 #include <exception> // for std::exception 15 16 namespace boost { namespace spirit { namespace iterator_policies 17 { 18 /////////////////////////////////////////////////////////////////////////// 19 // class illegal_backtracking 20 // thrown by buf_id_check CheckingPolicy if an instance of an iterator is 21 // used after another one has invalidated the queue 22 /////////////////////////////////////////////////////////////////////////// 23 class BOOST_SYMBOL_VISIBLE illegal_backtracking : public std::exception 24 { 25 public: illegal_backtracking()26 illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW {} ~illegal_backtracking()27 ~illegal_backtracking() BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE {} 28 what() const29 char const* what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE 30 { 31 return "boost::spirit::multi_pass::illegal_backtracking"; 32 } 33 }; 34 35 /////////////////////////////////////////////////////////////////////////////// 36 // class buf_id_check 37 // Implementation of the CheckingPolicy used by multi_pass 38 // This policy is most effective when used together with the std_deque 39 // StoragePolicy. 40 // 41 // If used with the fixed_size_queue StoragePolicy, it will not detect 42 // iterator dereferences that are out of the range of the queue. 43 /////////////////////////////////////////////////////////////////////////////// 44 struct buf_id_check 45 { 46 /////////////////////////////////////////////////////////////////////// 47 struct unique //: detail::default_checking_policy 48 { uniqueboost::spirit::iterator_policies::buf_id_check::unique49 unique() : buf_id(0) {} uniqueboost::spirit::iterator_policies::buf_id_check::unique50 unique(unique const& x) : buf_id(x.buf_id) {} 51 swapboost::spirit::iterator_policies::buf_id_check::unique52 void swap(unique& x) 53 { 54 boost::swap(buf_id, x.buf_id); 55 } 56 57 // called to verify that everything is ok. 58 template <typename MultiPass> docheckboost::spirit::iterator_policies::buf_id_check::unique59 static void docheck(MultiPass const& mp) 60 { 61 if (mp.buf_id != mp.shared()->shared_buf_id) 62 boost::throw_exception(illegal_backtracking()); 63 } 64 65 // called from multi_pass::clear_queue, so we can increment the count 66 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::buf_id_check::unique67 static void clear_queue(MultiPass& mp) 68 { 69 ++mp.shared()->shared_buf_id; 70 ++mp.buf_id; 71 } 72 73 template <typename MultiPass> destroyboost::spirit::iterator_policies::buf_id_check::unique74 static void destroy(MultiPass&) {} 75 76 protected: 77 unsigned long buf_id; 78 }; 79 80 /////////////////////////////////////////////////////////////////////// 81 struct shared 82 { sharedboost::spirit::iterator_policies::buf_id_check::shared83 shared() : shared_buf_id(0) {} 84 unsigned long shared_buf_id; 85 }; 86 }; 87 88 }}} 89 90 #endif 91