eina_cxx: Fix eina::accessor for C++ Eo wrappers
authorVitor Sousa <vitorsousasilva@gmail.com>
Mon, 3 Nov 2014 13:38:17 +0000 (11:38 -0200)
committerVitor Sousa <vitorsousasilva@gmail.com>
Mon, 5 Jan 2015 17:52:27 +0000 (15:52 -0200)
Created a specialization of the eina::accessor for C++ Eo wrappers.

Created an override of the "accessor" methods in the eina::list specialization
for Eo wrappers (in eina_list.hh). It is necessary to create accessors with the
correct type.

Created specializations of std::is_base_of to avoid compilation errors related
with _Eo_Opaque type.

Added new test cases in "eina_cxx_test_accessor.cc" to test the accessor
specialization.

Added efl::eina::eina_init to the existing test cases to correctly do the
on demand initialization required by the tests.

@fix

src/bindings/eina_cxx/eina_accessor.hh
src/bindings/eina_cxx/eina_eo_base_fwd.hh
src/bindings/eina_cxx/eina_list.hh
src/tests/eina_cxx/eina_cxx_test_accessor.cc

index 98be3af..e64d0ef 100644 (file)
@@ -4,6 +4,7 @@
 #include <Eina.h>
 #include <eina_error.hh>
 #include <eina_throw.hh>
+#include <eina_eo_base_fwd.hh>
 
 #include <memory>
 #include <iterator>
