forked from enlightenment/efl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
9.3 KiB
317 lines
9.3 KiB
#ifndef EINA_ITERATOR_HH_ |
|
#define EINA_ITERATOR_HH_ |
|
|
|
#include <Eina.h> |
|
|
|
#include <eina_eo_concrete_fwd.hh> |
|
|
|
#include <cstdlib> |
|
#include <iterator> |
|
|
|
/** |
|
* @addtogroup Eina_Cxx_Content_Access_Group |
|
* |
|
* @{ |
|
*/ |
|
|
|
namespace efl { namespace eina { |
|
|
|
/** |
|
* @defgroup Eina_Cxx_Iterator_Group Iterator |
|
* @ingroup Eina_Cxx_Content_Access_Group |
|
* |
|
* @{ |
|
*/ |
|
|
|
/** |
|
* Common implementations for iterators. |
|
*/ |
|
template <typename T> |
|
struct _common_iterator_base |
|
{ |
|
private: |
|
typedef _common_iterator_base<T> self_type; /**< Type for the iterator instantiation itself. */ |
|
public: |
|
typedef typename std::remove_reference<T>::type const value_type; /**< Type for elements returned by the iterator. */ |
|
typedef value_type* pointer; /**< Type for a pointer to an element. */ |
|
typedef value_type& reference; /**< Type for a reference to an element. */ |
|
typedef std::ptrdiff_t difference_type; /**< Type to represent the distance between two iterators. */ |
|
typedef std::input_iterator_tag iterator_category; /**< Defines the iterator as being an input iterator. */ |
|
|
|
/** |
|
* @brief Default constructor. Creates an iterator that points to nothing. |
|
*/ |
|
_common_iterator_base() {} |
|
|
|
/** |
|
* @brief Creates a iterator wrapping the given native @c Eina_Iterator handle. |
|
* @param iterator Handle to a native @c Eina_Iterator. |
|
* |
|
* This constructor creates an iterator that wraps the given native |
|
* @c Eina_Iterator handle, providing a generic interface to it. |
|
* |
|
* @warning The created iterator object gains ownership of the handle |
|
* and will deallocate it at destruction time. |
|
*/ |
|
explicit _common_iterator_base(Eina_Iterator* iterator) |
|
: _iterator(iterator) {} |
|
|
|
/** |
|
* @brief Release the internal native Eina iterator handle. |
|
*/ |
|
~_common_iterator_base() |
|
{ |
|
if(_iterator) |
|
eina_iterator_free(_iterator); |
|
} |
|
|
|
/** |
|
* @brief Creates an iterator from another iterator of the same type. |
|
* @param other Another iterator of the same type. |
|
* |
|
* @warning The supplied iterator transfer its internal handle to the |
|
* new iterator, thus @p other will point to nothing after the call |
|
* of this constructor. |
|
*/ |
|
_common_iterator_base(self_type const& other) |
|
: _iterator(other._iterator) |
|
{ |
|
other._iterator = 0; |
|
} |
|
|
|
/** |
|
* @brief Acquire the internal handle of the given iterator. |
|
* @param other Another iterator of the same type. |
|
* @return Reference for itself. |
|
* |
|
* @warning The supplied iterator transfer its internal handle to the |
|
* new iterator, thus @p other will point to nothing after the call |
|
* of this constructor. |
|
*/ |
|
_common_iterator_base& operator=(self_type const& other) |
|
{ |
|
_iterator = other._iterator; |
|
other._iterator = 0; |
|
return *this; |
|
} |
|
|
|
|
|
/** |
|
* @brief Get the handle for the wrapped @c Eina_Iterator. |
|
* @return Internal handle for the native Eina iterator. |
|
* |
|
* This member function returns the native @c Eina_Iterator 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_Iterator* native_handle() const |
|
{ |
|
return _iterator; |
|
} |
|
|
|
protected: |
|
/** |
|
* @internal |
|
*/ |
|
mutable Eina_Iterator* _iterator; |
|
|
|
/** |
|
* @brief Check if the iterators wrap the same handle. |
|
* @param lhs Iterator at the left side of the expression. |
|
* @param lhs Iterator at the right side of the expression. |
|
* @return @c true if both iterators wrap the same handle, @c false otherwise. |
|
*/ |
|
friend inline bool operator==(_common_iterator_base<T> const& lhs, _common_iterator_base<T> const& rhs) |
|
{ |
|
return lhs._iterator == rhs._iterator; |
|
} |
|
|
|
/** |
|
* @brief Check if the iterators wrap the different handles. |
|
* @param lhs Iterator at the left side of the expression. |
|
* @param lhs Iterator at the right side of the expression. |
|
* @return @c true if the iterators wrap different handles, @c false otherwise. |
|
*/ |
|
friend inline bool operator!=(_common_iterator_base<T> const& lhs, _common_iterator_base<T> const& rhs) |
|
{ |
|
return !(lhs == rhs); |
|
} |
|
}; |
|
|
|
/** |
|
* C++ wrappers to the native @c Eina_Iterator. |
|
* It provides a generic interface to the @c Eina_Iterator functions, and |
|
* automatically take care of allocating a deallocating resources using |
|
* the RAII programming idiom. |
|
*/ |
|
template <typename T, typename Enable = void> |
|
struct iterator |
|
: _common_iterator_base<typename std::enable_if<! ::efl::eo::is_eolian_object<T>::value, T const>::type> |
|
{ |
|
private: |
|
typedef _common_iterator_base<T const> base_type; /**< Type for the base class. */ |
|
typename base_type::pointer _value; /**< @internal */ |
|
typedef iterator<T> self_type; /**< Type for the specialized iterator itself. */ |
|
public: |
|
typedef typename base_type::value_type value_type; /**< Type for elements returned by the iterator. */ |
|
typedef typename base_type::pointer pointer; /**< Type for a pointer to an element. */ |
|
typedef typename base_type::reference reference; /**< Type for a reference to an element. */ |
|
typedef typename base_type::difference_type difference_type; /**< Type to represent the distance between two iterators. */ |
|
typedef typename base_type::iterator_category iterator_category; /**< Defines the iterator category as the same of the base class. */ |
|
|
|
/** |
|
* @brief Creates a iterator wrapping the given native @c Eina_Iterator handle. |
|
* |
|
* This constructor creates an iterator that wraps the given native |
|
* @c Eina_Iterator handle, providing a generic interface to it. |
|
*/ |
|
explicit iterator(Eina_Iterator* iterator_ = 0) |
|
: base_type(iterator_) |
|
, _value(nullptr) |
|
{ |
|
if(this->_iterator) |
|
++*this; |
|
} |
|
|
|
|
|
/** |
|
* @brief Move the iterator to the next position. |
|
* @return The 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. |
|
*/ |
|
self_type& operator++() |
|
{ |
|
void* data; |
|
Eina_Bool r = ::eina_iterator_next(this->_iterator, &data); |
|
if(!r) |
|
this->_iterator = 0; |
|
_value = static_cast<pointer>(data); |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Move the iterator to the next position. |
|
* @return The iterator itself. |
|
* |
|
* Works exactly like @ref operator++(). |
|
*/ |
|
self_type& operator++(int) |
|
{ |
|
return ++*this; |
|
} |
|
|
|
/** |
|
* @brief Get a reference to the element currently pointed by the iterator. |
|
* @return Reference to the current element. |
|
*/ |
|
value_type& operator*() const |
|
{ |
|
return *_value; |
|
} |
|
|
|
/** |
|
* @brief Return a pointer to the current element, which member will be accessed. |
|
* @return Pointer to the element currently pointed by the iterator. |
|
*/ |
|
pointer operator->() const |
|
{ |
|
return _value; |
|
} |
|
}; |
|
|
|
template <typename T> |
|
struct iterator<T, typename std::enable_if< ::efl::eo::is_eolian_object<T>::value, void>::type> |
|
: _common_iterator_base<Eo const> |
|
{ |
|
private: |
|
typedef _common_iterator_base<Eo const> base_type; /**< Type for the base class. */ |
|
typename base_type::pointer _value; /**< @internal */ |
|
typedef iterator<T> self_type; /**< Type for the specialized iterator itself. */ |
|
public: |
|
typedef typename base_type::value_type value_type; /**< Type for elements returned by the iterator. */ |
|
typedef typename base_type::pointer pointer; /**< Type for a pointer to an element. */ |
|
typedef typename base_type::reference reference; /**< Type for a reference to an element. */ |
|
typedef typename base_type::difference_type difference_type; /**< Type to represent the distance between two iterators. */ |
|
typedef typename base_type::iterator_category iterator_category; /**< Defines the iterator category as the same of the base class. */ |
|
|
|
/** |
|
* @brief Creates a iterator wrapping the given native @c Eina_Iterator handle. |
|
* |
|
* This constructor creates an iterator that wraps the given native |
|
* @c Eina_Iterator handle, providing a generic interface to it. |
|
*/ |
|
explicit iterator(Eina_Iterator* iterator_ = 0) |
|
: base_type(iterator_) |
|
, _value(nullptr) |
|
{ |
|
if(this->_iterator) |
|
++*this; |
|
} |
|
|
|
|
|
/** |
|
* @brief Move the iterator to the next position. |
|
* @return The 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. |
|
*/ |
|
self_type& operator++() |
|
{ |
|
void* data; |
|
Eina_Bool r = ::eina_iterator_next(this->_iterator, &data); |
|
if(!r) |
|
this->_iterator = 0; |
|
_value = static_cast<pointer>(data); |
|
return *this; |
|
} |
|
|
|
/** |
|
* @brief Move the iterator to the next position. |
|
* @return The iterator itself. |
|
* |
|
* Works exactly like @ref operator++(). |
|
*/ |
|
self_type& operator++(int) |
|
{ |
|
return ++**this; |
|
} |
|
|
|
/** |
|
* @brief Get a reference to the element currently pointed by the iterator. |
|
* @return Reference to the current element. |
|
*/ |
|
T const& operator*() const |
|
{ |
|
// relies on layout compatibility between eo::concrete and Eo* |
|
return *reinterpret_cast<T const*>(&_value); |
|
} |
|
|
|
/** |
|
* @brief Return a pointer to the current element, which member will be accessed. |
|
* @return Pointer to the element currently pointed by the iterator. |
|
*/ |
|
T const* operator->() const |
|
{ |
|
// relies on layout compatibility between eo::concrete and Eo* |
|
return reinterpret_cast<T const*>(&_value); |
|
} |
|
}; |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
} } |
|
|
|
/** |
|
* @} |
|
*/ |
|
|
|
#endif
|
|
|