range_run_impl.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  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_RANGE_RUN_MAY_16_2006_0807_PM)
  7. #define BOOST_SPIRIT_RANGE_RUN_MAY_16_2006_0807_PM
  8. #if defined(_MSC_VER)
  9. #pragma once
  10. #endif
  11. #include <boost/spirit/home/support/char_set/range_functions.hpp>
  12. #include <boost/assert.hpp>
  13. #include <algorithm>
  14. namespace boost { namespace spirit { namespace support { namespace detail
  15. {
  16. template <typename Run, typename Iterator, typename Range>
  17. inline bool
  18. try_merge(Run& run, Iterator iter, Range const& range)
  19. {
  20. // if *iter intersects with, or is adjacent to, 'range'...
  21. if (can_merge(*iter, range))
  22. {
  23. // merge range and *iter
  24. merge(*iter, range);
  25. // collapse all subsequent ranges that can merge with *iter:
  26. Iterator i = iter+1;
  27. // 1. skip subsequent ranges completely included in *iter
  28. while (i != run.end() && i->last <= iter->last)
  29. ++i;
  30. // 2. collapse next range if adjacent or overlapping with *iter
  31. if (i != run.end() && i->first-1 <= iter->last)
  32. {
  33. iter->last = i->last;
  34. ++i;
  35. }
  36. // erase all ranges that were collapsed
  37. run.erase(iter+1, i);
  38. return true;
  39. }
  40. return false;
  41. }
  42. template <typename Char>
  43. inline bool
  44. range_run<Char>::test(Char val) const
  45. {
  46. if (run.empty())
  47. return false;
  48. // search the ranges for one that potentially includes val
  49. typename storage_type::const_iterator iter =
  50. std::upper_bound(
  51. run.begin(), run.end(), val,
  52. range_compare<range_type>()
  53. );
  54. // return true if *(iter-1) includes val
  55. return iter != run.begin() && includes(*(--iter), val);
  56. }
  57. template <typename Char>
  58. inline void
  59. range_run<Char>::swap(range_run& other)
  60. {
  61. run.swap(other.run);
  62. }
  63. template <typename Char>
  64. void
  65. range_run<Char>::set(range_type const& range)
  66. {
  67. BOOST_ASSERT(is_valid(range));
  68. if (run.empty())
  69. {
  70. // the vector is empty, insert 'range'
  71. run.push_back(range);
  72. return;
  73. }
  74. // search the ranges for one that potentially includes 'range'
  75. typename storage_type::iterator iter =
  76. std::upper_bound(
  77. run.begin(), run.end(), range,
  78. range_compare<range_type>()
  79. );
  80. if (iter != run.begin())
  81. {
  82. // if *(iter-1) includes 'range', return early
  83. if (includes(*(iter-1), range))
  84. {
  85. return;
  86. }
  87. // if *(iter-1) can merge with 'range', merge them and return
  88. if (try_merge(run, iter-1, range))
  89. {
  90. return;
  91. }
  92. }
  93. // if *iter can merge with with 'range', merge them
  94. if (iter == run.end() || !try_merge(run, iter, range))
  95. {
  96. // no overlap, insert 'range'
  97. run.insert(iter, range);
  98. }
  99. }
  100. template <typename Char>
  101. void
  102. range_run<Char>::clear(range_type const& range)
  103. {
  104. BOOST_ASSERT(is_valid(range));
  105. if (!run.empty())
  106. {
  107. // search the ranges for one that potentially includes 'range'
  108. typename storage_type::iterator iter =
  109. std::upper_bound(
  110. run.begin(), run.end(), range,
  111. range_compare<range_type>()
  112. );
  113. // 'range' starts with or after another range:
  114. if (iter != run.begin())
  115. {
  116. typename storage_type::iterator const left_iter = iter-1;
  117. // 'range' starts after '*left_iter':
  118. if (left_iter->first < range.first)
  119. {
  120. // if 'range' is completely included inside '*left_iter':
  121. // need to break it apart into two ranges (punch a hole),
  122. if (left_iter->last > range.last)
  123. {
  124. Char save_last = left_iter->last;
  125. left_iter->last = range.first-1;
  126. run.insert(iter, range_type(range.last+1, save_last));
  127. return;
  128. }
  129. // if 'range' contains 'left_iter->last':
  130. // truncate '*left_iter' (clip its right)
  131. else if (left_iter->last >= range.first)
  132. {
  133. left_iter->last = range.first-1;
  134. }
  135. }
  136. // 'range' has the same left bound as '*left_iter': it
  137. // must be removed or truncated by the code below
  138. else
  139. {
  140. iter = left_iter;
  141. }
  142. }
  143. // remove or truncate subsequent ranges that overlap with 'range':
  144. typename storage_type::iterator i = iter;
  145. // 1. skip subsequent ranges completely included in 'range'
  146. while (i != run.end() && i->last <= range.last)
  147. ++i;
  148. // 2. clip left of next range if overlapping with 'range'
  149. if (i != run.end() && i->first <= range.last)
  150. i->first = range.last+1;
  151. // erase all ranges that 'range' contained
  152. run.erase(iter, i);
  153. }
  154. }
  155. template <typename Char>
  156. inline void
  157. range_run<Char>::clear()
  158. {
  159. run.clear();
  160. }
  161. }}}}
  162. #endif