/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #if !defined(BOOST_SPIRIT_RANGE_RUN_MAY_16_2006_0807_PM) #define BOOST_SPIRIT_RANGE_RUN_MAY_16_2006_0807_PM #if defined(_MSC_VER) #pragma once #endif #include #include #include namespace boost { namespace spirit { namespace support { namespace detail { template inline bool try_merge(Run& run, Iterator iter, Range const& range) { // if *iter intersects with, or is adjacent to, 'range'... if (can_merge(*iter, range)) { // merge range and *iter merge(*iter, range); // collapse all subsequent ranges that can merge with *iter: Iterator i = iter+1; // 1. skip subsequent ranges completely included in *iter while (i != run.end() && i->last <= iter->last) ++i; // 2. collapse next range if adjacent or overlapping with *iter if (i != run.end() && i->first-1 <= iter->last) { iter->last = i->last; ++i; } // erase all ranges that were collapsed run.erase(iter+1, i); return true; } return false; } template inline bool range_run::test(Char val) const { if (run.empty()) return false; // search the ranges for one that potentially includes val typename storage_type::const_iterator iter = std::upper_bound( run.begin(), run.end(), val, range_compare() ); // return true if *(iter-1) includes val return iter != run.begin() && includes(*(--iter), val); } template inline void range_run::swap(range_run& other) { run.swap(other.run); } template void range_run::set(range_type const& range) { BOOST_ASSERT(is_valid(range)); if (run.empty()) { // the vector is empty, insert 'range' run.push_back(range); return; } // search the ranges for one that potentially includes 'range' typename storage_type::iterator iter = std::upper_bound( run.begin(), run.end(), range, range_compare() ); if (iter != run.begin()) { // if *(iter-1) includes 'range', return early if (includes(*(iter-1), range)) { return; } // if *(iter-1) can merge with 'range', merge them and return if (try_merge(run, iter-1, range)) { return; } } // if *iter can merge with with 'range', merge them if (iter == run.end() || !try_merge(run, iter, range)) { // no overlap, insert 'range' run.insert(iter, range); } } template void range_run::clear(range_type const& range) { BOOST_ASSERT(is_valid(range)); if (!run.empty()) { // search the ranges for one that potentially includes 'range' typename storage_type::iterator iter = std::upper_bound( run.begin(), run.end(), range, range_compare() ); // 'range' starts with or after another range: if (iter != run.begin()) { typename storage_type::iterator const left_iter = iter-1; // 'range' starts after '*left_iter': if (left_iter->first < range.first) { // if 'range' is completely included inside '*left_iter': // need to break it apart into two ranges (punch a hole), if (left_iter->last > range.last) { Char save_last = left_iter->last; left_iter->last = range.first-1; run.insert(iter, range_type(range.last+1, save_last)); return; } // if 'range' contains 'left_iter->last': // truncate '*left_iter' (clip its right) else if (left_iter->last >= range.first) { left_iter->last = range.first-1; } } // 'range' has the same left bound as '*left_iter': it // must be removed or truncated by the code below else { iter = left_iter; } } // remove or truncate subsequent ranges that overlap with 'range': typename storage_type::iterator i = iter; // 1. skip subsequent ranges completely included in 'range' while (i != run.end() && i->last <= range.last) ++i; // 2. clip left of next range if overlapping with 'range' if (i != run.end() && i->first <= range.last) i->first = range.last+1; // erase all ranges that 'range' contained run.erase(iter, i); } } template inline void range_run::clear() { run.clear(); } }}}} #endif