eolian-cxx: Add support for ref parameters and correct ownership handling
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Wed, 8 Jun 2016 20:31:46 +0000 (17:31 -0300)
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Wed, 15 Jun 2016 01:44:02 +0000 (22:44 -0300)
22 files changed:
src/bindings/cxx/eina_cxx/Eina.hh
src/bindings/cxx/eina_cxx/eina_accessor.hh
src/bindings/cxx/eina_cxx/eina_deleter.hh [new file with mode: 0644]
src/bindings/cxx/eina_cxx/eina_ptrarray.hh
src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
src/lib/eolian_cxx/grammar/attribute_conditional.hpp
src/lib/eolian_cxx/grammar/c_type.hpp
src/lib/eolian_cxx/grammar/container.hpp
src/lib/eolian_cxx/grammar/converting_argument.hpp
src/lib/eolian_cxx/grammar/function_declaration.hpp
src/lib/eolian_cxx/grammar/function_definition.hpp
src/lib/eolian_cxx/grammar/klass_def.hpp
src/lib/eolian_cxx/grammar/parameter.hpp
src/lib/eolian_cxx/grammar/qualifier_def.hpp
src/lib/eolian_cxx/grammar/type.hpp
src/lib/eolian_cxx/grammar/type_impl.hpp
src/tests/eolian_cxx/complex.eo
src/tests/eolian_cxx/complex_cxx.cc
src/tests/eolian_cxx/eolian_cxx_test_binding.cc
src/tests/eolian_cxx/generic.eo
src/tests/eolian_cxx/name1_name2_type_generation.c
src/tests/eolian_cxx/name1_name2_type_generation.eo

index c8717a6..c986815 100644 (file)
@@ -25,6 +25,7 @@
 #include <eina_pp.hh>
 #include <eina_workarounds.hh>
 #include <eina_future.hh>
+#include <eina_deleter.hh>
 
 /**
  * @page eina_cxx_main Eina C++ (BETA)
index 800c3fa..33046a3 100644 (file)
@@ -215,6 +215,7 @@ struct accessor<T, typename std::enable_if< ! std::is_base_of<::efl::eo::concret
   _self_type& operator=(_self_type const& other)
   {
     _base_type::operator=(other);
+    return *this;
   }
 
   /**
diff --git a/src/bindings/cxx/eina_cxx/eina_deleter.hh b/src/bindings/cxx/eina_cxx/eina_deleter.hh
new file mode 100644 (file)
index 0000000..65f8da0
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef EINA_DELETERS_HH_
+#define EINA_DELETERS_HH_
+
+#include <eina_workarounds.hh>
+
+namespace efl { namespace eina {
+
+struct malloc_deleter
+{
+  template <typename T>
+  void operator()(T* object) const
+  {
+    object->~T();
+    free(object);
+  }
+};
+
+template <typename T>
+using unique_malloc_ptr = std::unique_ptr<T, malloc_deleter>;
+    
+} }
+
+#endif
index f47202e..b5de9d7 100644 (file)
@@ -516,6 +516,12 @@ public:
     insert(end(), other.begin(), other.end());
   }
 
+  ptr_array(ptr_array<T, CloneAllocator>&& 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<T, CloneAllocator>& operator=(ptr_array<T, CloneAllocator>&& other)
+  {
+    clear();
+    std::swap(other._impl._array, this->_impl._array);
+    return *this;
+  }
+  
   /**
    * @brief Remove all the elements of the array.
    */
index f90e4f7..bd7a883 100644 (file)
@@ -39,35 +39,45 @@ template <typename T>
 struct in_traits<eina::range_array<T>> { typedef eina::range_array<T> type; };
     
 template <typename T>
-struct out_traits { typedef T type; };
+struct out_traits { typedef T& type; };
+template <typename T>
+struct out_traits<T*> { typedef T* type; };
+template <>
+struct out_traits<Eina_Hash*> { typedef Eina_Hash*& type; };
+template <typename T>
+struct out_traits<eina::optional<T&>> { typedef eina::optional<T&> type; };
+template <>
+struct out_traits<void*> { typedef void*& type; };
 template <typename T>
 struct out_traits<efl::eina::future<T>> { typedef efl::eina::future<T>& type; };
 
 template <typename T>
-struct inout_traits { typedef T type; };
+struct inout_traits { typedef T& type; };
 template <typename T>
 struct inout_traits<efl::eina::future<T>> { typedef efl::eina::future<T>& type; };
 
