/src/contrib/boost/spirit/home/support/char_set/range_run_impl.hpp

http://pythonocc.googlecode.com/ · C++ Header · 189 lines · 133 code · 23 blank · 33 comment · 31 complexity · 6d463b963d489acc89097f8e0c15eace MD5 · raw file

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