jkxr/Projects/Android/jni/OpenJK/lib/gsl-lite/include/gsl/gsl-lite.h
Simon 4597b03873 Initial Commit
Opens in Android Studio but haven't even tried to build it yet (it won't.. I know that much!)
2022-09-18 16:37:21 +01:00

881 lines
20 KiB
C++

//
// gsl-lite is based on GSL: Guidelines Support Library,
// https://github.com/microsoft/gsl
//
// Copyright (c) 2015 Martin Moene
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#ifndef GSL_GSL_LITE_H_INCLUDED
#define GSL_GSL_LITE_H_INCLUDED
#include <exception>
#include <iterator>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
#define gsl_lite_VERSION "0.0.0"
// Configuration:
#ifndef gsl_FEATURE_HAVE_IMPLICIT_MACRO
# define gsl_FEATURE_HAVE_IMPLICIT_MACRO 1
#endif
#ifndef gsl_FEATURE_HAVE_OWNER_MACRO
# define gsl_FEATURE_HAVE_OWNER_MACRO 1
#endif
#ifndef gsl_CONFIG_THROWS_FOR_TESTING
# define gsl_CONFIG_THROWS_FOR_TESTING 0
#endif
#ifndef gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS
# define gsl_CONFIG_CONFIRMS_COMPILATION_ERRORS 0
#endif
// Compiler detection:
#if defined(_MSC_VER)
# define gsl_COMPILER_MSVC_VERSION (_MSC_VER / 100 - 5 - (_MSC_VER < 1900))
#else
# define gsl_COMPILER_MSVC_VERSION 0
# define gsl_COMPILER_NON_MSVC 1
#endif
#if ( __cplusplus >= 201103L )
# define gsl_CPP11_OR_GREATER 1
#endif
#if ( __cplusplus >= 201402L )
# define gsl_CPP14_OR_GREATER 1
#endif
// half-open range [lo..hi):
#define gsl_BETWEEN( v, lo, hi ) ( lo <= v && v < hi )
// Presence of C++ language features:
#if gsl_CPP11_OR_GREATER
# define gsl_HAVE_ALIAS_TEMPLATE 1
#endif
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 10
# define gsl_HAVE_AUTO 1
#endif
#if gsl_CPP11_OR_GREATER
# define gsl_HAVE_CONSTEXPR_11 1
#endif
#if gsl_CPP14_OR_GREATER
# define gsl_HAVE_CONSTEXPR_14 1
#endif
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 14
# define gsl_HAVE_ENUM_CLASS 1
#endif
#if gsl_CPP11_OR_GREATER
# define gsl_HAVE_IS_DEFAULT_CTOR 1
#endif
#if gsl_CPP11_OR_GREATER
# define gsl_HAVE_EXPLICIT_CONVERSION 1
#endif
#if gsl_CPP11_OR_GREATER
# define gsl_HAVE_INITIALIZER_LIST 1
#endif
#if gsl_CPP11_OR_GREATER
# define gsl_HAVE_NOEXCEPT 1
#endif
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 10
# define gsl_HAVE_NULLPTR 1
#endif
// Presence of C++ library features:
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 11
# define gsl_HAVE_ARRAY 1
#endif
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 9
# define gsl_HAVE_CONTAINER_DATA_METHOD 1
#endif
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 14
# define gsl_HAVE_SIZED_TYPES 1
#endif
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 10
# define gsl_HAVE_SHARED_PTR 1
# define gsl_HAVE_UNIQUE_PTR 1
#endif
#if gsl_CPP11_OR_GREATER || gsl_COMPILER_MSVC_VERSION >= 11
# define gsl_HAVE_TYPE_TRAITS 1
#endif
// For the rest, consider VC12, VC14 as C++11 for GSL Lite:
#if gsl_COMPILER_MSVC_VERSION >= 12
# undef gsl_CPP11_OR_GREATER
# define gsl_CPP11_OR_GREATER 1
#endif
// C++ feature usage:
#if gsl_HAVE_CONSTEXPR_11
# define gsl_constexpr constexpr
#else
# define gsl_constexpr /*nothing*/
#endif
#if gsl_HAVE_CONSTEXPR_14
# define gsl_constexpr14 constexpr
#else
# define gsl_constexpr14 /*nothing*/
#endif
#if gsl_HAVE_EXPLICIT_CONVERSION
# define gsl_explicit explicit
#else
# define gsl_explicit /*nothing*/
#endif
#if gsl_FEATURE_HAVE_IMPLICIT_MACRO
# define implicit
#endif
#if !gsl_HAVE_NOEXCEPT || gsl_CONFIG_THROWS_FOR_TESTING
# define gsl_noexcept /*nothing*/
#else
# define gsl_noexcept noexcept
#endif
#define gsl_DIMENSION_OF( a ) ( sizeof(a) / sizeof(0[a]) )
#if gsl_HAVE_ARRAY
# include <array>
#endif
#if gsl_HAVE_TYPE_TRAITS
# include <type_traits>
#endif
namespace gsl {
//
// GSL.owner: ownership pointers
//
#if gsl_HAVE_SHARED_PTR
using std::unique_ptr;
using std::shared_ptr;
#endif
#if gsl_HAVE_ALIAS_TEMPLATE
template< class T > using owner = T;
#else
template< class T > struct owner { typedef T type; };
#endif
#define gsl_HAVE_OWNER_TEMPLATE gsl_HAVE_ALIAS_TEMPLATE
#if gsl_FEATURE_HAVE_OWNER_MACRO
# if gsl_HAVE_OWNER_TEMPLATE
# define Owner(t) ::gsl::owner<t>
# else
# define Owner(t) ::gsl::owner<t>::type
# endif
#endif
//
// GSL.assert: assertions
//
#define Expects(x) ::gsl::fail_fast_assert((x))
#define Ensures(x) ::gsl::fail_fast_assert((x))
#if gsl_CONFIG_THROWS_FOR_TESTING
struct fail_fast : public std::runtime_error
{
fail_fast()
: std::runtime_error( "GSL assertion" ) {}
explicit fail_fast( char const * const message )
: std::runtime_error( message ) {}
};
inline void fail_fast_assert( bool cond )
{
if ( !cond )
throw fail_fast();
}
inline void fail_fast_assert( bool cond, char const * const message )
{
if ( !cond )
throw fail_fast( message );
}
#else // gsl_CONFIG_THROWS_FOR_TESTING
inline void fail_fast_assert( bool cond )
{
if ( !cond )
std::terminate();
}
inline void fail_fast_assert( bool cond, char const * const )
{
if ( !cond )
std::terminate();
}
#endif // gsl_CONFIG_THROWS_FOR_TESTING
//
// GSL.util: utilities
//
#if gsl_CPP11_OR_GREATER
template< class Fn >
class Final_act
{
public:
explicit Final_act( Fn action ) gsl_noexcept
: action_( std::move( action ) ) {}
~Final_act() gsl_noexcept { action_(); }
private:
Fn action_;
};
template< class Fn >
Final_act<Fn> finally( Fn const & action ) gsl_noexcept
{
return Final_act<Fn>( action );
}
template< class Fn >
Final_act<Fn> finally( Fn && action ) gsl_noexcept
{
return Final_act<Fn>( std::forward<Fn>( action ) );
}
#else // gsl_CPP11_OR_GREATER
class Final_act
{
public:
typedef void (*Action)();
Final_act( Action action )
: action_( action ) {}
~Final_act()
{
action_();
}
private:
Action action_;
};
template< class Fn >
Final_act finally( Fn const & f )
{
return Final_act(( f ));
}
#endif // gsl_CPP11_OR_GREATER
template< class T, class U >
T narrow_cast( U u ) gsl_noexcept
{
return static_cast<T>( u );
}
struct narrowing_error : public std::exception {};
template< class T, class U >
T narrow( U u )
{
T t = narrow_cast<T>( u );
if ( static_cast<U>( t ) != u )
{
throw narrowing_error();
}
return t;
}
//
// GSL.views: views
//
//
// at() - Bounds-checked way of accessing static arrays, std::array, std::vector.
//
template< class T, size_t N >
T & at( T(&arr)[N], size_t index )
{
Expects( index < N );
return arr[index];
}
#if gsl_HAVE_ARRAY
template< class T, size_t N >
T & at( std::array<T, N> & arr, size_t index )
{
Expects( index < N );
return arr[index];
}
#endif
template< class Cont >
typename Cont::value_type & at( Cont & cont, size_t index )
{
Expects( index < cont.size() );
return cont[index];
}
//
// not_null<> - Wrap any indirection and enforce non-null.
//
template<class T>
class not_null
{
public:
not_null( T t ) : ptr_ ( t ){ Expects( ptr_ != NULL ); }
not_null & operator=( T const & t ) { ptr_ = t ; Expects( ptr_ != NULL ); return *this; }
not_null( not_null const & other ) : ptr_ ( other.ptr_ ) {}
not_null & operator=( not_null const & other ) { ptr_ = other.ptr_; }
#if gsl_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG
template< typename U, typename Dummy =
typename std::enable_if<std::is_convertible<U, T>::value, void>::type >
not_null( not_null<U> const & other ) : ptr_( other.get() ) {}
template< typename U, typename Dummy =
typename std::enable_if<std::is_convertible<U, T>::value, void>::type >
not_null & operator=( not_null<U> const & other )
{
ptr_ = other.get();
return *this;
}
#else
template< typename U >
not_null( not_null<U> const & other ) : ptr_( other.get() ) {}
template< typename U >
not_null & operator=( not_null<U> const & other )
{
ptr_ = other.get();
return *this;
}
#endif
private:
// Prevent compilation when initialized with a nullptr or literal 0:
#if gsl_HAVE_NULLPTR
not_null( std::nullptr_t );
not_null & operator=( std::nullptr_t );
#endif
not_null( int );
not_null & operator=( int );
public:
T get() const
{
#if gsl_HAVE_NULLPTR && gsl_COMPILER_MSVC_VERSION > 0
// The assume() should help the optimizer:
__assume( ptr_ != nullptr );
#endif
return ptr_;
}
operator T() const { return get(); }
T operator->() const { return get(); }
bool operator==(T const & rhs) const { return ptr_ == rhs; }
bool operator!=(T const & rhs) const { return !(*this == rhs); }
private:
T ptr_;
not_null & operator++();
not_null & operator--();
not_null operator++( int );
not_null operator--( int );
not_null & operator+ ( size_t );
not_null & operator+=( size_t );
not_null & operator- ( size_t );
not_null & operator-=( size_t );
};
//
// Byte-specific type.
//
#if gsl_HAVE_ENUM_CLASS
# include <cstdint>
enum class byte : std::uint8_t {};
#elif gsl_HAVE_SIZED_TYPES
# include <cstdint>
typedef std::uint8_t byte;
#else
typedef unsigned char byte;
#endif
//
// array_view<> - A 1D view of contiguous T's, replace (*,len).
//
template< class T >
class array_view
{
template< class U > friend class array_view;
public:
typedef size_t size_type;
typedef T value_type;
typedef T & reference;
typedef T * pointer;
typedef T const * const_pointer;
typedef pointer iterator;
typedef const_pointer const_iterator;
#if gsl_BETWEEN( gsl_COMPILER_MSVC_VERSION, 6, 7 )
typedef std::reverse_iterator< iterator, T > reverse_iterator;
typedef std::reverse_iterator< const_iterator, const T > const_reverse_iterator;
#else
typedef std::reverse_iterator< iterator > reverse_iterator;
typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
#endif
typedef typename std::iterator_traits< iterator >::difference_type difference_type;
gsl_constexpr14 array_view()
: begin_( NULL )
, end_ ( NULL )
{
Expects( size() == 0 );
}
#if gsl_HAVE_NULLPTR
gsl_constexpr14 array_view( std::nullptr_t, size_type size )
: begin_( nullptr )
, end_ ( nullptr )
{
Expects( size == 0 );
}
#endif
gsl_constexpr14 array_view( pointer begin, pointer end )
: begin_( begin )
, end_ ( end )
{
Expects( begin <= end );
}
gsl_constexpr14 array_view( pointer & data, size_type size )
: begin_( data )
, end_ ( data + size )
{
Expects( size == 0 || ( size > 0 && data != NULL ) );
}
template< class U, size_t N >
gsl_constexpr14 array_view( U (&arr)[N] )
: begin_( arr )
, end_ ( arr + N )
{}
template< class U, size_t N >
gsl_constexpr14 array_view( U (&arr)[N], size_type size )
: begin_( arr )
, end_ ( arr + size )
{
Expects( size <= N );
}
#if gsl_HAVE_ARRAY
template< class U, size_t N >
gsl_constexpr14 array_view( std::array< U, N > & arr )
: begin_( arr.data() )
, end_ ( arr.data() + N )
{}
#endif
template< class Cont >
gsl_constexpr14 array_view( Cont & cont )
#if gsl_HAVE_CONTAINER_DATA_METHOD
: begin_( cont.data() )
, end_ ( cont.data() + cont.size() )
#else
: begin_( &cont[0] )
, end_ ( &cont[0] + cont.size() )
#endif
{}
#if gsl_HAVE_IS_DEFAULT_CTOR
gsl_constexpr14 array_view( array_view const & ) = default;
#else
gsl_constexpr14 array_view( array_view const & other )
: begin_( other.begin() )
, end_ ( other.end() )
{}
#endif
template< typename U >
gsl_constexpr14 array_view( array_view<U> const & other )
: begin_( other.begin() )
, end_ ( other.end() )
{}
array_view & operator=( array_view other )
{
other.swap( *this );
return *this;
}
#if 0
// Converting from other array_view ?
template< typename U > operator=();
#endif
gsl_constexpr14 iterator begin() const
{
return iterator( begin_ );
}
gsl_constexpr14 iterator end() const
{
return iterator( end_ );
}
gsl_constexpr14 const_iterator cbegin() const
{
return const_iterator( begin() );
}
gsl_constexpr14 const_iterator cend() const
{
return const_iterator( end() );
}
gsl_constexpr14 reverse_iterator rbegin() const
{
return reverse_iterator( end() );
}
gsl_constexpr14 reverse_iterator rend() const
{
return reverse_iterator( begin() );
}
gsl_constexpr14 const_reverse_iterator crbegin() const
{
return const_reverse_iterator( cend() );
}
gsl_constexpr14 const_reverse_iterator crend() const
{
return const_reverse_iterator( cbegin() );
}
gsl_constexpr14 operator bool () const gsl_noexcept
{
return begin_ != NULL;
}
gsl_constexpr14 reference operator[]( size_type index )
{
return at( index );
}
gsl_constexpr14 bool operator==( array_view const & other ) const gsl_noexcept
{
return size() == other.size()
&& (begin_ == other.begin_ || std::equal( this->begin(), this->end(), other.begin() ) );
}
gsl_constexpr14 bool operator!=( array_view const & other ) const gsl_noexcept
{
return !( *this == other );
}
gsl_constexpr14 bool operator< ( array_view const & other ) const gsl_noexcept
{
return std::lexicographical_compare( this->begin(), this->end(), other.begin(), other.end() );
}
gsl_constexpr14 bool operator<=( array_view const & other ) const gsl_noexcept
{
return !( other < *this );
}
gsl_constexpr14 bool operator> ( array_view const & other ) const gsl_noexcept
{
return ( other < *this );
}
gsl_constexpr14 bool operator>=( array_view const & other ) const gsl_noexcept
{
return !( *this < other );
}
gsl_constexpr14 reference at( size_type index )
{
Expects( index >= 0 && index < size());
return begin_[ index ];
}
gsl_constexpr14 pointer data() const gsl_noexcept
{
return begin_;
}
gsl_constexpr14 bool empty() const gsl_noexcept
{
return size() == 0;
}
gsl_constexpr14 size_type size() const gsl_noexcept
{
return std::distance( begin_, end_ );
}
gsl_constexpr14 size_type length() const gsl_noexcept
{
return size();
}
gsl_constexpr14 size_type used_length() const gsl_noexcept
{
return length();
}
gsl_constexpr14 size_type bytes() const gsl_noexcept
{
return sizeof( value_type ) * size();
}
gsl_constexpr14 size_type used_bytes() const gsl_noexcept
{
return bytes();
}
void swap( array_view & other ) gsl_noexcept
{
using std::swap;
swap( begin_, other.begin_ );
swap( end_ , other.end_ );
}
array_view< const byte > as_bytes() const gsl_noexcept
{
return array_view< const byte >( reinterpret_cast<const byte *>( data() ), bytes() );
}
array_view< byte > as_writeable_bytes() const gsl_noexcept
{
return array_view< byte >( reinterpret_cast<byte *>( data() ), bytes() );
}
template< typename U >
array_view< U > as_array_view() const gsl_noexcept
{
Expects( ( this->bytes() % sizeof(U) ) == 0 );
return array_view< U >( reinterpret_cast<U *>( this->data() ), this->bytes() / sizeof( U ) );
}
private:
// helpers for member as_array_view()
template< typename U >
gsl_constexpr14 array_view( U * & data, size_type size )
: begin_( data )
, end_ ( data + size )
{
Expects( size == 0 || ( size > 0 && data != NULL ) );
}
template< typename U >
gsl_constexpr14 array_view( U * const & data, size_type size )
: begin_( data )
, end_ ( data + size )
{
Expects( size == 0 || ( size > 0 && data != NULL ) );
}
private:
pointer begin_;
pointer end_;
};
// array_view creator functions (see ctors)
template< typename T >
gsl_constexpr14 array_view<T> as_array_view( T * begin, T * end )
{
return array_view<T>( begin, end );
}
template< typename T >
gsl_constexpr14 array_view<T> as_array_view( T * begin, size_t size )
{
return array_view<T>( begin, size );
}
template< typename T, size_t N >
gsl_constexpr14 array_view<T> as_array_view( T (&arr)[N] )
{
return array_view<T>( arr, N );
}
#if gsl_HAVE_ARRAY
template< typename T, size_t N >
gsl_constexpr14 array_view<T> as_array_view( std::array<T,N> & arr )
{
return array_view<T>( arr );
}
#endif
#if gsl_HAVE_AUTO
template< class Cont >
gsl_constexpr14 auto as_array_view( Cont & cont ) -> array_view< typename Cont::value_type >
{
return array_view< typename Cont::value_type >( cont );
}
#else
template< class T >
array_view<T> as_array_view( std::vector<T> & cont )
{
return array_view<T>( cont );
}
#endif
//
// String types:
//
typedef char * zstring;
typedef wchar_t * zwstring;
typedef const char * czstring;
typedef const wchar_t * cwzstring;
typedef array_view< char > string_view;
typedef array_view< wchar_t > wstring_view;
typedef array_view< const char > cstring_view;
typedef array_view< const wchar_t > cwstring_view;
// to_string() allow (explicit) conversions from string_view to string
inline std::string to_string( string_view const & view )
{
return std::string( view.data(), view.length() );
}
inline std::string to_string( cstring_view const & view )
{
return std::string( view.data(), view.length() );
}
inline std::wstring to_string( wstring_view const & view )
{
return std::wstring( view.data(), view.length() );
}
inline std::wstring to_string( cwstring_view const & view )
{
return std::wstring( view.data(), view.length() );
}
//
// ensure_sentinel()
//
// Provides a way to obtain an array_view from a contiguous sequence
// that ends with a (non-inclusive) sentinel value.
//
// Will fail-fast if sentinel cannot be found before max elements are examined.
//
namespace detail {
template<class T, class SizeType, const T Sentinel>
static array_view<T> ensure_sentinel( T * seq, SizeType max = std::numeric_limits<SizeType>::max() )
{
typedef T * pointer;
typedef typename std::iterator_traits<pointer>::difference_type difference_type;
pointer cur = seq;
while ( std::distance( seq, cur ) < static_cast<difference_type>( max ) && *cur != Sentinel )
++cur;
Expects( *cur == Sentinel );
return array_view<T>( seq, cur - seq );
}
} // namespace detail
//
// ensure_z - creates a string_view for a czstring or cwzstring.
// Will fail fast if a null-terminator cannot be found before
// the limit of size_type.
//
template< class T >
inline array_view<T> ensure_z( T * const & sz, size_t max = std::numeric_limits<size_t>::max() )
{
return detail::ensure_sentinel<T, size_t, 0>( sz, max );
// return detail::ensure<T, size_t, 0>::sentinel( sz, max );
}
template< class T, size_t N >
array_view<T> ensure_z( T (&sz)[N] )
{
return ensure_z( &sz[0], N );
}
# if gsl_HAVE_TYPE_TRAITS
template< class Cont >
array_view< typename std::remove_pointer<typename Cont::pointer>::type >
ensure_z( Cont& cont )
{
return ensure_z( cont.data(), cont.length() );
}
# endif
} // namespace gsl
#endif // GSL_GSL_LITE_H_INCLUDED
// end of file