+template <typename To, typename From, bool Own = false, typename Lhs, typename Rhs>
+void assign_out(Lhs& lhs, Rhs& rhs);
+  
 namespace impl {
 
-template <typename From, typename To>
+template <typename From, typename To, bool Own = false>
 struct tag
 {
   typedef To to;
   typedef From from;
+  typedef std::integral_constant<bool, Own> own;
 };
   
-template <typename To, typename From, typename Lhs, typename Rhs>
-void assign_out(Lhs& lhs, Rhs& rhs);
-  
 template <typename T>
-void assign_out_impl(T*& lhs, T& rhs, tag<T*, T>)
+void assign_out_impl(T& lhs, T*& rhs, tag<T&, T*>)
 {
-  *lhs = rhs;
+  lhs = *rhs;
 }
-template <typename U, typename T>
-void assign_out_impl(std::unique_ptr<T, void(*)(const void*)>& lhs, U* rhs, tag<std::unique_ptr<T, void(*)(const void*)>&, U*>)
+template <typename U, typename T, typename D>
+void assign_out_impl(std::unique_ptr<T, D>& lhs, U* rhs, tag<std::unique_ptr<T, D>&, U*, true>)
 {
+  // with own
   lhs.reset(rhs);
 }
 template <typename Tag>
@@ -101,31 +111,23 @@ void assign_out_impl(efl::eina::string_view& view, const char* string, Tag)
 {
   view = {string};
 }
-template <typename T, typename Rhs, typename U, typename O>
-void assign_out_impl(efl::eina::optional<T>& lhs, Rhs*& rhs, tag<efl::eina::optional<U>&, O>)
-{
-  if(rhs)
-    assign_out<U, O>(*lhs, rhs);
-  else
-    lhs.disengage();
-}
-template <typename T, typename Rhs, typename U, typename O>
-void assign_out_impl(efl::eina::optional<T>& lhs, Rhs& rhs, tag<efl::eina::optional<U>&, O>)
+template <typename Tag>
+void assign_out_impl(efl::eina::string_view* view, const char* string, Tag)
 {
-  assign_out<U, O>(*lhs, rhs);
+  if(view)
+    *view = {string};
 }
-template <typename T, typename Rhs, typename U, typename O>
-void assign_out_impl(efl::eina::optional<T>& lhs, Rhs*& rhs, tag<efl::eina::optional<U>, O>)
+template <typename T>
+void assign_out_impl(T*& lhs, T& rhs, tag<T*, T>) // optional
 {
-  if(rhs)
-    assign_out<U, O>(*lhs, rhs);
-  else
-    lhs.disengage();
+  if(lhs)
+    *lhs = rhs;
 }
-template <typename T, typename Rhs, typename U, typename O>
-void assign_out_impl(efl::eina::optional<T>& lhs, Rhs& rhs, tag<efl::eina::optional<U>, O>)
+template <typename T, typename Rhs, typename U, typename O, bool B>
+void assign_out_impl(efl::eina::optional<T>& lhs, Rhs& rhs, tag<efl::eina::optional<U&>, O, B>)
 {
-  assign_out<U, O>(*lhs, rhs);
+  if(lhs)
+    assign_out<U&, O, true>(*lhs, rhs);
 }
 template <typename Tag>
 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 <typename T, typename Tag>
-void assign_out_impl(efl::eina::list<T>& lhs, Eina_List* rhs, Tag)
+template <typename T>
+void assign_out_impl(efl::eina::list<T>& lhs, Eina_List* rhs, tag<efl::eina::list<T>&, Eina_List*, true>)
 {
   lhs = efl::eina::list<T>{rhs};
 }
+template <typename T>
+void assign_out_impl(efl::eina::range_list<T>& lhs, Eina_List* rhs, tag<efl::eina::range_list<T>&, Eina_List*>)
+{
+  lhs = efl::eina::range_list<T>{rhs};
+}
+template <typename T>
+void assign_out_impl(efl::eina::array<T>& lhs, Eina_Array* rhs, tag<efl::eina::array<T>&, Eina_Array*, true>)
+{
+  lhs = efl::eina::array<T>{rhs};
+}
+template <typename T>
+void assign_out_impl(efl::eina::range_array<T>& lhs, Eina_Array* rhs, tag<efl::eina::range_array<T>&, Eina_Array*>)
+{
+  lhs = efl::eina::range_array<T>{rhs};
+}
+inline void assign_out_impl(Eina_Hash*& lhs, Eina_Hash*& rhs, tag<Eina_Hash*&, Eina_Hash*, true>)
+{
+  lhs = rhs;
+}
+template <typename T>
+void assign_out_impl(efl::eina::iterator<T>& /*lhs*/, Eina_Iterator* /*rhs*/, tag<efl::eina::iterator<T>&, Eina_Iterator*>)
+{
+  // Must copy here
+  std::abort();
+}
+template <typename T>
+void assign_out_impl(efl::eina::iterator<T>& lhs, Eina_Iterator* rhs, tag<efl::eina::iterator<T>&, Eina_Iterator*, true>)
+{
+  lhs = efl::eina::iterator<T>{rhs};  
+}
+template <typename T>
+void assign_out_impl(efl::eina::accessor<T>& lhs, Eina_Accessor* rhs, tag<efl::eina::accessor<T>&, Eina_Accessor*>)
+{
+  lhs = efl::eina::accessor<T>{ ::eina_accessor_clone(rhs) };
+}
+template <typename T>
+void assign_out_impl(efl::eina::accessor<T>& lhs, Eina_Accessor* rhs, tag<efl::eina::accessor<T>&, Eina_Accessor*, true>)
+{
+  lhs = efl::eina::accessor<T>{rhs};  
+}
 }
     
