mirror of https://github.com/tstack/lnav
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
947 lines
23 KiB
C++
947 lines
23 KiB
C++
//
|
|
// Copyright (c) 2015 Arthur O'Dwyer
|
|
// Copyright 2017-2018 by Martin Moene
|
|
//
|
|
// https://github.com/martinmoene/ring-span-lite
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// (See accompanying file LICENSE.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
#pragma once
|
|
|
|
#ifndef NONSTD_RING_SPAN_LITE_HPP
|
|
# define NONSTD_RING_SPAN_LITE_HPP
|
|
|
|
# define ring_span_lite_MAJOR 0
|
|
# define ring_span_lite_MINOR 2
|
|
# define ring_span_lite_PATCH 0
|
|
|
|
# define ring_span_lite_VERSION \
|
|
nsrs_STRINGIFY(ring_span_lite_MAJOR) "." nsrs_STRINGIFY( \
|
|
ring_span_lite_MINOR) "." nsrs_STRINGIFY(ring_span_lite_PATCH)
|
|
|
|
# define nsrs_STRINGIFY(x) nsrs_STRINGIFY_(x)
|
|
# define nsrs_STRINGIFY_(x) # x
|
|
|
|
// ring-span-lite configuration:
|
|
|
|
# define nsrs_RING_SPAN_DEFAULT 0
|
|
# define nsrs_RING_SPAN_NONSTD 1
|
|
# define nsrs_RING_SPAN_STD 2
|
|
|
|
# if !defined(nsrs_CONFIG_SELECT_RING_SPAN)
|
|
# define nsrs_CONFIG_SELECT_RING_SPAN \
|
|
(nsrs_HAVE_STD_RING_SPAN ? nsrs_RING_SPAN_STD \
|
|
: nsrs_RING_SPAN_NONSTD)
|
|
# endif
|
|
|
|
# ifndef nsrs_CONFIG_STRICT_P0059
|
|
# define nsrs_CONFIG_STRICT_P0059 0
|
|
# endif
|
|
|
|
# define nsrs_RING_SPAN_LITE_EXTENSION (!nsrs_CONFIG_STRICT_P0059)
|
|
|
|
# ifndef nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS
|
|
# define nsrs_CONFIG_CONFIRMS_COMPILATION_ERRORS 0
|
|
# endif
|
|
|
|
// C++ language version detection (C++20 is speculative):
|
|
// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
|
|
|
|
# ifndef nsrs_CPLUSPLUS
|
|
# if defined(_MSVC_LANG) && !defined(__clang__)
|
|
# define nsrs_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
|
|
# else
|
|
# define nsrs_CPLUSPLUS __cplusplus
|
|
# endif
|
|
# endif
|
|
|
|
# define nsrs_CPP98_OR_GREATER (nsrs_CPLUSPLUS >= 199711L)
|
|
# define nsrs_CPP11_OR_GREATER (nsrs_CPLUSPLUS >= 201103L)
|
|
# define nsrs_CPP11_OR_GREATER_ (nsrs_CPLUSPLUS >= 201103L)
|
|
# define nsrs_CPP14_OR_GREATER (nsrs_CPLUSPLUS >= 201402L)
|
|
# define nsrs_CPP17_OR_GREATER (nsrs_CPLUSPLUS >= 201703L)
|
|
# define nsrs_CPP20_OR_GREATER (nsrs_CPLUSPLUS >= 202000L)
|
|
|
|
// Use C++XX std::ring_span if available and requested:
|
|
|
|
# define nsrs_HAVE_STD_RING_SPAN 0
|
|
|
|
//#if nsrs_CPP17_OR_GREATER && defined(__has_include )
|
|
//# if __has_include( <any> )
|
|
//# define nsrs_HAVE_STD_RING_SPAN 1
|
|
//# else
|
|
//# define nsrs_HAVE_STD_RING_SPAN 0
|
|
//# endif
|
|
//#else
|
|
//# define nsrs_HAVE_STD_RING_SPAN 0
|
|
//#endif
|
|
|
|
# define nsrs_USES_STD_RING_SPAN \
|
|
((nsrs_CONFIG_SELECT_RING_SPAN == nsrs_RING_SPAN_STD) \
|
|
|| ((nsrs_CONFIG_SELECT_RING_SPAN == nsrs_RING_SPAN_DEFAULT) \
|
|
&& nsrs_HAVE_STD_RING_SPAN))
|
|
|
|
// Compiler versions:
|
|
//
|
|
// MSVC++ 6.0 _MSC_VER == 1200 (Visual Studio 6.0)
|
|
// MSVC++ 7.0 _MSC_VER == 1300 (Visual Studio .NET 2002)
|
|
// MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio .NET 2003)
|
|
// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
|
|
// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
|
|
// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
|
|
// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
|
|
// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
|
|
// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
|
|
// ............_MSVC_LANG: 201402 for -std:c++14, default
|
|
// MSVC++ 14.1 _MSC_VER >= 1910 (Visual Studio 2017)
|
|
// ............_MSVC_LANG: 201402 for -std:c++14, default
|
|
// ............_MSVC_LANG: 201703 for -std:c++17
|
|
|
|
# if defined(_MSC_VER) && !defined(__clang__)
|
|
# define nsrs_COMPILER_MSVC_VER (_MSC_VER)
|
|
# define nsrs_COMPILER_MSVC_VERSION \
|
|
(_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900)))
|
|
# else
|
|
# define nsrs_COMPILER_MSVC_VER 0
|
|
# define nsrs_COMPILER_MSVC_VERSION 0
|
|
# endif
|
|
|
|
# define nsrs_COMPILER_VERSION(major, minor, patch) \
|
|
(10 * (10 * major + minor) + patch)
|
|
|
|
# if defined(__clang__)
|
|
# define nsrs_COMPILER_CLANG_VERSION \
|
|
nsrs_COMPILER_VERSION( \
|
|
__clang_major__, __clang_minor__, __clang_patchlevel__)
|
|
# else
|
|
# define nsrs_COMPILER_CLANG_VERSION 0
|
|
# endif
|
|
|
|
# if defined(__GNUC__) && !defined(__clang__)
|
|
# define nsrs_COMPILER_GNUC_VERSION \
|
|
nsrs_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
|
# else
|
|
# define nsrs_COMPILER_GNUC_VERSION 0
|
|
# endif
|
|
|
|
// half-open range [lo..hi):
|
|
//#define nsrs_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
|
|
|
|
// Presence of language and library features:
|
|
|
|
# ifdef _HAS_CPP0X
|
|
# define nsrs_HAS_CPP0X _HAS_CPP0X
|
|
# else
|
|
# define nsrs_HAS_CPP0X 0
|
|
# endif
|
|
|
|
// Unless defined otherwise below, consider VC14 as C++11 for ring-span-lite:
|
|
|
|
# if nsrs_COMPILER_MSVC_VER >= 1900
|
|
# undef nsrs_CPP11_OR_GREATER
|
|
# define nsrs_CPP11_OR_GREATER 1
|
|
# endif
|
|
|
|
# define nsrs_CPP11_90 \
|
|
(nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1500)
|
|
# define nsrs_CPP11_100 \
|
|
(nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1600)
|
|
# define nsrs_CPP11_110 \
|
|
(nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1700)
|
|
# define nsrs_CPP11_120 \
|
|
(nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1800)
|
|
# define nsrs_CPP11_140 \
|
|
(nsrs_CPP11_OR_GREATER_ || nsrs_COMPILER_MSVC_VER >= 1900)
|
|
|
|
# define nsrs_CPP14_000 (nsrs_CPP14_OR_GREATER)
|
|
# define nsrs_CPP17_000 (nsrs_CPP17_OR_GREATER)
|
|
|
|
// Presence of C++11 language features:
|
|
|
|
// half-open range [lo..hi):
|
|
# define nsrs_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
|
|
|
|
// Presence of C++11 language features:
|
|
|
|
# define nsrs_HAVE_CONSTEXPR_11 nsrs_CPP11_140
|
|
# define nsrs_HAVE_IS_DEFAULT nsrs_CPP11_140
|
|
# define nsrs_HAVE_IS_DELETE nsrs_CPP11_140
|
|
# define nsrs_HAVE_NOEXCEPT nsrs_CPP11_140
|
|
# define nsrs_HAVE_NULLPTR nsrs_CPP11_100
|
|
|
|
// Presence of C++14 language features:
|
|
|
|
# define nsrs_HAVE_CONSTEXPR_14 nsrs_CPP14_000
|
|
|
|
// Presence of C++17 language features:
|
|
// no tag
|
|
|
|
// Presence of C++ library features:
|
|
// no tag
|
|
|
|
// Compiler warning suppression:
|
|
|
|
# if defined(__clang__)
|
|
# pragma clang diagnostic push
|
|
# pragma clang diagnostic ignored "-Wundef"
|
|
# define nsrs_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
|
|
|
|
# elif defined __GNUC__
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wundef"
|
|
# define nsrs_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
|
|
|
|
# elif nsrs_COMPILER_MSVC_VERSION >= 140
|
|
# define nsrs_DISABLE_MSVC_WARNINGS(codes) \
|
|
__pragma(warning(push)) __pragma(warning(disable : codes))
|
|
# define nsrs_RESTORE_WARNINGS() __pragma(warning(pop))
|
|
|
|
// Suppress the following MSVC warnings:
|
|
// - C4345: initialization behavior changed
|
|
//
|
|
// Suppress the following MSVC GSL warnings:
|
|
// - C26439, gsl::f.6 : special function 'function' can be declared 'noexcept'
|
|
// - C26440, gsl::f.6 : function 'function' can be declared 'noexcept'
|
|
// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
|
|
// use brace initialization, gsl::narrow_cast or
|
|
// gsl::narrow
|
|
// - C26473: gsl::t.1 : don't cast between pointer types where the source type
|
|
// and the target type are the same
|
|
// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
|
|
// - C26490: gsl::t.1 : don't use reinterpret_cast
|
|
|
|
nsrs_DISABLE_MSVC_WARNINGS(4345 26439 26440 26472 26473 26481 26490)
|
|
|
|
# else
|
|
# define nsrs_RESTORE_WARNINGS() /*empty*/
|
|
# endif
|
|
|
|
// C++ feature usage:
|
|
|
|
# if nsrs_HAVE_CONSTEXPR_11
|
|
# define nsrs_constexpr constexpr
|
|
# else
|
|
# define nsrs_constexpr /*constexpr*/
|
|
# endif
|
|
|
|
# if nsrs_HAVE_CONSTEXPR_14
|
|
# define nsrs_constexpr14 constexpr
|
|
# else
|
|
# define nsrs_constexpr14 /*constexpr*/
|
|
# endif
|
|
|
|
# if nsrs_HAVE_NOEXCEPT
|
|
# define nsrs_noexcept noexcept
|
|
# define nsrs_noexcept_op noexcept
|
|
# else
|
|
# define nsrs_noexcept /*noexcept*/
|
|
# define nsrs_noexcept_op(expr) /*noexcept(expr)*/
|
|
# endif
|
|
|
|
# if nsrs_HAVE_NULLPTR
|
|
# define nsrs_nullptr nullptr
|
|
# else
|
|
# define nsrs_nullptr NULL
|
|
# endif
|
|
|
|
// includes:
|
|
|
|
# include <cassert>
|
|
# include <iterator>
|
|
# include <utility>
|
|
|
|
// additional includes:
|
|
|
|
# if !nsrs_CPP11_OR_GREATER
|
|
# include <algorithm> // std::swap() until C++11
|
|
# endif
|
|
|
|
namespace nonstd {
|
|
|
|
# if nsrs_CPP11_OR_GREATER
|
|
using std::move;
|
|
# else
|
|
template<typename T>
|
|
T const&
|
|
move(T const& t)
|
|
{
|
|
return t;
|
|
}
|
|
# endif
|
|
|
|
template<bool B, class T, class F>
|
|
struct conditional {
|
|
typedef T type;
|
|
};
|
|
|
|
template<class T, class F>
|
|
struct conditional<false, T, F> {
|
|
typedef F type;
|
|
};
|
|
|
|
# if nsrs_CPP11_OR_GREATER
|
|
|
|
template<bool B, class T, class F>
|
|
using conditional_t = typename conditional<B, T, F>::type;
|
|
|
|
template<bool B, class T = void>
|
|
using enable_if_t = typename std::enable_if<B, T>::type;
|
|
|
|
# endif
|
|
|
|
//
|
|
// element extraction policies:
|
|
//
|
|
|
|
template<class T>
|
|
struct null_popper {
|
|
typedef void return_type;
|
|
|
|
void operator()(T&) const nsrs_noexcept {}
|
|
};
|
|
|
|
template<class T>
|
|
struct default_popper {
|
|
typedef T return_type;
|
|
|
|
T operator()(T& t) const
|
|
{
|
|
return nonstd::move(t);
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
struct copy_popper {
|
|
typedef T return_type;
|
|
|
|
# if nsrs_RING_SPAN_LITE_EXTENSION
|
|
# if nsrs_CPP11_OR_GREATER
|
|
copy_popper(T t) : m_copy(std::move(t)) {}
|
|
# else
|
|
copy_popper(T const& t) : m_copy(t) {}
|
|
# endif
|
|
# else
|
|
copy_popper(T&& t) : copy(std::move(t)) {}
|
|
# endif
|
|
|
|
T operator()(T& t) const
|
|
{
|
|
using std::swap;
|
|
T result(m_copy);
|
|
swap(t, result);
|
|
return result;
|
|
}
|
|
|
|
T m_copy;
|
|
};
|
|
|
|
// forward-declare iterator:
|
|
|
|
namespace ring_detail {
|
|
|
|
template<class, bool>
|
|
class ring_iterator;
|
|
|
|
}
|
|
|
|
//
|
|
// ring span:
|
|
//
|
|
template<class T, class Popper = default_popper<T> >
|
|
class ring_span {
|
|
public:
|
|
typedef T value_type;
|
|
typedef T* pointer;
|
|
typedef T& reference;
|
|
typedef T const& const_reference;
|
|
|
|
typedef std::size_t size_type;
|
|
|
|
typedef ring_span<T, Popper> type;
|
|
|
|
typedef ring_detail::ring_iterator<type, false> iterator;
|
|
typedef ring_detail::ring_iterator<type, true> const_iterator;
|
|
|
|
# if nsrs_RING_SPAN_LITE_EXTENSION
|
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
|
# endif
|
|
|
|
// construction:
|
|
|
|
template<class ContiguousIterator>
|
|
ring_span(ContiguousIterator begin,
|
|
ContiguousIterator end,
|
|
Popper popper = Popper()) nsrs_noexcept
|
|
: m_data(&*begin)
|
|
, m_size(0)
|
|
, m_capacity(static_cast<size_type>(end - begin))
|
|
, m_front_idx(0)
|
|
, m_popper(nonstd::move(popper))
|
|
{
|
|
}
|
|
|
|
template<class ContiguousIterator>
|
|
ring_span(ContiguousIterator begin,
|
|
ContiguousIterator end,
|
|
ContiguousIterator first,
|
|
size_type size,
|
|
Popper popper = Popper()) nsrs_noexcept
|
|
: m_data(&*begin)
|
|
, m_size(size)
|
|
, m_capacity(static_cast<size_type>(end - begin))
|
|
, m_front_idx(static_cast<size_type>(first - begin))
|
|
, m_popper(nonstd::move(popper))
|
|
{
|
|
}
|
|
|
|
# if nsrs_HAVE_IS_DEFAULT
|
|
ring_span(ring_span&&) = default;
|
|
ring_span& operator=(ring_span&&) = default;
|
|
# else
|
|
private:
|
|
ring_span(ring_span const&);
|
|
ring_span& operator=(ring_span const&);
|
|
|
|
public:
|
|
# endif
|
|
|
|
// observers:
|
|
|
|
bool empty() const nsrs_noexcept
|
|
{
|
|
return m_size == 0;
|
|
}
|
|
|
|
bool full() const nsrs_noexcept
|
|
{
|
|
return m_size == m_capacity;
|
|
}
|
|
|
|
size_type size() const nsrs_noexcept
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
size_type capacity() const nsrs_noexcept
|
|
{
|
|
return m_capacity;
|
|
}
|
|
|
|
// element access:
|
|
|
|
reference front() nsrs_noexcept
|
|
{
|
|
return *begin();
|
|
}
|
|
|
|
const_reference front() const nsrs_noexcept
|
|
{
|
|
return *begin();
|
|
}
|
|
|
|
reference back() nsrs_noexcept
|
|
{
|
|
return *(--end());
|
|
}
|
|
|
|
const_reference back() const nsrs_noexcept
|
|
{
|
|
return *(--end());
|
|
}
|
|
|
|
// iteration:
|
|
|
|
iterator begin() nsrs_noexcept
|
|
{
|
|
return iterator(0, this);
|
|
}
|
|
|
|
const_iterator begin() const nsrs_noexcept
|
|
{
|
|
return cbegin();
|
|
}
|
|
|
|
const_iterator cbegin() const nsrs_noexcept
|
|
{
|
|
return const_iterator(0, this);
|
|
}
|
|
|
|
iterator end() nsrs_noexcept
|
|
{
|
|
return iterator(size(), this);
|
|
}
|
|
|
|
const_iterator end() const nsrs_noexcept
|
|
{
|
|
return cend();
|
|
}
|
|
|
|
const_iterator cend() const nsrs_noexcept
|
|
{
|
|
return const_iterator(size(), this);
|
|
}
|
|
|
|
# if nsrs_RING_SPAN_LITE_EXTENSION
|
|
|
|
reverse_iterator rbegin() nsrs_noexcept
|
|
{
|
|
return reverse_iterator(end());
|
|
}
|
|
|
|
reverse_iterator rend() nsrs_noexcept
|
|
{
|
|
return reverse_iterator(begin());
|
|
}
|
|
|
|
const_reverse_iterator rbegin() const nsrs_noexcept
|
|
{
|
|
return crbegin();
|
|
}
|
|
|
|
const_reverse_iterator rend() const nsrs_noexcept
|
|
{
|
|
return crend();
|
|
}
|
|
|
|
const_reverse_iterator crbegin() const nsrs_noexcept
|
|
{
|
|
return const_reverse_iterator(cend());
|
|
}
|
|
|
|
const_reverse_iterator crend() const nsrs_noexcept
|
|
{
|
|
return const_reverse_iterator(cbegin());
|
|
}
|
|
# endif
|
|
|
|
void erase_from(iterator first)
|
|
{
|
|
m_size = static_cast<size_type>(std::distance(begin(), first));
|
|
}
|
|
|
|
// element insertion, extraction:
|
|
|
|
typename Popper::return_type pop_front()
|
|
{
|
|
assert(!empty());
|
|
|
|
reference element = front_();
|
|
increment_front_();
|
|
|
|
return m_popper(element);
|
|
}
|
|
|
|
# if nsrs_RING_SPAN_LITE_EXTENSION
|
|
typename Popper::return_type pop_back()
|
|
{
|
|
assert(!empty());
|
|
|
|
reference element = back_();
|
|
decrement_back_();
|
|
|
|
return m_popper(element);
|
|
}
|
|
# endif
|
|
|
|
# if nsrs_CPP11_OR_GREATER
|
|
template<bool b = true,
|
|
typename
|
|
= nonstd::enable_if_t<b && std::is_copy_assignable<T>::value> >
|
|
void push_back(value_type const& value)
|
|
nsrs_noexcept_op((std::is_nothrow_copy_assignable<T>::value))
|
|
# else
|
|
void push_back(value_type const& value)
|
|
# endif
|
|
{
|
|
if (full())
|
|
increment_front_and_back_();
|
|
else
|
|
increment_back_();
|
|
|
|
back_() = value;
|
|
}
|
|
|
|
# if nsrs_CPP11_OR_GREATER
|
|
template<bool b = true,
|
|
typename
|
|
= nonstd::enable_if_t<b && std::is_move_assignable<T>::value> >
|
|
void push_back(value_type&& value)
|
|
nsrs_noexcept_op((std::is_nothrow_move_assignable<T>::value))
|
|
{
|
|
if (full())
|
|
increment_front_and_back_();
|
|
else
|
|
increment_back_();
|
|
|
|
back_() = std::move(value);
|
|
}
|
|
|
|
template<class... Args>
|
|
void emplace_back(Args&&... args)
|
|
nsrs_noexcept_op((std::is_nothrow_constructible<T, Args...>::value
|
|
&& std::is_nothrow_move_assignable<T>::value))
|
|
{
|
|
if (full())
|
|
increment_front_and_back_();
|
|
else
|
|
increment_back_();
|
|
|
|
back_() = T(std::forward<Args>(args)...);
|
|
}
|
|
# endif
|
|
|
|
# if nsrs_RING_SPAN_LITE_EXTENSION
|
|
|
|
# if nsrs_CPP11_OR_GREATER
|
|
template<bool b = true,
|
|
typename
|
|
= nonstd::enable_if_t<b && std::is_copy_assignable<T>::value> >
|
|
void push_front(T const& value)
|
|
nsrs_noexcept_op((std::is_nothrow_copy_assignable<T>::value))
|
|
# else
|
|
void push_front(T const& value)
|
|
# endif
|
|
{
|
|
if (full())
|
|
decrement_front_and_back_();
|
|
else
|
|
decrement_front_();
|
|
|
|
front_() = value;
|
|
}
|
|
|
|
# if nsrs_CPP11_OR_GREATER
|
|
template<bool b = true,
|
|
typename
|
|
= nonstd::enable_if_t<b && std::is_move_assignable<T>::value> >
|
|
void push_front(T&& value)
|
|
nsrs_noexcept_op((std::is_nothrow_move_assignable<T>::value))
|
|
{
|
|
if (full())
|
|
decrement_front_and_back_();
|
|
else
|
|
decrement_front_();
|
|
|
|
front_() = std::move(value);
|
|
}
|
|
|
|
template<typename... Args>
|
|
void emplace_front(Args&&... args)
|
|
nsrs_noexcept_op((std::is_nothrow_constructible<T, Args...>::value
|
|
&& std::is_nothrow_move_assignable<T>::value))
|
|
{
|
|
if (full())
|
|
decrement_front_and_back_();
|
|
else
|
|
decrement_front_();
|
|
|
|
front_() = T(std::forward<Args>(args)...);
|
|
}
|
|
# endif
|
|
# endif // nsrs_RING_SPAN_LITE_EXTENSION
|
|
|
|
// swap:
|
|
|
|
void swap(type& rhs)
|
|
nsrs_noexcept // nsrs_noexcept_op(std::is_nothrow_swappable<Popper>::value);
|
|
{
|
|
using std::swap;
|
|
swap(m_data, rhs.m_data);
|
|
swap(m_size, rhs.m_size);
|
|
swap(m_capacity, rhs.m_capacity);
|
|
swap(m_front_idx, rhs.m_front_idx);
|
|
swap(m_popper, rhs.m_popper);
|
|
}
|
|
|
|
private:
|
|
friend class ring_detail::ring_iterator<ring_span,
|
|
true>; // const_iterator;
|
|
friend class ring_detail::ring_iterator<ring_span, false>; // iterator;
|
|
|
|
size_type normalize_(size_type const idx) const nsrs_noexcept
|
|
{
|
|
return idx % m_capacity;
|
|
}
|
|
|
|
reference at(size_type idx) nsrs_noexcept
|
|
{
|
|
return m_data[normalize_(m_front_idx + idx)];
|
|
}
|
|
|
|
const_reference at(size_type idx) const nsrs_noexcept
|
|
{
|
|
return m_data[normalize_(m_front_idx + idx)];
|
|
}
|
|
|
|
reference front_() nsrs_noexcept
|
|
{
|
|
return *(m_data + m_front_idx);
|
|
}
|
|
|
|
const_reference front_() const nsrs_noexcept
|
|
{
|
|
return *(m_data + m_front_idx);
|
|
}
|
|
|
|
reference back_() nsrs_noexcept
|
|
{
|
|
return *(m_data + normalize_(m_front_idx + m_size - 1));
|
|
}
|
|
|
|
const_reference back_() const nsrs_noexcept
|
|
{
|
|
return *(m_data + normalize_(m_front_idx + m_size - 1));
|
|
}
|
|
|
|
void increment_front_() nsrs_noexcept
|
|
{
|
|
m_front_idx = normalize_(m_front_idx + 1);
|
|
--m_size;
|
|
}
|
|
|
|
void decrement_front_() nsrs_noexcept
|
|
{
|
|
m_front_idx = normalize_(m_front_idx + m_capacity - 1);
|
|
++m_size;
|
|
}
|
|
|
|
void increment_back_() nsrs_noexcept
|
|
{
|
|
++m_size;
|
|
}
|
|
|
|
void decrement_back_() nsrs_noexcept
|
|
{
|
|
--m_size;
|
|
}
|
|
|
|
void increment_front_and_back_() nsrs_noexcept
|
|
{
|
|
m_front_idx = normalize_(m_front_idx + 1);
|
|
}
|
|
|
|
void decrement_front_and_back_() nsrs_noexcept
|
|
{
|
|
m_front_idx = normalize_(m_front_idx + m_capacity - 1);
|
|
}
|
|
|
|
private:
|
|
pointer m_data;
|
|
size_type m_size;
|
|
size_type m_capacity;
|
|
size_type m_front_idx;
|
|
Popper m_popper;
|
|
};
|
|
|
|
// swap:
|
|
|
|
template<class T, class Popper>
|
|
inline void
|
|
swap(ring_span<T, Popper>& lhs, ring_span<T, Popper>& rhs)
|
|
nsrs_noexcept_op(nsrs_noexcept_op(lhs.swap(rhs)))
|
|
{
|
|
lhs.swap(rhs);
|
|
}
|
|
|
|
namespace ring_detail {
|
|
|
|
//
|
|
// ring iterator:
|
|
//
|
|
# if 0
|
|
template< class RS, bool is_const >
|
|
class ring_iterator : public std::iterator
|
|
<
|
|
std::random_access_iterator_tag
|
|
, typename nonstd::conditional<is_const, const typename RS::value_type, typename RS::value_type>::type
|
|
>
|
|
# endif
|
|
|
|
template<class RS, bool is_const>
|
|
class ring_iterator {
|
|
public:
|
|
typedef ring_iterator<RS, is_const> type;
|
|
|
|
typedef std::ptrdiff_t difference_type;
|
|
typedef typename RS::value_type value_type;
|
|
|
|
typedef typename nonstd::
|
|
conditional<is_const, const value_type, value_type>::type* pointer;
|
|
typedef typename nonstd::
|
|
conditional<is_const, const value_type, value_type>::type& reference;
|
|
typedef std::random_access_iterator_tag iterator_category;
|
|
|
|
# if nsrs_CPP11_OR_GREATER
|
|
ring_iterator() = default;
|
|
# else
|
|
ring_iterator() : m_idx(), m_rs() {}
|
|
# endif
|
|
|
|
# if nsrs_RING_SPAN_LITE_EXTENSION
|
|
// conversion to const iterator:
|
|
|
|
operator ring_iterator<RS, true>() const nsrs_noexcept
|
|
{
|
|
return ring_iterator<RS, true>(m_idx, m_rs);
|
|
}
|
|
# endif
|
|
|
|
// access content:
|
|
|
|
reference operator*() const nsrs_noexcept
|
|
{
|
|
return m_rs->at(m_idx);
|
|
}
|
|
|
|
// advance iterator:
|
|
|
|
type& operator++() nsrs_noexcept
|
|
{
|
|
++m_idx;
|
|
return *this;
|
|
}
|
|
|
|
type operator++(int) nsrs_noexcept
|
|
{
|
|
type r(*this);
|
|
++*this;
|
|
return r;
|
|
}
|
|
|
|
type& operator--() nsrs_noexcept
|
|
{
|
|
--m_idx;
|
|
return *this;
|
|
}
|
|
|
|
type operator--(int) nsrs_noexcept
|
|
{
|
|
type r(*this);
|
|
--*this;
|
|
return r;
|
|
}
|
|
|
|
# if defined(__clang__) || defined(__GNUC__)
|
|
# pragma GCC diagnostic push
|
|
# pragma GCC diagnostic ignored "-Wsign-conversion"
|
|
# endif
|
|
|
|
type& operator+=(int i) nsrs_noexcept
|
|
{
|
|
m_idx += i;
|
|
return *this;
|
|
}
|
|
|
|
type& operator-=(int i) nsrs_noexcept
|
|
{
|
|
m_idx -= i;
|
|
return *this;
|
|
}
|
|
|
|
# if defined(__clang__) || defined(__GNUC__)
|
|
# pragma GCC diagnostic pop
|
|
# endif
|
|
|
|
# if nsrs_RING_SPAN_LITE_EXTENSION
|
|
|
|
template<bool C>
|
|
difference_type operator-(ring_iterator<RS, C> const& rhs) const
|
|
nsrs_noexcept
|
|
{
|
|
return static_cast<difference_type>(this->m_idx)
|
|
- static_cast<difference_type>(rhs.m_idx);
|
|
}
|
|
# endif
|
|
|
|
// comparison:
|
|
|
|
template<bool C>
|
|
bool operator<(ring_iterator<RS, C> const& rhs) const nsrs_noexcept
|
|
{
|
|
assert(this->m_rs == rhs.m_rs);
|
|
return (this->m_idx < rhs.m_idx);
|
|
}
|
|
|
|
template<bool C>
|
|
bool operator==(ring_iterator<RS, C> const& rhs) const nsrs_noexcept
|
|
{
|
|
assert(this->m_rs == rhs.m_rs);
|
|
return (this->m_idx == rhs.m_idx);
|
|
}
|
|
|
|
// other comparisons expressed in <, ==:
|
|
|
|
template<bool C>
|
|
inline bool operator!=(ring_iterator<RS, C> const& rhs) const nsrs_noexcept
|
|
{
|
|
return !(*this == rhs);
|
|
}
|
|
|
|
template<bool C>
|
|
inline bool operator<=(ring_iterator<RS, C> const& rhs) const nsrs_noexcept
|
|
{
|
|
return !(rhs < *this);
|
|
}
|
|
|
|
template<bool C>
|
|
inline bool operator>(ring_iterator<RS, C> const& rhs) const nsrs_noexcept
|
|
{
|
|
return rhs < *this;
|
|
}
|
|
|
|
template<bool C>
|
|
inline bool operator>=(ring_iterator<RS, C> const& rhs) const nsrs_noexcept
|
|
{
|
|
return !(*this < rhs);
|
|
}
|
|
|
|
private:
|
|
friend RS; // clang: non-class friend type 'RS' is a C++11 extension
|
|
// [-Wc++11-extensions]
|
|
friend class ring_iterator<RS, !is_const>;
|
|
|
|
typedef typename RS::size_type size_type;
|
|
typedef
|
|
typename nonstd::conditional<is_const, const RS, RS>::type ring_type;
|
|
|
|
ring_iterator(size_type idx,
|
|
typename nonstd::conditional<is_const, const RS, RS>::type*
|
|
rs) nsrs_noexcept
|
|
: m_idx(idx)
|
|
, m_rs(rs)
|
|
{
|
|
}
|
|
|
|
private:
|
|
size_type m_idx;
|
|
ring_type* m_rs;
|
|
};
|
|
|
|
// advanced iterator:
|
|
|
|
template<class RS, bool C>
|
|
inline ring_iterator<RS, C>
|
|
operator+(ring_iterator<RS, C> it, int i) nsrs_noexcept
|
|
{
|
|
it += i;
|
|
return it;
|
|
}
|
|
|
|
template<class RS, bool C>
|
|
inline ring_iterator<RS, C>
|
|
operator-(ring_iterator<RS, C> it, int i) nsrs_noexcept
|
|
{
|
|
it -= i;
|
|
return it;
|
|
}
|
|
|
|
} // namespace ring_detail
|
|
} // namespace nonstd
|
|
|
|
nsrs_RESTORE_WARNINGS()
|
|
|
|
#endif // NONSTD_RING_SPAN_LITE_HPP
|