diff --git a/src/bindings/cxx/eina_cxx/eina_value.hh b/src/bindings/cxx/eina_cxx/eina_value.hh index 0f348c12e6..947b5d4672 100644 --- a/src/bindings/cxx/eina_cxx/eina_value.hh +++ b/src/bindings/cxx/eina_cxx/eina_value.hh @@ -304,15 +304,15 @@ struct _eina_value_traits::value>: } }; -class value; +class value_view; template -T get(value const& v); +T get(value_view const& v); /** * Store generic value */ -class value +class value_view { /** * @brief Initialize the eina::value with the given argument. @@ -329,8 +329,8 @@ public: /** * @brief Default constructor. Create an empty generic value storage. */ - value() - : _raw(_eina_value_traits::create()) + value_view() + : _raw(nullptr) { } @@ -339,7 +339,7 @@ public: * @param v Value to be stored. */ template - value(T v, typename std::enable_if<_eina_value_traits::is_specialized::value>::type* = 0) + value_view(T v, typename std::enable_if<_eina_value_traits::is_specialized::value>::type* = 0) { primitive_init(v); } @@ -348,7 +348,7 @@ public: * @brief Create an generic value storage holding a @c char value. * @param v @c char value to be stored. */ - value(char v) + value_view(char v) { primitive_init(v); } @@ -357,7 +357,7 @@ public: * @brief Create an generic value storage holding a @c short value. * @param v @c short value to be stored. */ - value(short v) + value_view(short v) { primitive_init(v); } @@ -366,7 +366,7 @@ public: * @brief Create an generic value storage holding a @c int value. * @param v @c int value to be stored. */ - value(int v) + value_view(int v) { primitive_init(v); } @@ -375,7 +375,7 @@ public: * @brief Create an generic value storage holding a @c long value. * @param v @c long value to be stored. */ - value(long v) + value_view(long v) { primitive_init(v); } @@ -384,7 +384,7 @@ public: * @brief Create an generic value storage holding a unsigned char value. * @param v unsigned char value to be stored. */ - value(unsigned char v) + value_view(unsigned char v) { primitive_init(v); } @@ -393,7 +393,7 @@ public: * @brief Create an generic value storage holding a unsigned short value. * @param v unsigned short value to be stored. */ - value(unsigned short v) + value_view(unsigned short v) { primitive_init(v); } @@ -402,7 +402,7 @@ public: * @brief Create an generic value storage holding a unsigned int value. * @param v unsigned int value to be stored. */ - value(unsigned int v) + value_view(unsigned int v) { primitive_init(v); } @@ -411,7 +411,7 @@ public: * @brief Create an generic value storage holding a unsigned long value. * @param v unsigned long value to be stored. */ - value(unsigned long v) + value_view(unsigned long v) { primitive_init(v); } @@ -420,7 +420,7 @@ public: * @brief Create an generic value storage holding a @c float value. * @param v @c float value to be stored. */ - value(float v) + value_view(float v) { primitive_init(v); } @@ -429,54 +429,19 @@ public: * @brief Create an generic value storage holding a @c double value. * @param v @c double value to be stored. */ - value(double v) + value_view(double v) { primitive_init(v); } - /** - * @brief Deallocate stored value. - */ - ~value() - { - eina_value_free(_raw); - } - - value(Eina_Value* raw) + value_view(Eina_Value* raw) : _raw(raw) {} - /** - * @brief Copy Constructor. Create an generic value storage holding the same value of @p other. - * @param other Another eina::value object. - */ - value(value const& other) - : _raw(_eina_value_traits::create()) - { - if(!eina_value_copy(const_cast(other._raw), _raw)) - { - EFL_CXX_THROW(eina::system_error(eina::get_error_code())); - } - } - - /** - * @brief Assignment operator. Replace the current stored value by the value in @p other. - * @param other Another eina::value object. - */ - value& operator=(value const& other) - { - eina_value_flush(_raw); - if(!eina_value_copy(const_cast(other._raw), _raw)) - { - EFL_CXX_THROW(eina::system_error(eina::get_error_code())); - } - return *this; - } - /** * @brief Swap stored values with the given eina::value object. * @param other Another eina::value object. */ - void swap(value& other) + void swap(value_view& other) { std::swap(_raw, other._raw); } @@ -511,7 +476,7 @@ public: { return ::eina_value_type_get(_raw); } -private: +protected: ::Eina_Value* _raw; /** @@ -530,7 +495,7 @@ private: * match the current stored value type. */ template - friend T get(value const& v) + friend T get(value_view const& v) { return _eina_value_traits::get(v._raw); } @@ -541,7 +506,7 @@ private: * @param lhs First eina::value object. * @param rhs Second eina::value object. */ -inline void swap(value& lhs, value& rhs) +inline void swap(value_view& lhs, value_view& rhs) { lhs.swap(rhs); } @@ -553,7 +518,7 @@ inline void swap(value& lhs, value& rhs) * @return @c true if the stored values are of the same type and equals * in content, @c false otherwise. */ -inline bool operator==(value const& lhs, value const& rhs) +inline bool operator==(value_view const& lhs, value_view const& rhs) { return lhs.type_info() == rhs.type_info() && eina_value_compare(lhs.native_handle(), rhs.native_handle()) == 0; @@ -569,7 +534,7 @@ inline bool operator==(value const& lhs, value const& rhs) * type identifier of @p lhs comes before the type indentifier * of @p rhs. Returns @c false in all other cases. */ -inline bool operator<(value const& lhs, value const& rhs) +inline bool operator<(value_view const& lhs, value_view const& rhs) { return std::less()(lhs.type_info(), rhs.type_info()) || (lhs.type_info() == rhs.type_info() @@ -577,16 +542,16 @@ inline bool operator<(value const& lhs, value const& rhs) } /** - * @brief More than comparison between two eina::value objects. - * @param lhs eina::value object at the left side of the expression. - * @param rhs eina::value object at the right side of the expression. + * @brief More than comparison between two eina::value_view objects. + * @param lhs eina::value_view object at the left side of the expression. + * @param rhs eina::value_view object at the right side of the expression. * @return For objects holding values of the same type, returns @c true * if @p lhs value is more than @p rhs value. For objects * holding values of different types, returns @c true if the * type identifier of @p lhs comes after the type indentifier * of @p rhs. Returns @c false in all other cases. */ -inline bool operator>(value const& lhs, value const& rhs) +inline bool operator>(value_view const& lhs, value_view const& rhs) { return std::less()(rhs.type_info(), lhs.type_info()) || (rhs.type_info() == lhs.type_info() @@ -594,16 +559,16 @@ inline bool operator>(value const& lhs, value const& rhs) } /** - * @brief Less than or equal comparison between two eina::value objects. - * @param lhs eina::value object at the left side of the expression. - * @param rhs eina::value object at the right side of the expression. + * @brief Less than or equal comparison between two eina::value_view objects. + * @param lhs eina::value_view object at the left side of the expression. + * @param rhs eina::value_view object at the right side of the expression. * @return For objects holding values of the same type, returns @c true * if @p lhs value is less than or equal to @p rhs value. For * objects holding values of different types, returns @c true if * the type identifier of @p lhs comes before the type * indentifier of @p rhs. Returns @c false in all other cases. */ -inline bool operator<=(value const& lhs, value const& rhs) +inline bool operator<=(value_view const& lhs, value_view const& rhs) { return !(lhs > rhs); } @@ -618,7 +583,7 @@ inline bool operator<=(value const& lhs, value const& rhs) * the type identifier of @p lhs comes after the type * indentifier of @p rhs. Returns @c false in all other cases. */ -inline bool operator>=(value const& lhs, value const& rhs) +inline bool operator>=(value_view const& lhs, value_view const& rhs) { return !(lhs < rhs); } @@ -631,11 +596,174 @@ inline bool operator>=(value const& lhs, value const& rhs) * @p lhs is different from the value of @rhs, @c false * otherwise. */ -inline bool operator!=(value const& lhs, value const& rhs) +inline bool operator!=(value_view const& lhs, value_view const& rhs) { return !(lhs == rhs); } +/** + * Store generic value + */ +struct value : value_view +{ + using value_view::value_view; + + value(std::nullptr_t) {} + value() : value_view(_eina_value_traits::create()) {} + explicit value(Eina_Value* raw) + : value_view(raw) {} + + value(Eina_Value const* raw) + : value_view(_eina_value_traits::create()) + { + if(!eina_value_copy(raw, _raw)) + { + eina_value_free(_raw); + EFL_CXX_THROW(eina::system_error(eina::get_error_code())); + } + } + + /** + * @brief Deallocate stored value. + */ + ~value() + { + if(_raw) + eina_value_free(_raw); + } + + /** + * @brief Copy Constructor. Create an generic value storage holding the same value of @p other. + * @param other Another eina::value object. + */ + value(value_view const& other) + : value_view(_eina_value_traits::create()) + { + if(!eina_value_copy(other.native_handle(), _raw)) + { + eina_value_free(_raw); + EFL_CXX_THROW(eina::system_error(eina::get_error_code())); + } + } + + /** + * @brief Assignment operator. Replace the current stored value by the value in @p other. + * @param other Another eina::value object. + */ + value& operator=(value other) + { + other.swap(*this); + return *this; + } + + void swap(value& other) + { + _base_get(other).swap(*this); + } +private: + static value_view& _base_get(value& v) { return v; } + static value_view const& _base_get(value const& v) { return v; } + /** + * @brief Swap the stored values between the given eina::value objects. + * @param lhs First eina::value object. + * @param rhs Second eina::value object. + */ + friend inline void swap(value& lhs, value& rhs) + { + lhs.swap(rhs); + } + + /** + * @brief Compare if the stored values are equal. + * @param lhs eina::value object at the left side of the expression. + * @param rhs eina::value object at the right side of the expression. + * @return @c true if the stored values are of the same type and equals + * in content, @c false otherwise. + */ + friend inline bool operator==(value const& lhs, value const& rhs) + { + return _base_get(lhs) == _base_get(rhs); + } + + /** + * @brief Less than comparison between two eina::value objects. + * @param lhs eina::value object at the left side of the expression. + * @param rhs eina::value object at the right side of the expression. + * @return For objects holding values of the same type, returns @c true + * if @p lhs value is less than @p rhs value. For objects + * holding values of different types, returns @c true if the + * type identifier of @p lhs comes before the type indentifier + * of @p rhs. Returns @c false in all other cases. + */ + friend inline bool operator<(value const& lhs, value const& rhs) + { + return _base_get(lhs) < _base_get(rhs); + } + + /** + * @brief More than comparison between two eina::value objects. + * @param lhs eina::value object at the left side of the expression. + * @param rhs eina::value object at the right side of the expression. + * @return For objects holding values of the same type, returns @c true + * if @p lhs value is more than @p rhs value. For objects + * holding values of different types, returns @c true if the + * type identifier of @p lhs comes after the type indentifier + * of @p rhs. Returns @c false in all other cases. + */ + friend inline bool operator>(value const& lhs, value const& rhs) + { + return _base_get(lhs) > _base_get(rhs); + } + + /** + * @brief Less than or equal comparison between two eina::value objects. + * @param lhs eina::value object at the left side of the expression. + * @param rhs eina::value object at the right side of the expression. + * @return For objects holding values of the same type, returns @c true + * if @p lhs value is less than or equal to @p rhs value. For + * objects holding values of different types, returns @c true if + * the type identifier of @p lhs comes before the type + * indentifier of @p rhs. Returns @c false in all other cases. + */ + friend inline bool operator<=(value const& lhs, value const& rhs) + { + return _base_get(lhs) <= _base_get(rhs); + } + + /** + * @brief More than or equal comparison between two eina::value objects. + * @param lhs eina::value object at the left side of the expression. + * @param rhs eina::value object at the right side of the expression. + * @return For objects holding values of the same type, returns @c true + * if @p lhs value is more than or equal to @p rhs value. For + * objects holding values of different types, returns @c true if + * the type identifier of @p lhs comes after the type + * indentifier of @p rhs. Returns @c false in all other cases. + */ + friend inline bool operator>=(value const& lhs, value const& rhs) + { + return _base_get(lhs) >= _base_get(rhs); + } + + /** + * @brief Compare if the stored values are different. + * @param lhs eina::value object at the left side of the expression. + * @param rhs eina::value object at the right side of the expression. + * @return @c true if the value types are different or if the value of + * @p lhs is different from the value of @rhs, @c false + * otherwise. + */ + friend inline bool operator!=(value const& lhs, value const& rhs) + { + return _base_get(lhs) != _base_get(rhs); + } +}; + +static_assert(std::is_standard_layout::value, ""); +static_assert(std::is_standard_layout::value, ""); +static_assert(sizeof(value) == sizeof(Eina_Value*), ""); +static_assert(sizeof(value_view) == sizeof(Eina_Value*), ""); + /** * @} */ diff --git a/src/bindings/cxx/eo_cxx/eo_concrete.hh b/src/bindings/cxx/eo_cxx/eo_concrete.hh index 11d2c5b5da..8b978275b9 100644 --- a/src/bindings/cxx/eo_cxx/eo_concrete.hh +++ b/src/bindings/cxx/eo_cxx/eo_concrete.hh @@ -211,10 +211,6 @@ template struct is_eolian_object : std::false_type {}; template struct is_eolian_object : is_eolian_object {}; -template -struct is_eolian_object : is_eolian_object {}; -template -struct is_eolian_object : is_eolian_object {}; template <> struct is_eolian_object : std::true_type {}; diff --git a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh index 570f5c822b..3e8c48bd34 100644 --- a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh +++ b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh @@ -64,6 +64,13 @@ struct inout_traits { typedef void* type; }; template struct inout_traits> { typedef efl::eina::future& 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); @@ -151,7 +158,17 @@ void assign_out_impl(efl::eina::optional& lhs, Rhs& rhs, tag(*lhs, rhs); } template -void assign_out_impl(eina::value& lhs, Eina_Value const& rhs, Tag) +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 = {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); @@ -324,6 +341,12 @@ Eo const* convert_to_c_impl(T v, tag { 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(); @@ -355,12 +378,24 @@ inline Eina_Value* convert_to_c_impl( ::efl::eina::value v, tag::type>) +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_Bool convert_to_c_impl( bool b, tag) { return b; @@ -632,6 +667,10 @@ inline efl::eina::value convert_to_return(Eina_Value* value, tag) +{ + return efl::eina::value_view{value}; +} template T convert_to_return(U* value, tag, typename std::enable_if::value || is_container::value>::type* = 0) { diff --git a/src/lib/eo/eo_base.eo b/src/lib/eo/eo_base.eo index ce567152b3..72d7906a68 100644 --- a/src/lib/eo/eo_base.eo +++ b/src/lib/eo/eo_base.eo @@ -200,7 +200,7 @@ abstract Eo.Base () being freed. ]] params { - @out wref: Eo.Base; + @in wref: ref(Eo.Base); } } wref_del { diff --git a/src/lib/eolian_cxx/grammar/c_type.hpp b/src/lib/eolian_cxx/grammar/c_type.hpp index 54b996d65a..6d814f80a4 100644 --- a/src/lib/eolian_cxx/grammar/c_type.hpp +++ b/src/lib/eolian_cxx/grammar/c_type.hpp @@ -19,6 +19,8 @@ struct c_type_visitor , std::make_tuple(name.namespaces, name.eolian_name , std::string{name.base_qualifier & qualifier_info::is_const ? " const" : ""}) , context_null {}); + if(name.base_qualifier & qualifier_info::is_ref) + n += '*'; return n; } template diff --git a/src/lib/eolian_cxx/grammar/converting_argument.hpp b/src/lib/eolian_cxx/grammar/converting_argument.hpp index 3b5cb1dcfc..cb3f750544 100644 --- a/src/lib/eolian_cxx/grammar/converting_argument.hpp +++ b/src/lib/eolian_cxx/grammar/converting_argument.hpp @@ -25,9 +25,10 @@ struct converting_argument_generator attributes::qualifier_def qualifier = param.type.original_type.visit(attributes::get_qualifier_visitor{}); return as_generator ( - attribute_reorder<1, -1, 2> + attribute_reorder<-1, -1, 2> ( - " ::efl::eolian::convert_to_c<" << c_type << ", " << parameter_type + " ::efl::eolian::convert_to_c<" << c_type + << ", " << parameter_type << (qualifier & qualifier_info::is_own ? ", true" : "") << ">(" << string << ")" diff --git a/src/lib/eolian_cxx/grammar/function_declaration.hpp b/src/lib/eolian_cxx/grammar/function_declaration.hpp index f01c214483..6e124dfd38 100644 --- a/src/lib/eolian_cxx/grammar/function_declaration.hpp +++ b/src/lib/eolian_cxx/grammar/function_declaration.hpp @@ -19,7 +19,7 @@ struct function_declaration_generator bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { return as_generator - (grammar::type(true) << " " << string << "(" << (parameter % ", ") << ") const;\n") + ("::efl::eolian::return_traits<" << grammar::type(true) << ">::type " << string << "(" << (parameter % ", ") << ") const;\n") .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters), context); } }; diff --git a/src/lib/eolian_cxx/grammar/function_definition.hpp b/src/lib/eolian_cxx/grammar/function_definition.hpp index a2de1aaf41..714cb1fbda 100644 --- a/src/lib/eolian_cxx/grammar/function_definition.hpp +++ b/src/lib/eolian_cxx/grammar/function_definition.hpp @@ -54,7 +54,7 @@ struct function_definition_generator return false; if(!as_generator - ("inline " << grammar::type(true) << " " << string << "::" << string << "(" << (parameter % ", ") << ") const\n{\n") + ("inline ::efl::eolian::return_traits<" << grammar::type(true) << ">::type " << string << "::" << string << "(" << (parameter % ", ") << ") const\n{\n") .generate(sink, std::make_tuple(f.return_type, _klass_name.eolian_name, escape_keyword(f.name), f.parameters), ctx)) return false; @@ -133,8 +133,8 @@ struct function_definition_generator .generate(sink, f.parameters, ctx)) return false; if(f.return_type != attributes::void_ - && !as_generator(scope_tab << "return ::efl::eolian::convert_to_return<" - << type(true) << ">(__return_value);\n" + && !as_generator(scope_tab << "return ::efl::eolian::convert_to_return< ::efl::eolian::return_traits<" + << type(true) << ">::type>(__return_value);\n" ).generate(sink, f.return_type, ctx)) return false; if(!as_generator("}\n").generate(sink, attributes::unused, ctx)) diff --git a/src/lib/eolian_cxx/grammar/type_impl.hpp b/src/lib/eolian_cxx/grammar/type_impl.hpp index 3e67d858ca..6e18b2bda1 100644 --- a/src/lib/eolian_cxx/grammar/type_impl.hpp +++ b/src/lib/eolian_cxx/grammar/type_impl.hpp @@ -102,9 +102,12 @@ struct visitor_generate r.base_qualifier.qualifier ^= qualifier_info::is_ref; return replace_base_type(r, " ::efl::eina::stringshare"); }} - , {"generic_value", nullptr, [&] + , {"generic_value", true, [&] { return regular_type_def{" ::efl::eina::value", regular.base_qualifier, {}}; }} + , {"generic_value", false, [&] + { return regular_type_def{" ::efl::eina::value_view", regular.base_qualifier, {}}; + }} }; if(regular.base_type == "void_ptr") { @@ -207,11 +210,11 @@ struct visitor_generate } bool operator()(attributes::klass_name klass) const { - if(as_generator(" " << *("::" << lower_case[string]) << "::" << string) - .generate(sink, std::make_tuple(attributes::cpp_namespaces(klass.namespaces), klass.eolian_name), *context)) - return true; - else - return false; + return + as_generator(" " << *("::" << lower_case[string]) << "::" << string) + .generate(sink, std::make_tuple(attributes::cpp_namespaces(klass.namespaces), klass.eolian_name), *context) + && (!(klass.base_qualifier & qualifier_info::is_ref) + || as_generator("&").generate(sink, attributes::unused, *context)); } bool operator()(attributes::complex_type_def const& complex) const {