-template <typename To, typename From, typename Lhs, typename Rhs>
+template <typename To, typename From, bool Own, typename Lhs, typename Rhs>
 void assign_out(Lhs& lhs, Rhs& rhs)
 {
-  return impl::assign_out_impl(lhs, rhs, impl::tag<To, From>{});
+  return impl::assign_out_impl(lhs, rhs, impl::tag<To, From, Own>{});
 }
     
 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<From, To>{});
 }
     
-template <typename T, typename U, typename V>
+template <typename T, typename U, bool Own = false, typename V>
 T convert_to_c(V&& object);
     
 namespace impl {
@@ -198,6 +240,43 @@ auto convert_to_c_impl
 }
 
 template <typename T>
+T convert_to_c_impl(T& /*v*/, tag<T, T, true>)
+{
+  std::abort();
+}
+template <typename T>
+T* convert_to_c_impl(T& v, tag<T*, T&>)
+{
+  return &v;
+}
+template <typename T>
+T* convert_to_c_impl(T& v, tag<T*, T&, true>)
+{
+  std::abort();
+}
+template <typename T>
+T* convert_to_c_impl(T const& v, tag<T*, T const&>) // not own
+{
+  return const_cast<T*>(&v);
+}
+template <typename T>
+T* convert_to_c_impl(T const& v, tag<T*, T const&, true>) // with own
+{
+  T* r = static_cast<T*>(malloc(sizeof(T)));
+  *r = v;
+  return r;
+}
+template <typename T>
+T const* convert_to_c_impl(T& v, tag<T const*, T&>)
+{
+  return &v;
+}
+template <typename T>
+T const* convert_to_c_impl(T* v, tag<T const*, T*>)
+{
+  return v;
+}
+template <typename T>
 T const& convert_to_c_impl(T const& v, tag<T, T const&>)
 {
   return v;
@@ -209,15 +288,27 @@ Eo* convert_to_c_impl(T v, tag<Eo*, T>
   return v._eo_ptr();
 }
 template <typename T>
+Eo* convert_to_c_impl(T v, tag<Eo*, T, true>
+                      , typename std::enable_if<eo::is_eolian_object<T>::value>::type* = 0)
+{
+  return ::eo_ref(v._eo_ptr());
+}
+template <typename T>
 Eo const* convert_to_c_impl(T v, tag<Eo const*, T>
                             , typename std::enable_if<eo::is_eolian_object<T>::value>::type* = 0)
 {
-  return v._eo_ptr();
+  return const_cast<Eo const*>(v._eo_ptr());
 }
 inline const char* convert_to_c_impl( ::efl::eina::string_view v, tag<const char*, ::efl::eina::string_view>)
 {
   return v.c_str();
 }
+inline const char* convert_to_c_impl( ::efl::eina::string_view v, tag<const char*, ::efl::eina::string_view, true>)
+{
+  char* string = static_cast<char*>(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<const char **, efl::eina::string_view*>)
 {
   std::abort();
@@ -254,6 +345,18 @@ T convert_to_c_impl(efl::eina::optional<T> const& optional, tag<T, efl::eina::op
 {
   return optional ? *optional : T{};
 }
+template <typename T>
+T* convert_to_c_impl(efl::eina::optional<T const&>const& optional, tag<T*, efl::eina::optional<T const&>const&, true>)
+{
+  if(optional)
+    {
+      T* r = static_cast<T*>(malloc(sizeof(T)));
+      *r = *optional;
+      return r;
+    }
+  else
+    return nullptr;
+}
 template <typename U, typename T>
 U convert_to_c_impl(efl::eina::optional<T> const& optional, tag<U, efl::eina::optional<T>const&>)
 {
@@ -270,15 +373,16 @@ Eina_List const* convert_to_c_impl(efl::eina::range_list<T> range, tag<Eina_List
   return range.native_handle();
 }
 template <typename T>
-Eina_List* convert_to_c_impl(efl::eina::list<T>const& c, tag<Eina_List *, efl::eina::list<T>const&>)
+Eina_List* convert_to_c_impl(efl::eina::list<T>const& c, tag<Eina_List *, efl::eina::list<T>const&, true>)
 {
   return const_cast<Eina_List*>(c.native_handle());
 }
 template <typename T>
-Eina_List const* convert_to_c_impl(efl::eina::list<T>const& c, tag<Eina_List const *, efl::eina::list<T>const&>)
+Eina_List const* convert_to_c_impl(efl::eina::list<T>const& c, tag<Eina_List const *, efl::eina::list<T>const&, true>)
 {
   return c.native_handle();
 }
+
 template <typename T>
 Eina_Array* convert_to_c_impl(efl::eina::range_array<T> range, tag<Eina_Array *, efl::eina::range_array<T>>)
 {
@@ -290,23 +394,54 @@ Eina_Array const* convert_to_c_impl(efl::eina::range_array<T> range, tag<Eina_Ar
   return range.native_handle();
 }
 template <typename T>
-Eina_Array* convert_to_c_impl(efl::eina::array<T>const& c, tag<Eina_Array *, efl::eina::array<T>const&>)
+Eina_Array* convert_to_c_impl(efl::eina::array<T>const& c, tag<Eina_Array *, efl::eina::array<T>const&, true>)
 {
-  return c.native_handle();
+  return const_cast<Eina_Array*>(c.native_handle());
 }
 template <typename T>
-Eina_Array const* convert_to_c_impl(efl::eina::array<T>const& c, tag<Eina_Array const *, efl::eina::array<T>const&>)
+Eina_Array const* convert_to_c_impl(efl::eina::array<T>const& c, tag<Eina_Array const *, efl::eina::array<T>const&, true>)
 {
   return c.native_handle();
 }
+template <typename T>
+Eina_Iterator* convert_to_c_impl(efl::eina::iterator<T>const& i, tag<Eina_Iterator *, efl::eina::iterator<T>const&>)
+{
+  return const_cast<Eina_Iterator*>(i.native_handle());
+}
+template <typename T>
+Eina_Iterator const* convert_to_c_impl(efl::eina::iterator<T>const& i, tag<Eina_Iterator const*, efl::eina::iterator<T>const&>)
+{
+  return i.native_handle();
+}
+template <typename T>
+Eina_Iterator* convert_to_c_impl(efl::eina::iterator<T>const& /*i*/, tag<Eina_Iterator *, efl::eina::iterator<T>const&, true>)
+{
+  // Eina Iterator must be copied
+  std::abort();
+}
+template <typename T>
+Eina_Accessor* convert_to_c_impl(efl::eina::accessor<T>const& i, tag<Eina_Accessor *, efl::eina::accessor<T>const&>)
+{
+  return const_cast<Eina_Accessor*>(i.native_handle());
+}
+template <typename T>
+Eina_Accessor const* convert_to_c_impl(efl::eina::accessor<T>const& i, tag<Eina_Accessor const*, efl::eina::accessor<T>const&>)
+{
+  return i.native_handle();
+}
+template <typename T>
+Eina_Accessor* convert_to_c_impl(efl::eina::accessor<T>const& i, tag<Eina_Accessor *, efl::eina::accessor<T>const&, true>)
+{
+  return ::eina_accessor_clone(const_cast<Eina_Accessor*>(i.native_handle()));
+}
 inline const char** convert_to_c_impl(efl::eina::string_view /*view*/, tag<char const **, efl::eina::string_view>)
 {
   std::abort();
 }
-// inline const char* convert_to_c_impl(std::string const& x, tag<const char*, std::string>)
-// {
-//    return x.c_str();
-// }
+inline const char** convert_to_c_impl(efl::eina::string_view /*view*/, tag<char const **, efl::eina::string_view, true>)
+{
+  std::abort();
+}
 inline const char* convert_to_c_impl(efl::eina::stringshare x, tag<const char*, efl::eina::stringshare>)
 {
    return x.c_str();
@@ -321,7 +456,6 @@ T* convert_to_c_impl(std::unique_ptr<U, Deleter>& v, tag<T*, std::unique_ptr<U,
 {
   return convert_to_c<T*, U*>(v.release());
 }
-
 template <typename T>
 Eina_Array** convert_to_c_impl(efl::eina::array<T>& /*c*/, tag<Eina_Array **, efl::eina::array<T>&>)
 {
@@ -334,10 +468,10 @@ Eina_Array** convert_to_c_impl(efl::eina::range_array<T>& /*c*/, tag<Eina_Array
 }
 }
     
-template <typename T, typename U, typename V>
+template <typename T, typename U, bool Own, typename V>
 T convert_to_c(V&& object)
 {
-  return impl::convert_to_c_impl(std::forward<V>(object), impl::tag<T, U>{});
+  return impl::convert_to_c_impl(std::forward<V>(object), impl::tag<T, U, Own>{});
 }
 namespace impl {
 template <typename T>
@@ -389,6 +523,11 @@ T convert_to_return(T value, tag<T, T>)
   return value;
 }
 template <typename T>
+T& convert_to_return(T* value, tag<T*, T&>)
+{
+  return *value;
+}
+template <typename T>
 T convert_to_return(Eo* value, tag<Eo*, T>, typename std::enable_if< eo::is_eolian_object<T>::value>::type* = 0)
 {
   return T{value};
@@ -479,23 +618,46 @@ inline eina::string_view convert_to_return(const char* value, tag<const char*, e
 {
   return {value};
 }
+inline eina::string_view convert_to_return(const char** value, tag<const char**, efl::eina::string_view>)
+{
+  return {*value};
+}
 inline std::string convert_to_return(const char* value, tag<const char*, std::string>)
 {
-  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<const char**, std::string>)
+{
+  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<Eina_Bool, bool>)
 {
   return !!value;
 }
-template <typename T>
-std::unique_ptr<T, void(*)(const void*)> convert_to_return(T* value, tag<T*, std::unique_ptr<T, void(*)(const void*)>>)
+template <typename T, typename D>
+std::unique_ptr<T, D> convert_to_return(T* value, tag<T*, std::unique_ptr<T, D>>)
 {
-  return std::unique_ptr<T, void(*)(const void*)>{value, (void(*)(const void*))&free};
+  return std::unique_ptr<T, D>{value, {}};
 }
-template <typename T, typename U>
-std::unique_ptr<T, void(*)(const void*)> convert_to_return(U* value, tag<U*, std::unique_ptr<T, void(*)(const void*)>>)
+template <typename T, typename U, typename D>
+std::unique_ptr<T, D> convert_to_return(U* value, tag<U*, std::unique_ptr<T, D>>)
 {
-  return std::unique_ptr<T, void(*)(const void*)>{convert_to_return(value, tag<U*, T*>{}), (void(*)(const void*))&free};
+  return std::unique_ptr<T, D>{convert_to_return(value, tag<U*, T*>{}), {}};
 }
 }
 
index 8bf107a..886b1ed 100644 (file)
@@ -56,7 +56,10 @@ struct attribute_conditional_terminal
 
 namespace type_traits {
 template <typename F, typename G>
-struct attributes_needed<functional_attribute_conditional_generator<F, G>> : attributes_needed<G> {};  
+struct attributes_needed<functional_attribute_conditional_generator<F, G>>
+  : std::conditional<attributes_needed<G>::value
+                     , attributes_needed<G>
+                     , std::integral_constant<int, 1>>::type {};  
 template <typename F>
 struct attributes_needed<functional_attribute_conditional_directive<F>> : std::integral_constant<int, 1> {};  
 }
index e6a72fd..54b996d 100644 (file)
@@ -17,7 +17,7 @@ struct c_type_visitor
     as_generator(" ::" << *(string << "_") << string << string << "*")
       .generate(std::back_insert_iterator<std::string>(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;
   }
index 4612612..ca86044 100644 (file)
@@ -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 <typename T>
-  void operator()(T& /*x*/) const
-  {
-  }
-};
-      
 template <typename OutputIterator, typename Context>
 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);
     }
 }
index 4a2d959..3b5cb1d 100644 (file)
@@ -22,11 +22,15 @@ struct converting_argument_generator
    template <typename OutputIterator, typename Context>
    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);
    }
index a6aa439..f01c214 100644 (file)
@@ -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);
   }
 };
index 170fa98..b228027 100644 (file)
@@ -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))
index b42d6f2..0c5d820 100644 (file)
 #include <memory>
 #include <set>
 
