You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
6.1 KiB
236 lines
6.1 KiB
3 years ago
|
/*=============================================================================
|
||
|
Copyright (c) 2001-2003 Joel de Guzman
|
||
|
http://spirit.sourceforge.net/
|
||
|
|
||
|
Use, modification and distribution is subject to 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)
|
||
|
=============================================================================*/
|
||
|
#ifndef BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_IPP
|
||
|
#define BOOST_XPRESSIVE_SPIRIT_RANGE_RUN_IPP
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
#include <algorithm> // for std::lower_bound
|
||
|
#include <boost/limits.hpp>
|
||
|
#include <boost/assert.hpp>
|
||
|
#include <boost/xpressive/detail/utility/chset/range_run.hpp>
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
namespace boost { namespace xpressive { namespace detail
|
||
|
{
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// range class implementation
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline range<Char>::range(Char first, Char last)
|
||
|
: first_(first)
|
||
|
, last_(last)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline bool range<Char>::is_valid() const
|
||
|
{
|
||
|
return this->first_ <= this->last_;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline bool range<Char>::includes(range<Char> const &r) const
|
||
|
{
|
||
|
return (this->first_ <= r.first_) && (this->last_ >= r.last_);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline bool range<Char>::includes(Char v) const
|
||
|
{
|
||
|
return (this->first_ <= v) && (this->last_ >= v);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline bool range<Char>::overlaps(range<Char> const &r) const
|
||
|
{
|
||
|
Char decr_first = (std::min)(this->first_, Char(this->first_-1));
|
||
|
Char incr_last = (std::max)(this->last_, Char(this->last_+1));
|
||
|
|
||
|
return (decr_first <= r.last_) && (incr_last >= r.first_);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline void range<Char>::merge(range<Char> const &r)
|
||
|
{
|
||
|
this->first_ = (std::min)(this->first_, r.first_);
|
||
|
this->last_ = (std::max)(this->last_, r.last_);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// range_run class implementation
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline bool range_run<Char>::empty() const
|
||
|
{
|
||
|
return this->run_.empty();
|
||
|
}
|
||
|
|
||
|
template<typename Char>
|
||
|
inline bool range_run<Char>::test(Char v) const
|
||
|
{
|
||
|
if(this->run_.empty())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const_iterator iter = std::lower_bound(
|
||
|
this->run_.begin()
|
||
|
, this->run_.end()
|
||
|
, range<Char>(v, v)
|
||
|
, range_compare<Char>()
|
||
|
);
|
||
|
|
||
|
return (iter != this->run_.end() && iter->includes(v))
|
||
|
|| (iter != this->run_.begin() && (--iter)->includes(v));
|
||
|
}
|
||
|
|
||
|
template<typename Char>
|
||
|
template<typename Traits>
|
||
|
inline bool range_run<Char>::test(Char v, Traits const &tr) const
|
||
|
{
|
||
|
const_iterator begin = this->run_.begin();
|
||
|
const_iterator end = this->run_.end();
|
||
|
|
||
|
for(; begin != end; ++begin)
|
||
|
{
|
||
|
if(tr.in_range_nocase(begin->first_, begin->last_, v))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline void range_run<Char>::swap(range_run<Char> &rr)
|
||
|
{
|
||
|
this->run_.swap(rr.run_);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
void range_run<Char>::merge(iterator iter, range<Char> const &r)
|
||
|
{
|
||
|
BOOST_ASSERT(iter != this->run_.end());
|
||
|
iter->merge(r);
|
||
|
|
||
|
iterator i = iter;
|
||
|
while(++i != this->run_.end() && iter->overlaps(*i))
|
||
|
{
|
||
|
iter->merge(*i);
|
||
|
}
|
||
|
|
||
|
this->run_.erase(++iter, i);
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
void range_run<Char>::set(range<Char> const &r)
|
||
|
{
|
||
|
BOOST_ASSERT(r.is_valid());
|
||
|
if(!this->run_.empty())
|
||
|
{
|
||
|
iterator iter = std::lower_bound(this->run_.begin(), this->run_.end(), r, range_compare<Char>());
|
||
|
|
||
|
if((iter != this->run_.end() && iter->includes(r)) ||
|
||
|
(iter != this->run_.begin() && (iter - 1)->includes(r)))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
else if(iter != this->run_.begin() && (iter - 1)->overlaps(r))
|
||
|
{
|
||
|
this->merge(--iter, r);
|
||
|
}
|
||
|
else if(iter != this->run_.end() && iter->overlaps(r))
|
||
|
{
|
||
|
this->merge(iter, r);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this->run_.insert(iter, r);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this->run_.push_back(r);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
void range_run<Char>::clear(range<Char> const &r)
|
||
|
{
|
||
|
BOOST_ASSERT(r.is_valid());
|
||
|
if(!this->run_.empty())
|
||
|
{
|
||
|
iterator iter = std::lower_bound(this->run_.begin(), this->run_.end(), r, range_compare<Char>());
|
||
|
iterator left_iter;
|
||
|
|
||
|
if((iter != this->run_.begin()) &&
|
||
|
(left_iter = (iter - 1))->includes(r.first_))
|
||
|
{
|
||
|
if(left_iter->last_ > r.last_)
|
||
|
{
|
||
|
Char save_last = left_iter->last_;
|
||
|
left_iter->last_ = r.first_-1;
|
||
|
this->run_.insert(iter, range<Char>(r.last_+1, save_last));
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
left_iter->last_ = r.first_-1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iterator i = iter;
|
||
|
for(; i != this->run_.end() && r.includes(*i); ++i) {}
|
||
|
if(i != this->run_.end() && i->includes(r.last_))
|
||
|
{
|
||
|
i->first_ = r.last_+1;
|
||
|
}
|
||
|
this->run_.erase(iter, i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline void range_run<Char>::clear()
|
||
|
{
|
||
|
this->run_.clear();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline typename range_run<Char>::const_iterator range_run<Char>::begin() const
|
||
|
{
|
||
|
return this->run_.begin();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////
|
||
|
template<typename Char>
|
||
|
inline typename range_run<Char>::const_iterator range_run<Char>::end() const
|
||
|
{
|
||
|
return this->run_.end();
|
||
|
}
|
||
|
|
||
|
}}} // namespace boost::xpressive::detail
|
||
|
|
||
|
#endif
|