/*
* This file is part of the DXX-Rebirth project .
* It is copyright by its individual contributors, as recorded in the
* project's Git history. See COPYING.txt at the top level for license
* terms and a link to the Git history.
*/
#pragma once
#include
#include
#include "dxxsconf.h"
#include "compiler-addressof.h"
#include "compiler-begin.h"
#include "compiler-type_traits.h"
template
struct partial_range_t
{
iterator m_begin, m_end;
partial_range_t(iterator b, iterator e) :
m_begin(b), m_end(e)
{
}
iterator begin() const { return m_begin; }
iterator end() const { return m_end; }
};
#ifdef DXX_HAVE_BOOST_FOREACH
#include
#include
namespace boost
{
template
struct range_mutable_iterator< partial_range_t >
{
typedef iterator type;
};
template
struct range_const_iterator< partial_range_t >
{
typedef iterator type;
};
}
#endif
template
struct partial_range_error_t : public std::out_of_range
{
partial_range_error_t(const std::string& s) :
std::out_of_range(s)
{
}
static void report(const char *desc, unsigned long expr, const T &t, unsigned long d)
{
char buf[84];
snprintf(buf, sizeof(buf), "%s %lu past %p end %lu", desc, expr, addressof(t), d);
throw partial_range_error_t(buf);
}
};
template
typename tt::enable_if::value, T &>::type partial_range(T &, U, U = U()) DXX_CXX11_EXPLICIT_DELETE;
template
static inline typename tt::enable_if::value, partial_range_t::value, typename T::const_iterator, typename T::iterator>::type>>::type partial_range(T &t, const U o, const U l) __attribute_warn_unused_result;
template
static inline typename tt::enable_if::value, partial_range_t::value, typename T::const_iterator, typename T::iterator>::type>>::type partial_range(T &t, const U o, const U l)
{
using std::advance;
using std::distance;
auto range_begin = begin(t);
auto range_end = range_begin;
#define PARTIAL_RANGE_CHECK_BOUND(EXPR,S) \
if (EXPR > d) \
partial_range_error_t::report(S, EXPR, t, d)
size_t d = distance(range_begin, end(t));
PARTIAL_RANGE_CHECK_BOUND(o, "begin");
PARTIAL_RANGE_CHECK_BOUND(l, "end");
#undef PARTIAL_RANGE_CHECK_BOUND
if (o <= l)
{
advance(range_begin, o);
advance(range_end, l);
}
return partial_range_t::value, typename T::const_iterator, typename T::iterator>::type>(range_begin, range_end);
}
template
static inline typename tt::enable_if::value, partial_range_t::value, typename T::const_iterator, typename T::iterator>::type>>::type partial_range(T &t, const U l) __attribute_warn_unused_result;
template
static inline typename tt::enable_if::value, partial_range_t::value, typename T::const_iterator, typename T::iterator>::type>>::type partial_range(T &t, const U l)
{
return partial_range(t, static_cast(0), l);
}