results_cache.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // results_cache.hpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_CORE_RESULTS_CACHE_HPP_EAN_10_04_2005
  9. // MS compatible compilers support #pragma once
  10. #if defined(_MSC_VER)
  11. # pragma once
  12. #endif
  13. #include <cstddef>
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/assert.hpp>
  16. #include <boost/xpressive/detail/detail_fwd.hpp>
  17. #include <boost/xpressive/detail/core/list.hpp>
  18. #include <boost/xpressive/detail/core/access.hpp>
  19. #include <boost/xpressive/match_results.hpp>
  20. namespace boost { namespace xpressive { namespace detail
  21. {
  22. ///////////////////////////////////////////////////////////////////////////////
  23. // nested_results
  24. #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
  25. template<typename BidiIter>
  26. struct nested_results
  27. : detail::list<match_results<BidiIter> >
  28. {
  29. friend struct results_cache<BidiIter>;
  30. friend struct match_results<BidiIter>;
  31. };
  32. #else
  33. template<typename BidiIter>
  34. struct nested_results
  35. : private detail::list<match_results<BidiIter> >
  36. {
  37. friend struct results_cache<BidiIter>;
  38. friend struct xpressive::match_results<BidiIter>;
  39. typedef list<xpressive::match_results<BidiIter> > base_type;
  40. typedef typename base_type::iterator iterator;
  41. typedef typename base_type::const_iterator const_iterator;
  42. typedef typename base_type::pointer pointer;
  43. typedef typename base_type::const_pointer const_pointer;
  44. typedef typename base_type::reference reference;
  45. typedef typename base_type::const_reference const_reference;
  46. typedef typename base_type::size_type size_type;
  47. using base_type::begin;
  48. using base_type::end;
  49. using base_type::size;
  50. using base_type::empty;
  51. using base_type::front;
  52. using base_type::back;
  53. };
  54. #endif
  55. ///////////////////////////////////////////////////////////////////////////////
  56. // results_cache
  57. //
  58. // cache storage for reclaimed match_results structs
  59. template<typename BidiIter>
  60. struct results_cache
  61. {
  62. typedef core_access<BidiIter> access;
  63. match_results<BidiIter> &append_new(nested_results<BidiIter> &out)
  64. {
  65. if(this->cache_.empty())
  66. {
  67. out.push_back(match_results<BidiIter>());
  68. }
  69. else
  70. {
  71. BOOST_ASSERT(access::get_nested_results(this->cache_.back()).empty());
  72. out.splice(out.end(), this->cache_, --this->cache_.end());
  73. }
  74. return out.back();
  75. }
  76. // move the last match_results struct into the cache
  77. void reclaim_last(nested_results<BidiIter> &out)
  78. {
  79. BOOST_ASSERT(!out.empty());
  80. // first, reclaim any nested results
  81. nested_results<BidiIter> &nested = access::get_nested_results(out.back());
  82. if(!nested.empty())
  83. {
  84. this->reclaim_all(nested);
  85. }
  86. // then, reclaim the last match_results
  87. this->cache_.splice(this->cache_.end(), out, --out.end());
  88. }
  89. // move the last n match_results structs into the cache
  90. void reclaim_last_n(nested_results<BidiIter> &out, std::size_t count)
  91. {
  92. for(; 0 != count; --count)
  93. {
  94. this->reclaim_last(out);
  95. }
  96. }
  97. void reclaim_all(nested_results<BidiIter> &out)
  98. {
  99. typedef typename nested_results<BidiIter>::iterator iter_type;
  100. // first, recursively reclaim all the nested results
  101. for(iter_type begin = out.begin(); begin != out.end(); ++begin)
  102. {
  103. nested_results<BidiIter> &nested = access::get_nested_results(*begin);
  104. if(!nested.empty())
  105. {
  106. this->reclaim_all(nested);
  107. }
  108. }
  109. // next, reclaim the results themselves
  110. this->cache_.splice(this->cache_.end(), out);
  111. }
  112. private:
  113. nested_results<BidiIter> cache_;
  114. };
  115. }}} // namespace boost::xpressive::detail
  116. #endif