-namespace efl { namespace eolian { namespace grammar { namespace attributes {
+namespace efl { namespace eolian { namespace grammar {
+
+namespace attributes {
+
+struct complex_type_def;
+  
+}
+
+namespace attributes {
 
 template <typename...Args, std::size_t I>
 bool lexicographical_compare_impl(std::tuple<Args...> const&
@@ -56,25 +64,6 @@ bool lexicographical_compare(std::tuple<T, U> 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<std::string> namespaces;
    std::string eolian_name;
    qualifier_def base_qualifier;
-   std::vector<pointer_indirection> pointers;
    class_type type;
 
    klass_name(std::vector<std::string> namespaces
               , std::string eolian_name, qualifier_def base_qualifier
-              , std::vector<pointer_indirection> 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<pointer_indirection> 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<const char> 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::tuple<std::vector<std::string>const&
                      , std::string const&
                      , qualifier_def const&
-                     , std::vector<pointer_indirection> 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<pointer_indirection> pointers;
    std::vector<std::string> 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<pointer_indirection> pointers;
-      template <typename T>
-      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 <typename T>
+  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<const char> 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<pointer_indirection> 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 <typename T>
   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_Function const> 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<void(Eolian_Class const*)> 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<Eolian_Event const> 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<attributes::parameter_def> : std::true_type {};
 template <>
 struct is_tuple<attributes::event_def> : std::true_type {};
   
-} } } }
+}
+
+} } }
 
 #endif
index f236841..b29805e 100644 (file)
@@ -7,20 +7,6 @@
 
 namespace efl { namespace eolian { namespace grammar {
 
-struct add_reference_visitor
-{
-   typedef void result_type;
-   template <typename T>
-   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 <typename OutputIterator, typename Context>
index 3ba1a89..b43b2f1 100644 (file)
@@ -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
 };
 
-inline qualifier_info qualifiers(Eolian_Type const* type)
+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)
 {
-  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;
+  return static_cast<qualifier_info>(static_cast<int>(lhs) | static_cast<int>(rhs));
 }
-        
-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 qualifier_bool operator&(qualifier_info lhs, qualifier_info rhs)
+{
+  return static_cast<qualifier_info>(static_cast<int>(lhs) & static_cast<int>(rhs));
 }
-
-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 qualifier_info operator^(qualifier_info lhs, qualifier_info rhs)
+{
+  return static_cast<qualifier_info>(static_cast<int>(lhs) & ~static_cast<int>(rhs));
 }
-        
-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;
-    }
+inline qualifier_info& operator|=(qualifier_info& lhs, qualifier_info rhs)
+{
+  lhs = static_cast<qualifier_info>(static_cast<int>(lhs) | static_cast<int>(rhs));
+  return lhs;
+}
+inline qualifier_info& operator&=(qualifier_info& lhs, qualifier_info rhs)
+{
+  lhs = static_cast<qualifier_info>(static_cast<int>(lhs) & static_cast<int>(rhs));
+  return lhs;
+}
+inline qualifier_info& operator^=(qualifier_info& lhs, qualifier_info rhs)
+{
+  lhs = static_cast<qualifier_info>(static_cast<int>(lhs) & ~static_cast<int>(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)
+{
+  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
index c2719c3..8a09b6e 100644 (file)
@@ -12,29 +12,50 @@ struct visitor_generate;
       
 struct type_generator
 {
+   type_generator(bool is_return = false)
+     : is_return(is_return) {}
+  
    template <typename OutputIterator, typename Context>
    bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
    {
-      return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false});
+      return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return});
    }
    template <typename OutputIterator, typename Context>
    bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
    {
       return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{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<type_generator> : std::true_type {};
+template <>
+struct is_generator<type_terminal> : std::true_type {};
 
 namespace type_traits {
 template <>
 struct attributes_needed<type_generator> : std::integral_constant<int, 1> {};  
+template <>
+struct attributes_needed<type_terminal> : std::integral_constant<int, 1> {};  
 }
 
-type_generator const type = {};
-
+      
 } } }
 
 #endif
index 7eda7ad..2e75e12 100644 (file)
@@ -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<attributes::pointer_indirection>* pointers;
-  typedef void result_type;
-  template <typename T>
-  void operator()(T& object) const
-  {
-     std::swap(*pointers, object.pointers);
-  }
-  void operator()(attributes::complex_type_def& complex) const
-  {
-    (*this)(complex.outer);
-  }
-};
-
-template <typename OutputIterator, typename Context>
-bool generate_pointers(OutputIterator sink, std::vector<attributes::pointer_indirection> 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 <typename T>
 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<OutputIterator, Context> visitor_type;
    typedef bool result_type;
@@ -105,14 +60,8 @@ struct visitor_generate
       }
       const match_table[] =
         {
-           {"void_ptr", nullptr, [&]
-            {
-              std::vector<attributes::pointer_indirection> 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<attributes::pointer_indirection>
-                                           {regular.pointers.begin(), std::prev(regular.pointers.end())}}
-                                        , {}};
+              { return regular_type_def{" ::efl::eina::value", regular.base_qualifier, {}};
               }}
         };
-
-      if(eina::optional<bool> 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<bool> 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<A>
+      // in A& @optional -> optional<A&>
+      // in A& @optional -> optional<A&>
+      // in own(A&) @optional -> A*
+      //
+      // out A @optional -> optional<A&>
+      // out A& @optional -> optional<A&>
+      // out own(A&) @optional -> optional<A*&>
+      else if(regular.base_qualifier & qualifier_info::is_optional)
        {
-         if(regular.pointers.empty() || (regular.pointers.size() == 1 && regular.pointers[0].reference == true))
+         attributes::regular_type_def no_optional_regular = regular;
+         no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_optional;
+         if(is_out)
            {
-             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);
+             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
            {
-             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);
+             // 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(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<attributes::pointer_indirection> 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;
-         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");
-         else
-           return false;
-       }
+      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<attributes::pointer_indirection> pointers;
-          pointers.swap(no_pointer_regular.pointers);
-          if(is_out)
-            pointers.push_back({{attributes::qualifier_info::is_none, {}}, true});
+          // std::vector<attributes::pointer_indirection> 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<bool> 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)
           {
index d7672e7..626298a 100644 (file)
@@ -30,22 +30,22 @@ class Complex (Eo.Base)
       }
       incontcont {
          params {
-           l: list<list<int*>>;
+           l: list<list<int>>;
          }
       }
       incontcontown {
          params {
-           l: own(list<list<int*>>);
+           l: own(list<list<int>>);
          }
       }
       incontowncontown {
          params {
-           l: own(list<own(list<int*>)>);
+           l: own(list<own(list<int>)>);
          }
       }
       incontowncont {
          params {
-           l: list<own(list<int*>)>;
+           l: list<own(list<int>)>;
          }
       }
       instringcont {
@@ -63,14 +63,140 @@ class Complex (Eo.Base)
            l: own(list<string>);
          }
       }
-
+      inarray {
+         params {
+           l: array<int>;
+         }
+      }
+      inarrayown {
+         params {
+           l: own(array<int>);
+         }
+      }
+      inhash {
+         params {
+           l: hash<int, int>;
+         }
+      }
+      inhashown {
+         params {
+           l: own(hash<int, int>);
+         }
+      }
+      initerator {
+         params {
+           l: iterator<int>;
+         }
+      }
+      initeratorown {
+         params {
+           l: own(iterator<int>);
+         }
+      }
+      inaccessor {
+         params {
+           l: accessor<int>;
+         }
+      }
+      inaccessorown {
+         params {
+           l: own(accessor<int>);
+         }
+      }
+      // out
+      outptrcont {
+         params {
+           @out l: list<int*>;
+         }
+      }
+      outclasscont {
+         params {
+           @out l: list<Eo.Base>;
+         }
+      }
+      outcontcont {
+         params {
+           @out l: list<list<int>>;
+         }
+      }
+      outcontcontown {
+         params {
+           @out l: own(list<list<int>>);
+         }
+      }
+      outcontowncontown {
+         params {
+           @out l: own(list<own(list<int>)>);
+         }
+      }
+      outcontowncont {
+         params {
+           @out l: list<own(list<int>)>;
+         }
+      }
+      outstringcont {
+         params {
+           @out l: list<string>;
+         }
+      }
+      outstringowncont {
+         params {
+           @out l: list<own(string)>;
+         }
+      }
+      outstringcontown {
+         params {
+           @out l: own(list<string>);
+         }
+      }
+      outarray {
+         params {
+           @out l: array<int>;
+         }
+      }
+      outarrayown {
+         params {
+           @out l: own(array<int>);
+         }
+      }
+      outhash {
+         params {
+           @out l: hash<int, int>;
+         }
+      }
+      outhashown {
+         params {
+           @out l: own(hash<int, int>);
+         }
+      }
+      outiterator {
+         params {
+           @out l: iterator<int>;
+         }
+      }
+      outiteratorown {
+         params {
+           @out l: own(iterator<int>);
+         }
+      }
+      outaccessor {
+         params {
+           @out l: accessor<int>;
+         }
+      }
+      outaccessorown {
+         params {
+           @out l: own(accessor<int>);
+         }
+      }
+      //
       foo {
          params {
-            l: list<int*>;
+            l: list<int>;
          }
       }
       bar {
-         return: array<int*>;
+         return: array<int>;
       }
       wrapper_r {
          return: Complex;
index 72f4608..91f8017 100644 (file)
@@ -37,12 +37,8 @@ struct test_param_type<void(T::*)(P), U>
    static_assert(std::is_same<P, U>::value, "Wrong type");
 };
 
-test_param_type<typeof( & nonamespace::Complex::inptrcont ), efl::eina::range_list<int>> inptrcont;
 test_param_type<typeof( & nonamespace::Complex::inclasscont ), efl::eina::range_list<eo::Base>> inclasscont;
-test_param_type<typeof( & nonamespace::Complex::inptrptrcont ), efl::eina::range_list<int*>> inptrptrcont;
-test_param_type<typeof( & nonamespace::Complex::inptrcontown ), efl::eina::list<int>const&> inptrcontown;
-test_param_type<typeof( & nonamespace::Complex::inptrptrcontown ), efl::eina::list<int*>const&> inptrptrcontown;
-test_param_type<typeof( & nonamespace::Complex::incontcont ), efl::eina::range_list<efl::eina::range_list<int>>> incontont;
+test_param_type<typeof( & nonamespace::Complex::incontcont ), efl::eina::range_list<efl::eina::range_list<int>>> incontcont;
 test_param_type<typeof( & nonamespace::Complex::incontcontown ), efl::eina::list<efl::eina::range_list<int>>const&> incontcontown;
 test_param_type<typeof( & nonamespace::Complex::incontowncontown ), efl::eina::list<efl::eina::list<int>>const&> incontowncontown;
 test_param_type<typeof( & nonamespace::Complex::incontowncont ), efl::eina::range_list<efl::eina::list<int>>> incontowncont;
@@ -50,6 +46,15 @@ test_param_type<typeof( & nonamespace::Complex::instringcont ), efl::eina::range
 test_param_type<typeof( & nonamespace::Complex::instringowncont ), efl::eina::range_list<efl::eina::string_view>> instringowncont;
 test_param_type<typeof( & nonamespace::Complex::instringcontown ), efl::eina::list<efl::eina::string_view>const&> instringcontown;
 
+test_param_type<typeof( & nonamespace::Complex::outclasscont ), efl::eina::range_list<eo::Base>&> outclasscont;
+test_param_type<typeof( & nonamespace::Complex::outcontcont ), efl::eina::range_list<efl::eina::range_list<int>>&> outcontcont;
+test_param_type<typeof( & nonamespace::Complex::outcontcontown ), efl::eina::list<efl::eina::range_list<int>>&> outcontcontown;
+test_param_type<typeof( & nonamespace::Complex::outcontowncontown ), efl::eina::list<efl::eina::list<int>>&> outcontowncontown;
+test_param_type<typeof( & nonamespace::Complex::outcontowncont ), efl::eina::range_list<efl::eina::list<int>>&> outcontowncont;
+test_param_type<typeof( & nonamespace::Complex::outstringcont ), efl::eina::range_list<efl::eina::string_view>&> outstringcont;
+test_param_type<typeof( & nonamespace::Complex::outstringowncont ), efl::eina::range_list<efl::eina::string_view>&> outstringowncont;
+test_param_type<typeof( & nonamespace::Complex::outstringcontown ), efl::eina::list<efl::eina::string_view>&> outstringcontown;
+
 test_param_type<typeof( & nonamespace::Complex::foo ), efl::eina::range_list<int>> foo;
 test_return_type<typeof( & nonamespace::Complex::bar ), efl::eina::range_array<int>> bar;
 test_return_type<typeof( & nonamespace::Complex::wrapper_r ), nonamespace::Complex> wrapper_r;
index 83cb394..c9ee5c8 100644 (file)
@@ -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,73 +54,109 @@ START_TEST(eolian_cxx_test_type_generation)
   efl::eo::eo_init eo_init;
 
   name1::name2::Type_Generation g;
+}
+END_TEST
+
+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);
-  std::unique_ptr<int> i (new int(42));
-  g.inintptr(i.get());
+  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* p = (int*)malloc(sizeof(int));
-    *p = 42;
-    std::unique_ptr<int, void(*)(const void*)> inintptrown(p, (void(*)(const void*))&free);
-    g.inintptrown(std::move(inintptrown));
+    int&i = g.returnrefint();
+    ck_assert(i == 42);
   }
   {
-    int** p = (int**)malloc(sizeof(int*));
-    *p = (int*)malloc(sizeof(int));
-    **p = 42;
-    std::unique_ptr<int*, void(*)(const void*)> inintptrownptr(p, (void(*)(const void*))&free);
-    g.inintptrownptr(std::move(inintptrownptr));
+    int i = g.returnint();
+    ck_assert(i == 42);
   }
   {
-    int*** p = (int***)malloc(sizeof(int**));
-    *p = (int**)malloc(sizeof(int*));
-    **p = (int*)malloc(sizeof(int));
-    ***p = 42;
-    std::unique_ptr<int**, void(*)(const void*)> inintptrownptrptr(p, (void(*)(const void*))&free);
-    g.inintptrownptrptr(std::move(inintptrownptrptr));
+    void* p = g.returnvoidptr();
+    ck_assert(*(int*)p == 42);
   }
   {
-    int*** p = (int***)malloc(sizeof(int**));
-    *p = (int**)malloc(sizeof(int*));
-    **p = (int*)malloc(sizeof(int));
-    ***p = 42;
-    std::unique_ptr<int**, void(*)(const void*)> inintptrptrownptr(p, (void(*)(const void*))&free);
-    g.inintptrptrownptr(std::move(inintptrptrownptr));
+    int& p = g.returnintptr();
+    ck_assert(p == 42);
   }
   {
-    int* p = (int*)malloc(sizeof(int));
-    *p = 42;
-    std::unique_ptr<int, void(*)(const void*)> inintptrownfree(p, (void(*)(const void*))&free);
-    g.inintptrownfree(std::move(inintptrownfree));
+    efl::eina::unique_malloc_ptr<int> 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");
   }
