ReflectedLeafType.h
// ReflectedLeafType.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2022
@import "IObject.h"
@import "ReflectedType.h"
namespace ceda
{
enum class ELeafType
{
Bool,
Int8,
Int16,
Int32,
Int64,
Uint8,
Uint16,
Uint32,
Uint64,
Float32,
Float64,
Char8,
Char16,
String8,
String16
};
@api ConstStringZ ToString(ELeafType t);
inline xostream& operator<<(xostream& os, ELeafType t)
{
os << ToString(t);
return os;
}
struct ReflectedLeafType
{
const TypeOps& ops;
ELeafType tag;
};
@api xostream& operator<<(xostream& os, const ReflectedLeafType& r);
/*
In the following we work with the platform dependent types. This is the best way to ensure we can reflect
all the arithmetic types. For example we sometimes use ssize_t in reflected APIs. On some platforms
ssize_t is the same as long but doesn't match int8, int16, int32 or int64 (e.g. int32 might be int and
int64 might be long long).
*/
/*
// Can't use is_arithmetic_v because it matches with const/volatile types
template<class T> struct is_leaf_type
{
constexpr static bool value = std::is_arithmetic_v<T> ||
std::is_same_v<T, string8> ||
std::is_same_v<T, string16>;
};
*/
template<class T> struct IsLeafType
{
constexpr static bool value =
std::is_same_v<T, bool> ||
std::is_same_v<T, char> ||
std::is_same_v<T, char16_t> ||
//std::is_same_v<T, char32_t> ||
//std::is_same_v<T, wchar_t> ||
std::is_same_v<T, signed char> ||
std::is_same_v<T, unsigned char> ||
std::is_same_v<T, short> ||
std::is_same_v<T, unsigned short> ||
std::is_same_v<T, int> ||
std::is_same_v<T, unsigned int> ||
std::is_same_v<T, long> ||
std::is_same_v<T, unsigned long> ||
std::is_same_v<T, long long> ||
std::is_same_v<T, unsigned long long> ||
std::is_same_v<T, float> ||
std::is_same_v<T, double> ||
//std::is_same_v<T, long double> ||
std::is_same_v<T, string8> ||
std::is_same_v<T, string16>;
};
constexpr ELeafType SignedIntegerELeafType(size_t size)
{
size_t bitsPerChar = 8;
size_t bits = size * bitsPerChar;
switch(bits)
{
case 8 : return ELeafType::Int8;
case 16 : return ELeafType::Int16;
case 32 : return ELeafType::Int32;
case 64 : return ELeafType::Int64;
default : return ELeafType (-1); // Hmmmm
}
}
constexpr ELeafType UnsignedIntegerELeafType(size_t size)
{
size_t bitsPerChar = 8;
size_t bits = size * bitsPerChar;
switch(bits)
{
case 8 : return ELeafType::Uint8;
case 16 : return ELeafType::Uint16;
case 32 : return ELeafType::Uint32;
case 64 : return ELeafType::Uint64;
default : return ELeafType (-1); // Hmmmm
}
}
template <typename T> struct GetELeafType_class { static ELeafType LeafType(); };
template<> struct GetELeafType_class<bool> { static ELeafType LeafType() { return ELeafType::Bool; } };
template<> struct GetELeafType_class<signed char> { static ELeafType LeafType() { return SignedIntegerELeafType(sizeof(signed char)); } };
template<> struct GetELeafType_class<short> { static ELeafType LeafType() { return SignedIntegerELeafType(sizeof(short)); } };
template<> struct GetELeafType_class<int> { static ELeafType LeafType() { return SignedIntegerELeafType(sizeof(int)); } };
template<> struct GetELeafType_class<long> { static ELeafType LeafType() { return SignedIntegerELeafType(sizeof(long)); } };
template<> struct GetELeafType_class<long long> { static ELeafType LeafType() { return SignedIntegerELeafType(sizeof(long long)); } };
template<> struct GetELeafType_class<unsigned char> { static ELeafType LeafType() { return UnsignedIntegerELeafType(sizeof(unsigned char)); } };
template<> struct GetELeafType_class<unsigned short> { static ELeafType LeafType() { return UnsignedIntegerELeafType(sizeof(unsigned short)); } };
template<> struct GetELeafType_class<unsigned int> { static ELeafType LeafType() { return UnsignedIntegerELeafType(sizeof(unsigned int)); } };
template<> struct GetELeafType_class<unsigned long> { static ELeafType LeafType() { return UnsignedIntegerELeafType(sizeof(unsigned long)); } };
template<> struct GetELeafType_class<unsigned long long> { static ELeafType LeafType() { return UnsignedIntegerELeafType(sizeof(unsigned long long)); } };
template<> struct GetELeafType_class<float32> { static ELeafType LeafType() { return ELeafType::Float32; } };
template<> struct GetELeafType_class<float64> { static ELeafType LeafType() { return ELeafType::Float64; } };
template<> struct GetELeafType_class<char8> { static ELeafType LeafType() { return ELeafType::Char8; } };
template<> struct GetELeafType_class<char16> { static ELeafType LeafType() { return ELeafType::Char16; } };
template<> struct GetELeafType_class<string8> { static ELeafType LeafType() { return ELeafType::String8; } };
template<> struct GetELeafType_class<string16> { static ELeafType LeafType() { return ELeafType::String16; } };
template<typename T> inline ELeafType GetELeafType() { return GetELeafType_class<T>::LeafType(); }
template<typename T>
inline const ReflectedLeafType& GetReflectedLeafType()
{
static ReflectedLeafType s =
{
GetTypeOps<T>(),
GetELeafType<T>()
};
return s;
}
template<typename T>
struct GetReflectedType_class<T, std::enable_if_t<IsLeafType<T>::value>>
{
static inline ReflectedType get()
{
ReflectedType r;
r.tag = EReflectedTypeTag::Leaf;
r.Leaf = &GetReflectedLeafType<T>();
return r;
}
};
} // namespace ceda