#pragma once
// Copyright (c) 2011, 2012 Alf P. Steinbach
//--------------------------------------------------------- Dependencies:
#include <progrock/cpp/u/natural_encoding.h> // CPP_NATURAL_ENCODING, RawEncodingUnitFor
#include <progrock/cpp/c++11_emulation.h> // CPP_STATIC_ASSERT, CPP_NOEXCEPT
#include <progrock/cpp/data/Size.h> // cpp::Size, cpp::bitsPerByte
#include <locale> // std::char_traits
#include <utility> // comparison operators
//--------------------------------------------------------- Interface:
// You might '#define U CPP_U' within a separately compiled file, for convenience.
// There is some risk that a macro U might conflict with e.g. template parameter.
#if CPP_NATURAL_ENCODING == CPP_ENCODING_UTF16
CPP_STATIC_ASSERT( sizeof( wchar_t ) == 2 ); // E.g. Windows.
# define CPP_U_ENCODING ::progrock::cpp::u::NaturalEncoding::utf16
# define CPP_U( aLiteral ) ::progrock::cpp::u::typed( L##aLiteral )
#elif CPP_NATURAL_ENCODING == CPP_ENCODING_UTF8
# define CPP_U_ENCODING ::progrock::cpp::u::NaturalEncoding::utf8
# define CPP_U( aLiteral ) ::progrock::cpp::u::typed( aLiteral )
#else
# error "The natural encoding for this OS is not supported, sorry."
#endif
namespace progrock { namespace cpp { namespace u {
using namespace std::rel_ops; // operator!= etc.
NaturalEncoding::Enum const encoding = CPP_U_ENCODING;
//typedef detail::EncodingTraits< encoding > Traits;
//
// Using the traits here brings in too much indirection for Visual C++ to handle:
//
//typedef Traits::Raw::Unit RawEncodingUnit;
//typedef Traits::Raw::ExtendedUnit RawExtendedEncodingUnit;
//typedef Traits::Unit EncodingUnit;
//typedef Traits::ExtendedUnit ExtendedEncodingUnit;
typedef RawEncodingUnitFor< encoding >::Type RawEncodingUnit;
typedef std::char_traits<RawEncodingUnit>::int_type RawExtendedEncodingUnit;
typedef enum: RawEncodingUnit {} EncodingUnit;
typedef enum: RawExtendedEncodingUnit {} ExtendedEncodingUnit;
typedef RawEncodingUnit RawCh; // For associative mnemonic value, although misleading!
typedef EncodingUnit Ch; // For associative mnemonic value, although misleading!
CPP_STATIC_ASSERT( sizeof( EncodingUnit ) == sizeof( RawEncodingUnit ) );
CPP_STATIC_ASSERT( sizeof( ExtendedEncodingUnit ) == sizeof( RawExtendedEncodingUnit ) );
namespace detail {
inline RawEncodingUnit raw( EncodingUnit const v ) CPP_NOEXCEPT
{
return v;
}
inline RawExtendedEncodingUnit raw( ExtendedEncodingUnit const v ) CPP_NOEXCEPT
{
return v;
}
template< class TpEncodingUnit > // Templating to de-emphasize re overload resolution.
inline RawEncodingUnit* raw( TpEncodingUnit* p ) CPP_NOEXCEPT;
template<>
inline RawEncodingUnit* raw<EncodingUnit>( EncodingUnit* p ) CPP_NOEXCEPT
{
return reinterpret_cast< RawEncodingUnit* >( p );
}
template< class TpEncodingUnit > // Templating to de-emphasize re overload resolution.
inline RawEncodingUnit const* raw( TpEncodingUnit const* p ) CPP_NOEXCEPT;
template<>
inline RawEncodingUnit const* raw<EncodingUnit>( EncodingUnit const* p ) CPP_NOEXCEPT
{
return reinterpret_cast< RawEncodingUnit const* >( p );
}
inline EncodingUnit typed( RawEncodingUnit const v ) CPP_NOEXCEPT
{
return EncodingUnit( v );
}
inline EncodingUnit* typed( RawEncodingUnit* const p ) CPP_NOEXCEPT
{
return reinterpret_cast< EncodingUnit* >( p );
}
inline EncodingUnit const* typed( RawEncodingUnit const* const p ) CPP_NOEXCEPT
{
return reinterpret_cast< EncodingUnit const* >( p );
}
} // namespace detail
template< Size size >
inline RawEncodingUnit (&raw( EncodingUnit (&s)[size] )) [size]
{
return reinterpret_cast< RawEncodingUnit (&)[size] >( s );
}
template< Size size >
inline RawEncodingUnit const (&raw( EncodingUnit const (&s)[size] ) CPP_NOEXCEPT)[size]
{
return reinterpret_cast< RawEncodingUnit const (&)[size] >( s );
}
template< size_t size >
inline EncodingUnit (&typed( RawEncodingUnit (&s)[size] ) CPP_NOEXCEPT)[size]
{
return reinterpret_cast< EncodingUnit (&)[size] >( s );
}
template< size_t size >
inline EncodingUnit const (&typed( RawEncodingUnit const (&s)[size] ) CPP_NOEXCEPT)[size]
{
return reinterpret_cast< EncodingUnit const (&)[size] >( s );
}
template< class Arg >
inline auto raw( Arg&& arg ) -> decltype( detail::raw( arg ) )
{
return detail::raw( arg );
}
template< class Arg >
inline auto typed( Arg&& arg ) -> decltype( detail::typed( arg ) )
{
return detail::typed( arg );
}
enum Adl {};
inline EncodingUnit typed( RawEncodingUnit const v, Adl ) CPP_NOEXCEPT
{
return EncodingUnit( v );
}
inline EncodingUnit* typed( RawEncodingUnit* const p, Adl ) CPP_NOEXCEPT
{
return reinterpret_cast< EncodingUnit* >( p );
}
inline EncodingUnit const* typed( RawEncodingUnit const* const p, Adl ) CPP_NOEXCEPT
{
return reinterpret_cast< EncodingUnit const* >( p );
}
template< size_t size >
inline EncodingUnit (&typed( RawEncodingUnit (&s)[size], Adl ) CPP_NOEXCEPT)[size]
{
return reinterpret_cast< EncodingUnit (&)[size] >( s );
}
template< size_t size >
inline EncodingUnit const (&typed( RawEncodingUnit const (&s)[size], Adl ) CPP_NOEXCEPT)[size]
{
return reinterpret_cast< EncodingUnit const (&)[size] >( s );
}
} } } // namespace progrock::cpp::u
namespace std {
// Requirements specified by C++11 ยง21.2.1/1 table 62.
template<>
struct char_traits< ::progrock::cpp::u::EncodingUnit >
{
private:
typedef ::progrock::cpp::u::Adl AdlCppU;
typedef ::progrock::cpp::u::RawEncodingUnit RawEncodingUnit;
static AdlCppU const cppU = AdlCppU();
public:
typedef ::progrock::cpp::u::EncodingUnit char_type;
typedef ::progrock::cpp::u::ExtendedEncodingUnit int_type;
typedef std::char_traits< RawEncodingUnit > Std;
typedef Std::off_type off_type;
typedef Std::pos_type pos_type;
typedef Std::state_type state_type;
static bool eq( char_type a, char_type b ) CPP_NOEXCEPT
{ return (a == b); }
static bool lt( char_type a, char_type b ) CPP_NOEXCEPT
{ return (a < b); }
static int compare( char_type const* s1, char_type const* s2, size_t n )
{ return Std::compare( raw( s1 ), raw( s2 ), n ); }
static size_t length( char_type const* s )
{ return Std::length( raw( s ) ); }
static char_type const* find( char_type const* s, size_t n, char_type const a )
{ return typed( Std::find( raw( s ), n, raw( a ) ), cppU ); }
static char_type* move( char_type* s1, char_type const* s2, size_t n )
{ return typed( Std::move( raw( s1 ), raw( s2 ), n ), cppU ); }
static char_type* copy( char_type* s1, char_type const* s2, size_t n )
{ return typed( Std::copy( raw( s1 ), raw( s2 ), n ), cppU ); }
static void assign( char_type& c1, char_type const c2 ) CPP_NOEXCEPT
{ c1 = c2; }
static char_type* assign( char_type* s, size_t n, char_type const a )
{ return typed( Std::assign( raw( s ), n, raw( a ) ), cppU ); }
static int_type not_eof( int_type const c ) CPP_NOEXCEPT
{ return int_type( Std::not_eof( Std::int_type( c ) ) ); }
static char_type to_char_type( int_type const c ) CPP_NOEXCEPT
{ return typed( raw( c ), cppU ); }
static int_type to_int_type( char_type const c ) CPP_NOEXCEPT
{ return int_type( c ); }
static bool eq_int_type( int_type const c1, int_type const c2 ) CPP_NOEXCEPT
{ return (c1 == c2); }
static int_type eof() CPP_NOEXCEPT
{ return int_type( Std::eof() ); }
};
} // namespace std
namespace progrock { namespace cpp { namespace u {
typedef std::char_traits< Ch > ChTraits;
} } } // namespace progrock::cpp::u