2021-10-28 20:35:48 +00:00
/***
Copyright ( C ) 2021 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
File : AuroraEnum . hpp
Date : 2021 - 10 - 28
Author : Reece
* * */
# pragma once
2021-10-28 21:18:32 +00:00
///////////////////////////////////////////////////////////////////////////////////////////
/// Configuration
///////////////////////////////////////////////////////////////////////////////////////////
2021-10-28 21:15:29 +00:00
# if defined(AUE_OUT_OF_ECOSYSTEM)
2021-11-19 14:38:03 +00:00
# if !defined(AUE_NOCPPSTL)
# include <unordered_map>
# include <string>
# include <functional>
# if !defined(AU_AuHashMap)
# define AU_AuHashMap
template < typename T , typename Z >
using AuHashMap = std : : unordered_map < T , Z > ;
# endif
# if !defined(AU_AuString)
# define AU_AuString
using AuString = std : : string ;
# endif
# if !defined(AU_AuConsumer)
# define AU_AuConsumer
template < typename . . . T >
using AuConsumer = std : : function < void ( T . . . ) > ;
# endif
# endif
# if !defined(AU_AuUInt)
# define AU_AuUInt
using AuUInt = size_t ;
# endif
2021-10-28 21:49:27 +00:00
2021-10-28 21:15:29 +00:00
# endif
2021-10-28 20:35:48 +00:00
///////////////////////////////////////////////////////////////////////////////////////////
/// Utilities
///////////////////////////////////////////////////////////////////////////////////////////
/// @hideinitializer
# define AUE_BRACKET_SCOPE(...) __VA_ARGS__
/// @hideinitializer
# define AUE_STRIP_BRACKETS_(X) X
/// @hideinitializer
# define AUE_STRIP_BRACKETS(X) AUE_STRIP_BRACKETS_(AUE_BRACKET_SCOPE X)
/// @hideinitializer
# define AUE_EMIT_ARRAY(val) val,
/// @hideinitializer
2021-10-28 22:19:29 +00:00
# define AUE_EMIT_A(val) #val,
2021-10-28 20:35:48 +00:00
2021-10-28 22:19:29 +00:00
/// @hideinitializer
# define AUE_EMIT_D(name, val) name::val,
2021-10-28 20:35:48 +00:00
/// @hideinitializer
# define AUE_EMIT_PAIRNAME(name, val) {#val, name::val},
/// @hideinitializer
# define AUE_EMIT_CALL(name, val) consumer(name::val);
/// @hideinitializer
# define AUE_EMIT_CHECK(name, val) if (codename == #val) {return name::val;}
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
# define AUE_DEFINE(name, vals) enum class name { AU_FOR_EACH(AUE_EMIT_ARRAY, AUE_STRIP_BRACKETS(vals)) kEnumCount }; \
2021-10-29 17:03:01 +00:00
static inline const AuString k # # name # # ToString [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH ( AUE_EMIT_A , AUE_STRIP_BRACKETS ( vals ) ) } ; \
static inline const name k # # name # # Values [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH_THAT ( AUE_EMIT_D , name , AUE_STRIP_BRACKETS ( vals ) ) } ; \
2021-10-28 21:43:28 +00:00
inline const AuHashMap < AuString , name > k # # name # # FromString = { AU_FOR_EACH_THAT ( AUE_EMIT_PAIRNAME , name , AUE_STRIP_BRACKETS ( vals ) ) { " kEnumCount " , name : : kEnumCount } } ; \
2021-10-28 20:35:48 +00:00
static inline name name # # FromString ( const AuString & codename ) { AU_FOR_EACH_THAT ( AUE_EMIT_CHECK , name , AUE_STRIP_BRACKETS ( vals ) ) return name : : kEnumCount ; } \
2021-10-28 21:43:28 +00:00
static inline name name # # FromHashString ( const AuString & codename ) { auto itr = k # # name # # FromString . find ( codename ) ; if ( itr = = k # # name # # FromString . end ( ) ) return name : : kEnumCount ; return itr - > second ; } \
2021-10-28 21:54:58 +00:00
static inline const AuString & name # # ToString ( name val ) { static const AuString invalid = " kEnumCount " ; if ( static_cast < AuUInt > ( val ) > = static_cast < AuUInt > ( name : : kEnumCount ) ) return invalid ; return k # # name # # ToString [ static_cast < AuUInt > ( val ) ] ; } \
2021-10-29 17:03:01 +00:00
static inline bool name # # IsValid ( name val ) { return static_cast < AuUInt > ( val ) < static_cast < AuUInt > ( name : : kEnumCount ) ; } \
2021-10-28 23:34:25 +00:00
static inline void name # # ForEach ( const AuConsumer < name > & consumer ) { AU_FOR_EACH_THAT ( AUE_EMIT_CALL , name , AUE_STRIP_BRACKETS ( vals ) ) } \
static const AuUInt k # # name # # Count = static_cast < AuUInt > ( name : : kEnumCount ) ; \
2021-10-29 09:47:22 +00:00
static const name k # # name # # Invalid = name : : kEnumCount ; \
2021-10-28 23:34:25 +00:00
static const name k # # name # # MaxLegal = static_cast < name > ( k # # name # # Count - 1 ) ; \
static const name k # # name # # MinLegal = static_cast < name > ( 0 ) ;
2021-11-19 14:38:03 +00:00
# define AUE_ITERATE(name, index) name index = static_cast<name>(0); static_cast<AuUInt>(index) < static_cast<AuUInt>(name::kEnumCount); index = static_cast<name>(static_cast<AuUInt>(index) + 1)
///////////////////////////////////////////////////////////////////////////////////////////
// Limited support for when there is no STL or STL-like library available
///////////////////////////////////////////////////////////////////////////////////////////
# if defined(AUE_NOCPPSTL)
# undef AUE_DEFINE
# define AUE_DEFINE(name, vals) enum class name { AU_FOR_EACH(AUE_EMIT_ARRAY, AUE_STRIP_BRACKETS(vals)) kEnumCount }; \
static inline const char * k # # name # # ToString [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH ( AUE_EMIT_A , AUE_STRIP_BRACKETS ( vals ) ) } ; \
static inline const name k # # name # # Values [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH_THAT ( AUE_EMIT_D , name , AUE_STRIP_BRACKETS ( vals ) ) } ; \
static inline const char * name # # ToString ( name val ) { static const char * invalid = " kEnumCount " ; if ( static_cast < AuUInt > ( val ) > = static_cast < AuUInt > ( name : : kEnumCount ) ) return invalid ; return k # # name # # ToString [ static_cast < AuUInt > ( val ) ] ; } \
static inline bool name # # IsValid ( name val ) { return static_cast < AuUInt > ( val ) < static_cast < AuUInt > ( name : : kEnumCount ) ; } \
static const AuUInt k # # name # # Count = static_cast < AuUInt > ( name : : kEnumCount ) ; \
static const name k # # name # # Invalid = name : : kEnumCount ; \
static const name k # # name # # MaxLegal = static_cast < name > ( k # # name # # Count - 1 ) ; \
static const name k # # name # # MinLegal = static_cast < name > ( 0 ) ;
# endif