#ifndef VARIANT_H
#define VARIANT_H
#include <string.h>
#include <new>
#include <string>
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#include <sstream>
#include <cstdint>
#include "Utils.h"
#include "Namespace.h"
BEGIN_NAMESPACE
typedef bool boolean_t;
typedef float float32_t;
typedef double float64_t;
typedef void* pointer_t;
typedef const char* cstring_t;
enum VariantType
{
#define VARIANT_TYPES \
VARIANT_MACRO(boolean_t) VARIANT_MACRO(char) \
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)
#define VARIANT_MACRO(type) \
VT_##type,
VARIANT_TYPES
#undef VARIANT_MACRO
VT_Unknown
};
template<typename T>
VariantType variantTypeFromType();
template <typename T>
constexpr T n_max(const T a) { return a; }
template <typename T, typename ... Ts>
constexpr T n_max(const T a, const Ts ... args) { return (a>n_max(args...))?a:n_max(args...); }
constexpr size_t maxTypeSize = n_max(
#define VARIANT_MACRO(type) \
sizeof(type),
VARIANT_TYPES
#undef VARIANT_MACRO
0);
static_assert(maxTypeSize == 8, "Not a big deal if this happens, just comment this line, but a bit unexpected");
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);
// Next try canConvert and then convert?
return T();
}
Variant() { m_type = VT_Unknown; m_null = true; }
~Variant() { }
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
//operator void() { return; }
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;
};
END_NAMESPACE
#endif // VARIANT_H