efl/src/bindings/eina_cxx/eina_value.hh

386 lines
7.5 KiB
C++

#ifndef _EFL_EINA_EINA_VALUE_HH
#define _EFL_EINA_EINA_VALUE_HH
#include <Eina.h>
#include <eina_stringshare.hh>
#include <eina_type_traits.hh>
namespace efl { namespace eina {
template <typename T, typename Enable = void>
struct _eina_value_traits;
template <typename T>
struct _eina_value_traits_base;
template <typename T>
struct _eina_value_traits_aux;
template <typename T>
struct _eina_value_traits_base
{
typedef T type;
static ::Eina_Value* create()
{
return eina_value_new(_eina_value_traits<T>::value_type());
}
static void set_type( ::Eina_Value* v)
{
eina_value_setup(v, _eina_value_traits<T>::value_type());
}
static void set( ::Eina_Value* v, type c)
{
::eina_value_set(v, c);
}
static type get( ::Eina_Value* v)
{
if(_eina_value_traits<T>::value_type() == eina_value_type_get(v))
{
type vv;
if(::eina_value_get(v, &vv))
return vv;
else
throw eina::system_error(eina::get_error_code());
}
else
throw eina::system_error(EINA_ERROR_VALUE_FAILED, eina::eina_error_category());
}
};
// Indirection for uint64_t. uint64_t can be a typedef for unsigned
// long, so we can't specialize on the same template
template <>
struct _eina_value_traits_aux<uint64_t>
: _eina_value_traits_base<uint64_t>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_UINT64;
}
};
template <typename T, typename Enable>
struct _eina_value_traits : _eina_value_traits_aux<T>
{
};
template <>
struct _eina_value_traits<unsigned char>
: _eina_value_traits_base<unsigned char>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_UCHAR;
}
};
template <>
struct _eina_value_traits<unsigned short>
: _eina_value_traits_base<unsigned short>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_USHORT;
}
};
template <>
struct _eina_value_traits<unsigned int>
: _eina_value_traits_base<unsigned int>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_UINT;
}
};
template <>
struct _eina_value_traits<unsigned long>
: _eina_value_traits_base<unsigned long>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_ULONG;
}
};
template <>
struct _eina_value_traits<char>
: _eina_value_traits_base<char>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_CHAR;
}
};
template <>
struct _eina_value_traits<short>
: _eina_value_traits_base<short>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_SHORT;
}
};
template <>
struct _eina_value_traits<int>
: _eina_value_traits_base<int>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_INT;
}
};
template <>
struct _eina_value_traits<long>
: _eina_value_traits_base<long>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_LONG;
}
};
template <>
struct _eina_value_traits<float>
: _eina_value_traits_base<float>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_FLOAT;
}
};
template <>
struct _eina_value_traits<double>
: _eina_value_traits_base<double>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_DOUBLE;
}
};
template <>
struct _eina_value_traits<stringshare>
: _eina_value_traits_base<stringshare>
{
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_STRINGSHARE;
}
static void set( ::Eina_Value* v, type c)
{
::eina_value_set(v, c.data());
}
static type get( ::Eina_Value* v)
{
char* c_str;
::eina_value_get(v, &c_str);
return stringshare(c_str, steal_stringshare_ref);
}
};
template <>
struct _eina_value_traits<std::string>
: _eina_value_traits_base<std::string>
{
typedef typename _eina_value_traits_base<std::string>::type type;
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_STRING;
}
static void set( ::Eina_Value* v, type c)
{
::eina_value_set(v, c.c_str());
}
static type get( ::Eina_Value* v)
{
char* c_str;
::eina_value_get(v, &c_str);
std::string r(c_str);
::free(c_str);
return r;
}
};
template <typename T>
struct _eina_value_traits<T[], typename eina::enable_if<eina::is_pod<T>::value>::type>
: _eina_value_traits_base<T[]>
{
typedef typename _eina_value_traits_base<T[]>::type type;
static ::Eina_Value_Type const* value_type()
{
return EINA_VALUE_TYPE_ARRAY;
}
static void set( ::Eina_Value* v, type c)
{
::eina_value_set(v, c.c_str());
}
static type get( ::Eina_Value* v)
{
char* c_str;
::eina_value_get(v, &c_str);
std::string r(c_str);
::free(c_str);
return r;
}
};
class value;
template <typename T>
T get(value const& v);
class value
{
template <typename T>
void primitive_init(T v)
{
_raw = _eina_value_traits<T>::create();
_eina_value_traits<T>::set(_raw, v);
}
public:
value()
: _raw(_eina_value_traits<char>::create())
{
}
template <typename T>
value(T v)
{
primitive_init(v);
}
value(char v)
{
primitive_init(v);
}
value(short v)
{
primitive_init(v);
}
value(int v)
{
primitive_init(v);
}
value(long v)
{
primitive_init(v);
}
value(unsigned char v)
{
primitive_init(v);
}
value(unsigned short v)
{
primitive_init(v);
}
value(unsigned int v)
{
primitive_init(v);
}
value(unsigned long v)
{
primitive_init(v);
}
value(float v)
{
primitive_init(v);
}
value(double v)
{
primitive_init(v);
}
~value()
{
eina_value_free(_raw);
}
value(value const& other)
: _raw(_eina_value_traits<char>::create())
{
if(!eina_value_copy(const_cast<Eina_Value const*>(other._raw), _raw))
throw eina::system_error(eina::get_error_code());
}
value& operator=(value const& other)
{
eina_value_flush(_raw);
if(!eina_value_copy(const_cast<Eina_Value const*>(other._raw), _raw))
throw eina::system_error(eina::get_error_code());
return *this;
}
void swap(value& other)
{
std::swap(_raw, other._raw);
}
typedef Eina_Value* native_handle_type;
native_handle_type native_handle() const
{
return _raw;
}
typedef Eina_Value_Type const* type_info_t;
type_info_t type_info() const
{
return ::eina_value_type_get(_raw);
}
private:
::Eina_Value* _raw;
template <typename T>
friend T get(value const& v)
{
return _eina_value_traits<T>::get(v._raw);
}
};
inline void swap(value& lhs, value& rhs)
{
lhs.swap(rhs);
}
inline bool operator==(value const& lhs, value const& rhs)
{
return lhs.type_info() == rhs.type_info()
&& eina_value_compare(lhs.native_handle(), rhs.native_handle()) == 0;
}
inline bool operator<(value const& lhs, value const& rhs)
{
return std::less<Eina_Value_Type const*>()(lhs.type_info(), rhs.type_info())
|| (lhs.type_info() == rhs.type_info()
&& eina_value_compare(lhs.native_handle(), rhs.native_handle()) < 0);
}
inline bool operator>(value const& lhs, value const& rhs)
{
return std::less<Eina_Value_Type const*>()(rhs.type_info(), lhs.type_info())
|| (rhs.type_info() == lhs.type_info()
&& eina_value_compare(lhs.native_handle(), rhs.native_handle()) > 0);
}
inline bool operator<=(value const& lhs, value const& rhs)
{
return !(lhs > rhs);
}
inline bool operator>=(value const& lhs, value const& rhs)
{
return !(lhs < rhs);
}
inline bool operator!=(value const& lhs, value const& rhs)
{
return !(lhs == rhs);
}
} }
#endif