-  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<efl::eina::string_view, void(*)(const void*)> 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
 
-START_TEST(eolian_cxx_test_type_generation_in)
+START_TEST(eolian_cxx_test_type_generation_optional)
 {
-  efl::eo::eo_init i;
+  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<int> 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);
 }
index 20f471b..c4a2257 100644 (file)
@@ -101,7 +101,7 @@ class Generic (Eo.Base)
      prefix,event1;
      prefix,event2: Generic;
      prefix,event3: int;
-     prefix,event4: list<int*>;
+     prefix,event4: list<int>;
      prefix,event5: Generic.Event;
    }
 }
index 28b8c85..9af748d 100644 (file)
@@ -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)
index 66b6461..e202423 100644 (file)
@@ -2,45 +2,46 @@ class Name1.Name2.Type_Generation (Eo.Base)
 {
    data: Type_Generation_Data;
    methods {
-     // in void ptr
-     invoidptr {
+     // inref
+     inrefint {
        params {
-         @in v: void*;
+         @in v: ref(int);
        }
      }
-     inint {
+     inrefintown {
        params {
-         @in v: int;
+         @in v: own(ref(int));
        }
      }
-     inintptr {
+     inrefintownfree {
        params {
-         @in v: int*;
+         @in v: free(own(ref(int)), free);
        }
      }
-     inintptrown {
+     // in void ptr
+     invoidptr {
        params {
-         @in v: own(int*);
+         @in v: void_ptr;
        }
      }
-     inintptrownptr {
+     inint {
        params {
-         @in v: own(int*)*;
+         @in v: int;
        }
      }
-     inintptrownptrptr {
+     inintptr {
        params {
-         @in v: own(int*)**;
+         @in v: ref(int);
        }
      }
-     inintptrptrownptr {
+     inintptrown {
        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 {