@@ -37,7 +38,7 @@ namespace efl { namespace eina {
  * Wraps an native Eina_Accessor and provide random access to data structures.
  */
 template <typename T>
-struct accessor
+struct accessor_common_base
 {
   typedef unsigned int key_type; /**< Type for accessor key. */
   typedef T mapped_type; /**< Type for accessor mapped elements. */
@@ -47,7 +48,7 @@ struct accessor
   /**
    * @brief Default constructor. Creates an empty accessor.
    */
-  accessor() : _impl(0) {}
+  accessor_common_base() : _impl(0) {}
 
   /**
    * @brief Create an accessor object that wraps the given Eina accessor.
@@ -60,7 +61,7 @@ struct accessor
    * gains ownership of the given handle, deallocating it at destruction
    * time.
    */
-  explicit accessor(Eina_Accessor* impl)
+  explicit accessor_common_base(Eina_Accessor* impl)
     : _impl(impl)
   {
     assert(_impl != 0);
@@ -74,7 +75,7 @@ struct accessor
    * accessor object, so that the newly created object can be used
    * freely.
    */
-  accessor(accessor<T> const& other)
+  accessor_common_base(accessor_common_base<T> const& other)
     : _impl(eina_accessor_clone(other._impl))
   {}
 
@@ -86,7 +87,7 @@ struct accessor
    * This operator replaces the current native Eina accessor by a copy
    * of the native accessor inside the given object.
    */
-  accessor<T>& operator=(accessor<T> const& other)
+  accessor_common_base<T>& operator=(accessor_common_base<T> const& other)
   {
     eina_accessor_free(_impl);
     _impl = eina_accessor_clone(other._impl);
@@ -98,12 +99,119 @@ struct accessor
   /**
    * @brief Destructor. Free the internal @c Eina_Acessor.
    */
-  ~accessor()
+  ~accessor_common_base()
   {
     eina_accessor_free(_impl);
   }
 
   /**
+   * @brief Get the handle for the wrapped @c Eina_Accessor.
+   * @return Internal handle for the native Eina accessor.
+   *
+   * This member function returns the native @c Eina_Accessor handle
+   * that is wrapped inside this object.
+   *
+   * @warning It is important to take care when using it, since the
+   * handle will be automatically release upon object destruction.
+   */
+  Eina_Accessor* native_handle() const;
+
+  /**
+   * @brief Swap content between both objects.
+   * @param other Other accessor object.
+   *
+   * This member function swaps the internal @c Eina_Acessor with the
+   * given accessor object.
+   */
+  void swap(accessor_common_base<T>& other)
+  {
+    std::swap(_impl, other._impl);
+  }
+  /**
+   * @brief Cast to @c boolean based on the wrapped @c Eina_Accessor.
+   * @return @c true if the wrapped handle is not @c NULL, @c false otherwise.
+   *
+   * Boolean typecast overload for easy validation of the accessor
+   * object. Returns @c false if it does not have an internal
+   * @c Eina_Accessor, i.e. if the current handle is not @c NULL.
+   */
+  explicit operator bool() const
+  {
+    return native_handle() ? &accessor_common_base<T>::native_handle : 0 ;
+  }
+
+  /**
+   * @internal
+   * Member variable for storing the native Eina_Accessor pointer.
+   */
+  Eina_Accessor* _impl;
+};
+
+template <typename T, typename Enable = T>
+struct accessor;
+
+template <typename T>
+struct accessor<T, typename std::enable_if< ! std::is_base_of<efl::eo::base, T>::value, T>::type>
+  : accessor_common_base<T>
+{
+  typedef accessor_common_base<T> _base_type;
+  typedef accessor<T> _self_type;
+
+  typedef typename _base_type::key_type key_type;
+  typedef typename _base_type::mapped_type mapped_type;
+  typedef typename _base_type::value_type value_type;
+  typedef typename _base_type::size_type size_type;
+
+  /**
+   * @brief Default constructor. Creates an empty accessor.
+   */
+  accessor() : _base_type() {}
+
+  /**
+   * @brief Create an accessor object that wraps the given Eina accessor.
+   * @param impl Native @c Eina_Accessor to be wrapped.
+   *
+   * This constructor creates an accessor object that wraps the given
+   * Eina_Accessor and provides access to the data pointed by it.
+   *
+   * @warning It is important to note that the created accessor object
+   * gains ownership of the given handle, deallocating it at destruction
+   * time.
+   */
+  explicit accessor(Eina_Accessor* impl) : _base_type(impl) {}
+
+  /**
+   * @brief Copy constructor. Creates a copy of the given accessor object.
+   * @param other Other accessor object.
+   *
+   * This constructor clones the internal @c Eina_Accessor of the given
+   * accessor object, so that the newly created object can be used
+   * freely.
+   */
+  accessor(_self_type const& other) : _base_type(other)  {}
+
+  /**
+   * @brief Assignment Operator. Replace the current content.
+   * @param other Other accessor object.
+   * @throw <tt>eina::system_error</tt> if the Eina accessor could not be cloned.
+   *
+   * This operator replaces the current native Eina accessor by a copy
+   * of the native accessor inside the given object.
+   */
+  _self_type& operator=(_self_type const& other)
+  {
+    _base_type::operator=(other);
+  }
+
+  /**
+   * @brief Destructor. Free the internal @c Eina_Acessor.
+   */
+  ~accessor()
+  {
+    // Cleanup is already done in the base class.
+  }
+
+  /**
    * @brief Retrieve the data of the accessor at a given position.
    * @param i The position of the element.
    * @return Constant reference to the retrieved data.
@@ -115,9 +223,9 @@ struct accessor
    */
   mapped_type& operator[](size_type i) const
   {
-    assert(_impl != 0);
+    assert(this->_impl != 0);
     void* p;
-    if(!eina_accessor_data_get(_impl, i, &p))
+    if(!eina_accessor_data_get(this->_impl, i, &p))
       {
         eina::error_code ec = efl::eina::get_error_code();
         EFL_CXX_THROW(eina::system_error(ec, "EFL Eina Error"));
@@ -125,17 +233,121 @@ struct accessor
     return *static_cast<mapped_type*>(p);
   }
 
+  using _base_type::native_handle;
+
   /**
-   * @brief Get the handle for the wrapped @c Eina_Accessor.
-   * @return Internal handle for the native Eina accessor.
+   * @brief Swap content between both objects.
+   * @param other Other accessor object.
    *
-   * This member function returns the native @c Eina_Accessor handle
-   * that is wrapped inside this object.
+   * This member function swaps the internal @c Eina_Acessor with the
+   * given accessor object.
+   */
+  void swap(_self_type& other)
+  {
+    _base_type::swap(other);
+  }
+
+  /**
+   * @brief Cast to @c boolean based on the wrapped @c Eina_Accessor.
+   * @return @c true if the wrapped handle is not @c NULL, @c false otherwise.
    *
-   * @warning It is important to take care when using it, since the
-   * handle will be automatically release upon object destruction.
+   * Boolean typecast overload for easy validation of the accessor
+   * object. Returns @c false if it does not have an internal
+   * @c Eina_Accessor, i.e. if the current handle is not @c NULL.
    */
-  Eina_Accessor* native_handle() const;
+  explicit operator bool() const
+  {
+    return native_handle() ? &_self_type::native_handle : 0 ;
+  }
+};
+
+template <typename T>
+struct accessor<T, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value, T>::type>
+  : accessor_common_base<T>
+{
+  typedef accessor_common_base<T> _base_type;
+  typedef accessor<T> _self_type;
+
+  typedef typename _base_type::key_type key_type;
+  typedef typename _base_type::mapped_type mapped_type;
+  typedef typename _base_type::value_type value_type;
+  typedef typename _base_type::size_type size_type;
+
+  /**
+   * @brief Default constructor. Creates an empty accessor.
+   */
+  accessor() : _base_type() {}
+
+  /**
+   * @brief Create an accessor object that wraps the given Eina accessor.
+   * @param impl Native @c Eina_Accessor to be wrapped.
+   *
+   * This constructor creates an accessor object that wraps the given
+   * Eina_Accessor and provides access to the data pointed by it.
+   *
+   * @warning It is important to note that the created accessor object
+   * gains ownership of the given handle, deallocating it at destruction
+   * time.
+   */
+  explicit accessor(Eina_Accessor* impl) : _base_type(impl) {}
+
+  /**
+   * @brief Copy constructor. Creates a copy of the given accessor object.
+   * @param other Other accessor object.
+   *
+   * This constructor clones the internal @c Eina_Accessor of the given
+   * accessor object, so that the newly created object can be used
+   * freely.
+   */
+  accessor(_self_type const& other) : _base_type(other)  {}
+
+  /**
+   * @brief Assignment Operator. Replace the current content.
+   * @param other Other accessor object.
+   * @throw <tt>eina::system_error</tt> if the Eina accessor could not be cloned.
+   *
+   * This operator replaces the current native Eina accessor by a copy
+   * of the native accessor inside the given object.
+   */
+  _self_type& operator=(_self_type const& other)
+  {
+    _base_type::operator=(other);
+  }
+
+  /**
+   * @brief Destructor. Free the internal @c Eina_Acessor.
+   */
+  ~accessor()
+  {
+    // Cleanup is already done in the base class.
+  }
+
+  /**
+   * @brief Retrieve the data of the accessor at a given position.
+   * @param i The position of the element.
+   * @return Constant reference to the retrieved data.
+   * @throw <tt>eina::system_error</tt> if the given element could not be retrieved.
+   *
+   * This operator retrieves a constant reference to the element at the
+   * given position. If the element could not be retrieved an
+   * <tt>eina::system_error</tt> is thrown.
+   */
+  mapped_type operator[](size_type i) const
+  {
+    assert(this->_impl != 0);
+    void* p;
+    if(!eina_accessor_data_get(this->_impl, i, &p))
+      {
+        eina::error_code ec = efl::eina::get_error_code();
+        EFL_CXX_THROW(eina::system_error(ec, "EFL Eina Error"));
+      }
+
+    // TODO Do we need to ref this Eo* instance ?
+
+    return mapped_type(::eo_ref(static_cast<Eo*>(p)));
+  }
+
+  using _base_type::native_handle;
 
   /**
    * @brief Swap content between both objects.
@@ -144,10 +356,11 @@ struct accessor
    * This member function swaps the internal @c Eina_Acessor with the
    * given accessor object.
    */
-  void swap(accessor<T>& other)
+  void swap(_self_type& other)
   {
-    std::swap(_impl, other._impl);
+    _base_type::swap(other);
   }
+
   /**
    * @brief Cast to @c boolean based on the wrapped @c Eina_Accessor.
    * @return @c true if the wrapped handle is not @c NULL, @c false otherwise.
@@ -158,15 +371,8 @@ struct accessor
    */
   explicit operator bool() const
   {
-    return native_handle() ? &accessor<T>::native_handle : 0 ;
+    return native_handle() ? &_self_type::native_handle : 0 ;
   }
-private:
-
-  /**
-   * @internal
-   * Member variable for storing the native Eina_Accessor pointer.
-   */
-  Eina_Accessor* _impl;
 };
 
 /**
@@ -191,11 +397,14 @@ void swap(accessor<U>& lhs, accessor<U>& rhs)
  * @{
  */
 
+template <typename T, class Enable = T>
+struct accessor_iterator;
+
 /**
  * Random access iterator for <tt>eina::accessor</tt>.
  */
 template <typename T>
-struct accessor_iterator
+struct accessor_iterator<T, typename std::enable_if< ! std::is_base_of<efl::eo::base, T>::value, T>::type>
 {
   typedef T value_type; /**< Type of the elements. */
   typedef value_type* pointer; /**< Pointer to element type. */
@@ -339,102 +548,254 @@ struct accessor_iterator
     std::swap(_accessor, other._accessor);
   }
 
-private:
   accessor<T> _accessor; /**< @internal  */
   unsigned int _index; /**< @internal */
+};
+
+/**
+ * Specialization for all data types that are not derivated from efl::eo::base.
+ */
+template <typename T>
+struct accessor_iterator<T, typename std::enable_if<std::is_base_of<efl::eo::base, T>::value, T>::type>
+{
+  typedef T value_type; /**< Type of the elements. */
+  typedef value_type* pointer; /**< Pointer to element type. */
+  typedef value_type& reference; /**< Reference to element type. */
+  typedef std::ptrdiff_t difference_type; /**< Type to represent the distance between two @ref accessor_iterators */
+  typedef std::input_iterator_tag iterator_category; /**< Defines the iterator as being a random access iterator. */
+
 
   /**
-   * @brief Check if @p lhs and @p rhs point to the same position.
-   * @param lhs @c accessor_iterator at the left side of the expression.
-   * @param rhs @c accessor_iterator at the right side of the expression.
-   * @return @c true if both @p lhs and @p rhs point to the same position.
+   * @brief Creates an @c accessor_iterator to the given <tt>eina::accessor</tt>.
+   * @param a <tt>eina::accessor</tt> object.
+   * @param pos Initial position of the iterator (Default = @c 0).
+   *
+   * This constructor creates an @c accessor_iterator for the given
+   * <tt>eina::accessor</tt> object. The position initially pointed by
+   * the iterator can be supplied via the @p pos argument, by default
+   * it is the first position (index @c 0).
+   */
+  accessor_iterator(accessor<T> const& a, unsigned int pos = 0u)
+    : _accessor(a), _index(pos), _tmp_value(0)
+  {}
+
+  ~accessor_iterator()
+  {
+    if(_tmp_value) {
+     delete _tmp_value;
+    }
+  }
+
+  /**
+   * @brief Move the iterator forward by @p i positions.
+   * @param i Number of positions to move.
+   * @return The @c accessor_iterator itself.
+   */
+  accessor_iterator<T>& operator+=(difference_type i)
+  {
+    _index += i;
+    return *this;
+  }
+
+  /**
+   * @brief Move the iterator back by @p i positions.
+   * @param i Number of positions to move.
+   * @return The @c accessor_iterator itself.
    */
-  template <typename U>
-  friend bool operator==(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+  accessor_iterator<T>& operator-=(difference_type i)
   {
-    return lhs._index == rhs._index;
+    _index -= i;
+    return *this;
   }
 
   /**
-   * @brief Get the distance between two <tt>accessor_iterator</tt>s.
-   * @param lhs @c accessor_iterator at the left side of the expression.
-   * @param rhs @c accessor_iterator at the right side of the expression.
-   * @return The number of elements between @p lhs and @p rhs.
+   * @brief Get the element @p i positions away from the current element.
+   * @param i Position relative to the current element.
+   * @return Copy of the element @p i positions away from the
+   *         element currently pointed by the @c accessor_iterator.
    */
-  template <typename U>
-  friend typename accessor_iterator<U>::difference_type
-  operator-(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+  value_type operator[](difference_type i)
   {
-    return lhs._index - rhs._index;
+    return _accessor[_index + i];
   }
 
   /**
-   * @brief Get an @c accessor_iterator moved @p rhs positions forward.
-   * @param lhs @c accessor_iterator object.
-   * @param rhs Number of positions relative to the current element.
-   * @return Copy of @p lhs moved @p rhs positions forward.
+   * @brief Move the iterator to the next position.
+   * @return The @c accessor_iterator itself.
+   *
+   * This operator increments the iterator, making it point to the
+   * position right after the current one.
+   * At the end, it returns a reference to itself.
    */
-  template <typename U>
-  friend
-  accessor_iterator<U> operator+(accessor_iterator<U> lhs
-                                 , typename accessor_iterator<U>::difference_type rhs)
+  accessor_iterator<T>& operator++()
   {
-    lhs._index += rhs;
-    return lhs;
+    ++_index;
+    return *this;
   }
 
   /**
-   * @brief Get an @c accessor_iterator moved @p lhs positions forward.
-   * @param lhs Number of positions relative to the current element.
-   * @param rhs @c accessor_iterator object.
-   * @return Copy of @p rhs moved @p lhs positions forward.
+   * @brief Move the iterator to the previous position.
+   * @return The @c accessor_iterator itself.
+   *
+   * This operator decrements the iterator, making it point to the
+   * position right before the current one.
+   * At the end, it returns a reference to itself.
    */
-  template <typename U>
-  friend
-  accessor_iterator<U> operator+(typename accessor_iterator<U>::difference_type lhs
-                               , accessor_iterator<U> rhs)
+  accessor_iterator<T>& operator--()
   {
-    return rhs + lhs;
+    --_index;
+    return *this;
   }
 
   /**
-   * @brief Check if @p lhs points to a position before the position pointed by @p rhs.
-   * @param lhs @c accessor_iterator at the left side of the expression.
-   * @param rhs @c accessor_iterator at the right side of the expression.
-   * @return @c true if @p lhs points to a position before the position
-   *         pointed by @p rhs, @c false otherwise.
+   * @brief Move the iterator to the next position.
+   * @return A copy of the @c accessor_iterator before the change.
+   *
+   * This operator increments the iterator, making it point to the
+   * position right after the current one.
+   * At the end, it returns a copy of the @c accessor_iterator before
+   * the change.
    */
-  template <typename U>
-  friend bool operator<(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+  accessor_iterator<T>& operator++(int)
   {
-    return lhs._index < rhs._index;
+    accessor_iterator<T> tmp(*this);
+    ++*this;
+    return tmp;
   }
 
   /**
-   * @brief Check if the position pointed by @p lhs is the same or is before the one pointed by @p rhs.
-   * @param lhs @c accessor_iterator at the left side of the expression.
-   * @param rhs @c accessor_iterator at the right side of the expression.
-   * @return @c true if the position pointed by @p lhs is the same or is
-   *            before the position pointed by @p rhs, @c false otherwise.
+   * @brief Move the iterator to the previous position.
+   * @return A copy of the @c accessor_iterator before the change.
+   *
+   * This operator decrements the iterator, making it point to the
+   * position right before the current one.
+   * At the end, it returns a copy of the @c accessor_iterator before
+   * the change.
    */
-  template <typename U>
-  friend bool operator<=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+  accessor_iterator<T>& operator--(int)
   {
-    return lhs._index <= rhs._index;
+    accessor_iterator<T> tmp(*this);
+    --*this;
+    return tmp;
   }
+
+  /**
+   * @brief Get a reference to the element currently pointed by the @c accessor_iterator.
+   * @return Copy of the current element.
+   */
+  value_type operator*() const
+  {
+    return _accessor[_index];
+  }
+
+  /**
+   * @brief Return a pointer to a copy of the current element, which member will be accessed.
+   * @return Pointer a copy of the element currently pointed by the @c accessor_iterator.
+   */
+  pointer operator->() const
+  {
+    if(!_tmp_value)
+      {
+         _tmp_value = new value_type(_accessor[_index]);
+      }
+    else
+      {
+         *_tmp_value = _accessor[_index];
+      }
+    return _tmp_value;
+  }
+
+  /**
+   * @brief Swap content with the given @c accessor_iterator.
+   * @param other Another @c accessor_iterator of the same type.
+   */
+  void swap(accessor_iterator<T>& other)
+  {
+    std::swap(_index, other._index);
+    std::swap(_accessor, other._accessor);
+    std::swap(_tmp_value, other._tmp_value);
+  }
+
+  accessor<T> _accessor; /**< @internal */
+  unsigned int _index; /**< @internal */
+  pointer _tmp_value; /**< @internal */
 };
 
 /**
- * @brief Check if the position pointed by @p lhs is the same or is after the one pointed by @p rhs.
+ * @brief Check if @p lhs and @p rhs point to the same position.
  * @param lhs @c accessor_iterator at the left side of the expression.
  * @param rhs @c accessor_iterator at the right side of the expression.
- * @return @c true if the position pointed by @p lhs is the same or is
- *            after the position pointed by @p rhs, @c false otherwise.
+ * @return @c true if both @p lhs and @p rhs point to the same position.
  */
 template <typename U>
-bool operator>=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+bool operator==(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
 {
-  return !(lhs < rhs);
+  return lhs._index == rhs._index;
+}
+
+/**
+ * @brief Check if @p lhs and @p rhs point to different positions.
+ * @param lhs @c accessor_iterator at the left side of the expression.
+ * @param rhs @c accessor_iterator at the right side of the expression.
+ * @return @c true if @p lhs and @p rhs point to different positions.
+ */
+template <typename U>
+bool operator!=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+{
+  return !(lhs == rhs);
+}
+
+/**
+ * @brief Get the distance between two <tt>accessor_iterator</tt>s.
+ * @param lhs @c accessor_iterator at the left side of the expression.
+ * @param rhs @c accessor_iterator at the right side of the expression.
+ * @return The number of elements between @p lhs and @p rhs.
+ */
+template <typename U>
+typename accessor_iterator<U>::difference_type
+operator-(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+{
+  return lhs._index - rhs._index;
+}
+
+/**
+ * @brief Get an @c accessor_iterator moved @p rhs positions forward.
+ * @param lhs @c accessor_iterator object.
+ * @param rhs Number of positions relative to the current element.
+ * @return Copy of @p lhs moved @p rhs positions forward.
+ */
+template <typename U>
+accessor_iterator<U> operator+(accessor_iterator<U> lhs
+                             , typename accessor_iterator<U>::difference_type rhs)
+{
+  lhs += rhs;
+  return lhs;
+}
+
+/**
+ * @brief Get an @c accessor_iterator moved @p lhs positions forward.
+ * @param lhs Number of positions relative to the current element.
+ * @param rhs @c accessor_iterator object.
+ * @return Copy of @p rhs moved @p lhs positions forward.
+ */
+template <typename U>
+accessor_iterator<U> operator+(typename accessor_iterator<U>::difference_type lhs
+                             , accessor_iterator<U> const& rhs)
+{
+  return rhs + lhs;
+}
+
+/**
+ * @brief Check if @p lhs points to a position before the position pointed by @p rhs.
+ * @param lhs @c accessor_iterator at the left side of the expression.
+ * @param rhs @c accessor_iterator at the right side of the expression.
+ * @return @c true if @p lhs points to a position before the position
+ *         pointed by @p rhs, @c false otherwise.
+ */
+template <typename U>
+bool operator<(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+{
+  return lhs._index < rhs._index;
 }
 
 /**
@@ -447,19 +808,33 @@ bool operator>=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs
 template <typename U>
 bool operator>(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
 {
-  return !(lhs <= rhs);
+  return rhs < lhs;
 }
 
 /**
- * @brief Check if @p lhs and @p rhs point to different positions.
+ * @brief Check if the position pointed by @p lhs is the same or is before the one pointed by @p rhs.
  * @param lhs @c accessor_iterator at the left side of the expression.
  * @param rhs @c accessor_iterator at the right side of the expression.
- * @return @c true if @p lhs and @p rhs point to different positions.
+ * @return @c true if the position pointed by @p lhs is the same or is
+ *            before the position pointed by @p rhs, @c false otherwise.
  */
 template <typename U>
-bool operator!=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+bool operator<=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
 {
-  return !(lhs == rhs);
+  return !(rhs < lhs);
+}
+
+/**
+ * @brief Check if the position pointed by @p lhs is the same or is after the one pointed by @p rhs.
+ * @param lhs @c accessor_iterator at the left side of the expression.
+ * @param rhs @c accessor_iterator at the right side of the expression.
+ * @return @c true if the position pointed by @p lhs is the same or is
+ *            after the position pointed by @p rhs, @c false otherwise.
+ */
+template <typename U>
+bool operator>=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
+{
+  return !(lhs < rhs);
 }
 
 /**
index 9898694..b160a6d 100644 (file)
@@ -1,10 +1,33 @@
 #ifndef EINA_EO_BASE_FWD_HH
 #define EINA_EO_BASE_FWD_HH
 
+#include <Eo.h>
+#include <type_traits>
+
 namespace efl { namespace eo {
 
 struct base;
     
 } }
 
+namespace std {
+template <>
+struct is_base_of< ::efl::eo::base, ::Eo > : std::false_type {};
+template <>
+struct is_base_of< ::efl::eo::base, const ::Eo > : std::false_type {};
+template <>
+struct is_base_of< ::efl::eo::base, volatile ::Eo > : std::false_type {};
+template <>
+struct is_base_of< ::efl::eo::base, const volatile ::Eo > : std::false_type {};
+
+template <>
+struct is_base_of< const ::efl::eo::base, ::Eo > : std::false_type {};
+template <>
+struct is_base_of< const ::efl::eo::base, const ::Eo > : std::false_type {};
+template <>
+struct is_base_of< const ::efl::eo::base, volatile ::Eo > : std::false_type {};
+template <>
+struct is_base_of< const ::efl::eo::base, const volatile ::Eo > : std::false_type {};
+}
+
 #endif
index b2b6745..b810971 100644 (file)
@@ -413,6 +413,27 @@ public:
   using _base_type::max_size;
   using _base_type::native_handle;
 
+  /**
+   * @brief Get a constant @ref eina::accessor for the list.
+   * @return Constant <tt>eina::accessor</tt> to the list.
+   *
+   * Version of @ref accessor() to const-qualified inline lists. Returns
+   * a const-qualified <tt>eina::accessor</tt> instead.
+   */
+  eina::accessor<T const> accessor() const
+  {
+    return eina::accessor<T const>(eina_list_accessor_new(this->_impl._list));
+  }
+
+  /**
+   * @brief Get a @ref eina::accessor for the list.
+   * @return <tt>eina::accessor</tt> to the list.
+   */
+  eina::accessor<T> accessor()
+  {
+    return eina::accessor<T>(eina_list_accessor_new(this->_impl._list));
+  }
+
   friend bool operator==(list<T, CloneAllocator> const& rhs, list<T, CloneAllocator> const& lhs)
   {
     return rhs.size() == lhs.size() && std::equal(rhs.begin(), rhs.end(), lhs.begin());
index 8d04ecc..bf7502f 100644 (file)
@@ -4,13 +4,26 @@
 #endif
 
 #include "Eina.hh"
+#include "Eo.hh"
 
 #include <algorithm>
 
 #include <check.h>
 
+
+const Eo_Class *simple_class_get(void);
+#define MY_CLASS simple_class_get()
+
+struct wrapper : efl::eo::base
+{
+  explicit wrapper(Eo* o)
+    : base(o) {}
+};
+
 START_TEST(eina_cxx_accessor_indexing)
 {
+  efl::eina::eina_init eina_init;
+
   efl::eina::ptr_list<int> list;
   list.push_back(new int(5));
   list.push_back(new int(10));
@@ -26,8 +39,36 @@ START_TEST(eina_cxx_accessor_indexing)
 }
 END_TEST
 
+START_TEST(eina_cxx_eo_accessor_indexing)
+{
+  efl::eina::eina_init eina_init;
+  efl::eo::eo_init eo_init;
+
+  efl::eina::list<wrapper> list;
+
+  wrapper const w1(eo_add(MY_CLASS, NULL));
+  wrapper const w2(eo_add(MY_CLASS, NULL));
+  wrapper const w3(eo_add(MY_CLASS, NULL));
+  wrapper const w4(eo_add(MY_CLASS, NULL));
+
+  list.push_back(w1);
+  list.push_back(w2);
+  list.push_back(w3);
+  list.push_back(w4);
+
+  efl::eina::accessor<wrapper> accessor(list.accessor());
+
+  ck_assert(accessor[0] == w1);
+  ck_assert(accessor[1] == w2);
+  ck_assert(accessor[2] == w3);
+  ck_assert(accessor[3] == w4);
+}
+END_TEST
+
 START_TEST(eina_cxx_accessor_iterator)
 {
+  efl::eina::eina_init eina_init;
+
   efl::eina::ptr_list<int> list;
   list.push_back(new int(5));
   list.push_back(new int(10));
@@ -38,6 +79,12 @@ START_TEST(eina_cxx_accessor_iterator)
   for(efl::eina::accessor_iterator<int> first (list.accessor())
         , last (list.accessor(), list.size()); first != last; ++first, ++pos)
     {
+       if(pos >= 4u)
+         {
+            ck_assert_msg(0, "accessor_iterator out of bounds");
+            break;
+         }
+
       ck_assert(pos != 0u || *first == 5);
       ck_assert(pos != 1u || *first == 10);
       ck_assert(pos != 2u || *first == 15);
@@ -46,8 +93,45 @@ START_TEST(eina_cxx_accessor_iterator)
 }
 END_TEST
 
+START_TEST(eina_cxx_eo_accessor_iterator)
+{
+  efl::eina::eina_init eina_init;
+  efl::eo::eo_init eo_init;
+
+  efl::eina::list<wrapper> list;
+
+  wrapper const w1(eo_add(MY_CLASS, NULL));
+  wrapper const w2(eo_add(MY_CLASS, NULL));
+  wrapper const w3(eo_add(MY_CLASS, NULL));
+  wrapper const w4(eo_add(MY_CLASS, NULL));
+
+  list.push_back(w1);
+  list.push_back(w2);
+  list.push_back(w3);
+  list.push_back(w4);
+
+  std::size_t pos = 0u;
+  for(efl::eina::accessor_iterator<wrapper> first (list.accessor())
+        , last (list.accessor(), list.size()); first != last; ++first, ++pos)
+    {
+       if(pos >= 4u)
+         {
+            ck_assert_msg(0, "accessor_iterator out of bounds");
+            break;
+         }
+
+       ck_assert(pos != 0u || *first == w1);
+       ck_assert(pos != 1u || *first == w2);
+       ck_assert(pos != 2u || *first == w3);
+       ck_assert(pos != 3u || *first == w4);
+    }
+}
+END_TEST
+
 START_TEST(eina_cxx_accessor_relops)
 {
+  efl::eina::eina_init eina_init;
+
   efl::eina::ptr_list<int> list;
   list.push_back(new int(5));
   list.push_back(new int(10));
@@ -101,6 +185,8 @@ void
 eina_test_accessor(TCase* tc)
 {
   tcase_add_test(tc, eina_cxx_accessor_indexing);
+  tcase_add_test(tc, eina_cxx_eo_accessor_indexing);
   tcase_add_test(tc, eina_cxx_accessor_iterator);
+  tcase_add_test(tc, eina_cxx_eo_accessor_iterator);
   tcase_add_test(tc, eina_cxx_accessor_relops);
 }