diff --git a/include/boost/half_open_range.hpp b/include/boost/half_open_range.hpp new file mode 100644 index 0000000..d430c6d --- /dev/null +++ b/include/boost/half_open_range.hpp @@ -0,0 +1,366 @@ +// (C) Copyright Jeremy Siek and David Abrahams 2000-2001. Permission to copy, +// use, modify, sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided "as is" +// without express or implied warranty, and with no claim as to its suitability +// for any purpose. +// +// Revision History: +// 30 Jan 2001 Initial Checkin (David Abrahams) + +#ifndef BOOST_HALF_OPEN_RANGE_HPP_ +# define BOOST_HALF_OPEN_RANGE_HPP_ + +# include +# include +# include +# include +# include +# include + +namespace boost { + +namespace detail { + +// Template class choose_finish -- allows us to maintain the invariant that +// start() <= finish() on half_open_range specializations that support random +// access. +template +struct choose_finish +{ + template + struct rebind + { + static T choose(const T&, const T& finish) + { return finish; } + }; +}; + +template <> +struct choose_finish +{ + template + struct rebind + { + static T choose(const T& start, const T& finish) + { return finish < start ? start : finish; } + }; +}; +} + +template +struct half_open_range +{ + typedef iterator_adaptor, + counting_iterator_traits > iterator; + + private: // utility type definitions + typedef std::less less_value; + typedef typename boost::detail::iterator_traits::iterator_category category; + + public: + typedef iterator const_iterator; + typedef typename counting_iterator_traits::value_type value_type; + typedef typename counting_iterator_traits::difference_type difference_type; + typedef typename counting_iterator_traits::reference reference; + typedef typename counting_iterator_traits::reference const_reference; + typedef typename counting_iterator_traits::pointer pointer; + typedef typename counting_iterator_traits::pointer const_pointer; + + // It would be nice to select an unsigned type, but this is appropriate + // since the library makes an attempt to select a difference_type which can + // hold the difference between any two iterators. + typedef typename counting_iterator_traits::difference_type size_type; + + half_open_range(Incrementable start, Incrementable finish) + : m_start(start), + m_finish( + detail::choose_finish::template rebind::choose(start, finish)) + {} + + // Implicit conversion from std::pair allows us + // to accept the results of std::equal_range(), for example. + half_open_range(const std::pair& x) + : m_start(x.first), + m_finish( + detail::choose_finish::template rebind::choose(x.first,x.second)) + {} + + half_open_range& operator=(const std::pair& x) + { + m_start = x.first; + m_finish = + detail::choose_finish::template rebind::choose(x.first,x.second); + } + + iterator begin() const { return iterator(m_start); } + iterator end() const { return iterator(m_finish); } + + Incrementable front() const { assert(!this->empty()); return m_start; } + Incrementable back() const { assert(!this->empty()); return boost::prior(m_finish); } + + Incrementable start() const { return m_start; } + Incrementable finish() const { return m_finish; } + + size_type size() const { return boost::detail::distance(begin(), end()); } + + bool empty() const + { + return m_finish == m_start; + } + + void swap(half_open_range& x) { + std::swap(m_start, x.m_start); + std::swap(m_finish, x.m_finish); + } + + public: // functions requiring random access elements + + // REQUIRES: x is reachable from this->front() + bool contains(const value_type& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + return !less_value()(x, m_start) && less_value()(x, m_finish); + } + + bool contains(const half_open_range& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + return x.empty() || !less_value()(x.m_start, m_start) && !less_value()(m_finish, x.m_finish); + } + + bool intersects(const half_open_range& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + return less_value()( + less_value()(this->m_start, x.m_start) ? x.m_start : this->m_start, + less_value()(this->m_finish, x.m_finish) ? this->m_finish : x.m_finish); + } + + half_open_range& operator&=(const half_open_range& x) + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + + if (less_value()(this->m_start, x.m_start)) + this->m_start = x.m_start; + + if (less_value()(x.m_finish, this->m_finish)) + this->m_finish = x.m_finish; + + if (less_value()(this->m_finish, this->m_start)) + this->m_start = this->m_finish; + + return *this; + } + + half_open_range& operator|=(const half_open_range& x) + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + + if (!x.empty()) + { + if (this->empty()) + { + *this = x; + } + else + { + if (less_value()(x.m_start, this->m_start)) + this->m_start = x.m_start; + + if (less_value()(this->m_finish, x.m_finish)) + this->m_finish = x.m_finish; + } + } + return *this; + } + + // REQUIRES: x is reachable from this->front() + const_iterator find(const value_type& x) const + { + BOOST_STATIC_ASSERT((boost::is_same::value)); + + return const_iterator(this->contains(x) ? x : m_finish); + } + + // REQUIRES: index >= 0 && index < size() + value_type operator[](size_type index) const + { + assert(index >= 0 && index < size()); + return m_start + index; + } + + value_type at(size_type index) const + { + if (index < 0 || index >= size()) + throw std::out_of_range(std::string("half_open_range")); + return m_start + index; + } + + private: // data members + Incrementable m_start, m_finish; +}; + +template +half_open_range operator|( + half_open_range x, + const half_open_range& y) +{ + return x |= y; +} + +template +half_open_range operator&( + half_open_range x, + const half_open_range& y) +{ + return x &= y; +} + +template +inline bool operator==( + const half_open_range& x, + const half_open_range& y) +{ + const bool y_empty = y.empty(); + return x.empty() ? y_empty : !y_empty && x.start() == y.start() && x.finish() == y.finish(); +} + +template +inline bool operator!=( + const half_open_range& x, + const half_open_range& y) +{ + return !(x == y); +} + +template +inline half_open_range +make_half_open_range(Incrementable first, Incrementable last) +{ + return half_open_range(first, last); +} + +template +bool intersects( + const half_open_range& x, + const half_open_range& y) +{ + return x.intersects(y); +} + +template +bool contains( + const half_open_range& x, + const half_open_range& y) +{ + return x.contains(y); +} + +} // namespace boost + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +namespace std { +template struct less > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + less cmp; + return !y.empty() && ( + cmp(x.start(), y.start()) + || !cmp(y.start(), x.start()) + && cmp(x.finish(), y.finish())); + } +}; + +template struct less_equal > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + typedef boost::half_open_range range; + less cmp; + return !cmp(y,x); + } +}; +template struct greater > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + typedef boost::half_open_range range; + less cmp; + return cmp(y,x); + } +}; + +template struct greater_equal > + : binary_function< + boost::half_open_range, + boost::half_open_range,bool> +{ + bool operator()( + const boost::half_open_range& x, + const boost::half_open_range& y) const + { + typedef boost::half_open_range range; + less cmp; + return !cmp(x,y); + } +}; +} // namespace std + +#else + +namespace boost { +// Can't partially specialize std::less et al, so we must provide the operators +template +bool operator<(const half_open_range& x, + const half_open_range& y) +{ + return !y.empty() && ( + x.empty() || std::less()(x.start(), y.start()) + || !std::less()(y.start(), x.start()) + && std::less()(x.finish(), y.finish())); +} + +template +bool operator>(const half_open_range& x, + const half_open_range& y) +{ + return y < x; +} + +template +bool operator<=(const half_open_range& x, + const half_open_range& y) +{ + return !(y < x); +} + +template +bool operator>=(const half_open_range& x, + const half_open_range& y) +{ + return !(x < y); +} +} // namespace boost + +#endif + + +#endif // BOOST_HALF_OPEN_RANGE_HPP_