diff --git a/src/bindings/cxx/eina_cxx/Eina.hh b/src/bindings/cxx/eina_cxx/Eina.hh index c8717a6ee1..c98681551d 100644 --- a/src/bindings/cxx/eina_cxx/Eina.hh +++ b/src/bindings/cxx/eina_cxx/Eina.hh @@ -25,6 +25,7 @@ #include #include #include +#include /** * @page eina_cxx_main Eina C++ (BETA) diff --git a/src/bindings/cxx/eina_cxx/eina_accessor.hh b/src/bindings/cxx/eina_cxx/eina_accessor.hh index 800c3fa122..33046a3f7f 100644 --- a/src/bindings/cxx/eina_cxx/eina_accessor.hh +++ b/src/bindings/cxx/eina_cxx/eina_accessor.hh @@ -215,6 +215,7 @@ struct accessor + +namespace efl { namespace eina { + +struct malloc_deleter +{ + template + void operator()(T* object) const + { + object->~T(); + free(object); + } +}; + +template +using unique_malloc_ptr = std::unique_ptr; + +} } + +#endif diff --git a/src/bindings/cxx/eina_cxx/eina_ptrarray.hh b/src/bindings/cxx/eina_cxx/eina_ptrarray.hh index f47202ebb5..b5de9d7290 100644 --- a/src/bindings/cxx/eina_cxx/eina_ptrarray.hh +++ b/src/bindings/cxx/eina_cxx/eina_ptrarray.hh @@ -516,6 +516,12 @@ public: insert(end(), other.begin(), other.end()); } + ptr_array(ptr_array&& other) + : _base_type() + { + std::swap(other._impl._array, this->_impl._array); + } + /** * @brief Creates a copy of a @c ptr_array with a different clone allocator. * @param other Another @c ptr_array with a different clone allocator. @@ -554,6 +560,13 @@ public: return *this; } + ptr_array& operator=(ptr_array&& other) + { + clear(); + std::swap(other._impl._array, this->_impl._array); + return *this; + } + /** * @brief Remove all the elements of the array. */ diff --git a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh index f90e4f79e5..bd7a883dc8 100644 --- a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh +++ b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh @@ -39,35 +39,45 @@ template struct in_traits> { typedef eina::range_array type; }; template -struct out_traits { typedef T type; }; +struct out_traits { typedef T& 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::future& type; }; template -struct inout_traits { typedef T type; }; +struct inout_traits { typedef T& type; }; template struct inout_traits> { typedef efl::eina::future& type; }; +template +void assign_out(Lhs& lhs, Rhs& rhs); + namespace impl { -template +template struct tag { typedef To to; typedef From from; + typedef std::integral_constant own; }; -template -void assign_out(Lhs& lhs, Rhs& rhs); - template -void assign_out_impl(T*& lhs, T& rhs, tag) +void assign_out_impl(T& lhs, T*& rhs, tag) { - *lhs = rhs; + lhs = *rhs; } -template -void assign_out_impl(std::unique_ptr& lhs, U* rhs, tag&, U*>) +template +void assign_out_impl(std::unique_ptr& lhs, U* rhs, tag&, U*, true>) { + // with own lhs.reset(rhs); } template @@ -101,31 +111,23 @@ void assign_out_impl(efl::eina::string_view& view, const char* string, Tag) { view = {string}; } -template -void assign_out_impl(efl::eina::optional& lhs, Rhs*& rhs, tag&, O>) +template +void assign_out_impl(efl::eina::string_view* view, const char* string, Tag) { - if(rhs) - assign_out(*lhs, rhs); - else - lhs.disengage(); + if(view) + *view = {string}; } -template -void assign_out_impl(efl::eina::optional& lhs, Rhs& rhs, tag&, O>) +template +void assign_out_impl(T*& lhs, T& rhs, tag) // optional { - assign_out(*lhs, rhs); + if(lhs) + *lhs = rhs; } -template -void assign_out_impl(efl::eina::optional& lhs, Rhs*& rhs, tag, O>) +template +void assign_out_impl(efl::eina::optional& lhs, Rhs& rhs, tag, O, B>) { - if(rhs) - assign_out(*lhs, rhs); - else - lhs.disengage(); -} -template -void assign_out_impl(efl::eina::optional& lhs, Rhs& rhs, tag, O>) -{ - assign_out(*lhs, rhs); + if(lhs) + assign_out(*lhs, rhs); } template void assign_out_impl(eina::value& lhs, Eina_Value const& rhs, Tag) @@ -135,17 +137,57 @@ void assign_out_impl(eina::value& lhs, Eina_Value const& rhs, Tag) eina_value_copy(&rhs, v); lhs = {v}; } -template -void assign_out_impl(efl::eina::list& lhs, Eina_List* rhs, Tag) +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 +template void assign_out(Lhs& lhs, Rhs& rhs) { - return impl::assign_out_impl(lhs, rhs, impl::tag{}); + return impl::assign_out_impl(lhs, rhs, impl::tag{}); } namespace impl { @@ -185,7 +227,7 @@ auto convert_inout(V& object) -> decltype(impl::convert_inout_impl(object, impl: return impl::convert_inout_impl(object, impl::tag{}); } -template +template T convert_to_c(V&& object); namespace impl { @@ -197,6 +239,43 @@ auto convert_to_c_impl 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) { @@ -209,15 +288,27 @@ Eo* convert_to_c_impl(T v, tag return v._eo_ptr(); } template +Eo* convert_to_c_impl(T v, tag + , typename std::enable_if::value>::type* = 0) +{ + return ::eo_ref(v._eo_ptr()); +} +template Eo const* convert_to_c_impl(T v, tag , typename std::enable_if::value>::type* = 0) { - return v._eo_ptr(); + return const_cast(v._eo_ptr()); } inline const char* convert_to_c_impl( ::efl::eina::string_view v, tag) { return v.c_str(); } +inline const 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 const char** convert_to_c_impl(efl::eina::string_view* /*view*/, tag) { std::abort(); @@ -254,6 +345,18 @@ T convert_to_c_impl(efl::eina::optional const& optional, tag +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&>) { @@ -270,15 +373,16 @@ Eina_List const* convert_to_c_impl(efl::eina::range_list range, tag -Eina_List* convert_to_c_impl(efl::eina::listconst& c, tagconst&>) +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&>) +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>) { @@ -290,23 +394,54 @@ Eina_Array const* convert_to_c_impl(efl::eina::range_array range, tag -Eina_Array* convert_to_c_impl(efl::eina::arrayconst& c, tagconst&>) +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_Array const* convert_to_c_impl(efl::eina::arrayconst& c, tagconst&>) +Eina_Iterator* convert_to_c_impl(efl::eina::iteratorconst& i, tagconst&>) { - return c.native_handle(); + 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 const char* convert_to_c_impl(std::string const& x, tag) -// { -// return x.c_str(); -// } +inline const 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(); @@ -321,7 +456,6 @@ T* convert_to_c_impl(std::unique_ptr& v, tag(v.release()); } - template Eina_Array** convert_to_c_impl(efl::eina::array& /*c*/, tag&>) { @@ -334,10 +468,10 @@ Eina_Array** convert_to_c_impl(efl::eina::range_array& /*c*/, tag +template T convert_to_c(V&& object) { - return impl::convert_to_c_impl(std::forward(object), impl::tag{}); + return impl::convert_to_c_impl(std::forward(object), impl::tag{}); } namespace impl { template @@ -389,6 +523,11 @@ T convert_to_return(T 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) { return T{value}; @@ -479,23 +618,46 @@ inline eina::string_view convert_to_return(const char* value, tag) +{ + return {*value}; +} inline std::string convert_to_return(const char* value, tag) { - return {value}; + if(value) + { + std::string r{value}; + free((void*)value); + return r; + } + else + return {}; +} +inline std::string convert_to_return(const char** value, tag) +{ + 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>) +template +std::unique_ptr convert_to_return(T* value, tag>) { - return std::unique_ptr{value, (void(*)(const void*))&free}; + return std::unique_ptr{value, {}}; } -template -std::unique_ptr convert_to_return(U* value, tag>) +template +std::unique_ptr convert_to_return(U* value, tag>) { - return std::unique_ptr{convert_to_return(value, tag{}), (void(*)(const void*))&free}; + return std::unique_ptr{convert_to_return(value, tag{}), {}}; } } diff --git a/src/lib/eolian_cxx/grammar/attribute_conditional.hpp b/src/lib/eolian_cxx/grammar/attribute_conditional.hpp index 8bf107a041..886b1edb35 100644 --- a/src/lib/eolian_cxx/grammar/attribute_conditional.hpp +++ b/src/lib/eolian_cxx/grammar/attribute_conditional.hpp @@ -56,7 +56,10 @@ struct attribute_conditional_terminal namespace type_traits { template -struct attributes_needed> : attributes_needed {}; +struct attributes_needed> + : std::conditional::value + , attributes_needed + , std::integral_constant>::type {}; template struct attributes_needed> : std::integral_constant {}; } diff --git a/src/lib/eolian_cxx/grammar/c_type.hpp b/src/lib/eolian_cxx/grammar/c_type.hpp index e6a72fd025..54b996d65a 100644 --- a/src/lib/eolian_cxx/grammar/c_type.hpp +++ b/src/lib/eolian_cxx/grammar/c_type.hpp @@ -17,7 +17,7 @@ struct c_type_visitor as_generator(" ::" << *(string << "_") << string << string << "*") .generate(std::back_insert_iterator(n) , std::make_tuple(name.namespaces, name.eolian_name - , std::string{is_const(name.base_qualifier) ? " const" : ""}) + , std::string{name.base_qualifier & qualifier_info::is_const ? " const" : ""}) , context_null {}); return n; } diff --git a/src/lib/eolian_cxx/grammar/container.hpp b/src/lib/eolian_cxx/grammar/container.hpp index 4612612360..ca86044c40 100644 --- a/src/lib/eolian_cxx/grammar/container.hpp +++ b/src/lib/eolian_cxx/grammar/container.hpp @@ -8,27 +8,6 @@ namespace efl { namespace eolian { namespace grammar { -struct container_subtype_modify -{ - typedef void result_type; - void operator()(attributes::complex_type_def& /*x*/) const - { - } - - void operator()(attributes::regular_type_def& x) const - { - if(x.base_type == "string") - remove_own(x.base_qualifier); - else if(!x.pointers.empty()) - x.pointers.pop_back(); - } - - template - void operator()(T& /*x*/) const - { - } -}; - template void generate_container(OutputIterator sink, attributes::complex_type_def const& complex, Context const& context , std::string const& name) @@ -36,7 +15,6 @@ void generate_container(OutputIterator sink, attributes::complex_type_def const& if(!complex.subtypes.empty()) { attributes::type_def subtype = complex.subtypes[0]; - subtype.original_type.visit(container_subtype_modify{}); as_generator(" "<< name << "<" << type << ">").generate(sink, subtype, context); } } diff --git a/src/lib/eolian_cxx/grammar/converting_argument.hpp b/src/lib/eolian_cxx/grammar/converting_argument.hpp index 4a2d959163..3b5cb1dcfc 100644 --- a/src/lib/eolian_cxx/grammar/converting_argument.hpp +++ b/src/lib/eolian_cxx/grammar/converting_argument.hpp @@ -22,11 +22,15 @@ struct converting_argument_generator template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& ctx) const { + attributes::qualifier_def qualifier = param.type.original_type.visit(attributes::get_qualifier_visitor{}); return as_generator ( attribute_reorder<1, -1, 2> ( - " ::efl::eolian::convert_to_c<" << c_type << ", " << parameter_type << ">(" << string << ")" + " ::efl::eolian::convert_to_c<" << c_type << ", " << parameter_type + << (qualifier & qualifier_info::is_own + ? ", true" : "") + << ">(" << string << ")" ) ).generate(sink, param, ctx); } diff --git a/src/lib/eolian_cxx/grammar/function_declaration.hpp b/src/lib/eolian_cxx/grammar/function_declaration.hpp index a6aa43948e..f01c214483 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 << " " << string << "(" << (parameter % ", ") << ") const;\n") + (grammar::type(true) << " " << 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 170fa986e9..b2280271d9 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 << " " << string << "::" << string << "(" << (parameter % ", ") << ") const\n{\n") + ("inline " << grammar::type(true) << " " << 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; @@ -105,9 +105,19 @@ struct function_definition_generator attribute_conditional([] (attributes::parameter_def const& p) -> bool { return p.direction != attributes::parameter_direction::in; }) [ - attribute_reorder<-1, 1, 2, 2> - (scope_tab << "::efl::eolian::assign_out<" << parameter_type << ", " << c_type - << ">(" << string << ", __out_param_" << string << ");\n") + attribute_reorder<-1, 1, 1, 2, 2> + ( + scope_tab << "::efl::eolian::assign_out<" << parameter_type << ", " << c_type + << + ( + attribute_conditional([] (attributes::type_def const& type) + { return type.original_type.visit(attributes::get_qualifier_visitor{}) & qualifier_info::is_own; }) + [ + ", true" + ] | eps + ) + << ">(" << string << ", __out_param_" << string << ");\n" + ) ] | eps ; @@ -116,7 +126,7 @@ struct function_definition_generator if(f.return_type != attributes::void_ && !as_generator(scope_tab << "return ::efl::eolian::convert_to_return<" - << type<< ">(__return_value);\n" + << type(true) << ">(__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/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp index b42d6f2d44..0c5d82056d 100644 --- a/src/lib/eolian_cxx/grammar/klass_def.hpp +++ b/src/lib/eolian_cxx/grammar/klass_def.hpp @@ -18,7 +18,15 @@ #include #include -namespace efl { namespace eolian { namespace grammar { namespace attributes { +namespace efl { namespace eolian { namespace grammar { + +namespace attributes { + +struct complex_type_def; + +} + +namespace attributes { template bool lexicographical_compare_impl(std::tuple const& @@ -56,25 +64,6 @@ bool lexicographical_compare(std::tuple const& lhs && std::get<1>(lhs) < std::get<1>(rhs)); } -struct pointer_indirection -{ - qualifier_def qualifier; - bool reference; -}; -inline bool operator<(pointer_indirection const& lhs, pointer_indirection const& rhs) -{ - return lexicographical_compare(std::make_tuple(lhs.qualifier, lhs.reference) - , std::make_tuple(rhs.qualifier, rhs.reference)); -} -inline bool operator==(pointer_indirection const& lhs, pointer_indirection const& rhs) -{ - return lhs.qualifier == rhs.qualifier && lhs.reference == rhs.reference; -} -inline bool operator!=(pointer_indirection const& lhs, pointer_indirection const& rhs) -{ - return !(lhs == rhs); -} - struct type_def; bool operator==(type_def const& rhs, type_def const& lhs); bool operator!=(type_def const& rhs, type_def const& lhs); @@ -89,19 +78,16 @@ struct klass_name std::vector namespaces; std::string eolian_name; qualifier_def base_qualifier; - std::vector pointers; class_type type; klass_name(std::vector namespaces , std::string eolian_name, qualifier_def base_qualifier - , std::vector pointers , class_type type) : namespaces(namespaces), eolian_name(eolian_name), base_qualifier(base_qualifier) - , pointers(pointers), type(type) {} - klass_name(Eolian_Class const* klass, qualifier_def base_qualifier - , std::vector pointers) + , type(type) {} + klass_name(Eolian_Class const* klass, qualifier_def base_qualifier) : eolian_name( ::eolian_class_name_get(klass)) - , base_qualifier(base_qualifier), pointers(pointers) + , base_qualifier(base_qualifier) { for(efl::eina::iterator namespace_iterator ( ::eolian_class_namespaces_get(klass)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) @@ -131,7 +117,7 @@ struct klass_name inline bool operator==(klass_name const& lhs, klass_name const& rhs) { return lhs.namespaces == rhs.namespaces && lhs.eolian_name == rhs.eolian_name - && lhs.base_qualifier == rhs.base_qualifier && lhs.pointers == rhs.pointers; + && lhs.base_qualifier == rhs.base_qualifier/* && lhs.pointers == rhs.pointers*/; } inline bool operator!=(klass_name const& lhs, klass_name const& rhs) { @@ -142,14 +128,13 @@ inline bool operator<(klass_name const& lhs, klass_name const& rhs) typedef std::tupleconst& , std::string const& , qualifier_def const& - , std::vector const& , class_type > tuple_type; return lexicographical_compare(tuple_type(lhs.namespaces, lhs.eolian_name - , lhs.base_qualifier, lhs.pointers + , lhs.base_qualifier , lhs.type) , tuple_type(rhs.namespaces, rhs.eolian_name - , rhs.base_qualifier, rhs.pointers + , rhs.base_qualifier , rhs.type)); } @@ -187,14 +172,12 @@ struct regular_type_def { std::string base_type; qualifier_def base_qualifier; - std::vector pointers; std::vector namespaces; }; inline bool operator==(regular_type_def const& rhs, regular_type_def const& lhs) { - return rhs.base_type == lhs.base_type && rhs.base_qualifier == lhs.base_qualifier - && rhs.pointers == lhs.pointers; + return rhs.base_type == lhs.base_type && rhs.base_qualifier == lhs.base_qualifier; } inline bool operator!=(regular_type_def const& rhs, regular_type_def const& lhs) { @@ -230,23 +213,23 @@ struct type_def { set(eolian_type); } - struct set_pointer_visitor - { - typedef void result_type; - std::vector pointers; - template - void operator()(T& v) const - { - v.pointers = pointers; - } - void operator()(complex_type_def& complex) const - { - (*this)(complex.outer); - } - }; void set(Eolian_Type const* eolian_type); }; +struct get_qualifier_visitor +{ + typedef qualifier_def result_type; + template + qualifier_def operator()(T const& object) const + { + return object.base_qualifier; + } + qualifier_def operator()(complex_type_def const& complex) const + { + return complex.outer.base_qualifier; + } +}; + inline bool operator==(type_def const& lhs, type_def const& rhs) { return lhs.original_type == rhs.original_type && lhs.c_type == rhs.c_type; @@ -273,29 +256,17 @@ inline void type_def::set(Eolian_Type const* eolian_type) for(efl::eina::iterator namespace_iterator( ::eolian_type_namespaces_get(eolian_type)) , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) namespaces.push_back(&*namespace_iterator); - original_type = {regular_type_def{ ::eolian_type_name_get(eolian_type), {qualifiers(eolian_type), {}}, {}, namespaces}}; + original_type = {regular_type_def{ ::eolian_type_name_get(eolian_type), {qualifiers(eolian_type), {}}, namespaces}}; } break; case EOLIAN_TYPE_POINTER: { - std::vector pointers - {{ {qualifiers(eolian_type), {}}, false }}; - Eolian_Type const* base_type = eolian_type_base_type_get(eolian_type); - while(eolian_type_type_get(base_type) == EOLIAN_TYPE_POINTER) - { - pointers.push_back({{qualifiers(base_type), {}}}); - base_type = eolian_type_base_type_get(base_type); - } - - set(base_type); - original_type.visit(set_pointer_visitor{pointers}); - c_type = ::eolian_type_c_type_get(eolian_type); - break; + throw std::runtime_error(""); } case EOLIAN_TYPE_CLASS: { Eolian_Class const* klass = eolian_type_class_get(eolian_type); - original_type = klass_name(klass, {qualifiers(eolian_type), {}}, {}); + original_type = klass_name(klass, {qualifiers(eolian_type), {}}); } break; case EOLIAN_TYPE_COMPLEX: @@ -329,7 +300,7 @@ struct add_optional_qualifier_visitor template void operator()(T& object) const { - add_optional(object.base_qualifier); + object.base_qualifier.qualifier |= qualifier_info::is_optional; } void operator()(complex_type_def& complex) const { @@ -612,26 +583,34 @@ struct klass_def Eolian_Function_Type type = ::eolian_function_type_get(function); if(type == EOLIAN_PROPERTY) { - if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_GET) - && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) - functions.push_back({function, EOLIAN_PROP_GET}); - if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_SET) - && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) - functions.push_back({function, EOLIAN_PROP_SET}); + try { + if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_GET) + && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) + functions.push_back({function, EOLIAN_PROP_GET}); + } catch(std::exception const&) {} + try { + if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_SET) + && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) + functions.push_back({function, EOLIAN_PROP_SET}); + } catch(std::exception const&) {} } else - if(! ::eolian_function_is_legacy_only(function, type) - && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) - functions.push_back({function, type}); + try { + if(! ::eolian_function_is_legacy_only(function, type) + && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) + functions.push_back({function, type}); + } catch(std::exception const&) {} } for(efl::eina::iterator eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_METHOD)) , functions_last; eolian_functions != functions_last; ++eolian_functions) { - Eolian_Function const* function = &*eolian_functions; - Eolian_Function_Type type = ::eolian_function_type_get(function); - if(! ::eolian_function_is_legacy_only(function, EOLIAN_METHOD) - && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) - functions.push_back({function, EOLIAN_METHOD}); + try { + Eolian_Function const* function = &*eolian_functions; + Eolian_Function_Type type = eolian_function_type_get(function); + if(! ::eolian_function_is_legacy_only(function, EOLIAN_METHOD) + && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) + functions.push_back({function, EOLIAN_METHOD}); + } catch(std::exception const&) {} } std::function inherit_algo = [&] (Eolian_Class const* klass) @@ -640,7 +619,7 @@ struct klass_def , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator) { Eolian_Class const* inherit = ::eolian_class_get_by_name(&*inherit_iterator); - inherits.insert({inherit, {}, {}}); + inherits.insert({inherit, {}}); inherit_algo(inherit); } }; @@ -665,7 +644,9 @@ struct klass_def for(efl::eina::iterator event_iterator( ::eolian_class_events_get(klass)) , event_last; event_iterator != event_last; ++event_iterator) { - events.push_back(&*event_iterator); + try { + events.push_back(&*event_iterator); + } catch(std::exception const&) {} } } @@ -673,7 +654,7 @@ struct klass_def inline klass_name get_klass_name(klass_def const& klass) { - return {klass.namespaces, klass.eolian_name, {qualifier_info::is_none, {}}, {}, klass.type}; + return {klass.namespaces, klass.eolian_name, {qualifier_info::is_none, {}}, klass.type}; } inline Eolian_Class const* get_klass(klass_name const& klass_name_) @@ -703,6 +684,8 @@ struct is_tuple : std::true_type {}; template <> struct is_tuple : std::true_type {}; -} } } } +} + +} } } #endif diff --git a/src/lib/eolian_cxx/grammar/parameter.hpp b/src/lib/eolian_cxx/grammar/parameter.hpp index f236841707..b29805e24a 100644 --- a/src/lib/eolian_cxx/grammar/parameter.hpp +++ b/src/lib/eolian_cxx/grammar/parameter.hpp @@ -7,20 +7,6 @@ namespace efl { namespace eolian { namespace grammar { -struct add_reference_visitor -{ - typedef void result_type; - template - void operator()(T& object) const - { - object.pointers.insert(object.pointers.begin(), {{}, true}); - } - void operator()(attributes::complex_type_def& complex) const - { - (*this)(complex.outer); - } -}; - struct parameter_type_generator { template diff --git a/src/lib/eolian_cxx/grammar/qualifier_def.hpp b/src/lib/eolian_cxx/grammar/qualifier_def.hpp index 3ba1a89553..b43b2f1b8f 100644 --- a/src/lib/eolian_cxx/grammar/qualifier_def.hpp +++ b/src/lib/eolian_cxx/grammar/qualifier_def.hpp @@ -10,68 +10,74 @@ namespace efl { namespace eolian { namespace grammar { namespace attributes { enum class qualifier_info { is_none , is_own = 1 -, is_const = 4 -, is_const_own -, is_optional = 8 -, is_optional_own -, is_optional_const -, is_optional_const_own +, is_const = 2 +, is_optional = 4 +, is_ref = 8 }; +struct qualifier_bool +{ + qualifier_info v; + qualifier_bool(qualifier_info v) + : v(v) {} + + typedef qualifier_info(qualifier_bool::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const + { + return v != qualifier_info::is_none ? &qualifier_bool::operator qualifier_info : nullptr; + } + operator qualifier_info() const { return v; } +}; +inline qualifier_bool operator|(qualifier_info lhs, qualifier_info rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} +inline qualifier_bool operator&(qualifier_info lhs, qualifier_info rhs) +{ + return static_cast(static_cast(lhs) & static_cast(rhs)); +} +inline qualifier_info operator^(qualifier_info lhs, qualifier_info rhs) +{ + return static_cast(static_cast(lhs) & ~static_cast(rhs)); +} +inline qualifier_info& operator|=(qualifier_info& lhs, qualifier_info rhs) +{ + lhs = static_cast(static_cast(lhs) | static_cast(rhs)); + return lhs; +} +inline qualifier_info& operator&=(qualifier_info& lhs, qualifier_info rhs) +{ + lhs = static_cast(static_cast(lhs) & static_cast(rhs)); + return lhs; +} +inline qualifier_info& operator^=(qualifier_info& lhs, qualifier_info rhs) +{ + lhs = static_cast(static_cast(lhs) & ~static_cast(rhs)); + return lhs; +} +inline qualifier_bool operator|(qualifier_bool lhs, qualifier_info rhs) +{ + lhs.v |= rhs; + return lhs; +} +inline qualifier_bool operator&(qualifier_bool lhs, qualifier_info rhs) +{ + lhs.v &= rhs; + return lhs; +} +inline qualifier_bool operator^(qualifier_bool lhs, qualifier_info rhs) +{ + lhs.v ^= rhs; + return lhs; +} + inline qualifier_info qualifiers(Eolian_Type const* type) { - bool is_own = ::eolian_type_is_own(type); - bool is_const = ::eolian_type_is_const(type); - if(is_own && is_const) - return qualifier_info::is_const_own; - else if(is_own) - return qualifier_info::is_own; - else if(is_const) - return qualifier_info::is_const; - else - return qualifier_info::is_none; -} - -inline bool is_own(qualifier_info i) -{ - switch(i) - { - case qualifier_info::is_own: - case qualifier_info::is_const_own: - case qualifier_info::is_optional_own: - case qualifier_info::is_optional_const_own: - return true; - default: - return false; - } -} - -inline bool is_const(qualifier_info i) -{ - switch(i) - { - case qualifier_info::is_const: - case qualifier_info::is_const_own: - case qualifier_info::is_optional_const: - case qualifier_info::is_optional_const_own: - return true; - default: - return false; - } -} - -inline bool is_optional(qualifier_info i) -{ - switch(i) - { - case qualifier_info::is_optional: - case qualifier_info::is_optional_own: - case qualifier_info::is_optional_const: - case qualifier_info::is_optional_const_own: - return true; - default: - return false; - } + qualifier_info is_own = ::eolian_type_is_own(type) ? qualifier_info::is_own : qualifier_info::is_none; + qualifier_info is_const = ::eolian_type_is_const(type) ? qualifier_info::is_const : qualifier_info::is_none; + qualifier_info is_ref = ::eolian_type_is_ref(type) ? qualifier_info::is_ref : qualifier_info::is_none; + return is_own | is_const | is_ref; } struct qualifier_def @@ -82,8 +88,30 @@ struct qualifier_def qualifier_def() : qualifier(qualifier_info::is_none) {} qualifier_def(qualifier_info info, std::string free_function) : qualifier(info), free_function(std::move(free_function)) {} + + typedef qualifier_info(qualifier_bool::*unspecified_bool_type)() const; + operator unspecified_bool_type() const + { + return qualifier != qualifier_info::is_none ? &qualifier_bool::operator qualifier_info : nullptr; + } }; +inline qualifier_def operator|(qualifier_def lhs, qualifier_info rhs) +{ + lhs.qualifier = lhs.qualifier | rhs; + return lhs; +} +inline qualifier_def operator&(qualifier_def lhs, qualifier_info rhs) +{ + lhs.qualifier = lhs.qualifier & rhs; + return lhs; +} +inline qualifier_def operator^(qualifier_def lhs, qualifier_info rhs) +{ + lhs.qualifier = lhs.qualifier ^ rhs; + return lhs; +} + inline bool operator<(qualifier_def const& lhs, qualifier_def const& rhs) { return lhs.qualifier < rhs.qualifier || @@ -102,81 +130,8 @@ inline bool operator!=(qualifier_def const& lhs, qualifier_def const& rhs) return !(rhs == lhs); } -inline void add_optional(qualifier_def& q) -{ - switch (q.qualifier) - { - case qualifier_info::is_none: - q.qualifier = qualifier_info::is_optional; - break; - case qualifier_info::is_own: - q.qualifier = qualifier_info::is_optional_own; - break; - case qualifier_info::is_const: - q.qualifier = qualifier_info::is_optional_const; - break; - case qualifier_info::is_const_own: - q.qualifier = qualifier_info::is_optional_const_own; - break; - default: - break; - } } -inline void remove_optional(qualifier_def& q) -{ - switch (q.qualifier) - { - case qualifier_info::is_optional: - q.qualifier = qualifier_info::is_none; - break; - case qualifier_info::is_optional_own: - q.qualifier = qualifier_info::is_own; - break; - case qualifier_info::is_optional_const: - q.qualifier = qualifier_info::is_const; - break; - case qualifier_info::is_optional_const_own: - q.qualifier = qualifier_info::is_const_own; - break; - default: - break; - } -} -inline void remove_own(qualifier_def& q) -{ - switch (q.qualifier) - { - case qualifier_info::is_own: - q.qualifier = qualifier_info::is_none; - break; - case qualifier_info::is_const_own: - q.qualifier = qualifier_info::is_const; - break; - case qualifier_info::is_optional_own: - q.qualifier = qualifier_info::is_optional; - break; - case qualifier_info::is_optional_const_own: - q.qualifier = qualifier_info::is_optional_const; - break; - default: - break; - } -} - -inline bool is_optional(qualifier_def const& i) -{ - return is_optional(i.qualifier); -} -inline bool is_own(qualifier_def const& i) -{ - return is_own(i.qualifier); -} -inline bool is_const(qualifier_def const& i) -{ - return is_const(i.qualifier); -} - - -} } } } +using attributes::qualifier_info; +} } } #endif diff --git a/src/lib/eolian_cxx/grammar/type.hpp b/src/lib/eolian_cxx/grammar/type.hpp index c2719c35c1..8a09b6e199 100644 --- a/src/lib/eolian_cxx/grammar/type.hpp +++ b/src/lib/eolian_cxx/grammar/type.hpp @@ -12,29 +12,50 @@ struct visitor_generate; struct type_generator { + type_generator(bool is_return = false) + : is_return(is_return) {} + template bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const { - return type.original_type.visit(visitor_generate{sink, &context, type.c_type, false}); + return type.original_type.visit(visitor_generate{sink, &context, type.c_type, false, is_return}); } template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { return param.type.original_type.visit(visitor_generate{sink, &context, param.c_type - , param.direction != attributes::parameter_direction::in}); + , param.direction != attributes::parameter_direction::in, false}); } + + bool is_return; }; +struct type_terminal +{ + type_generator const operator()(bool is_return) const + { + return type_generator(is_return); + } +} const type = {}; + +type_generator const as_generator(type_terminal) +{ + return type_generator{}; +} + template <> struct is_eager_generator : std::true_type {}; +template <> +struct is_generator : std::true_type {}; namespace type_traits { template <> struct attributes_needed : std::integral_constant {}; +template <> +struct attributes_needed : std::integral_constant {}; } -type_generator const type = {}; - + } } } #endif diff --git a/src/lib/eolian_cxx/grammar/type_impl.hpp b/src/lib/eolian_cxx/grammar/type_impl.hpp index 7eda7ad47d..2e75e126a4 100644 --- a/src/lib/eolian_cxx/grammar/type_impl.hpp +++ b/src/lib/eolian_cxx/grammar/type_impl.hpp @@ -9,52 +9,6 @@ namespace efl { namespace eolian { namespace grammar { -namespace detail { - -bool has_own(attributes::regular_type_def const& def) -{ - for(auto&& c : def.pointers) - if(is_own(c.qualifier)) - return true; - return false; -} - -} - -namespace detail { - -struct swap_pointers_visitor -{ - std::vector* pointers; - typedef void result_type; - template - void operator()(T& object) const - { - std::swap(*pointers, object.pointers); - } - void operator()(attributes::complex_type_def& complex) const - { - (*this)(complex.outer); - } -}; - -template -bool generate_pointers(OutputIterator sink, std::vector const& pointers, Context const& - , bool no_reference) -{ - for(auto first = pointers.rbegin() - , last = pointers.rend(); first != last; ++first) - { - if(std::next(first) == last && first->reference && !no_reference) - *sink++ = '&'; - else - *sink++ = '*'; - } - return true; -} - -} - template T const* as_const_pointer(T* p) { return p; } @@ -90,6 +44,7 @@ struct visitor_generate Context const* context; std::string c_type; bool is_out; + bool is_return; typedef visitor_generate visitor_type; typedef bool result_type; @@ -105,14 +60,8 @@ struct visitor_generate } const match_table[] = { - {"void_ptr", nullptr, [&] - { - std::vector pointers = regular.pointers; - pointers.insert(pointers.begin(), {{}, false}); - return attributes::regular_type_def{"void", regular.base_qualifier, pointers, {}}; - }} // signed primitives - , {"byte", nullptr, [&] { return replace_base_type(regular, " char"); }} + {"byte", nullptr, [&] { return replace_base_type(regular, " char"); }} , {"llong", nullptr, [&] { return replace_base_type(regular, " long long"); }} , {"int8", nullptr, [&] { return replace_base_type(regular, " int8_t"); }} , {"int16", nullptr, [&] { return replace_base_type(regular, " int16_t"); }} @@ -133,25 +82,42 @@ struct visitor_generate , {"ptrdiff", nullptr, [&] { return replace_base_type(regular, " ptrdiff_t"); }} , {"intptr", nullptr, [&] { return replace_base_type(regular, " intptr_t"); }} - , {"string", true, [&] { return replace_base_type(regular, " ::std::string"); }} - , {"string", false, [&] { return replace_base_type(regular, " ::efl::eina::string_view"); }} + , {"string", true, [&] + { + regular_type_def r = regular; + r.base_qualifier.qualifier ^= qualifier_info::is_ref; + if(is_out || is_return) + return replace_base_type(r, " ::std::string"); + else return replace_base_type(r, " ::efl::eina::string_view"); + }} + , {"string", false, [&] + { + regular_type_def r = regular; + r.base_qualifier.qualifier ^= qualifier_info::is_ref; + return replace_base_type(r, " ::efl::eina::string_view"); + }} , {"generic_value", nullptr, [&] - { return regular_type_def{" ::efl::eina::value", regular.base_qualifier - , {regular.pointers.empty() - || (regular.pointers.size() == 1 && regular.pointers[0].reference) - ? regular.pointers - : std::vector - {regular.pointers.begin(), std::prev(regular.pointers.end())}} - , {}}; + { return regular_type_def{" ::efl::eina::value", regular.base_qualifier, {}}; }} }; - - if(eina::optional b = call_match + if(regular.base_type == "void_ptr") + { + if(regular.base_qualifier & qualifier_info::is_ref) + throw std::runtime_error("ref of void_ptr is invalid"); + return as_generator + ( + lit("void") << (regular.base_qualifier & qualifier_info::is_const ? " const" : "") + << "*" + << (is_out ? "&" : "") + ) + .generate(sink, attributes::unused, *context); + } + else if(eina::optional b = call_match (match_table , [&] (match const& m) { return (!m.name || *m.name == regular.base_type) - && (!m.has_own || *m.has_own == is_own(regular.base_qualifier)) + && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own)) ; } , [&] (attributes::type_def::variant_type const& v) @@ -161,94 +127,83 @@ struct visitor_generate { return *b; } - else if(attributes::is_optional(regular.base_qualifier)) + // in A @optional -> optional + // in A& @optional -> optional + // in A& @optional -> optional + // in own(A&) @optional -> A* + // + // out A @optional -> optional + // out A& @optional -> optional + // out own(A&) @optional -> optional + else if(regular.base_qualifier & qualifier_info::is_optional) { - if(regular.pointers.empty() || (regular.pointers.size() == 1 && regular.pointers[0].reference == true)) - { - attributes::complex_type_def def - {attributes::regular_type_def{" ::efl::eina::optional", {}}}; - attributes::regular_type_def no_optional_regular = regular; - attributes::remove_optional(no_optional_regular.base_qualifier); - - def.subtypes.push_back({no_optional_regular, c_type}); - return (*this)(def); - } - else - { - attributes::regular_type_def no_optional_regular = regular; - attributes::remove_optional(no_optional_regular.base_qualifier); - no_optional_regular.pointers[0].reference = 0; - return (*this)(no_optional_regular); - } - } - // else if(detail::has_own(regular) && !regular.pointers.empty()) - // { - // attributes::complex_type_def def - // {attributes::regular_type_def{" ::efl::eolian::own_ptr", attributes::qualifier_info::is_none, {}}}; - - // attributes::complex_type_def tagged_def - // {attributes::regular_type_def{" ::efl::eolian::own", attributes::qualifier_info::is_none, {}}}; - - // auto pointer_iterator = regular.pointers.begin() - // , pointer_last = regular.pointers.end(); - - // for(;pointer_iterator != pointer_last && !attributes::is_own(pointer_iterator->qualifier) - // ;++pointer_iterator) - // { - // tagged_def.outer.pointers.push_back(*pointer_iterator); - // tagged_def.outer.pointers.front().reference = false; - // } - - // assert(attributes::is_own(pointer_iterator->qualifier)); - - // attributes::regular_type_def base_type (regular); - // base_type.pointers.clear(); - - // for(;pointer_iterator != pointer_last; ++pointer_iterator) - // { - // base_type.pointers.insert(base_type.pointers.begin(), *pointer_iterator); - // attributes::remove_own(base_type.pointers.back().qualifier); - // } - - // tagged_def.subtypes.push_back({base_type, c_type}); - // def.subtypes.push_back({tagged_def, c_type}); - // return (*this)(def); - // } - else if(detail::has_own(regular) && !regular.pointers.empty()) - { - attributes::regular_type_def pointee = regular; - std::vector pointers; - std::swap(pointers, pointee.pointers); - pointers.erase(pointers.begin()); - - attributes::pointer_indirection reference {{attributes::qualifier_info::is_none,{}}, true}; - - return as_generator(" ::std::unique_ptr<" << type).generate - (sink, attributes::type_def{pointee, c_type}, *context) - && detail::generate_pointers(sink, pointers, *context, true) - && as_generator(", void(*)(const void*)>").generate(sink, attributes::unused, *context) - && (!is_out || detail::generate_pointers(sink, {reference}, *context, false)); - } - else - { - auto pointers = regular.pointers; + attributes::regular_type_def no_optional_regular = regular; + no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_optional; if(is_out) - pointers.push_back({{attributes::qualifier_info::is_none,{}}, true}); - if(as_generator(*(string << "_") << string << (is_const(regular.base_qualifier)? " const" : "")) - .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context)) - return detail::generate_pointers(sink, pointers, *context - , regular.base_type == "void"); + { + if(no_optional_regular.base_qualifier & qualifier_info::is_own) + { + return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context) + && (*this)(no_optional_regular) + && as_generator("&>").generate(sink, attributes::unused, *context); + } + else if(no_optional_regular.base_qualifier & qualifier_info::is_ref) + { + no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_ref; + return (*this)(no_optional_regular) + && as_generator("**").generate(sink, attributes::unused, *context); + } + else + return (*this)(no_optional_regular) + && as_generator("*").generate(sink, attributes::unused, *context); + } else - return false; + { + // regular.base_qualifier & qualifier_info::is_ref + return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context) + && (*this)(no_optional_regular) + && as_generator(">").generate(sink, attributes::unused, *context); + } } + else if((is_return || is_out) && regular.base_qualifier & qualifier_info::is_ref + && regular.base_qualifier & qualifier_info::is_own) + { + if(as_generator + ( + " ::std::unique_ptr<" + << *(string << "_") + << string + << (regular.base_qualifier & qualifier_info::is_const ? " const" : "") + << ", ::efl::eina::malloc_deleter>" + ) + .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context)) + return true; + else + return false; + } + else + { + if(as_generator + ( + *(string << "_") + << string + << (regular.base_qualifier & qualifier_info::is_const + || (regular.base_qualifier & qualifier_info::is_ref + && !is_return && !is_out) + ? " const" : "") + << (regular.base_qualifier & qualifier_info::is_ref? "&" : "") + ) + .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context)) + return true; + else + return false; + } } bool operator()(attributes::klass_name klass) const { - if(is_out) - klass.pointers.push_back({{attributes::qualifier_info::is_none, {}}, true}); if(as_generator(" " << *("::" << lower_case[string]) << "::" << string) .generate(sink, std::make_tuple(attributes::cpp_namespaces(klass.namespaces), klass.eolian_name), *context)) - return detail::generate_pointers(sink, klass.pointers, *context, false); + return true; else return false; } @@ -286,26 +241,25 @@ struct visitor_generate }} , {"hash", nullptr, nullptr , [&] - { regular_type_def r{"Eina_Hash", complex.outer.base_qualifier, complex.outer.pointers, {}}; - r.pointers.push_back({{qualifier_info::is_none, {}}, false}); + { regular_type_def r{"Eina_Hash*", complex.outer.base_qualifier, {}}; return r; }} , {"promise", nullptr, nullptr, [&] { return replace_outer - (complex, regular_type_def{" ::efl::eina::future", complex.outer.base_qualifier, {}, {}}); + (complex, regular_type_def{" ::efl::eina::future", complex.outer.base_qualifier, {}}); } } , {"iterator", nullptr, nullptr, [&] { return replace_outer - (complex, regular_type_def{" ::efl::eina::iterator", complex.outer.base_qualifier, {}, {}}); + (complex, regular_type_def{" ::efl::eina::iterator", complex.outer.base_qualifier, {}}); } } , {"accessor", nullptr, nullptr, [&] { return replace_outer - (complex, regular_type_def{" ::efl::eina::accessor", complex.outer.base_qualifier, {}, {}}); + (complex, regular_type_def{" ::efl::eina::accessor", complex.outer.base_qualifier, {}}); } } }; @@ -313,13 +267,14 @@ struct visitor_generate auto default_match = [&] (attributes::complex_type_def const& complex) { regular_type_def no_pointer_regular = complex.outer; - std::vector pointers; - pointers.swap(no_pointer_regular.pointers); - if(is_out) - pointers.push_back({{attributes::qualifier_info::is_none, {}}, true}); + // std::vector pointers; + // pointers.swap(no_pointer_regular.pointers); + // if(is_out) + // pointers.push_back({{attributes::qualifier_info::is_none, {}}, true}); return visitor_type{sink, context, c_type, false}(no_pointer_regular) && as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context) - && detail::generate_pointers(sink, pointers, *context, false); + ; + // && detail::generate_pointers(sink, pointers, *context, false); }; if(eina::optional b = call_match @@ -327,8 +282,8 @@ struct visitor_generate , [&] (match const& m) { return (!m.name || *m.name == complex.outer.base_type) - && (!m.has_own || *m.has_own == is_own(complex.outer.base_qualifier)) - && (!m.is_const || *m.is_const == is_const(complex.outer.base_qualifier)); + && (!m.has_own || *m.has_own == bool(complex.outer.base_qualifier & qualifier_info::is_own)) + && (!m.is_const || *m.is_const == bool(complex.outer.base_qualifier & qualifier_info::is_const)); } , [&] (attributes::type_def::variant_type const& v) { diff --git a/src/tests/eolian_cxx/complex.eo b/src/tests/eolian_cxx/complex.eo index d7672e7182..626298a2e4 100644 --- a/src/tests/eolian_cxx/complex.eo +++ b/src/tests/eolian_cxx/complex.eo @@ -30,22 +30,22 @@ class Complex (Eo.Base) } incontcont { params { - l: list>; + l: list>; } } incontcontown { params { - l: own(list>); + l: own(list>); } } incontowncontown { params { - l: own(list)>); + l: own(list)>); } } incontowncont { params { - l: list)>; + l: list)>; } } instringcont { @@ -63,14 +63,140 @@ class Complex (Eo.Base) l: own(list); } } - + inarray { + params { + l: array; + } + } + inarrayown { + params { + l: own(array); + } + } + inhash { + params { + l: hash; + } + } + inhashown { + params { + l: own(hash); + } + } + initerator { + params { + l: iterator; + } + } + initeratorown { + params { + l: own(iterator); + } + } + inaccessor { + params { + l: accessor; + } + } + inaccessorown { + params { + l: own(accessor); + } + } + // out + outptrcont { + params { + @out l: list; + } + } + outclasscont { + params { + @out l: list; + } + } + outcontcont { + params { + @out l: list>; + } + } + outcontcontown { + params { + @out l: own(list>); + } + } + outcontowncontown { + params { + @out l: own(list)>); + } + } + outcontowncont { + params { + @out l: list)>; + } + } + outstringcont { + params { + @out l: list; + } + } + outstringowncont { + params { + @out l: list; + } + } + outstringcontown { + params { + @out l: own(list); + } + } + outarray { + params { + @out l: array; + } + } + outarrayown { + params { + @out l: own(array); + } + } + outhash { + params { + @out l: hash; + } + } + outhashown { + params { + @out l: own(hash); + } + } + outiterator { + params { + @out l: iterator; + } + } + outiteratorown { + params { + @out l: own(iterator); + } + } + outaccessor { + params { + @out l: accessor; + } + } + outaccessorown { + params { + @out l: own(accessor); + } + } + // foo { params { - l: list; + l: list; } } bar { - return: array; + return: array; } wrapper_r { return: Complex; diff --git a/src/tests/eolian_cxx/complex_cxx.cc b/src/tests/eolian_cxx/complex_cxx.cc index 72f4608b7f..91f8017e6a 100644 --- a/src/tests/eolian_cxx/complex_cxx.cc +++ b/src/tests/eolian_cxx/complex_cxx.cc @@ -37,12 +37,8 @@ struct test_param_type static_assert(std::is_same::value, "Wrong type"); }; -test_param_type> inptrcont; test_param_type> inclasscont; -test_param_type> inptrptrcont; -test_param_typeconst&> inptrcontown; -test_param_typeconst&> inptrptrcontown; -test_param_type>> incontont; +test_param_type>> incontcont; test_param_type>const&> incontcontown; test_param_type>const&> incontowncontown; test_param_type>> incontowncont; @@ -50,6 +46,15 @@ test_param_type> instringowncont; test_param_typeconst&> instringcontown; +test_param_type&> outclasscont; +test_param_type>&> outcontcont; +test_param_type>&> outcontcontown; +test_param_type>&> outcontowncontown; +test_param_type>&> outcontowncont; +test_param_type&> outstringcont; +test_param_type&> outstringowncont; +test_param_type&> outstringcontown; + test_param_type> foo; test_return_type> bar; test_return_type wrapper_r; diff --git a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc index 83cb394658..c9ee5c8e9b 100644 --- a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc +++ b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc @@ -11,7 +11,7 @@ START_TEST(eolian_cxx_test_binding_constructor_only_required) { - efl::eo::eo_init i; + efl::eo::eo_init init; nonamespace::Generic g ( @@ -54,65 +54,6 @@ START_TEST(eolian_cxx_test_type_generation) efl::eo::eo_init eo_init; name1::name2::Type_Generation g; - - g.invoidptr(nullptr); - g.inint(42); - std::unique_ptr i (new int(42)); - g.inintptr(i.get()); - { - int* p = (int*)malloc(sizeof(int)); - *p = 42; - std::unique_ptr inintptrown(p, (void(*)(const void*))&free); - g.inintptrown(std::move(inintptrown)); - } - { - int** p = (int**)malloc(sizeof(int*)); - *p = (int*)malloc(sizeof(int)); - **p = 42; - std::unique_ptr inintptrownptr(p, (void(*)(const void*))&free); - g.inintptrownptr(std::move(inintptrownptr)); - } - { - int*** p = (int***)malloc(sizeof(int**)); - *p = (int**)malloc(sizeof(int*)); - **p = (int*)malloc(sizeof(int)); - ***p = 42; - std::unique_ptr inintptrownptrptr(p, (void(*)(const void*))&free); - g.inintptrownptrptr(std::move(inintptrownptrptr)); - } - { - int*** p = (int***)malloc(sizeof(int**)); - *p = (int**)malloc(sizeof(int*)); - **p = (int*)malloc(sizeof(int)); - ***p = 42; - std::unique_ptr inintptrptrownptr(p, (void(*)(const void*))&free); - g.inintptrptrownptr(std::move(inintptrptrownptr)); - } - { - int* p = (int*)malloc(sizeof(int)); - *p = 42; - std::unique_ptr inintptrownfree(p, (void(*)(const void*))&free); - g.inintptrownfree(std::move(inintptrownfree)); - } - g.instring("foobar"); - // { - // efl::eina::string_view v("foobar"); - // g.instringptr(&v); - // } - g.instringown("foobar"); - // { - // std::string v("foobar"); - // g.instringptrown(&v); - // } - // { - // std::unique_ptr v - // ((efl::eina::string_view*)malloc(sizeof(string_view)), (void(*)(const void*))&free); - // g.instringptrown(v); - // } - // { - // std::string v("foobar"); - // g.instringptrown(&v); - // } } END_TEST @@ -121,6 +62,101 @@ START_TEST(eolian_cxx_test_type_generation_in) efl::eo::eo_init i; name1::name2::Type_Generation g; + + int v = 42; + g.inrefint(v); + g.inrefintown(42); + g.inrefintownfree(42); + g.invoidptr(nullptr); + g.inint(42); + g.inintptr(42); + g.inintptrown(42); + g.inintptrownfree(42); + g.instring("foobar"); + g.instringown("foobar"); +} +END_TEST + +START_TEST(eolian_cxx_test_type_generation_return) +{ + efl::eo::eo_init i; + + name1::name2::Type_Generation g; + + { + int&i = g.returnrefint(); + ck_assert(i == 42); + } + { + int i = g.returnint(); + ck_assert(i == 42); + } + { + void* p = g.returnvoidptr(); + ck_assert(*(int*)p == 42); + } + { + int& p = g.returnintptr(); + ck_assert(p == 42); + } + { + efl::eina::unique_malloc_ptr p = g.returnintptrown(); + ck_assert(*p == 42); + } + { + efl::eina::string_view string = g.returnstring(); + ck_assert_str_eq(string.c_str(), "foobar"); + } + { + std::string string = g.returnstring(); + ck_assert_str_eq(string.c_str(), "foobar"); + } +} +END_TEST + +START_TEST(eolian_cxx_test_type_generation_optional) +{ + efl::eo::eo_init init; + + using efl::eina::optional; + + name1::name2::Type_Generation g; + + g.optionalinvoidptr(NULL); + g.optionalinvoidptr(&g); + g.optionalinvoidptr(nullptr); + + int i = 42; + g.optionalinint(nullptr); + g.optionalinint(i); + + g.optionalinintptr(i); + g.optionalinintptr(nullptr); + + g.optionalinintptrown(i); + g.optionalinintptrown(nullptr); + + g.optionalinintptrownfree(i); + g.optionalinintptrownfree(nullptr); + + i = 0; + g.optionaloutint(&i); + ck_assert(i == 42); + g.optionaloutint(nullptr); + + i = 0; + int* j = nullptr; + g.optionaloutintptr(&j); + ck_assert(j != nullptr); + ck_assert(*j == 42); + g.optionaloutintptr(nullptr); + + i = 0; + efl::eina::unique_malloc_ptr k = nullptr; + g.optionaloutintptrown(k); + ck_assert(!!k); + ck_assert(*k == 42); + g.optionaloutintptrown(nullptr); } END_TEST @@ -177,5 +213,7 @@ eolian_cxx_test_binding(TCase* tc) tcase_add_test(tc, eolian_cxx_test_binding_constructor_all_optionals); tcase_add_test(tc, eolian_cxx_test_type_generation); tcase_add_test(tc, eolian_cxx_test_type_generation_in); + tcase_add_test(tc, eolian_cxx_test_type_generation_return); + tcase_add_test(tc, eolian_cxx_test_type_generation_optional); tcase_add_test(tc, eolian_cxx_test_type_callback); } diff --git a/src/tests/eolian_cxx/generic.eo b/src/tests/eolian_cxx/generic.eo index 20f471ba83..c4a2257283 100644 --- a/src/tests/eolian_cxx/generic.eo +++ b/src/tests/eolian_cxx/generic.eo @@ -101,7 +101,7 @@ class Generic (Eo.Base) prefix,event1; prefix,event2: Generic; prefix,event3: int; - prefix,event4: list; + prefix,event4: list; prefix,event5: Generic.Event; } } diff --git a/src/tests/eolian_cxx/name1_name2_type_generation.c b/src/tests/eolian_cxx/name1_name2_type_generation.c index 28b8c853ad..9af748da7f 100644 --- a/src/tests/eolian_cxx/name1_name2_type_generation.c +++ b/src/tests/eolian_cxx/name1_name2_type_generation.c @@ -16,6 +16,23 @@ typedef struct _Type_Generation_Data Type_Generation_Data; #include "name1_name2_type_generation.eo.h" +void _name1_name2_type_generation_inrefint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int* v EINA_UNUSED) +{ + ck_assert(*v == 42); +} + +void _name1_name2_type_generation_inrefintown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int* v EINA_UNUSED) +{ + ck_assert(*v == 42); + free(v); +} + +void _name1_name2_type_generation_inrefintownfree(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int* v EINA_UNUSED) +{ + ck_assert(*v == 42); + free(v); +} + void _name1_name2_type_generation_invoidptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, void *v) { ck_assert(v == NULL); @@ -58,7 +75,8 @@ void _name1_name2_type_generation_inintptrownfree(Eo *obj EINA_UNUSED, Type_Gene void * _name1_name2_type_generation_returnvoidptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED) { - return NULL; + static int i = 42; + return &i; } void _name1_name2_type_generation_instring(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char *v EINA_UNUSED) @@ -70,6 +88,11 @@ void _name1_name2_type_generation_instringptr(Eo *obj EINA_UNUSED, Type_Generati { ck_assert_str_eq(*v, "foobar"); } +void _name1_name2_type_generation_instringptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char * *v) +{ + ck_assert_str_eq(*v, "foobar"); + free((void*)*v); +} void _name1_name2_type_generation_instringown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, const char *v EINA_UNUSED) { @@ -89,6 +112,11 @@ void _name1_name2_type_generation_instringownptr(Eo *obj EINA_UNUSED, Type_Gener free(v); } +int* _name1_name2_type_generation_returnrefint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED) +{ + static int i = 42; + return &i; +} int _name1_name2_type_generation_returnint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED) { return 42; @@ -96,12 +124,15 @@ int _name1_name2_type_generation_returnint(Eo *obj EINA_UNUSED, Type_Generation_ int * _name1_name2_type_generation_returnintptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED) { - return NULL; + static int i = 42; + return &i; } int * _name1_name2_type_generation_returnintptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED) { - return NULL; + int* i = malloc(sizeof(int)); + *i = 42; + return i; } int ** _name1_name2_type_generation_returnintptrownptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED) @@ -211,18 +242,29 @@ void _name1_name2_type_generation_optionaloutvoidptr(Eo *obj EINA_UNUSED, Type_G void _name1_name2_type_generation_optionaloutint(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int *v EINA_UNUSED) { + if(v) + *v = 42; } void _name1_name2_type_generation_optionaloutintptr(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED) { + static int i = 42; + if(v) + *v = &i; } void _name1_name2_type_generation_optionaloutintptrown(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED) { + int* i = malloc(sizeof(int)); + *i = 42; + if(v) *v = i; } void _name1_name2_type_generation_optionaloutintptrownfree(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, int **v EINA_UNUSED) { + int* i = malloc(sizeof(int)); + *i = 42; + if(v) *v = i; } void _name1_name2_type_generation_optionalinclassname(Eo *obj EINA_UNUSED, Type_Generation_Data *pd EINA_UNUSED, Name1_Name2_Type_Generation *v EINA_UNUSED) diff --git a/src/tests/eolian_cxx/name1_name2_type_generation.eo b/src/tests/eolian_cxx/name1_name2_type_generation.eo index 66b6461a81..e202423a08 100644 --- a/src/tests/eolian_cxx/name1_name2_type_generation.eo +++ b/src/tests/eolian_cxx/name1_name2_type_generation.eo @@ -2,10 +2,26 @@ class Name1.Name2.Type_Generation (Eo.Base) { data: Type_Generation_Data; methods { + // inref + inrefint { + params { + @in v: ref(int); + } + } + inrefintown { + params { + @in v: own(ref(int)); + } + } + inrefintownfree { + params { + @in v: free(own(ref(int)), free); + } + } // in void ptr invoidptr { params { - @in v: void*; + @in v: void_ptr; } } inint { @@ -15,32 +31,17 @@ class Name1.Name2.Type_Generation (Eo.Base) } inintptr { params { - @in v: int*; + @in v: ref(int); } } inintptrown { params { - @in v: own(int*); - } - } - inintptrownptr { - params { - @in v: own(int*)*; - } - } - inintptrownptrptr { - params { - @in v: own(int*)**; - } - } - inintptrptrownptr { - params { - @in v: own(int**)*; + @in v: own(ref(int)); } } inintptrownfree { params { - @in v: free(own(int*), free); + @in v: free(own(ref(int)), free); } } instring { @@ -48,72 +49,58 @@ class Name1.Name2.Type_Generation (Eo.Base) @in v: string; } } - /* instringptr { params { - @in v: string*; + @in v: ref(string); } - }*/ + } instringown { params { @in v: own(string); } } - /* no sense instringptrown { params { - @in v: own(string*); + @in v: own(ref(string)); } } - instringownptrown { - params { - @in v: own(own(string)*); - } - }*/ // return + returnrefint { + return: ref(int); + } returnvoidptr { - return: void*; + return: void_ptr; } returnint { return: int; } returnintptr { - return: int*; + return: ref(int); } returnintptrown { - return: own(int*); - } - returnintptrownptr { - return: own(int*)*; - } - returnintptrownptrptr { - return: own(int*)**; - } - returnintptrptrownptr { - return: own(int**)*; + return: own(ref(int)); } returnintptrownfree { params { - @in v: free(own(int*), free); + @in v: free(own(ref(int)), free); } } returnstring { return: string; } returnstringptr { - return: string*; + return: ref(string); } returnstringown { return: own(string); } returnstringownptr { - return: own(string*); + return: own(ref(string)); } - // out outvoidptr { params { - @out v: void*; + @out v: void_ptr; } } outint { @@ -123,17 +110,17 @@ class Name1.Name2.Type_Generation (Eo.Base) } outintptr { params { - @out v: int*; + @out v: ref(int); } } outintptrown { params { - @out v: own(int*); + @out v: own(ref(int)); } } outintptrownfree { params { - @out v: free(own(int*), free); + @out v: free(own(ref(int)), free); } } inclassname { @@ -153,7 +140,7 @@ class Name1.Name2.Type_Generation (Eo.Base) } optionalinvoidptr { params { - @in v: void* @optional; + @in v: void_ptr @optional; } } optionalinint { @@ -163,22 +150,22 @@ class Name1.Name2.Type_Generation (Eo.Base) } optionalinintptr { params { - @in v: int* @optional; + @in v: ref(int) @optional; } } optionalinintptrown { params { - @in v: own(int*) @optional; + @in v: own(ref(int)) @optional; } } optionalinintptrownfree { params { - @in v: free(own(int*), free) @optional; + @in v: free(own(ref(int)), free) @optional; } } optionaloutvoidptr { params { - @out v: void* @optional; + @out v: void_ptr @optional; } } optionaloutint { @@ -188,17 +175,17 @@ class Name1.Name2.Type_Generation (Eo.Base) } optionaloutintptr { params { - @out v: int* @optional; + @out v: ref(int) @optional; } } optionaloutintptrown { params { - @out v: own(int*) @optional; + @out v: own(ref(int)) @optional; } } optionaloutintptrownfree { params { - @out v: free(own(int*), free) @optional; + @out v: free(own(ref(int)), free) @optional; } } optionalinclassname {