#ifndef EFL_EOLIAN_INTEROP_HH #define EFL_EOLIAN_INTEROP_HH #include #include #include #include #include #include #include #include "eo_concrete.hh" namespace efl { namespace eolian { template struct in_traits { typedef T const& type; }; template struct in_traits::value>::type> { typedef T type; }; template struct in_traits::value>::type> { typedef T type; }; template struct in_traits { typedef std::function type; }; template <> struct in_traits { typedef eina::string_view type; }; template <> struct in_traits { typedef eina::string_view const type; }; template <> struct in_traits { typedef eina::stringshare type; }; template <> struct in_traits { typedef eina::stringshare const type; }; template <> struct in_traits { typedef efl::eina::strbuf type; }; template <> struct in_traits { typedef efl::eina::strbuf const type; }; template struct in_traits { typedef T& type; }; template struct in_traits { typedef T* type; }; template struct in_traits> { typedef std::unique_ptr type; }; template struct in_traits> { typedef eina::range_list type; }; template struct in_traits> { typedef eina::range_array type; }; template struct out_traits { typedef T& type; }; template <> struct out_traits { typedef void* type; }; template struct out_traits { typedef T* type; }; template <> struct out_traits { typedef Eina_Hash*& type; }; template struct out_traits> { typedef eina::optional type; }; template <> struct out_traits { typedef void*& type; }; template <> struct out_traits { typedef efl::eina::strbuf_wrapper& type; }; template struct inout_traits { typedef T& type; }; template <> struct inout_traits { typedef void* type; }; template struct return_traits { typedef T type; }; template <> struct return_traits { typedef eina::value_view type; }; template <> struct return_traits { typedef eina::value_view type; }; template void assign_out(Lhs& lhs, Rhs& rhs); namespace impl { template struct tag { typedef To to; typedef From from; typedef std::integral_constant own; }; template void assign_out_impl(T*& lhs, T* rhs, tag) { lhs = rhs; } template void assign_out_impl(T& lhs, T*& rhs, tag, typename std::enable_if::value>::type* = 0) { lhs = *rhs; } template void assign_out_impl(T const& lhs, T const*& rhs, tag) { const_cast(lhs) = *rhs; } inline void assign_out_impl(void*&, void*&, tag) { std::abort(); // out parameter of void type? } inline void assign_out_impl(void*&, void*&, tag) { // do nothing, it is an inout parameter of void } template void assign_out_impl(std::unique_ptr& lhs, U* rhs, tag&, U*, true>) { // with own lhs.reset(rhs); } template void assign_out_impl(bool& lhs, Eina_Bool rhs, Tag) { lhs = rhs; } template void assign_out_impl(T& lhs, T& rhs, tag) { lhs = rhs; } template void assign_out_impl(T& lhs, Eo* rhs, tag , typename std::enable_if::value>::type* = 0) { lhs._reset(rhs); } template void assign_out_impl(T& lhs, Eo const* rhs, tag , typename std::enable_if::value>::type* = 0) { lhs._reset(const_cast(rhs)); } template void assign_out_impl(efl::eina::string_view& view, const char* string, Tag) { view = {string}; } template void assign_out_impl(efl::eina::string_view* view, const char* string, Tag) { if(view) *view = {string}; } template void assign_out_impl(efl::eina::stringshare& to, const char* from, Tag) { to = from; } template void assign_out_impl(T*& lhs, T& rhs, tag) // optional { if(lhs) *lhs = rhs; } template void assign_out_impl(efl::eina::optional& lhs, Rhs& rhs, tag, O, B>) { if(lhs) assign_out(*lhs, rhs); } template void assign_out_impl(eina::value& lhs, Eina_Value& rhs, Tag) { Eina_Value* v = eina_value_new(EINA_VALUE_TYPE_CHAR); eina_value_flush(v); eina_value_copy(&rhs, v); lhs.reset(v); eina_value_flush(&rhs); } // This is a invalid use-case that is used in EFL. This leaks template void assign_out_impl(eina::value_view& lhs, Eina_Value& rhs, Tag) { Eina_Value* v = eina_value_new(EINA_VALUE_TYPE_CHAR); eina_value_flush(v); eina_value_copy(&rhs, v); lhs.reset(v); } template void assign_out_impl(efl::eina::list& lhs, Eina_List* rhs, tag&, Eina_List*, true>) { lhs = efl::eina::list{rhs}; } template void assign_out_impl(efl::eina::range_list& lhs, Eina_List* rhs, tag&, Eina_List*>) { lhs = efl::eina::range_list{rhs}; } template void assign_out_impl(efl::eina::array& lhs, Eina_Array* rhs, tag&, Eina_Array*, true>) { lhs = efl::eina::array{rhs}; } template void assign_out_impl(efl::eina::range_array& lhs, Eina_Array* rhs, tag&, Eina_Array*>) { lhs = efl::eina::range_array{rhs}; } inline void assign_out_impl(Eina_Hash*& lhs, Eina_Hash*& rhs, tag) { lhs = rhs; } template void assign_out_impl(efl::eina::iterator& /*lhs*/, Eina_Iterator* /*rhs*/, tag&, Eina_Iterator*>) { // Must copy here std::abort(); } template void assign_out_impl(efl::eina::iterator& lhs, Eina_Iterator* rhs, tag&, Eina_Iterator*, true>) { lhs = efl::eina::iterator{rhs}; } template void assign_out_impl(efl::eina::accessor& lhs, Eina_Accessor* rhs, tag&, Eina_Accessor*>) { lhs = efl::eina::accessor{ ::eina_accessor_clone(rhs) }; } template void assign_out_impl(efl::eina::accessor& lhs, Eina_Accessor* rhs, tag&, Eina_Accessor*, true>) { lhs = efl::eina::accessor{rhs}; } } template void assign_out(Lhs& lhs, Rhs& rhs) { return impl::assign_out_impl(lhs, rhs, impl::tag{}); } namespace impl { template T* convert_inout_impl(T& v, tag) { return v; } inline Eina_Bool convert_inout_impl(bool v, tag) { return v ? EINA_TRUE : EINA_FALSE; } inline void* convert_inout_impl(void* v, tag) { return v; } template T& convert_inout_impl(T& v, tag) { return v; } template Eo* convert_inout_impl(T& v, tag , typename std::enable_if::value>::type* = 0) { return v._eo_ptr(); } template Eo const* convert_inout_impl(T v, tag , typename std::enable_if::value>::type* = 0) { return v._eo_ptr(); } } template auto convert_inout(V& object) -> decltype(impl::convert_inout_impl(object, impl::tag{})) { return impl::convert_inout_impl(object, impl::tag{}); } template T convert_to_c(V&& object); template struct function_wrapper; namespace impl { template auto convert_to_c_impl (V&& v, tag, typename std::enable_if::type, U>::value>::type* =0) -> decltype(std::forward(v)) { return std::forward(v); } template T convert_to_c_impl(T& /*v*/, tag) { std::abort(); } template T* convert_to_c_impl(T& v, tag) { return &v; } template T* convert_to_c_impl(T& /*v*/, tag) { std::abort(); } template T* convert_to_c_impl(T const& v, tag) // not own { return const_cast(&v); } template T* convert_to_c_impl(T const& v, tag) // with own { T* r = static_cast(malloc(sizeof(T))); *r = v; return r; } template T const* convert_to_c_impl(T& v, tag) { return &v; } template T const* convert_to_c_impl(T* v, tag) { return v; } template T const& convert_to_c_impl(T const& v, tag) { return v; } template Eo* convert_to_c_impl(T v, tag , typename std::enable_if::value>::type* = 0) { return v._eo_ptr(); } template Eo* convert_to_c_impl(T v, tag , typename std::enable_if::value>::type* = 0) { return ::efl_ref(v._eo_ptr()); } template Eo const* convert_to_c_impl(T v, tag , typename std::enable_if::value>::type* = 0) { return const_cast(v._eo_ptr()); } template Eo** convert_to_c_impl(T& v, tag , typename std::enable_if::value>::type* = 0) { return reinterpret_cast(static_cast(&v)); } inline const char* convert_to_c_impl( ::efl::eina::string_view v, tag) { return v.c_str(); } inline char* convert_to_c_impl( ::efl::eina::string_view v, tag) { char* string = static_cast(malloc(v.size() + 1)); std::strcpy(string, v.c_str()); return string; } inline char** convert_to_c_impl(efl::eina::string_view& /*view*/, tag) { std::abort(); } inline const char** convert_to_c_impl(efl::eina::string_view& /*view*/, tag) { std::abort(); } inline const char* convert_to_c_impl( std::string const& v, tag) { std::size_t len = v.size()+1; char* buffer = static_cast(malloc(len)); std::memcpy(buffer, v.data(), len); return buffer; } inline const char** convert_to_c_impl(std::string* /*view*/, tag) { std::abort(); } inline Eina_Value* convert_to_c_impl( ::efl::eina::value v, tag::type>) { Eina_Value* nv = eina_value_new(v.type_info()); eina_value_copy(v.native_handle(), nv); return nv; } inline Eina_Value const* convert_to_c_impl( ::efl::eina::value& v, tag::type>) { Eina_Value* nv = eina_value_new(v.type_info()); eina_value_copy(v.native_handle(), nv); return nv; } inline Eina_Value const* convert_to_c_impl( ::efl::eina::value_view const& v, tag::type>) { return v.native_handle(); } inline Eina_Value* convert_to_c_impl( ::efl::eina::value_view& v, tag::type>) { return v.native_handle(); } inline Eina_Value* convert_to_c_impl( ::efl::eina::value_view const& v, tag::type>) { return const_cast(v.native_handle()); } inline Eina_Value const& convert_to_c_impl( ::efl::eina::value_view const& v, tag::type>) { return *v.native_handle(); } inline const Eina_Value convert_to_c_impl( ::efl::eina::value_view const& v, tag::type>) { return *v.native_handle(); } inline Eina_Bool convert_to_c_impl( bool b, tag) { return b; } template T convert_to_c_impl(efl::eina::optional const& optional, tagconst&>) { return optional ? *optional : T{}; } template T* convert_to_c_impl(efl::eina::optionalconst& optional, tagconst&, true>) { if(optional) { T* r = static_cast(malloc(sizeof(T))); *r = *optional; return r; } else return nullptr; } template U convert_to_c_impl(efl::eina::optional const& optional, tagconst&>) { return impl::convert_to_c_impl(optional ? *optional : T{}, tag::type>{}); } template Eina_List* convert_to_c_impl(efl::eina::range_list range, tag>) { return range.native_handle(); } template Eina_List const* convert_to_c_impl(efl::eina::range_list range, tag>) { return range.native_handle(); } template Eina_List* convert_to_c_impl(efl::eina::listconst& c, tagconst&, true>) { return const_cast(c.native_handle()); } template Eina_List const* convert_to_c_impl(efl::eina::listconst& c, tagconst&, true>) { return c.native_handle(); } template Eina_Array* convert_to_c_impl(efl::eina::range_array range, tag>) { return range.native_handle(); } template Eina_Array const* convert_to_c_impl(efl::eina::range_array range, tag>) { return range.native_handle(); } template Eina_Array* convert_to_c_impl(efl::eina::arrayconst& c, tagconst&, true>) { return const_cast(c.native_handle()); } template Eina_Array const* convert_to_c_impl(efl::eina::arrayconst& c, tagconst&, true>) { return c.native_handle(); } template Eina_Iterator* convert_to_c_impl(efl::eina::iteratorconst& i, tagconst&>) { return const_cast(i.native_handle()); } template Eina_Iterator const* convert_to_c_impl(efl::eina::iteratorconst& i, tagconst&>) { return i.native_handle(); } template Eina_Iterator* convert_to_c_impl(efl::eina::iteratorconst& /*i*/, tagconst&, true>) { // Eina Iterator must be copied std::abort(); } template Eina_Accessor* convert_to_c_impl(efl::eina::accessorconst& i, tagconst&>) { return const_cast(i.native_handle()); } template Eina_Accessor const* convert_to_c_impl(efl::eina::accessorconst& i, tagconst&>) { return i.native_handle(); } template Eina_Accessor* convert_to_c_impl(efl::eina::accessorconst& i, tagconst&, true>) { return ::eina_accessor_clone(const_cast(i.native_handle())); } inline const char** convert_to_c_impl(efl::eina::string_view /*view*/, tag) { std::abort(); } inline char** convert_to_c_impl(efl::eina::string_view /*view*/, tag) { std::abort(); } inline const char* convert_to_c_impl(efl::eina::stringshare x, tag) { return x.c_str(); } inline const char* convert_to_c_impl(efl::eina::stringshare x, tag) { return eina_stringshare_ref(x.c_str()); } inline Eina_Strbuf* convert_to_c_impl(efl::eina::strbuf& x, tag) { return x.native_handle(); } template T* convert_to_c_impl(std::unique_ptr& v, tag>) { return convert_to_c(v.release()); } template Eina_Array** convert_to_c_impl(efl::eina::array& /*c*/, tag&>) { std::abort(); } template Eina_Array** convert_to_c_impl(efl::eina::range_array& /*c*/, tag&>) { std::abort(); } template T* convert_to_c_impl(T const* p, tag) // needed for property_get { return const_cast(p); } template typename std::add_pointer::type convert_to_c_impl(std::function , tag < typename std::add_pointer::type , std::function >) // needed for property_get { return nullptr; // not implemented naked functions } } template T convert_to_c(V&& object) { return impl::convert_to_c_impl(std::forward(object), impl::tag{}); } namespace impl { template struct is_range : std::false_type {}; template struct is_range> : std::true_type {}; template struct is_range> : std::true_type {}; template struct is_container : std::false_type {}; template struct is_container> : std::true_type {}; template struct is_container> : std::true_type {}; // event template T convert_to_event(void* value, typename std::enable_if< eo::is_eolian_object::value>::type* = 0) { return T{::efl_ref(static_cast(value))}; } template T convert_to_event(void* value, typename std::enable_if< is_container::value || is_range::value>::type* = 0) { return T{static_cast(value)}; } template T convert_to_event(void* value, typename std::enable_if< !std::is_pointer::value && !is_container::value && !is_range::value && !eo::is_eolian_object::value>::type* = 0) { return *static_cast(value); } template T convert_to_event(void* value, typename std::enable_if::value>::type* = 0) { return *static_cast(value); } } template T convert_to_event(void* value) { return impl::convert_to_event(value); } namespace impl { template T convert_to_return(T value, tag) { return value; } template T convert_to_return(U const value, tag) { return value; } template T& convert_to_return(T* value, tag) { return *value; } template T convert_to_return(Eo* value, tag, typename std::enable_if< eo::is_eolian_object::value>::type* = 0) { T v{eo::detail::ref(value)}; return v; } template T convert_to_return(Eo const* value, tag, typename std::enable_if::value>::type* = 0) { return T{const_cast(eo::detail::ref(value))}; } template eina::list convert_to_return(Eina_List* value, tag>) { return eina::list{value}; } template eina::list convert_to_return(Eina_List const* value, tag>) { return eina::list{const_cast(value)}; } template eina::range_list convert_to_return(Eina_List* value, tag>) { return eina::range_list{value}; } template eina::range_list convert_to_return(Eina_List const* value, tag>) { return eina::range_list{const_cast(value)}; } template eina::array convert_to_return(Eina_Array* value, tag>) { return eina::array{value}; } template eina::array convert_to_return(Eina_Array const* value, tag>) { return eina::array{const_cast(value)}; } template eina::range_array convert_to_return(Eina_Array* value, tag>) { return eina::range_array{value}; } template eina::range_array convert_to_return(Eina_Array const* value, tag>) { return eina::range_array{const_cast(value)}; } template eina::iterator convert_to_return(Eina_Iterator* value, tag>) { return eina::iterator{ value }; } template eina::accessor convert_to_return(Eina_Accessor* value, tag>) { return eina::accessor{ value }; } // Eina_Value* inline efl::eina::value convert_to_return(Eina_Value* value, tag) { return efl::eina::value{value}; } inline efl::eina::value_view convert_to_return(Eina_Value* value, tag) { return efl::eina::value_view{value}; } inline efl::eina::value_view convert_to_return(Eina_Value const* value, tag) { return efl::eina::value_view{const_cast(value)}; } template T convert_to_return(U* value, tag, typename std::enable_if::value || is_container::value>::type* = 0) { // const should be to the type if value is const return T{const_cast::type*>(value)}; } inline eina::stringshare convert_to_return(const Eina_Stringshare* value, tag) { return efl::eina::stringshare(value); } template T convert_to_return(const char** /*value*/, tag, typename std::enable_if::value>::type* = 0) { std::abort(); } inline eina::string_view convert_to_return(const char* value, tag) { return {value}; } inline eina::string_view convert_to_return(const char** value, tag) { return {*value}; } template inline std::string convert_to_return(const char* value, tag , typename std::enable_if::type, std::string>::value>::type* = 0) { if(value) { std::string r{value}; free((void*)value); return r; } else return {}; } template inline std::string convert_to_return(const char** value, tag , typename std::enable_if::type, std::string>::value>::type* = 0) { if(value) { std::string r{*value}; free((void*)*value); free((void*)value); return r; } else return {}; } template inline std::string convert_to_return(char* value, tag , typename std::enable_if::type, std::string>::value>::type* = 0) { if(value) { std::string r{value}; free((void*)value); return r; } else return {}; } template inline std::string convert_to_return(char** value, tag , typename std::enable_if::type, std::string>::value>::type* = 0) { if(value) { std::string r{*value}; free((void*)*value); free((void*)value); return r; } else return {}; } inline bool convert_to_return(Eina_Bool value, tag) { return !!value; } template std::unique_ptr convert_to_return(T* value, tag>) { return std::unique_ptr{value, {}}; } template std::unique_ptr convert_to_return(U* value, tag>) { return std::unique_ptr{convert_to_return(value, tag{}), {}}; } } template T convert_to_return(U& object) { return impl::convert_to_return(object, impl::tag{}); } /// Miscellaneous template struct is_constructor_lambda : std::false_type {}; template struct is_constructor_lambda() ())> : std::true_type {}; template struct is_constructor_lambda() (std::declval()))> : std::true_type {}; template inline void do_eo_add(Eo*& object, P const& parent , Efl_Class const* klass , typename std::enable_if< eo::is_eolian_object

