#pragma once
#include <cstring>
#include "Common.h"
BEGIN_NAMESPACE
typedef bool boolean_t;
typedef float float32_t;
typedef double float64_t;
typedef void* pointer_t;
typedef const char* cstring_t;
typedef std::string string_t;
class Variant;
// TODO: User types
// TODO: other types, datetime, color, 3d points, matrixes, ???
enum VariantType
{
#define VARIANT_TYPES \
/* VARIANT_MACRO(ArgList_t) */ VARIANT_MACRO(boolean_t) VARIANT_MACRO(char) /* VARIANT_MACRO(wchar_t) */ \
VARIANT_MACRO(int8_t) VARIANT_MACRO(int16_t) VARIANT_MACRO(int32_t) VARIANT_MACRO(int64_t) \
VARIANT_MACRO(uint8_t) VARIANT_MACRO(uint16_t) VARIANT_MACRO(uint32_t) VARIANT_MACRO(uint64_t) \
VARIANT_MACRO(float32_t) VARIANT_MACRO(float64_t) VARIANT_MACRO(pointer_t) VARIANT_MACRO(cstring_t) \
VARIANT_MACRO(String) VARIANT_MACRO(WidgetFlags)
//VARIANT_MACRO(enum_t) VARIANT_MACRO(string_t)
#define VARIANT_MACRO(type) \
VT_##type,
VARIANT_TYPES
#undef VARIANT_MACRO
VT_Unknown
};
template<typename T>
VariantType variantTypeFromType();
const size_t maxTypeSize = 80;
class Variant
{
public:
template<typename T>
void setValue(const T &a_val)
{
m_type = variantTypeFromType<T>();
m_null = false;
STATIC_ASSERT(sizeof(T) <= maxTypeSize, typeTooBig);
memset(m_data, 0, maxTypeSize);
new (m_data)T(a_val);
}
template<typename T>
const T variant_cast() const {
STATIC_ASSERT(sizeof(T) <= maxTypeSize, typeTooBig);
if (VariantType(m_type) == variantTypeFromType<T>())
{
// return reinterpret_cast<const T&>(m_data);
union Temp { T* t; const char* d; };// m_data[maxTypeSize]; };
Temp tmp;
tmp.d = m_data;
T t = *tmp.t;
//memcpy(tmp.m_data, m_data, maxTypeSize);
return t;//tmp.t;
}
// Next try canConvert and then convert?
return T();
}
Variant() { m_type = VT_Unknown; m_null = true; }
~Variant()
{
if (m_type == VT_String) {
String* v = reinterpret_cast<String*>(m_data);
v->~String(); // Properly tidy up, TODO: need to do this for all non-basic types
}
}
template<typename T>
Variant(const T& a_val) { setValue(a_val); }
template<typename T>
operator const T() const { return variant_cast<T>(); }
template<typename T>
const T value() const { return variant_cast<T>(); }
operator const char*() const { m_str = toString(); return m_str.c_str(); } // TODO
bool isNull() const { return m_null; }
bool isValid() const { return !m_null && (m_type != VT_Unknown); }
VariantType type() const { return (VariantType)m_type; }
const char* typeName() const;
bool operator==(const Variant &v) const { return compareEquality(v); }
bool operator!=(const Variant &v) const { return !compareEquality(v); }
// TODO: probably just comparing memory is not correct, what if it is a pointer to a string for example
bool compareEquality(const Variant &v) const { return (m_type == v.m_type) && (memcmp(m_data, v.m_data, maxTypeSize) == 0); }
static VariantType nameToType(const char* a_name);
static const char* typeToName(VariantType a_type);
template<typename T>
static Variant fromValue(const T &value) { return Variant(value); }
String toString() const;
private:
mutable std::string m_str; // TODO: should see if there is a way to avoid needing this member variable needed for const char* cast
char m_data[maxTypeSize];
uint32_t m_type : 31;
uint32_t m_null : 1;
};
/*
// Experimentation with idea of smart enums
class EnumBaseBase
{
public:
struct EnumMaps;
EnumBaseBase() : value(0) {}
static const String& toStringHelper(const EnumMaps& a_maps, int a_val);
static int fromStringHelper(const EnumMaps& a_maps, const String& a_str);
static EnumMaps& initMapsHelper(const char* enumName, const char* enumValues);
int value;
};
template <class Derived>
class EnumBase : public EnumBaseBase
{
public:
operator const char* () const { return toStringHelper(initMaps(), value).data(); }
String toString() const { return toStringHelper(initMaps(), value); }
static const String& toString(Derived a_val) { return toStringHelper(initMaps(), a_val.value); }
static int fromString(const String& a_str) { return fromStringHelper(initMaps(), a_str); }
static Vector<int> allValues() { return initMaps().valueList; }
static EnumMaps& initMaps() { return initMapsHelper(Derived::enumName(), Derived::enumValues()); }
};
#define DECLARE_ENUM(EnumName, ...) \
class EnumName : public EnumBase<EnumName> \
{ \
public: \
enum { __VA_ARGS__ }; \
EnumName(int a_val) { value = a_val; } \
static const char* enumName() { return #EnumName; } \
static const char* enumValues() { return #__VA_ARGS__; } \
};
*/
END_NAMESPACE