1 // Copyright (c) 2001-2012 Hartmut Kaiser 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #if !defined(BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM) 7 #define BOOST_SPIRIT_ITERATOR_COMBINE_POLICIES_APR_06_2008_0136PM 8 9 #include <boost/config.hpp> 10 #include <boost/type_traits/is_empty.hpp> 11 12 namespace boost { namespace spirit { namespace iterator_policies 13 { 14 /////////////////////////////////////////////////////////////////////////// 15 // The purpose of the multi_pass_unique template is to eliminate 16 // empty policy classes (policies not containing any data items) from the 17 // multiple inheritance chain. This is necessary since some compilers 18 // fail to apply the empty base optimization if multiple inheritance is 19 // involved. 20 // Additionally this can be used to combine separate policies into one 21 // single multi_pass_policy as required by the multi_pass template 22 /////////////////////////////////////////////////////////////////////////// 23 24 /////////////////////////////////////////////////////////////////////////// 25 // select the correct derived classes based on if a policy is empty 26 template <typename T 27 , typename Ownership, typename Checking, typename Input, typename Storage 28 , bool OwnershipIsEmpty = boost::is_empty<Ownership>::value 29 , bool CheckingIsEmpty = boost::is_empty<Checking>::value 30 , bool InputIsEmpty = boost::is_empty<Input>::value> 31 struct multi_pass_unique; 32 33 /////////////////////////////////////////////////////////////////////////// 34 template <typename T, typename Ownership, typename Checking 35 , typename Input, typename Storage> 36 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 37 , false, false, false> 38 : Ownership, Checking, Input, Storage 39 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique40 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique41 multi_pass_unique(T& x) : Input(x) {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique42 multi_pass_unique(T const& x) : Input(x) {} 43 44 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique45 static void destroy(MultiPass& mp) 46 { 47 Ownership::destroy(mp); 48 Checking::destroy(mp); 49 Input::destroy(mp); 50 Storage::destroy(mp); 51 } 52 swapboost::spirit::iterator_policies::multi_pass_unique53 void swap(multi_pass_unique& x) 54 { 55 this->Ownership::swap(x); 56 this->Checking::swap(x); 57 this->Input::swap(x); 58 this->Storage::swap(x); 59 } 60 61 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique62 inline static void clear_queue(MultiPass& mp) 63 { 64 Checking::clear_queue(mp); 65 Storage::clear_queue(mp); 66 } 67 }; 68 69 /////////////////////////////////////////////////////////////////////////// 70 template <typename T, typename Ownership, typename Checking 71 , typename Input, typename Storage> 72 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 73 , false, false, true> 74 : Ownership, Checking, Storage 75 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique76 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique77 multi_pass_unique(T const&) {} 78 79 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique80 static void destroy(MultiPass& mp) 81 { 82 Ownership::destroy(mp); 83 Checking::destroy(mp); 84 Input::destroy(mp); 85 Storage::destroy(mp); 86 } 87 swapboost::spirit::iterator_policies::multi_pass_unique88 void swap(multi_pass_unique& x) 89 { 90 this->Ownership::swap(x); 91 this->Checking::swap(x); 92 this->Storage::swap(x); 93 } 94 95 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique96 inline static void clear_queue(MultiPass& mp) 97 { 98 Checking::clear_queue(mp); 99 Storage::clear_queue(mp); 100 } 101 102 // implement input policy functions by forwarding to the Input type 103 template <typename MultiPass> advance_inputboost::spirit::iterator_policies::multi_pass_unique104 inline static void advance_input(MultiPass& mp) 105 { Input::advance_input(mp); } 106 107 template <typename MultiPass> get_inputboost::spirit::iterator_policies::multi_pass_unique108 inline static typename MultiPass::reference get_input(MultiPass& mp) 109 { return Input::get_input(mp); } 110 111 template <typename MultiPass> input_at_eofboost::spirit::iterator_policies::multi_pass_unique112 inline static bool input_at_eof(MultiPass const& mp) 113 { return Input::input_at_eof(mp); } 114 115 template <typename MultiPass, typename TokenType> input_is_validboost::spirit::iterator_policies::multi_pass_unique116 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) 117 { return Input::input_is_valid(mp, curtok); } 118 }; 119 120 /////////////////////////////////////////////////////////////////////////// 121 template <typename T, typename Ownership, typename Checking 122 , typename Input, typename Storage> 123 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 124 , false, true, false> 125 : Ownership, Input, Storage 126 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique127 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique128 multi_pass_unique(T& x) : Input(x) {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique129 multi_pass_unique(T const& x) : Input(x) {} 130 131 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique132 static void destroy(MultiPass& mp) 133 { 134 Ownership::destroy(mp); 135 Input::destroy(mp); 136 Storage::destroy(mp); 137 } 138 swapboost::spirit::iterator_policies::multi_pass_unique139 void swap(multi_pass_unique& x) 140 { 141 this->Ownership::swap(x); 142 this->Input::swap(x); 143 this->Storage::swap(x); 144 } 145 146 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique147 inline static void clear_queue(MultiPass& mp) 148 { 149 Checking::clear_queue(mp); 150 Storage::clear_queue(mp); 151 } 152 153 // checking policy functions are forwarded to the Checking type 154 template <typename MultiPass> docheckboost::spirit::iterator_policies::multi_pass_unique155 inline static void docheck(MultiPass const& mp) 156 { Checking::docheck(mp); } 157 }; 158 159 /////////////////////////////////////////////////////////////////////////// 160 template <typename T, typename Ownership, typename Checking 161 , typename Input, typename Storage> 162 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 163 , false, true, true> 164 : Ownership, Storage 165 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique166 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique167 multi_pass_unique(T const&) {} 168 169 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique170 static void destroy(MultiPass& mp) 171 { 172 Ownership::destroy(mp); 173 Input::destroy(mp); 174 Storage::destroy(mp); 175 } 176 swapboost::spirit::iterator_policies::multi_pass_unique177 void swap(multi_pass_unique& x) 178 { 179 this->Ownership::swap(x); 180 this->Storage::swap(x); 181 } 182 183 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique184 inline static void clear_queue(MultiPass& mp) 185 { 186 Checking::clear_queue(mp); 187 Storage::clear_queue(mp); 188 } 189 190 // implement input policy functions by forwarding to the Input type 191 template <typename MultiPass> advance_inputboost::spirit::iterator_policies::multi_pass_unique192 inline static void advance_input(MultiPass& mp) 193 { Input::advance_input(mp); } 194 195 template <typename MultiPass> get_inputboost::spirit::iterator_policies::multi_pass_unique196 inline static typename MultiPass::reference get_input(MultiPass& mp) 197 { return Input::get_input(mp); } 198 199 template <typename MultiPass> input_at_eofboost::spirit::iterator_policies::multi_pass_unique200 inline static bool input_at_eof(MultiPass const& mp) 201 { return Input::input_at_eof(mp); } 202 203 template <typename MultiPass, typename TokenType> input_is_validboost::spirit::iterator_policies::multi_pass_unique204 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) 205 { return Input::input_is_valid(mp, curtok); } 206 207 // checking policy functions are forwarded to the Checking type 208 template <typename MultiPass> docheckboost::spirit::iterator_policies::multi_pass_unique209 inline static void docheck(MultiPass const& mp) 210 { Checking::docheck(mp); } 211 }; 212 213 /////////////////////////////////////////////////////////////////////////// 214 template <typename T, typename Ownership, typename Checking 215 , typename Input, typename Storage> 216 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 217 , true, false, false> 218 : Checking, Input, Storage 219 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique220 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique221 multi_pass_unique(T& x) : Input(x) {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique222 multi_pass_unique(T const& x) : Input(x) {} 223 224 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique225 static void destroy(MultiPass& mp) 226 { 227 Checking::destroy(mp); 228 Input::destroy(mp); 229 Storage::destroy(mp); 230 } 231 swapboost::spirit::iterator_policies::multi_pass_unique232 void swap(multi_pass_unique& x) 233 { 234 this->Checking::swap(x); 235 this->Input::swap(x); 236 this->Storage::swap(x); 237 } 238 239 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique240 inline static void clear_queue(MultiPass& mp) 241 { 242 Checking::clear_queue(mp); 243 Storage::clear_queue(mp); 244 } 245 246 // ownership policy functions are forwarded to the Ownership type 247 template <typename MultiPass> cloneboost::spirit::iterator_policies::multi_pass_unique248 inline static void clone(MultiPass& mp) 249 { Ownership::clone(mp); } 250 251 template <typename MultiPass> releaseboost::spirit::iterator_policies::multi_pass_unique252 inline static bool release(MultiPass& mp) 253 { return Ownership::release(mp); } 254 255 template <typename MultiPass> is_uniqueboost::spirit::iterator_policies::multi_pass_unique256 inline static bool is_unique(MultiPass const& mp) 257 { return Ownership::is_unique(mp); } 258 }; 259 260 /////////////////////////////////////////////////////////////////////////// 261 template <typename T, typename Ownership, typename Checking 262 , typename Input, typename Storage> 263 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 264 , true, false, true> 265 : Checking, Storage 266 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique267 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique268 multi_pass_unique(T const&) {} 269 270 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique271 static void destroy(MultiPass& mp) 272 { 273 Checking::destroy(mp); 274 Input::destroy(mp); 275 Storage::destroy(mp); 276 } 277 swapboost::spirit::iterator_policies::multi_pass_unique278 void swap(multi_pass_unique& x) 279 { 280 this->Checking::swap(x); 281 this->Storage::swap(x); 282 } 283 284 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique285 inline static void clear_queue(MultiPass& mp) 286 { 287 Checking::clear_queue(mp); 288 Storage::clear_queue(mp); 289 } 290 291 // implement input policy functions by forwarding to the Input type 292 template <typename MultiPass> advance_inputboost::spirit::iterator_policies::multi_pass_unique293 inline static void advance_input(MultiPass& mp) 294 { Input::advance_input(mp); } 295 296 template <typename MultiPass> get_inputboost::spirit::iterator_policies::multi_pass_unique297 inline static typename MultiPass::reference get_input(MultiPass& mp) 298 { return Input::get_input(mp); } 299 300 template <typename MultiPass> input_at_eofboost::spirit::iterator_policies::multi_pass_unique301 inline static bool input_at_eof(MultiPass const& mp) 302 { return Input::input_at_eof(mp); } 303 304 template <typename MultiPass, typename TokenType> input_is_validboost::spirit::iterator_policies::multi_pass_unique305 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) 306 { return Input::input_is_valid(mp, curtok); } 307 308 // ownership policy functions are forwarded to the Ownership type 309 template <typename MultiPass> cloneboost::spirit::iterator_policies::multi_pass_unique310 inline static void clone(MultiPass& mp) 311 { Ownership::clone(mp); } 312 313 template <typename MultiPass> releaseboost::spirit::iterator_policies::multi_pass_unique314 inline static bool release(MultiPass& mp) 315 { return Ownership::release(mp); } 316 317 template <typename MultiPass> is_uniqueboost::spirit::iterator_policies::multi_pass_unique318 inline static bool is_unique(MultiPass const& mp) 319 { return Ownership::is_unique(mp); } 320 }; 321 322 /////////////////////////////////////////////////////////////////////////// 323 template <typename T, typename Ownership, typename Checking 324 , typename Input, typename Storage> 325 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 326 , true, true, false> 327 : Input, Storage 328 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique329 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique330 multi_pass_unique(T& x) : Input(x) {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique331 multi_pass_unique(T const& x) : Input(x) {} 332 333 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique334 static void destroy(MultiPass& mp) 335 { 336 Input::destroy(mp); 337 Storage::destroy(mp); 338 } 339 swapboost::spirit::iterator_policies::multi_pass_unique340 void swap(multi_pass_unique& x) 341 { 342 this->Input::swap(x); 343 this->Storage::swap(x); 344 } 345 346 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique347 inline static void clear_queue(MultiPass& mp) 348 { 349 Checking::clear_queue(mp); 350 Storage::clear_queue(mp); 351 } 352 353 // checking policy functions are forwarded to the Checking type 354 template <typename MultiPass> docheckboost::spirit::iterator_policies::multi_pass_unique355 inline static void docheck(MultiPass const& mp) 356 { Checking::docheck(mp); } 357 358 // ownership policy functions are forwarded to the Ownership type 359 template <typename MultiPass> cloneboost::spirit::iterator_policies::multi_pass_unique360 inline static void clone(MultiPass& mp) 361 { Ownership::clone(mp); } 362 363 template <typename MultiPass> releaseboost::spirit::iterator_policies::multi_pass_unique364 inline static bool release(MultiPass& mp) 365 { return Ownership::release(mp); } 366 367 template <typename MultiPass> is_uniqueboost::spirit::iterator_policies::multi_pass_unique368 inline static bool is_unique(MultiPass const& mp) 369 { return Ownership::is_unique(mp); } 370 }; 371 372 /////////////////////////////////////////////////////////////////////////// 373 template <typename T, typename Ownership, typename Checking 374 , typename Input, typename Storage> 375 struct multi_pass_unique<T, Ownership, Checking, Input, Storage 376 , true, true, true> 377 : Storage 378 { multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique379 multi_pass_unique() {} multi_pass_uniqueboost::spirit::iterator_policies::multi_pass_unique380 multi_pass_unique(T const&) {} 381 382 template <typename MultiPass> destroyboost::spirit::iterator_policies::multi_pass_unique383 static void destroy(MultiPass& mp) 384 { 385 Input::destroy(mp); 386 Storage::destroy(mp); 387 } 388 swapboost::spirit::iterator_policies::multi_pass_unique389 void swap(multi_pass_unique& x) 390 { 391 this->Storage::swap(x); 392 } 393 394 template <typename MultiPass> clear_queueboost::spirit::iterator_policies::multi_pass_unique395 inline static void clear_queue(MultiPass& mp) 396 { 397 Checking::clear_queue(mp); 398 Storage::clear_queue(mp); 399 } 400 401 // implement input policy functions by forwarding to the Input type 402 template <typename MultiPass> advance_inputboost::spirit::iterator_policies::multi_pass_unique403 inline static void advance_input(MultiPass& mp) 404 { Input::advance_input(mp); } 405 406 template <typename MultiPass> get_inputboost::spirit::iterator_policies::multi_pass_unique407 inline static typename MultiPass::reference get_input(MultiPass& mp) 408 { return Input::get_input(mp); } 409 410 template <typename MultiPass> input_at_eofboost::spirit::iterator_policies::multi_pass_unique411 inline static bool input_at_eof(MultiPass const& mp) 412 { return Input::input_at_eof(mp); } 413 414 template <typename MultiPass, typename TokenType> input_is_validboost::spirit::iterator_policies::multi_pass_unique415 inline static bool input_is_valid(MultiPass& mp, TokenType& curtok) 416 { return Input::input_is_valid(mp, curtok); } 417 418 // checking policy functions are forwarded to the Checking type 419 template <typename MultiPass> docheckboost::spirit::iterator_policies::multi_pass_unique420 inline static void docheck(MultiPass const& mp) 421 { Checking::docheck(mp); } 422 423 // ownership policy functions are forwarded to the Ownership type 424 template <typename MultiPass> cloneboost::spirit::iterator_policies::multi_pass_unique425 inline static void clone(MultiPass& mp) 426 { Ownership::clone(mp); } 427 428 template <typename MultiPass> releaseboost::spirit::iterator_policies::multi_pass_unique429 inline static bool release(MultiPass& mp) 430 { return Ownership::release(mp); } 431 432 template <typename MultiPass> is_uniqueboost::spirit::iterator_policies::multi_pass_unique433 inline static bool is_unique(MultiPass const& mp) 434 { return Ownership::is_unique(mp); } 435 }; 436 437 /////////////////////////////////////////////////////////////////////////// 438 // the multi_pass_shared structure is used to combine the shared data items 439 // of all policies into one single structure 440 /////////////////////////////////////////////////////////////////////////// 441 template<typename T, typename Ownership, typename Checking, typename Input 442 , typename Storage> 443 struct multi_pass_shared : Ownership, Checking, Input, Storage 444 { multi_pass_sharedboost::spirit::iterator_policies::multi_pass_shared445 explicit multi_pass_shared(T& input) : Input(input) {} multi_pass_sharedboost::spirit::iterator_policies::multi_pass_shared446 explicit multi_pass_shared(T const& input) : Input(input) {} 447 }; 448 449 /////////////////////////////////////////////////////////////////////////// 450 // This is a default implementation of a policy class as required by the 451 // multi_pass template, combining 4 separate policies into one. Any other 452 // multi_pass policy class needs to follow the scheme as shown below. 453 template<typename Ownership, typename Checking, typename Input 454 , typename Storage> 455 struct default_policy 456 { 457 typedef Ownership ownership_policy; 458 typedef Checking checking_policy; 459 typedef Input input_policy; 460 typedef Storage storage_policy; 461 462 /////////////////////////////////////////////////////////////////////// 463 template <typename T> 464 struct unique : multi_pass_unique<T 465 , typename Ownership::unique, typename Checking::unique 466 , typename Input::BOOST_NESTED_TEMPLATE unique<T> 467 , typename Storage::BOOST_NESTED_TEMPLATE unique< 468 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> > 469 { 470 typedef typename Ownership::unique ownership_policy; 471 typedef typename Checking::unique checking_policy; 472 typedef typename Input::BOOST_NESTED_TEMPLATE unique<T> 473 input_policy; 474 typedef typename Storage::BOOST_NESTED_TEMPLATE unique< 475 typename input_policy::value_type> storage_policy; 476 477 typedef multi_pass_unique<T, ownership_policy, checking_policy 478 , input_policy, storage_policy> unique_base_type; 479 uniqueboost::spirit::iterator_policies::default_policy::unique480 unique() {} uniqueboost::spirit::iterator_policies::default_policy::unique481 explicit unique(T& input) : unique_base_type(input) {} uniqueboost::spirit::iterator_policies::default_policy::unique482 explicit unique(T const& input) : unique_base_type(input) {} 483 }; 484 485 /////////////////////////////////////////////////////////////////////// 486 template <typename T> 487 struct shared : multi_pass_shared<T 488 , typename Ownership::shared, typename Checking::shared 489 , typename Input::BOOST_NESTED_TEMPLATE shared<T> 490 , typename Storage::BOOST_NESTED_TEMPLATE shared< 491 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> > 492 { 493 typedef typename Ownership::shared ownership_policy; 494 typedef typename Checking::shared checking_policy; 495 typedef typename Input::BOOST_NESTED_TEMPLATE shared<T> 496 input_policy; 497 typedef typename Storage::BOOST_NESTED_TEMPLATE shared< 498 typename Input::BOOST_NESTED_TEMPLATE unique<T>::value_type> 499 storage_policy; 500 501 typedef multi_pass_shared<T, ownership_policy, checking_policy 502 , input_policy, storage_policy> shared_base_type; 503 sharedboost::spirit::iterator_policies::default_policy::shared504 explicit shared(T& input) 505 : shared_base_type(input), inhibit_clear_queue_(false) {} sharedboost::spirit::iterator_policies::default_policy::shared506 explicit shared(T const& input) 507 : shared_base_type(input), inhibit_clear_queue_(false) {} 508 509 // This is needed for the correct implementation of expectation 510 // points. Normally expectation points flush any multi_pass 511 // iterator they may act on, but if the corresponding error handler 512 // is of type 'retry' no flushing of the internal buffers should be 513 // executed (even if explicitly requested). 514 bool inhibit_clear_queue_; 515 }; 516 }; 517 518 }}} 519 520 #endif 521