::value>::type* = 0) { bool const is_ref = true; object = ::_efl_add_internal_start(__FILE__, __LINE__, klass, parent._eo_ptr(), is_ref, EINA_FALSE); object = ::_efl_add_end(object, is_ref, EINA_FALSE); } template struct void_t { typedef void type; }; template auto call_lambda(F&& f, U&) -> typename void_t::type { f(); } template auto call_lambda(F&& f, U& object) -> typename void_t::type { f(object); } template void do_eo_add(Eo*& object, P const& parent, Efl_Class const* klass , U& proxy , F&& f , typename std::enable_if< eo::is_eolian_object

::value>::type* = 0) { bool const is_ref = true; object = ::_efl_add_internal_start(__FILE__, __LINE__, klass, parent._eo_ptr(), is_ref, EINA_FALSE); ::efl::eolian::call_lambda(std::forward(f), proxy); object = ::_efl_add_end(object, is_ref, EINA_FALSE); } template struct light_address_of_operator { operator T* () const { return static_cast(static_cast(static_cast(this)->p)); } }; template struct light_address_of_operator { operator T const* () const { return static_cast(static_cast(static_cast(this)->p)); } }; template struct address_of_operator : light_address_of_operator, Args>... { operator T* () { return p; }; address_of_operator(T* p) : p(p) {} T* p; }; template struct address_of_operator : light_address_of_operator, Args>... { operator T const* () { return p; }; address_of_operator(T const* p) : p(p) {} T const* p; }; } } // namespace efl { namespace eolian { #endif // EFL_EOLIAN_INTEROP_HH