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
///////////////////////////////////////////////////////////////////////////////////////////
2022-07-22 08:20:17 +00:00
# if defined(AUE_OUT_OF_ECOSYSTEM) && defined(__cplusplus)
# if !defined(AU_LANG_CPP)
# define AU_LANG_CPP
# endif
2021-10-28 21:15:29 +00:00
2021-11-19 14:38:03 +00:00
# if !defined(AUE_NOCPPSTL)
# include <unordered_map>
# include <string>
# 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
2024-04-20 00:35:00 +00:00
# if !defined(AU_AuROString)
# define AU_AuROString
using AuROString = std : : string_view ;
# endif
2021-11-19 14:38:03 +00:00
# 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
2022-01-30 02:37:56 +00:00
# define _AUE_BRACKET_SCOPE(...) __VA_ARGS__
2021-10-28 20:35:48 +00:00
/// @hideinitializer
2022-01-30 02:37:56 +00:00
# define __AUE_STRIP_BRACKETS(X) X
2021-10-28 20:35:48 +00:00
/// @hideinitializer
2022-01-30 02:37:56 +00:00
# define _AUE_STRIP_BRACKETS(X) __AUE_STRIP_BRACKETS(_AUE_BRACKET_SCOPE X)
2021-10-28 20:35:48 +00:00
/// @hideinitializer
2022-01-30 02:37:56 +00:00
# define _AUE_EMIT_ARRAY(val) val,
2021-10-28 20:35:48 +00:00
/// @hideinitializer
2022-01-30 02:37:56 +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
2022-01-30 02:37:56 +00:00
# define _AUE_EMIT_D(name, val) name::val,
2021-10-28 20:35:48 +00:00
2022-07-22 08:20:17 +00:00
/// @hideinitializer
# define _AUE_EMIT_E(name, val) val,
2021-10-28 20:35:48 +00:00
/// @hideinitializer
2022-01-30 02:37:56 +00:00
# define _AUE_EMIT_PAIRNAME(name, val) {#val, name::val},
2021-10-28 20:35:48 +00:00
/// @hideinitializer
2022-01-30 02:37:56 +00:00
# define _AUE_EMIT_CALL(name, val) consumer(name::val);
2021-10-28 20:35:48 +00:00
/// @hideinitializer
2022-01-30 02:37:56 +00:00
# define _AUE_EMIT_CHECK(name, val) if (codename == #val) {return name::val;}
2021-10-28 20:35:48 +00:00
2024-01-23 19:11:38 +00:00
# if defined(__cplusplus)
# define _AUE_EMIT_CCHECK(name, val) if (strcmp(#val, codename) == 0) { return name::val; }
# else
# define _AUE_EMIT_CCHECK(name, val) if (strcmp(#val, codename) == 0) { return k ## name ## val; }
# endif
2024-04-20 00:35:00 +00:00
# if !defined(_AUE_DISABLE_STRING_VIEWS) && !defined(AU_LANG_CPP_14) && !defined(AU_LANG_CPP_17)
# define _AUE_STRING_VIEW AuROString
# else
# define _AUE_STRING_VIEW AuString
# endif
2024-01-23 19:11:38 +00:00
2021-10-28 20:35:48 +00:00
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
2022-01-30 02:37:56 +00:00
# define AUE_DEFINE_VA(name, ...) AUE_DEFINE(name, (__VA_ARGS__))
2022-07-22 08:20:17 +00:00
# if defined(AU_LANG_CPP)
# define AUE_DEFINE_DECL_LANG(name, vals) enum class name : AuUInt32 { AU_FOR_EACH(_AUE_EMIT_ARRAY, _AUE_STRIP_BRACKETS(vals)) kEnumCount, kEnumInvalid = (AuUInt32) -1, eEnumInvalid = (AuUInt32)-1, eEnumCount = kEnumCount };
2023-07-03 16:58:16 +00:00
# define AUE_DEFINE_DECL_EXT(name, vals, ext) enum class name : ext { AU_FOR_EACH(_AUE_EMIT_ARRAY, _AUE_STRIP_BRACKETS(vals)) kEnumCount, kEnumInvalid = (ext) -1, eEnumInvalid = (ext)-1, eEnumCount = kEnumCount };
2021-10-28 20:35:48 +00:00
2022-07-22 08:20:17 +00:00
# else
# define AUE_DEFINE_DECL_LANG(name, vals) enum name : uint32_ct { AU_FOR_EACH(_AUE_EMIT_ARRAY, _AUE_STRIP_BRACKETS(vals)) k ## name ## EnumCount, k ## name ## EnumInvalid = (uint32_ct) -1, e ## name ## EnumInvalid = (uint32_ct)-1, e ## name ## EnumCount = k ## name ## EnumCount };
# define AUE_DEFINE_DECL_EXT(name, vals, ext) enum name : ext { AU_FOR_EACH(_AUE_EMIT_ARRAY, _AUE_STRIP_BRACKETS(vals)) k ## name ## EnumCount, k ## name ## EnumInvalid = (ext) -1, e ## name ## EnumInvalid = (ext)-1, e ## name ## EnumCount = k ## name ## EnumCount };
2021-11-19 14:38:03 +00:00
2022-07-22 08:20:17 +00:00
# endif
2021-11-19 14:38:03 +00:00
# if defined(AUE_NOCPPSTL)
2022-07-22 08:20:17 +00:00
# define AUE_DEFINE_BODY(name, vals) \
inline const char * k # # name # # ToString [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH ( _AUE_EMIT_A , _AUE_STRIP_BRACKETS ( vals ) ) } ; \
inline const name k # # name # # Values [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH_THAT ( _AUE_EMIT_D , name , _AUE_STRIP_BRACKETS ( vals ) ) } ; \
2024-01-23 19:11:38 +00:00
inline const char * name # # ToString ( name val ) { static const char * invalid = " kEnumInvalid " ; if ( static_cast < AuUInt > ( val ) > = static_cast < AuUInt > ( name : : kEnumCount ) ) return invalid ; return k # # name # # ToString [ static_cast < AuUInt > ( val ) ] ; } \
inline name name # # FromString ( const char * codename ) { AU_FOR_EACH_THAT ( _AUE_EMIT_CCHECK , name , _AUE_STRIP_BRACKETS ( vals ) ) return name : : kEnumInvalid ; } \
2022-07-22 08:20:17 +00:00
inline bool name # # IsValid ( name val ) { return static_cast < AuUInt > ( val ) < static_cast < AuUInt > ( name : : kEnumCount ) ; } \
2024-01-23 19:11:38 +00:00
template < typename T > \
inline void name # # ForEach ( const T & consumer ) { AU_FOR_EACH_THAT ( _AUE_EMIT_CALL , name , _AUE_STRIP_BRACKETS ( vals ) ) } \
2022-07-22 08:20:17 +00:00
static const AuUInt k # # name # # Count = static_cast < AuUInt > ( name : : kEnumCount ) ; \
2024-01-23 19:11:38 +00:00
static const name k # # name # # Invalid = name : : kEnumInvalid ; \
2022-07-22 08:20:17 +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 ) ;
# elif defined(AU_LANG_CPP)
# define AUE_DEFINE_BODY(name, vals) \
inline const AuString k # # name # # ToString [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH ( _AUE_EMIT_A , _AUE_STRIP_BRACKETS ( vals ) ) } ; \
inline const name k # # name # # Values [ static_cast < AuUInt > ( name : : kEnumCount ) ] = { AU_FOR_EACH_THAT ( _AUE_EMIT_D , name , _AUE_STRIP_BRACKETS ( vals ) ) } ; \
2024-01-23 19:11:38 +00:00
inline const AuHashMap < AuString , name > k # # name # # FromString = { AU_FOR_EACH_THAT ( _AUE_EMIT_PAIRNAME , name , _AUE_STRIP_BRACKETS ( vals ) ) { " kEnumInvalid " , name : : kEnumCount } } ; \
2024-04-20 00:35:00 +00:00
inline name name # # FromString ( const _AUE_STRING_VIEW & codename ) { AU_FOR_EACH_THAT ( _AUE_EMIT_CHECK , name , _AUE_STRIP_BRACKETS ( vals ) ) return name : : kEnumInvalid ; } \
inline name name # # FromHashString ( const _AUE_STRING_VIEW & codename ) { auto itr = k # # name # # FromString . find ( codename ) ; if ( itr = = k # # name # # FromString . end ( ) ) return name : : kEnumInvalid ; return itr - > second ; } \
2024-01-23 19:11:38 +00:00
inline const AuString & name # # ToString ( name val ) { static const AuString invalid = " kEnumInvalid " ; if ( static_cast < AuUInt > ( val ) > = static_cast < AuUInt > ( name : : kEnumCount ) ) return invalid ; return k # # name # # ToString [ static_cast < AuUInt > ( val ) ] ; } \
2022-07-22 08:20:17 +00:00
inline bool name # # IsValid ( name val ) { return static_cast < AuUInt > ( val ) < static_cast < AuUInt > ( name : : kEnumCount ) ; } \
2024-01-23 19:11:38 +00:00
template < typename T > \
inline void name # # ForEach ( const T & consumer ) { AU_FOR_EACH_THAT ( _AUE_EMIT_CALL , name , _AUE_STRIP_BRACKETS ( vals ) ) } \
2022-07-22 08:20:17 +00:00
static const AuUInt k # # name # # Count = static_cast < AuUInt > ( name : : kEnumCount ) ; \
2024-01-23 19:11:38 +00:00
static const name k # # name # # Invalid = name : : kEnumInvalid ; \
2022-07-22 08:20:17 +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 ) ;
# elif defined(AU_LANG_C)
# define AUE_DEFINE_BODY(name, vals) \
static const char * k # # name # # ToString [ ( size_ct ) ( k # # name # # EnumCount ) ] = { AU_FOR_EACH ( _AUE_EMIT_A , _AUE_STRIP_BRACKETS ( vals ) ) } ; \
static const name k # # name # # Values [ ( size_ct ) ( k # # name # # EnumCount ) ] = { AU_FOR_EACH_THAT ( _AUE_EMIT_E , name , _AUE_STRIP_BRACKETS ( vals ) ) } ; \
2024-01-23 19:11:38 +00:00
static name name # # FromString ( const char * codename ) { AU_FOR_EACH_THAT ( _AUE_EMIT_CCHECK , name , _AUE_STRIP_BRACKETS ( vals ) ) return k # # name # # EnumInvalid ; } \
static const char * name # # ToString ( name val ) { static const char * invalid = " kEnumInvalid " ; if ( ( size_ct ) ( val ) > = ( size_ct ) ( k # # name # # EnumCount ) ) return invalid ; return k # # name # # ToString [ ( size_ct ) ( val ) ] ; } \
2022-07-22 08:20:17 +00:00
static bool name # # IsValid ( name val ) { return ( size_ct ) ( val ) < ( size_ct ) ( k # # name # # EnumCount ) ; } \
static const size_ct k # # name # # Count = ( size_ct ) ( k # # name # # EnumCount ) ; \
2024-01-23 19:11:38 +00:00
static const name k # # name # # Invalid = k # # name # # EnumInvalid ; \
2022-07-22 08:20:17 +00:00
static const name k # # name # # MaxLegal = ( name ) ( k # # name # # Count - 1 ) ; \
static const name k # # name # # MinLegal = ( name ) ( 0 ) ;
# endif
# define AUE_DEFINE(name, vals) AUE_DEFINE_DECL_LANG(name, vals) AUE_DEFINE_BODY(name, vals)
2023-07-03 16:58:16 +00:00
# define AUE_DEFINE_EXT(name, ext, vals) AUE_DEFINE_DECL_EXT(name, vals, ext) AUE_DEFINE_BODY(name, vals)
2022-07-22 08:20:17 +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)