1 /*============================================================================= 2 Boost.Wave: A Standard compliant C++ preprocessor library 3 4 Definition of the unput queue iterator 5 6 http://www.boost.org/ 7 8 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost 9 Software License, Version 1.0. (See accompanying file 10 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 =============================================================================*/ 12 #if !defined(BOOST_UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED) 13 #define BOOST_UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED 14 15 #include <list> 16 17 #include <boost/assert.hpp> 18 #include <boost/iterator_adaptors.hpp> 19 20 #include <boost/wave/wave_config.hpp> 21 #include <boost/wave/token_ids.hpp> // token_id 22 23 // this must occur after all of the includes and before any code appears 24 #ifdef BOOST_HAS_ABI_HEADERS 25 #include BOOST_ABI_PREFIX 26 #endif 27 28 /////////////////////////////////////////////////////////////////////////////// 29 namespace boost { 30 namespace wave { 31 namespace util { 32 33 /////////////////////////////////////////////////////////////////////////////// 34 // 35 // unput_queue_iterator 36 // 37 // The unput_queue_iterator templates encapsulates an unput_queue together 38 // with the direct input to be read after the unput queue is emptied 39 // 40 // This version is for the new iterator_adaptors (was released with 41 // Boost V1.31.0) 42 // 43 /////////////////////////////////////////////////////////////////////////////// 44 template <typename IteratorT, typename TokenT, typename ContainerT> 45 class unput_queue_iterator 46 : public boost::iterator_adaptor< 47 unput_queue_iterator<IteratorT, TokenT, ContainerT>, 48 IteratorT, TokenT const, std::forward_iterator_tag> 49 { 50 typedef boost::iterator_adaptor< 51 unput_queue_iterator<IteratorT, TokenT, ContainerT>, 52 IteratorT, TokenT const, std::forward_iterator_tag> 53 base_type; 54 55 public: 56 typedef ContainerT container_type; 57 typedef IteratorT iterator_type; 58 unput_queue_iterator(IteratorT const & it,ContainerT & queue)59 unput_queue_iterator(IteratorT const &it, ContainerT &queue) 60 : base_type(it), unput_queue(queue) 61 {} 62 get_unput_queue()63 ContainerT &get_unput_queue() 64 { return unput_queue; } get_unput_queue() const65 ContainerT const &get_unput_queue() const 66 { return unput_queue; } get_base_iterator()67 IteratorT &get_base_iterator() 68 { return base_type::base_reference(); } get_base_iterator() const69 IteratorT const &get_base_iterator() const 70 { return base_type::base_reference(); } 71 operator =(unput_queue_iterator const & rhs)72 unput_queue_iterator &operator= (unput_queue_iterator const &rhs) 73 { 74 if (this != &rhs) { 75 unput_queue = rhs.unput_queue; 76 base_type::operator=(rhs); 77 } 78 return *this; 79 } 80 dereference() const81 typename base_type::reference dereference() const 82 { 83 if (!unput_queue.empty()) 84 return unput_queue.front(); 85 return *base_type::base_reference(); 86 } 87 increment()88 void increment() 89 { 90 if (!unput_queue.empty()) { 91 // there exist pending tokens in the unput queue 92 unput_queue.pop_front(); 93 } 94 else { 95 // the unput_queue is empty, so advance the base iterator 96 ++base_type::base_reference(); 97 } 98 } 99 100 template < 101 typename OtherDerivedT, typename OtherIteratorT, 102 typename V, typename C, typename R, typename D 103 > equal(boost::iterator_adaptor<OtherDerivedT,OtherIteratorT,V,C,R,D> const & x) const104 bool equal( 105 boost::iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D> 106 const &x) const 107 { 108 // two iterators are equal, if both begin() iterators of the queue 109 // objects are equal and the base iterators are equal as well 110 OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x); 111 return 112 ((unput_queue.empty() && rhs.unput_queue.empty()) || 113 (&unput_queue == &rhs.unput_queue && 114 unput_queue.begin() == rhs.unput_queue.begin() 115 ) 116 ) && 117 (get_base_iterator() == rhs.get_base_iterator()); 118 } 119 120 private: 121 ContainerT &unput_queue; 122 }; 123 124 namespace impl { 125 126 /////////////////////////////////////////////////////////////////////////// 127 template <typename IteratorT, typename TokenT, typename ContainerT> 128 struct gen_unput_queue_iterator 129 { 130 typedef ContainerT container_type; 131 typedef IteratorT iterator_type; 132 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> 133 return_type; 134 135 static container_type last; 136 137 static return_type generateboost::wave::util::impl::gen_unput_queue_iterator138 generate(iterator_type const &it) 139 { 140 return return_type(it, last); 141 } 142 143 static return_type generateboost::wave::util::impl::gen_unput_queue_iterator144 generate(ContainerT &queue, iterator_type const &it) 145 { 146 return return_type(it, queue); 147 } 148 }; 149 150 template <typename IteratorT, typename TokenT, typename ContainerT> 151 typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>:: 152 container_type 153 gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>::last = 154 typename gen_unput_queue_iterator<IteratorT, TokenT, ContainerT>:: 155 container_type(); 156 157 /////////////////////////////////////////////////////////////////////////// 158 template <typename IteratorT, typename TokenT, typename ContainerT> 159 struct gen_unput_queue_iterator< 160 unput_queue_iterator<IteratorT, TokenT, ContainerT>, 161 TokenT, ContainerT> 162 { 163 typedef ContainerT container_type; 164 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> 165 iterator_type; 166 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> 167 return_type; 168 169 static container_type last; 170 171 static return_type generateboost::wave::util::impl::gen_unput_queue_iterator172 generate(iterator_type &it) 173 { 174 return return_type(it.base(), last); 175 } 176 177 static return_type generateboost::wave::util::impl::gen_unput_queue_iterator178 generate(ContainerT &queue, iterator_type &it) 179 { 180 return return_type(it.base(), queue); 181 } 182 }; 183 184 /////////////////////////////////////////////////////////////////////////// 185 template <typename IteratorT> 186 struct assign_iterator 187 { 188 static void do_boost::wave::util::impl::assign_iterator189 do_ (IteratorT &dest, IteratorT const &src) 190 { 191 dest = src; 192 } 193 }; 194 195 /////////////////////////////////////////////////////////////////////////// 196 // 197 // Look for the first non-whitespace token and return this token id. 198 // Note though, that the embedded unput_queues are not touched in any way! 199 // 200 template <typename IteratorT> 201 struct next_token 202 { 203 static boost::wave::token_id peekboost::wave::util::impl::next_token204 peek(IteratorT it, IteratorT end, bool skip_whitespace = true) 205 { 206 using namespace boost::wave; 207 if (skip_whitespace) { 208 for (++it; it != end; ++it) { 209 if (!IS_CATEGORY(*it, WhiteSpaceTokenType) && 210 T_NEWLINE != token_id(*it)) 211 { 212 break; // stop at the first non-whitespace token 213 } 214 } 215 } 216 else { 217 ++it; // we have at least to look ahead 218 } 219 if (it != end) 220 return token_id(*it); 221 return T_EOI; 222 } 223 }; 224 225 template <typename IteratorT, typename TokenT, typename ContainerT> 226 struct next_token< 227 unput_queue_iterator<IteratorT, TokenT, ContainerT> > { 228 229 typedef unput_queue_iterator<IteratorT, TokenT, ContainerT> iterator_type; 230 231 static boost::wave::token_id peekboost::wave::util::impl::next_token232 peek(iterator_type it, iterator_type end, bool skip_whitespace = true) 233 { 234 using namespace boost::wave; 235 236 typename iterator_type::container_type &queue = it.get_unput_queue(); 237 238 // first try to find it in the unput_queue 239 if (0 != queue.size()) { 240 typename iterator_type::container_type::iterator cit = queue.begin(); 241 typename iterator_type::container_type::iterator cend = queue.end(); 242 243 if (skip_whitespace) { 244 for (++cit; cit != cend; ++cit) { 245 if (!IS_CATEGORY(*cit, WhiteSpaceTokenType) && 246 T_NEWLINE != token_id(*cit)) 247 { 248 break; // stop at the first non-whitespace token 249 } 250 } 251 } 252 else { 253 ++cit; // we have at least to look ahead 254 } 255 if (cit != cend) 256 return token_id(*cit); 257 } 258 259 // second try to move on into the base iterator stream 260 typename iterator_type::iterator_type base_it = it.get_base_iterator(); 261 typename iterator_type::iterator_type base_end = end.get_base_iterator(); 262 263 if (0 == queue.size()) 264 ++base_it; // advance, if the unput queue is empty 265 266 if (skip_whitespace) { 267 for (/**/; base_it != base_end; ++base_it) { 268 if (!IS_CATEGORY(*base_it, WhiteSpaceTokenType) && 269 T_NEWLINE != token_id(*base_it)) 270 { 271 break; // stop at the first non-whitespace token 272 } 273 } 274 } 275 if (base_it == base_end) 276 return T_EOI; 277 278 return token_id(*base_it); 279 } 280 }; 281 282 /////////////////////////////////////////////////////////////////////////////// 283 } // namespace impl 284 285 /////////////////////////////////////////////////////////////////////////////// 286 } // namespace util 287 } // namespace wave 288 } // namespace boost 289 290 // the suffix header occurs after all of the code 291 #ifdef BOOST_HAS_ABI_HEADERS 292 #include BOOST_ABI_SUFFIX 293 #endif 294 295 #endif // !defined(BOOST_UNPUT_QUEUE_ITERATOR_HPP_76DA23D0_4893_4AD5_ABCC_6CED7CFB89BC_INCLUDED) 296