241 lines
5.0 KiB
C++

//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// 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)
//
// Official repository: https://github.com/boostorg/beast
//
#ifndef MYX_BACKPORTS_CPP_SPAN_HPP_
#define MYX_BACKPORTS_CPP_SPAN_HPP_
#pragma once
#if ( __cplusplus >= 201103L ) && ( __cplusplus < 201703L )
#include <myx/backports/cpp/helpers.hpp>
#include <algorithm>
#include <iterator>
#include <string>
#include <type_traits>
namespace std {
template< class T, class E, class = void >
struct is_contiguous_container : std::false_type {}; // NOLINT
template< class T, class E >
struct is_contiguous_container< T, E, void_t<
decltype(
std::declval< std::size_t& >() = std::declval< T const& >().size(),
std::declval< E*& >() = std::declval< T& >().data() ),
typename std::enable_if<
std::is_same<
typename std::remove_cv< E >::type,
typename std::remove_cv<
typename std::remove_pointer<
decltype( std::declval< T& >().data() )
>::type
>::type
>::value
>::type > > : std::true_type
{};
/** A range of bytes expressed as a ContiguousContainer
This class implements a non-owning reference to a storage
area of a certain size and having an underlying integral
type with size of 1.
@tparam T The type pointed to by span iterators
*/
template< class T >
class span // NOLINT
{
T* m_data = nullptr;
std::size_t m_size = 0;
public:
/// The type of value, including cv qualifiers
using ElementType = T;
/// The type of value of each span element
using ValueType = typename std::remove_const< T >::type;
/// The type of integer used to index the span
using IndexType = std::ptrdiff_t;
/// A pointer to a span element
using Pointer = T*;
/// A reference to a span element
using Reference = T&;
/// The iterator used by the container
using Iterator = Pointer;
/// The const pointer used by the container
using ConstPointer = T const*;
/// The const reference used by the container
using ConstReference = T const&;
/// The const iterator used by the container
using ConstIterator = ConstPointer;
/// Constructor
span() = default;
/// Constructor
span( span const& ) = default;
/// Assignment
span& operator=( span const& ) = default;
/** Constructor
* @param data A pointer to the beginning of the range of elements
* @param size The number of elements pointed to by `data`
*/
span( T* data, std::size_t size ) :
m_data( data ),
m_size( size )
{
}
/** Constructor
* @param container The container to construct from
*/
template< class ContiguousContainer,
class = typename std::enable_if<
is_contiguous_container<
ContiguousContainer, T >::value >::type
>
explicit
span( ContiguousContainer&& container ) :
m_data( container.data() ),
m_size( container.size() )
{
}
template< class CharT, class Traits, class Allocator >
explicit
span( std::basic_string< CharT, Traits, Allocator >& s ) :
m_data( &s[0] ),
m_size( s.size() )
{
}
template< class CharT, class Traits, class Allocator >
explicit
span( std::basic_string< CharT, Traits, Allocator > const& s ) :
m_data( s.data() ),
m_size( s.size() )
{
}
/** Assignment
* @param container The container to assign from
*/
template< class ContiguousContainer >
typename std::enable_if< is_contiguous_container<
ContiguousContainer, T >::value,
span& >::type
operator=( ContiguousContainer&& container )
{
m_data = container.data();
m_size = container.size();
return( *this );
}
template< class CharT, class Traits, class Allocator >
span&
operator=( std::basic_string<
CharT, Traits, Allocator >& s )
{
m_data = &s[0];
m_size = s.size();
return( *this );
}
template< class CharT, class Traits, class Allocator >
span&
operator=( std::basic_string<
CharT, Traits, Allocator > const& s )
{
m_data = s.data();
m_size = s.size();
return( *this );
}
/// Returns `true` if the span is empty
bool
empty() const
{
return( m_size == 0 );
}
/// Returns a pointer to the beginning of the span
T*
data() const
{
return( m_data );
}
/// Returns the number of elements in the span
std::size_t
size() const
{
return( m_size );
}
/// Returns an iterator to the beginning of the span
Iterator
begin() const
{
return( m_data );
}
/// Returns an iterator to the beginning of the span
ConstIterator
cbegin() const
{
return( m_data );
}
/// Returns an iterator to one past the end of the span
Iterator
end() const
{
return( m_data + m_size );
}
/// Returns an iterator to one past the end of the span
ConstIterator
cend() const
{
return( m_data + m_size );
}
}; // class span
} // namespace std
#endif // if ( __cplusplus >= 201103L ) && ( __cplusplus < 201703L )
#endif // ifndef MYX_BACKPORTS_CPP_SPAN_HPP_