eina_cxx: add documentation to the Eina C++ header files.

Summary:
Added documentation to almost all classes that are intended for direct use by the library users.
Marked classes/functions used by the library itself as @internal.
Modified the Doxyfile.in to enable the generation of documentation to the bindings.

Reviewers: felipealmeida, cedric, woohyun, smohanty, raster

CC: savio, cedric

Differential Revision: https://phab.enlightenment.org/D947

Signed-off-by: Cedric BAIL <c.bail@partner.samsung.com>
This commit is contained in:
vitor.sousa 2014-06-04 22:34:42 +02:00 committed by Cedric BAIL
parent 5e7a9b1225
commit 0902b6a6f8
20 changed files with 5539 additions and 190 deletions

View File

@ -594,6 +594,7 @@ WARN_LOGFILE =
# with spaces.
INPUT = @top_srcdir@/src/lib \
@top_srcdir@/src/bindings \
@srcdir@/main.dox \
@srcdir@/pkgconfig.dox \
@srcdir@/eina_examples.dox \
@ -626,7 +627,8 @@ INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.h \
*.x
*.x \
*.hh
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.

View File

@ -1,6 +1,11 @@
#ifndef EINA_HH_
#define EINA_HH_
/**
* @file
* @brief Eina C++
*/
#include <eina_iterator.hh>
#include <eina_ptrarray.hh>
#include <eina_ptrlist.hh>
@ -16,8 +21,37 @@
#include <eina_optional.hh>
#include <eina_integer_sequence.hh>
/**
* @defgroup Eina_Cxx Eina C++
*
* @defgroup Eina_Cxx_Data_Types_Group Data Types
* @ingroup Eina_Cxx
*
* @defgroup Eina_Cxx_Content_Access_Group Content Access
* @ingroup Eina_Cxx_Data_Types_Group
*
* @defgroup Eina_Cxx_Containers_Group Containers
* @ingroup Eina_Cxx_Data_Types_Group
*
* @defgroup Eina_Cxx_Tools_Group Tools
* @ingroup Eina_Cxx
*
*/
namespace efl { namespace eina {
/**
* @addtogroup Eina_Cxx
*
* @{
*/
/**
* @brief Initialize the Eina library.
*
* Initialize all the Eina modules upon construction and finalize them
* upon destruction, using the RAII programming idiom.
*/
struct eina_init
{
eina_init()
@ -30,6 +64,12 @@ struct eina_init
}
};
/**
* @brief Initialize the mutexes of the Eina library.
*
* Set up all the mutexes in all Eina modules upon construction and
* shut them down upon destruction, using the RAII programming idiom.
*/
struct eina_threads_init
{
eina_threads_init()
@ -42,6 +82,10 @@ struct eina_threads_init
}
};
/**
* @}
*/
} }
#endif

View File

@ -9,25 +9,82 @@
#include <cstdlib>
#include <cassert>
/**
* @addtogroup Eina_Cxx_Content_Access_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Accessor_Group Accessor
* @ingroup Eina_Cxx_Content_Access_Group
*
* @brief These classes manage accessor on containers.
*
* These classes allow to access elements of a container in a
* generic way, without knowing which container is used (like
* iterators in the C++ STL). Accessors allows random access (that is, any
* element in the container). For sequential access, see
* @ref Eina_Cxx_Iterator_Group.
*
* @{
*/
/**
* Wraps an native Eina_Accessor and provide random access to data structures.
*/
template <typename T>
struct accessor
{
typedef unsigned int key_type;
typedef T mapped_type;
typedef T value_type;
typedef std::size_t size_type;
typedef unsigned int key_type; /**< Type for accessor key. */
typedef T mapped_type; /**< Type for accessor mapped elements. */
typedef T value_type; /**< Type for accessor elements. Same as @ref mapped_type. */
typedef std::size_t size_type; /**< Type for size information used in the accessor. */
/**
* @brief Default constructor. Creates an empty accessor.
*/
accessor() : _impl(0) {}
/**
* @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)
: _impl(impl)
{
assert(_impl != 0);
}
/**
* @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(accessor<T> const& other)
: _impl(eina_accessor_clone(other._impl))
{}
/**
* @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.
*/
accessor<T>& operator=(accessor<T> const& other)
{
eina_accessor_free(_impl);
@ -36,11 +93,25 @@ struct accessor
throw eina::system_error(efl::eina::get_error_code(), "Error cloning accessor");
return *this;
}
/**
* @brief Destructor. Free the internal @c Eina_Acessor.
*/
~accessor()
{
eina_accessor_free(_impl);
}
/**
* @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(_impl != 0);
@ -53,98 +124,242 @@ struct accessor
return *static_cast<mapped_type*>(p);
}
/**
* @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<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<T>::native_handle : 0 ;
}
private:
/**
* @internal
* Member variable for storing the native Eina_Accessor pointer.
*/
Eina_Accessor* _impl;
};
/**
* @brief Swap the contents of the two accessor objects.
* @param lhs First accessor object.
* @param rhs Second accessor object.
*/
template <typename U>
void swap(accessor<U>& lhs, accessor<U>& rhs)
{
lhs.swap(rhs);
}
/**
* @}
*/
/**
* @defgroup Eina_Cxx_Accessor_Iterator_Group Accessor Iterator
* @ingroup Eina_Cxx_Content_Access_Group
*
* @{
*/
/**
* Random access iterator for <tt>eina::accessor</tt>.
*/
template <typename T>
struct accessor_iterator
{
typedef T value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
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::random_access_iterator_tag iterator_category; /**< Defines the iterator as being a random access iterator. */
/**
* @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)
{}
/**
* @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.
*/
accessor_iterator<T>& operator-=(difference_type i)
{
_index -= i;
return *this;
}
/**
* @brief Get the element @p i positions away from the current element.
* @param i Position relative to the current element.
* @return Reference to the element @p i positions away from the
* element currently pointed by the @c accessor_iterator.
*/
value_type& operator[](difference_type i)
{
return _accessor[_index + i];
}
/**
* @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.
*/
accessor_iterator<T>& operator++()
{
++_index;
return *this;
}
/**
* @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.
*/
accessor_iterator<T>& operator--()
{
--_index;
return *this;
}
/**
* @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.
*/
accessor_iterator<T>& operator++(int)
{
accessor_iterator<T> tmp(*this);
++*this;
return tmp;
}
/**
* @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.
*/
accessor_iterator<T>& operator--(int)
{
accessor_iterator<T> tmp(*this);
--*this;
return tmp;
}
/**
* @brief Get a reference to the element currently pointed by the @c accessor_iterator.
* @return Reference to the current element.
*/
value_type& operator*() const
{
return _accessor[_index];
}
/**
* @brief Return a pointer to the current element, which member will be accessed.
* @return Pointer to the element currently pointed by the @c accessor_iterator.
*/
pointer operator->() const
{
return &**this;
}
/**
* @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);
}
private:
accessor<T> _accessor;
unsigned int _index;
private:
accessor<T> _accessor; /**< @internal */
unsigned int _index; /**< @internal */
/**
* @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.
*/
template <typename U>
friend bool operator==(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
{
return lhs._index == rhs._index;
}
/**
* @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>
friend typename accessor_iterator<U>::difference_type
operator-(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
@ -152,6 +367,12 @@ private:
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>
friend
accessor_iterator<U> operator+(accessor_iterator<U> lhs
@ -161,6 +382,12 @@ private:
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>
friend
accessor_iterator<U> operator+(typename accessor_iterator<U>::difference_type lhs
@ -169,12 +396,26 @@ private:
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>
friend bool operator<(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
{
return lhs._index < rhs._index;
}
/**
* @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.
*/
template <typename U>
friend bool operator<=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
{
@ -182,30 +423,63 @@ private:
}
};
/**
* @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);
}
/**
* @brief Check if @p lhs points to a position after 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 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);
}
/**
* @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 Swap content between two <tt>accessor_iterator</tt>s.
* @param lhs First @c accessor_iterator.
* @param rhs Second @c accessor_iterator.
*/
template <typename U>
void swap(accessor_iterator<U>& lhs, accessor_iterator<U>& rhs)
{
lhs.swap(rhs);
}
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -6,8 +6,31 @@
#include <cstdlib>
#include <type_traits>
/**
* @addtogroup Eina_Cxx_Containers_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Clone_Allocators_Group Clone Allocators
* @ingroup Eina_Cxx_Containers_Group
*
* Clone allocators is a formalized way to pointer containers control
* the memory of the stored objects, allowing users to apply custom
* allocators/deallocators for the cloned objects.
*
* @{
*/
/**
* This allocator creates copies of objects on the heap, calling their
* copy constructor to make then equivalent to the given reference.
*
* The created objects are released with the default delete.
*/
struct heap_copy_allocator
{
template <typename T>
@ -27,6 +50,11 @@ struct heap_copy_allocator
}
};
/**
* This allocator allows users to create custom allocation schemes by
* overloading the <tt>new_clone(T const& v)</tt> and
* <tt>delete_clone(T* p)</tt> functions.
*/
struct heap_clone_allocator
{
template <typename T>
@ -41,6 +69,14 @@ struct heap_clone_allocator
}
};
/**
* This allocator does not allocate or deallocate anything. It simple
* gets non-const-qualified pointers for objects, which allow
* containers to hold elements without having ownership on them.
*
* It is commonly used to create a pointer container that is a view into
* another existing container.
*/
struct view_clone_allocator
{
template <typename T>
@ -54,6 +90,11 @@ struct view_clone_allocator
}
};
/**
* This allocator does not define an @c allocate_clone member function,
* so it should be used to disable operations that require elements to
* be cloned.
*/
struct heap_no_copy_allocator
{
template <typename T>
@ -67,6 +108,13 @@ struct heap_no_copy_allocator
}
};
/**
* Manages allocation and deallocation of memory using the function
* @c malloc and @c free. This allocator does not calls constructors,
* the content of the newly allocated objects are assigned using
* @c memcpy, so it is likely only plausible with types that have
* <em>standard-layout</em>.
*/
struct malloc_clone_allocator
{
template <typename T>
@ -86,6 +134,14 @@ struct malloc_clone_allocator
}
};
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -5,48 +5,129 @@
#include <system_error>
/**
* @addtogroup Eina_Cxx_Tools_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Error_Group Error Handling
* @ingroup Eina_Cxx_Tools_Group
*
* @brief Functions for handling Eina errors.
*
* Integrates the Eina errors with the standard error representation
* defined in the @c system_error library.
*
* @{
*/
/** <tt>std::errc</tt> for Eina errors. */
using std::errc;
/** <tt>std::system_error</tt> for Eina errors. */
using std::system_error;
/** <tt>std::error_code</tt> for Eina errors. */
using std::error_code;
/** <tt>std::error_condition</tt> for Eina errors. */
using std::error_condition;
/** <tt>std::error_category</tt> for Eina errors. */
typedef std::error_category system_error_category;
/**
* @brief Return a @c Eina_Error for an unknown error.
* @return @c Eina_Error indicating a unknown/external error condition.
*
* This function returns an @c Eina_Error indicating a unknown/external
* error condition. When first called, this function will register the
* said error within the other Eina errors, together with a error
* message.
*/
inline Eina_Error unknown_error()
{
static Eina_Error error = eina_error_msg_static_register("Error from C++ from another value category error");
return error;
}
/**
* @brief Gets a <tt>std::generic_category</tt> instance as a <tt>eina::system_error_category</tt>.
* @return a <tt>std::generic_category</tt> instance as a <tt>eina::system_error_category</tt>.
*/
inline system_error_category const& get_generic_category()
{
return ::std::generic_category();
}
/**
* @brief Gets a <tt>std::system_category</tt> instance as a <tt>eina::system_error_category</tt>.
* @return <tt>std::system_category</tt> instance as a <tt>eina::system_error_category</tt>.
*/
inline system_error_category const& get_system_category()
{
return ::std::system_category();
}
/**
* @brief Typesafe representation of an @c Eina_Error.
*
* Used for improved compatibility with @e system_error library.
*/
enum error_type {};
/**
* @brief Specialized error category for Eina errors.
*/
struct error_category : system_error_category
{
/**
* @brief Name of the error category.
* @return String containing the word "eina"
*/
const char* name() const throw()
{
return "eina";
}
/**
* @brief Check if the given error code is equivalent to the given error condition.
* @param code Integer representing the error code.
* @param condition <tt>eina::error_condition</tt> object.
* @return @c true if @c code is equivalent to @c condition.
*/
bool equivalent(int code, eina::error_condition const& condition) const throw()
{
return code == condition.value();
}
/**
* @brief Check if the given error code is equivalent to the given error condition.
* @param code <tt>eina::error_code</tt> object.
* @param condition Integer representing the error condition.
* @return @c true if @c code is equivalent to @c condition.
*/
bool equivalent(eina::error_code const& code, int condition) const throw()
{
return code.value() == condition;
}
/**
* @brief Get the message related with the given error condition.
* @param condition Eina error condition.
* @return String containing the message related with the given error condition.
*
* This member function returns the error message related with the
* given error condition code.
*
* @note When the given condition code is not registered within the
* Eina errors it will return a string indicating that an error
* message is not available.
*/
std::string message(int condition) const
{
const char* e = ::eina_error_msg_get(condition);
@ -54,12 +135,29 @@ struct error_category : system_error_category
}
};
/**
* @brief Get a default <tt>eina::error_category</tt> object.
* @return Reference to a static instance of an <tt>eina::error_category</tt>.
*/
inline eina::system_error_category& eina_error_category()
{
static error_category _error_category;
return _error_category;
}
/**
* @brief Gets the error code for the last Eina error.
* @return <tt>eina::error_code</tt> for the last Eina error.
*
* This function gets the error code for the last Eina error and
* consumes it. The category of the returned <tt>eina::error_code</tt>
* is @c eina_error_category.
*
* @note If no errors have been occurred or if this functions have
* already been called after the last error occurrence a call to this
* function will return a default <tt>eina::error_code</tt> to indicates
* that there is no unconsumed error.
*/
inline eina::error_code get_error_code()
{
Eina_Error error = eina_error_get();
@ -72,6 +170,14 @@ inline eina::error_code get_error_code()
return eina::error_code();
}
/**
* @brief Sets an error code in the Eina library.
* @param e Error code. Should be an @c eina_error_category error.
*
* This function sets an error code in the Eina library. If the category
* of the given error code is not @c eina_error_category it will
* register an unknown error instead.
*/
inline void set_error_code(eina::error_code const& e)
{
if(e.category() == eina_error_category())
@ -80,6 +186,13 @@ inline void set_error_code(eina::error_code const& e)
eina_error_set(unknown_error());
}
/**
* @brief Gets the error condition for the last Eina error.
* @return <tt>eina::error_condition</tt> for the last Eina error.
*
* This function works exactly like @ref get_error_code but returns an
* <tt>eina::error_condition</tt> object instead.
*/
inline eina::error_condition get_error_condition()
{
Eina_Error error = eina_error_get();
@ -92,12 +205,35 @@ inline eina::error_condition get_error_condition()
return eina::error_condition();
}
/**
* @brief Gets the enum value of the last Eina error.
* @return Value of the last Eina error as an @c error_type.
*
* This function returns the error code for the last Eina error.
*
* Differently from @ref get_error_code and @ref get_error_condition,
* this function does not consume the last error.
*/
inline error_type get_error_code_enum()
{
return static_cast<error_type>( ::eina_error_get() );
}
/**
* @brief Throw an exception if there is a error set in Eina library.
* @throw <tt>eina::system_error</tt> containing the error identifier.
*
* This function is meant to be used after executing a operation that
* may set an Eina error. If an error code has been set this function
* will throw an exception.
*
* The thrown exception holds an <tt>eina::error_code</tt> equivalent to
* the one returned by @ref get_error_code.
*
* Like the @ref get_error_code function, this one consumes the last
* error code.
*/
inline void throw_on_error()
{
eina::error_code ec = get_error_code();
@ -107,13 +243,28 @@ inline void throw_on_error()
}
}
/**
* @}
*/
} }
/**
* @internal
* Template specialization for interoperability with the @e system_error
* standard library.
* @{
*/
namespace std {
template <> struct is_error_condition_enum< ::efl::eina::error_type> : true_type {};
template <> struct is_error_code_enum< ::efl::eina::error_type> : true_type {};
}
/**
* @}
*/
/**
* @}
*/
#endif

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,24 @@
#include <iterator>
#include <algorithm>
/**
* @addtogroup Eina_Cxx_Containers_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Inline_List_Group Inline List
* @ingroup Eina_Cxx_Containers_Group
*
* @{
*/
/**
* @internal
*/
template <typename T>
struct _inlist_node
{
@ -19,18 +35,27 @@ struct _inlist_node
T object;
};
/**
* @internal
*/
template <typename T>
_inlist_node<T>* _get_node(Eina_Inlist* l)
{
return static_cast<_inlist_node<T>*>(static_cast<void*>(l));
}
/**
* @internal
*/
template <typename T>
_inlist_node<T> const* _get_node(Eina_Inlist const* l)
{
return const_cast<Eina_Inlist*>(l);
}
/**
* @internal
*/
template <typename T>
Eina_Inlist* _get_list(_inlist_node<T>* n)
{
@ -40,38 +65,85 @@ Eina_Inlist* _get_list(_inlist_node<T>* n)
return 0;
}
/**
* @internal
*/
template <typename T>
Eina_Inlist const* _get_list(_inlist_node<T> const* n)
{
return _get_list(const_cast<_inlist_node<T>*>(n));
}
/**
* @internal
* Iterator for Inline List
*/
template <typename T>
struct _inlist_iterator
{
typedef typename std::remove_const<T>::type value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename std::remove_const<T>::type value_type; /**< Type for the list elements. */
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::bidirectional_iterator_tag iterator_category; /**< Defines the iterator as being a bidirectional iterator. */
/**
* @brief Default constructor. Creates an uninitialized iterator.
*/
_inlist_iterator() {}
/**
* @brief Creates an iterator from a inline list and a node.
* @param list Pointer to the inline list.
* @param node Pointer to the node.
*/
explicit _inlist_iterator(_inlist_node<value_type>* list, _inlist_node<value_type>* node)
: _list(list), _node(node) {}
/**
* @brief Copy constructor. Creates a copy of the given iterator.
* @param other Other iterator.
*/
_inlist_iterator(_inlist_iterator<typename std::remove_const<T>::type> const& other)
: _list(other._list), _node(other._node) {}
/**
* @brief Move the iterator to the next position in the list.
* @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.
*/
_inlist_iterator<T>& operator++()
{
_node = _get_node<value_type>(_node->__in_list.next);
return *this;
}
/**
* @brief Move the iterator to the next position in the list.
* @return Copy of the iterator before the increment.
*
* This operator increments the iterator, making it point to the next
* position right after the current one.
* At the end, it returns a copy of the iterator before the increment.
*/
_inlist_iterator<T> operator++(int)
{
_inlist_iterator<T> tmp(*this);
++*this;
return tmp;
}
/**
* @brief Move the iterator to the previous position in the list.
* @return The 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.
*/
_inlist_iterator<T>& operator--()
{
if(_node)
@ -80,32 +152,65 @@ struct _inlist_iterator
_node = _get_node<value_type>(_list->__in_list.last);
return *this;
}
/**
* @brief Move the iterator to the previous position in the list.
* @return Copy of the iterator before the decrement.
*
* 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 iterator before the decrement.
*/
_inlist_iterator<T> operator--(int)
{
_inlist_iterator<T> tmp(*this);
--*this;
return tmp;
}
/**
* @brief Get a reference to the element currently pointed by the iterator.
* @return Reference to the current element.
*/
T& operator*() const
{
return _node->object;
}
/**
* @brief Return a pointer to the current element, which member will be accessed.
* @return Pointer to the element currently pointed by the iterator.
*/
T* operator->() const
{
return &_node->object;
}
/**
* @internal
*/
_inlist_node<value_type>* native_handle()
{
return _node;
}
/**
* @internal
*/
_inlist_node<value_type> const* native_handle() const
{
return _node;
}
private:
_inlist_node<value_type>* _list;
_inlist_node<value_type>* _node;
_inlist_node<value_type>* _list; /**< Handle to the original list. */
_inlist_node<value_type>* _node; /**< Handle to the current node. */
/**
* @brief Check if both iterators are pointing to the same node.
* @param lhs First iterator to be compared.
* @param rhs Second iterator to be compared.
* @return @c true if both iterators are pointing to the same node, @c false otherwise.
*/
template <typename U>
friend struct _inlist_iterator;
friend bool operator==(_inlist_iterator<T> lhs, _inlist_iterator<T> rhs)
@ -114,12 +219,21 @@ private:
}
};
/**
* @brief Check if iterators are not pointing to the same node.
* @param lhs First iterator to be compared.
* @param rhs Second iterator to be compared.
* @return @c true if iterators are not pointing to the same node, @c false otherwise.
*/
template <typename T>
bool operator!=(_inlist_iterator<T> lhs, _inlist_iterator<T> rhs)
{
return !(lhs == rhs);
}
/**
* @internal
*/
struct _inlist_access_traits {
template <typename T>
struct const_iterator
@ -242,49 +356,93 @@ struct _inlist_access_traits {
template <typename T, typename Allocator>
class inlist;
/**
* @ingroup Eina_Cxx_Range_Group
*
* Range for inline list elements.
*/
template <typename T>
struct range_inlist : _range_template<T, _inlist_access_traits>
{
typedef _range_template<T, _inlist_access_traits> _base_type;
typedef typename _base_type::value_type value_type;
typedef typename _base_type::native_handle_type native_handle_type;
typedef _range_template<T, _inlist_access_traits> _base_type; /**< Type for the base class. */
typedef typename _base_type::value_type value_type; /**< The type of each element. */
typedef typename _base_type::native_handle_type native_handle_type; /** Type for the native Eina inline list handle. */
/**
* @brief Creates a range from a native Eina inline list handle.
*/
range_inlist(native_handle_type list)
: _base_type(list) {}
/**
* @brief Creates a range from a inline list object.
*/
template <typename Allocator>
range_inlist(inlist<value_type, Allocator>& list)
: _base_type(list.native_handle())
{}
};
/**
* @brief Check the given ranges are equal to each other.
* @param lhs Range object at the left side of the expression.
* @param rhs Range object at the right side of the expression.
* @return @c true if the ranges are equal, @c false otherwise.
*
* This operator checks if the given ranges are equal to each other. To
* be considered equal both ranges need to have the same size, and each
* element in one range must be equal to the element at the same
* position in the other.
*/
template <typename T>
bool operator==(range_inlist<T>const& lhs, range_inlist<T>const& rhs)
{
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
/**
* @brief Returns the opposite of @ref operator==(range_inlist<T>const& lhs, range_inlist<T>const& rhs).
*/
template <typename U>
bool operator!=(range_inlist<U> const& lhs, range_inlist<U>const& rhs)
{
return !(lhs == rhs);
}
/**
* Common implementations for inline list.
*/
template <typename T, typename Allocator>
struct _inlist_common_base
{
typedef typename Allocator::template rebind<_inlist_node<T> >::other node_allocator_type;
typedef Allocator allocator_type;
typedef _inlist_node<T> node_type;
typedef typename Allocator::template rebind<_inlist_node<T> >::other node_allocator_type; /**< Type for the allocator of the node. */
typedef Allocator allocator_type; /**< Type for the allocator. */
typedef _inlist_node<T> node_type; /**< Type for the list node. */
/**
* @brief Creates a list with the given allocator.
* @param allocator Allocator object.
*/
_inlist_common_base(Allocator allocator)
: _impl(allocator) {}
/**
* @brief Creates an empty inline list.
*/
_inlist_common_base()
{}
/**
* @brief Destructor. Deallocate all nodes of the list.
*/
~_inlist_common_base()
{
clear();
}
/**
* @brief Deallocate all nodes of the list.
*/
void clear()
{
Eina_Inlist* p = _impl._list;
@ -301,11 +459,18 @@ struct _inlist_common_base
}
_impl._list = 0;
}
/**
* @brief Get the allocator used by the list.
*/
node_allocator_type& get_node_allocator()
{
return _impl;
}
/**
* @internal
*/
// For EBO
struct _inlist_impl : node_allocator_type
{
@ -317,40 +482,77 @@ struct _inlist_common_base
Eina_Inlist* _list;
};
_inlist_impl _impl;
_inlist_impl _impl; /**< @internal */
private:
/** Disabled copy constructor. */
_inlist_common_base(_inlist_common_base const& other);
/** Disabled assignment operator. */
_inlist_common_base& operator=(_inlist_common_base const& other);
};
/**
* C++ wrapper for the native Eina inline list.
*
* It provides an OOP interface to the @c Eina_Inlist functions, and
* automatically take care of allocating and deallocating resources using
* the RAII programming idiom.
*
* It also provides additional member functions to facilitate the access
* to the list content, much like a STL list.
*/
template <typename T, typename Allocator = std::allocator<T> >
class inlist : protected _inlist_common_base<T, Allocator>
{
typedef _inlist_common_base<T, Allocator> _base_type;
typedef typename _base_type::node_type _node_type;
typedef _inlist_common_base<T, Allocator> _base_type; /**< Type for the base class. */
typedef typename _base_type::node_type _node_type; /**< Type for each node */
public:
typedef typename _base_type::allocator_type allocator_type;
typedef typename allocator_type::value_type value_type;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef _inlist_iterator<T const> const_iterator;
typedef _inlist_iterator<T> iterator;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef typename _base_type::allocator_type allocator_type; /**< Type for the allocator. */
typedef typename allocator_type::value_type value_type; /**< The type of each element. */
typedef typename allocator_type::reference reference; /**< Type for a reference to an element. */
typedef typename allocator_type::const_reference const_reference; /**< Type for a constant reference to an element. */
typedef _inlist_iterator<T const> const_iterator; /**< Type for constant iterator for this kind of container. */
typedef _inlist_iterator<T> iterator; /**< Type for iterator for this kind of container. */
typedef typename allocator_type::pointer pointer; /**< Type for a pointer to an element. */
typedef typename allocator_type::const_pointer const_pointer; /**< Type for a constant pointer for an element. */
typedef std::size_t size_type; /**< Type for size information. */
typedef std::ptrdiff_t difference_type; /**< Type to represent the distance between two iterators. */
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator for this kind of container. */
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; /**< Type for constant reverse iterator for this kind of container. */
using _base_type::clear;
/**
* @brief Default constructor. Creates an empty inline list.
*/
inlist() {}
/**
* @brief Construct an inline list object with @p n copies of @p t.
* @param n Number of elements.
* @param t Value to be copied to each element.
*
* This constructor creates an inline list with @p n elements, each
* one as a copy of @p t.
*/
inlist(size_type n, value_type const& t)
{
while(n--)
push_back(t);
}
/**
* @brief Create a inline list coping the elements from the given range.
* @param i Iterator to the initial position. The element pointed by this iterator will be copied.
* @param j Iterator to the final position. The element pointed by this iterator will NOT be copied.
*
* This constructor creates a inline list with copies of the elements
* between @p i and @p j in the same order.
*
* @note The ending element (pointed by @p j) is not copied.
*/
template <typename InputIterator>
inlist(InputIterator i, InputIterator const& j
, allocator_type const& alloc = allocator_type()
@ -363,29 +565,74 @@ public:
++i;
}
}
/**
* @brief Copy constructor. Creates a copy of the given inline list.
* @param other Another inline list of the same type.
*
* This constructor creates an inline list containing a copy of each
* element inside @p other in the same order.
*/
inlist(inlist<T, Allocator>const& other)
: _base_type()
{
insert(end(), other.begin(), other.end());
}
/**
* @brief Replace current content with the content of another inline list.
* @param other Another inline list of the same type.
*
* This assignment operator replaces the content of the list by a copy
* of the content of @p other. The list size is adjusted accordingly
* and the newly copied elements keep their original order.
*/
inlist<T, Allocator>& operator=(inlist<T, Allocator>const& other)
{
clear();
insert(end(), other.begin(), other.end());
return *this;
}
/**
* @brief Get the current size of the inline list.
* @return Number of elements in the inline list.
*
* This member function returns the current number of elements inside
* the inline list.
*/
size_type size() const
{
return _inlist_access_traits::size<T>(native_handle());
}
/**
* @brief Check if the inline list is empty.
* @return @c true if the inline list is empty, @c false otherwise.
*
* This member function returns @c true if the inline list does not
* contain any elements, otherwise it returns @c false.
*/
bool empty() const
{
return _inlist_access_traits::empty<T>(native_handle());
}
/**
* @brief Get the allocator used in this inline list.
*/
allocator_type get_allocator() const
{
return allocator_type(this->get_node_allocator());
}
/**
* @brief Add a copy of the given element at the end of the inline list.
* @param value Element to be added at the end of the inline list.
*
* This member function allocates a new element at the end of the
* inline list, the content of @p value is copied to the new element.
*/
void push_back(T const& value)
{
_node_type* node ( this->get_node_allocator().allocate(1) );
@ -401,6 +648,15 @@ public:
throw;
}
}
/**
* @brief Add a copy of the given element at the beginning of the inline list.
* @param value Element to be added at the beginning of the inline list.
*
* This member function allocates a new element at the beginning of
* the inline list, the content of @p value is copied to the new
* element.
*/
void push_front(T const& value)
{
_node_type* node ( this->get_node_allocator().allocate(1) );
@ -416,14 +672,36 @@ public:
throw;
}
}
/**
* @brief Remove the last element of the inline list.
*/
void pop_back()
{
this->_impl._list = eina_inlist_remove(this->_impl._list, this->_impl._list->last);
}
/**
* @brief Remove the first element of the inline list.
*/
void pop_front()
{
this->_impl._list = eina_inlist_remove(this->_impl._list, this->_impl._list);
}
/**
* @brief Insert a new element at the given position.
* @param i Iterator pointing to the position where the new element will be inserted.
* @param t Value to be copied to the new element.
* @return Iterator pointing to the new element inserted.
*
* This member function inserts a copy of the element @p t at the
* position @p i. The new element comes right before the element
* originally pointed by @p i.
*
* At the end, a valid iterator pointing to the element just inserted
* is returned.
*/
iterator insert(iterator i, value_type const& t)
{
_node_type* node ( this->get_node_allocator().allocate(1) );
@ -442,6 +720,21 @@ public:
throw;
}
}
/**
* @brief Insert @p n copies of @p t at the given position.
* @param i Iterator pointing to the position where the new elements will be inserted.
* @param n Number of elements to be inserted.
* @param t Value to be copied to each new inserted element.
* @return Iterator pointing to the first inserted element.
*
* This member function inserts @p n new elements at position @p i
* in the inline list, each one as a copy of @p t. The new elements
* come right before the element originally pointed by @p i.
*
* At the end, a valid iterator pointing to the first element inserted
* is returned.
*/
iterator insert(iterator i, size_t n, value_type const& t)
{
iterator r = i;
@ -452,6 +745,18 @@ public:
return r;
}
/**
* @brief Insert the elements between the given range at the given position.
* @param p Iterator pointing to the position where the new elements will be inserted.
* @param i Iterator to the initial position. The element pointed by this iterator will be copied.
* @param j Iterator to the final position. The element pointed by this iterator will NOT be copied.
* @return Iterator pointing to the first inserted element.
*
* This member function inserts a copy of the elements between @p i
* and @p j at the position @p p. The new elements come right before
* the element originally pointed by @p p. Note that the element
* pointed by @p j is not copied.
*/
template <typename InputIterator>
iterator insert(iterator p, InputIterator i, InputIterator j
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
@ -471,6 +776,15 @@ public:
return r;
}
/**
* @brief Remove the element at the given position.
* @param q Iterator pointing to the element to be removed.
* @return Iterator pointing to the element after the removed one.
*
* This member function removes the element pointed by the iterator
* @p q, reducing the list size by one. At the end, a valid iterator
* pointing to the element right after the removed one is returned.
*/
iterator erase(iterator q)
{
if(q.native_handle())
@ -483,6 +797,20 @@ public:
return q;
}
/**
* @brief Remove the elements between the given range.
* @param i Iterator pointing to the starting position to be removed.
* @param j Iterator pointing to the ending position to be removed.
* The element pointed by this iterator is not removed.
* @return Iterator pointing to the new position of the first
* non-removed element after the removed ones (i.e. the one
* originally pointed by @p j).
*
* This member function removes the elements between the iterators
* @p i and @p j, including the element pointed by @p i but not the
* element pointed by @j.
*/
iterator erase(iterator i, iterator j)
{
while(i != j)
@ -493,6 +821,18 @@ public:
return end();
}
/**
* @brief Replace the content of the inline list by the elements in the given range.
* @param i Iterator pointing to the beginning of the elements to be copied.
* @param j Iterator pointing to the end of the elements to be copied.
* Note that the element pointed by j will NOT be copied.
*
* This member function replaces the current elements by copies of the
* elements between the iterators @p i and @p j, including the element
* pointed by @p i but not the one pointed by @p j. The size of the
* list is adjusted accordingly and the newly copied elements remain
* in their original order.
*/
template <typename InputIterator>
void assign(InputIterator i, InputIterator j
, typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
@ -501,99 +841,296 @@ public:
insert(end(), i, j);
}
/**
* @brief Replace the content of the inline list by @p n copies @p t.
* @param n Number of elements.
* @param t Value to be copied to each element.
*/
void assign(size_type n, value_type const& t)
{
clear();
insert(end(), n, t);
}
/**
* @brief Get a reference to the last element.
* @return Reference to the last element in the inline list.
*/
value_type& back()
{
return _inlist_access_traits::back<T>(native_handle());
}
/**
* @brief Get a constant reference to the last element.
* @return Constant reference to the last element in the inline list.
*
* Version of @ref back() for const-qualified inline list objects.
* Returns a constant reference instead.
*/
value_type const& back() const
{
return _inlist_access_traits::back<T>(native_handle());
}
/**
* @brief Get a reference to the first element.
* @return Reference to the first element of the inline list.
*/
value_type& front()
{
return _inlist_access_traits::front<T>(native_handle());
}
/**
* @brief Get a constant reference to the first element.
* @return Constant reference to the first element of the inline list.
*
* Version of @ref front() for const-qualified inline list objects.
* Returns a constant reference instead.
*/
value_type const& front() const
{
return _inlist_access_traits::front<T>(native_handle());
}
/**
* @brief Get a constant iterator pointing to the first element of the inline list.
* @return Constant iterator to the initial position of the inline list.
*
* Version of @ref begin() for const-qualified inline list objects.
* Returns a constant iterator instead.
*/
const_iterator begin() const
{
return _inlist_access_traits::begin<T>(native_handle());
}
/**
* @brief Get a constant iterator to the position following the last element of the inline list.
* @return Constant iterator to the final position of the inline list.
*
* Version of @ref end() for const-qualified inline list objects.
* Returns a constant iterator instead.
*/
const_iterator end() const
{
return _inlist_access_traits::end<T>(native_handle());
}
/**
* @brief Get an iterator pointing to the first element of the inline list.
* @return Iterator to the initial position of the inline list.
*
* This member function returns an iterator pointing to the first
* element of the inline list. If the list is empty the returned
* iterator is the same as the one returned by @ref end().
*/
iterator begin()
{
return _inlist_access_traits::begin<T>(native_handle());
}
/**
* @brief Get an iterator to the position following the last element of the inline list.
* @return Iterator to the final position of the inline list.
*
* This member function returns an iterator to the position following
* the last element in the inline list. If the list is empty the
* returned iterator is the same as the one returned by @ref begin().
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
iterator end()
{
return _inlist_access_traits::end<T>(native_handle());
}
/**
* @brief Get a constant reverse iterator pointing to the reverse begin of the inline list.
* @return Constant reverse iterator pointing to the reverse begin of the inline list.
*
* Version of @ref rbegin() for const-qualified inline list objects.
* Returns a constant reverse iterator instead.
*/
const_reverse_iterator rbegin() const
{
return reverse_iterator(end());
}
/**
* @brief Get a constant reverse iterator pointing to the reverse end of the inline list.
* @return Constant reverse iterator pointing to the reverse end of the inline list.
*
* Version of @ref rend() for const-qualified inline list objects.
* Returns a constant reverse iterator instead.
*/
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
/**
* @brief Get a reverse iterator pointing to the reverse begin of the inline list.
* @return Reverse iterator pointing to the reverse begin of the inline list.
*
* This member function returns a reverse iterator pointing to the
* last element of the inline list. If the list is empty the returned
* reverse iterator is the same as the one returned by @ref rend().
*/
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
/**
* @brief Get a reverse iterator pointing to the reverse end of the inline list.
* @return Reverse iterator pointing to the reverse end of the inline list.
*
* This member function returns a reverse iterator pointing to the
* position before the first element of the inline list. If the list
* is empty the returned iterator is the same as the one returned by
* @ref rbegin().
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
reverse_iterator rend()
{
return reverse_iterator(begin());
}
/**
* @brief Get a constant iterator pointing to the first element of the inline list.
* @return Constant iterator to the initial position of the inline list.
*
* This member function works like @ref begin() const but is granted
* to return a constant iterator even for lists that are not
* const-qualified.
*/
const_iterator cbegin() const
{
return begin();
}
/**
* @brief Get a constant iterator to the position following the last element of the inline list.
* @return Constant iterator to the final position of the inline list.
*
* This member function works like @ref end() const but is granted to
* return a constant iterator even for lists that are not
* const-qualified.
*/
const_iterator cend() const
{
return end();
}
/**
* @brief Get a constant reverse iterator pointing to the reverse begin of the inline list.
* @return Constant reverse iterator pointing to the reverse begin of the inline list.
*
* This member function works like @ref rbegin() const but is granted
* to return a constant reverse iterator even for lists that are not
* const-qualified.
*/
const_reverse_iterator crbegin() const
{
return rbegin();
}
/**
* @brief Get a constant reverse iterator pointing to the reverse end of the inline list.
* @return Constant reverse iterator pointing to the reverse end of the inline list.
*
* This member function works like @ref rend() const but is granted to
* return a constant reverse iterator even for lists that are not
* const-qualified.
*/
const_reverse_iterator crend() const
{
return rend();
}
/**
* @brief Swap content between two inline lists.
* @param other Other inline list of the same type.
*/
void swap(inlist<T, Allocator>& other)
{
std::swap(this->_impl._list, other._impl._list);
}
/**
* @brief Get the maximum number of elements a inline list can hold.
* @return Maximum number of elements a inline list can hold.
*/
size_type max_size() const { return -1; }
/**
* @brief Get the handle for the wrapped Eina_Inlist.
* @return Internal handle for the native Eina inline list.
*
* This member function returns the native Eina_Inlist 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_Inlist* native_handle()
{
return this->_impl._list;
}
/**
* @brief Get the handle for the wrapped Eina_Inlist.
* @return Internal handle for the native Eina inline list.
*
* This member function returns the native Eina_Inlist 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_Inlist const* native_handle() const
{
return this->_impl._list;
}
/**
* @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_inlist_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_inlist_accessor_new(this->_impl._list));
}
};
/**
* @brief Check if two inline lists are equal.
* @param lhs Inline list at the left side of the expression.
* @param rhs Inline list at the right side of the expression.
* @return @c true if the lists are equals, @c false otherwise.
*
* This operator checks if the given inline lists are equal. To be
* considered equal both lists need to have the same number of elements,
* and each element in one list must be equal to the element at the same
* position in the other list.
*/
template <typename T, typename Allocator1, typename Allocator2>
bool operator==(inlist<T, Allocator1> const& lhs, inlist<T, Allocator2> const& rhs)
{
@ -601,18 +1138,33 @@ bool operator==(inlist<T, Allocator1> const& lhs, inlist<T, Allocator2> const& r
std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
/**
* @brief Return the opposite of @ref operator==(inlist<T, Allocator1> const& lhs, inlist<T, Allocator2> const& rhs).
*/
template <typename T, typename Allocator1, typename Allocator2>
bool operator!=(inlist<T, Allocator1> const& lhs, inlist<T, Allocator2> const& rhs)
{
return !(lhs == rhs);
}
/**
* @brief Swap content between two inline lists.
* @param other Other inline list of the same type.
*/
template <typename T, typename Allocator>
void swap(inlist<T, Allocator>& lhs, inlist<T, Allocator>& rhs)
{
lhs.swap(rhs);
}
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -1,18 +1,42 @@
#ifndef EINA_CXX_EINA_INTEGER_SEQUENCE_HH
#define EINA_CXX_EINA_INTEGER_SEQUENCE_HH
/**
* @addtogroup Eina_Cxx_Data_Types_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Integer_Sequence_Group Integer Sequence
* @ingroup Eina_Cxx_Data_Types_Group
*
* @{
*/
/**
* Compile-time sequence of integers.
*/
template <typename T, T... Ints>
struct integer_sequence
{
typedef T value_type;
typedef T value_type; /**< Type of the integers. */
/**
* @brief Get the number of elements in the sequence.
* @return <tt>std::size_t</tt> representing the sequence size.
*/
static constexpr std::size_t size() { return sizeof...(Ints); }
typedef integer_sequence<T, Ints...> type;
typedef integer_sequence<T, Ints...> type; /**< Type for the sequence instantiation. */
};
template<class S1, class S2> struct concat;
/**
* Compile-time concatenation of two integer sequences.
*/
template<typename T, T... I1, T... I2>
struct concat<integer_sequence<T, I1...>, integer_sequence<T, I2...> >
: integer_sequence<T, I1..., (sizeof...(I1)+I2)...> {};
@ -21,6 +45,10 @@ template<class S1, class S2>
using Concat = typename concat<S1, S2>::type;
template<typename T, T N> struct gen_seq;
/**
* Make a compile time sequence of integers from @c 0 to <tt>N-1</tt>.
*/
template<typename T, T N> using make_integer_sequence = typename gen_seq<T, N>::type;
template<typename T, T N>
@ -30,12 +58,26 @@ struct gen_seq : Concat<make_integer_sequence<T, N/2>
template<> struct gen_seq<std::size_t, 0> : integer_sequence<std::size_t>{};
template<> struct gen_seq<std::size_t, 1> : integer_sequence<std::size_t, 0>{};
/**
* Compile time sequence of indexes.
*/
template <std::size_t... I>
using index_sequence = integer_sequence<std::size_t, I...>;
/**
* Make a compile time sequence of indexes from @c 0 to <tt>N-1</tt>.
*/
template <std::size_t I>
using make_index_sequence = make_integer_sequence<std::size_t, I>;
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -6,33 +6,86 @@
#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;
typedef _common_iterator_base<T> self_type; /**< Type for the iterator instantiation itself. */
public:
typedef T const value_type;
typedef value_type* pointer;
typedef value_type& reference;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
typedef T 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 an OOP 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;
@ -41,38 +94,76 @@ public:
}
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 an OOP interface to the @c Eina_Iterator functions, and
* automatically take care of allocating a deallocating resources using
* the RAII programming idiom.
*/
template <typename T>
struct iterator : _common_iterator_base<T const>
{
private:
typedef _common_iterator_base<T const> base_type;
typename base_type::pointer _value;
typedef iterator<T> self_type;
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;
typedef typename base_type::pointer pointer;
typedef typename base_type::reference reference;
typedef typename base_type::difference_type difference_type;
typedef typename base_type::iterator_category iterator_category;
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 an OOP interface to it.
*/
explicit iterator(Eina_Iterator* iterator = 0)
: base_type(iterator)
{
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;
@ -82,20 +173,45 @@ public:
_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;
}
};
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -3,8 +3,17 @@
#include <Eina.h>
/**
* @addtogroup Eina_Cxx_Containers_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @internal
*/
inline Eina_List* _eina_list_prepend_relative_list(Eina_List* list, const void* data, Eina_List* relative) EINA_ARG_NONNULL(2)
{
if(relative)
@ -13,6 +22,9 @@ inline Eina_List* _eina_list_prepend_relative_list(Eina_List* list, const void*
return ::eina_list_append(list, data);
}
/**
* @internal
*/
inline Eina_Inlist *_eina_inlist_prepend_relative(Eina_Inlist *in_list,
Eina_Inlist *in_item,
Eina_Inlist *in_relative) EINA_ARG_NONNULL(2)
@ -25,4 +37,8 @@ inline Eina_Inlist *_eina_inlist_prepend_relative(Eina_Inlist *in_list,
} }
/**
* @}
*/
#endif

View File

@ -3,39 +3,102 @@
#include <sstream>
/**
* @addtogroup Eina_Cxx_Tools_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Log_Group Log
* @ingroup Eina_Cxx_Tools_Group
*
* @{
*/
/**
* Types to represent each log level.
*
* @{
*/
namespace log_level {
/**
* Type for representing a critical log level.
*/
struct critical_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_CRITICAL; };
/** Critical log level */
critical_t const critical = {};
/**
* Type for representing an error log level.
*/
struct error_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_ERR; };
/** Error log level */
error_t const error = {};
/**
* Type for representing an information log level.
*/
struct info_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_INFO; };
/** Information log level */
info_t const info = {};
/**
* Type for representing a debug log level.
*/
struct debug_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_DBG; };
/** Debug log level */
debug_t const debug = {};
/**
* Type for representing a warning log level.
*/
struct warn_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_WARN; };
/** Warning log level */
warn_t const warning = {};
}
/**
* @}
*/
/**
* Base implementation for log domains.
*/
template <typename D>
struct _domain_base
{
/**
* @brief Set the domain log level based on the given log level type.
*
* @{
*/
void set_level(log_level::critical_t l) { set_level(l.value); }
void set_level(log_level::error_t l) { set_level(l.value); }
void set_level(log_level::info_t l) { set_level(l.value); }
void set_level(log_level::debug_t l) { set_level(l.value); }
void set_level(log_level::warn_t l) { set_level(l.value); }
/**
* @}
*/
/**
* @brief Set the domain log level to the level specified by the given identifier.
* @param l Eina native identifier to a log level.
*/
void set_level( ::Eina_Log_Level l)
{
::eina_log_domain_registered_level_set(static_cast<D&>(*this).domain_raw(), l);
}
/**
* @brief Get the domain log level.
* @return Eina native identifier representing the current log level of the domain.
*/
::Eina_Log_Level get_level() const
{
return static_cast< ::Eina_Log_Level>
@ -43,35 +106,72 @@ struct _domain_base
}
};
/**
* @internal
*/
struct global_domain : _domain_base<global_domain>
{
int domain_raw() const { return EINA_LOG_DOMAIN_GLOBAL; }
};
/**
* General purpose log domain.
* It is always registered and available everywhere.
*/
struct global_domain const global_domain = {};
/**
* @internal
*/
struct default_domain : _domain_base<default_domain>
{
int domain_raw() const { return EINA_LOG_DOMAIN_DEFAULT; }
};
/**
* Default log domain.
* If the macro @c EINA_LOG_DOMAIN_DEFAULT is not defined to anything
* different it will be equivalent to @c global_domain.
*/
struct default_domain const default_domain = {};
/**
* Class for creating log domains. It register a new domain upon
* construction and unregister it upon destruction, following the RAII
* programming idiom.
*/
struct log_domain : _domain_base<log_domain>
{
/**
* @brief Creates a new log domain.
* @param name Name of the domain.
* @param color Color of the domain name.
*/
log_domain(char const* name, char const* color = "black")
: _domain( ::eina_log_domain_register(name, color))
{
}
/**
* @brief Unregister the domain.
*/
~log_domain()
{
::eina_log_domain_unregister(_domain);
}
int domain_raw() const { return _domain; }
private:
/**
* @internal
*
* Member variable that holds the domain identifier.
*/
int _domain;
};
/**
* @internal
*/
inline void _log(std::stringstream const& stream, int domain, ::Eina_Log_Level level
, const char* file, const char* function, int line)
{
@ -79,6 +179,17 @@ inline void _log(std::stringstream const& stream, int domain, ::Eina_Log_Level l
, "%s", stream.str().c_str());
}
/**
* @def EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*
* Logs a message with level %p LEVEL on the domain %p DOMAIN.
*
* It works like a STL output stream and should be used with the left
* shift operator. Example:
* \code{.py}
* EINA_CXX_DOM_LOG(my_domain, my_log_level) << "My log message.";
* \endcode
*/
#define EINA_CXX_DOM_LOG(DOMAIN, LEVEL) \
for( bool run = ::eina_log_domain_level_check((DOMAIN), LEVEL); run;) \
for(std::stringstream stream; run ; \
@ -86,39 +197,157 @@ inline void _log(std::stringstream const& stream, int domain, ::Eina_Log_Level l
, __FILE__, __FUNCTION__, __LINE__), run = false) \
stream
/**
* @def EINA_CXX_DOM_LOG_CRIT(DOMAIN)
*
* Logs a message with level %c EINA_LOG_LEVEL_CRITICAL on the domain
* %p DOMAIN.
*
* It is a short for EINA_CXX_DOM_LOG(DOMAIN, ::EINA_LOG_LEVEL_CRITICAL).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_DOM_LOG_CRIT(DOMAIN) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_CRITICAL)
/**
* @def EINA_CXX_DOM_LOG_ERR(DOMAIN)
*
* Logs a message with level %c EINA_LOG_LEVEL_ERR on the domain
* %p DOMAIN.
*
* It is a short for EINA_CXX_DOM_LOG(DOMAIN, ::EINA_LOG_LEVEL_ERR).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_DOM_LOG_ERR(DOMAIN) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_ERR)
/**
* @def EINA_CXX_DOM_LOG_INFO(DOMAIN)
*
* Logs a message with level %c EINA_LOG_LEVEL_INFO on the domain
* %p DOMAIN.
*
* It is a short for EINA_CXX_DOM_LOG(DOMAIN, ::EINA_LOG_LEVEL_INFO).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_DOM_LOG_INFO(DOMAIN) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_INFO)
/**
* @def EINA_CXX_DOM_LOG_DBG(DOMAIN)
*
* Logs a message with level %c EINA_LOG_LEVEL_DBG on the domain
* %p DOMAIN.
*
* It is a short for EINA_CXX_DOM_LOG(DOMAIN, ::EINA_LOG_LEVEL_DBG).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_DOM_LOG_DBG(DOMAIN) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_DBG)
/**
* @def EINA_CXX_DOM_LOG_WARN(DOMAIN)
*
* Logs a message with level %c EINA_LOG_LEVEL_WARN on the domain
* %p DOMAIN.
*
* It is a short for EINA_CXX_DOM_LOG(DOMAIN, ::EINA_LOG_LEVEL_WARN).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_DOM_LOG_WARN(DOMAIN) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_WARN)
/**
* @def EINA_CXX_LOG(LEVEL)
*
* Logs a message with level %p LEVEL on the default domain
* %c EINA_LOG_DOMAIN_DEFAULT.
*
* It is a short for EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, LEVEL).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_LOG(LEVEL) \
EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, LEVEL)
/**
* @def EINA_CXX_LOG_CRIT()
*
* Logs a message with level %c EINA_LOG_LEVEL_CRITICAL on the default
* domain %c EINA_LOG_DOMAIN_DEFAULT.
*
* It is a short for EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, ::EINA_LOG_LEVEL_CRITICAL).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_LOG_CRIT() \
EINA_CXX_LOG(EINA_LOG_LEVEL_CRITICAL)
/**
* @def EINA_CXX_LOG_ERR()
*
* Logs a message with level %c EINA_LOG_LEVEL_ERR on the default
* domain %c EINA_LOG_DOMAIN_DEFAULT.
*
* It is a short for EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, ::EINA_LOG_LEVEL_ERR).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_LOG_ERR() \
EINA_CXX_LOG(EINA_LOG_LEVEL_ERR)
/**
* @def EINA_CXX_LOG_INFO()
*
* Logs a message with level %c EINA_LOG_LEVEL_INFO on the default
* domain %c EINA_LOG_DOMAIN_DEFAULT.
*
* It is a short for EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, ::EINA_LOG_LEVEL_INFO).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_LOG_INFO() \
EINA_CXX_LOG(EINA_LOG_LEVEL_INFO)
/**
* @def EINA_CXX_LOG_DBG()
*
* Logs a message with level %c EINA_LOG_LEVEL_DBG on the default
* domain %c EINA_LOG_DOMAIN_DEFAULT.
*
* It is a short for EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, ::EINA_LOG_LEVEL_DBG).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_LOG_DBG() \
EINA_CXX_LOG(EINA_LOG_LEVEL_DBG)
/**
* @def EINA_CXX_LOG_WARN()
*
* Logs a message with level %c EINA_LOG_LEVEL_WARN on the default
* domain %c EINA_LOG_DOMAIN_DEFAULT.
*
* It is a short for EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, ::EINA_LOG_LEVEL_WARN).
*
* @see EINA_CXX_DOM_LOG(DOMAIN, LEVEL)
*/
#define EINA_CXX_LOG_WARN() \
EINA_CXX_LOG(EINA_LOG_LEVEL_WARN)
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -5,8 +5,17 @@
#include <algorithm>
#include <utility>
/**
* @addtogroup Eina_Cxx_Data_Types_Group
*
* @{
*/
namespace efl_eina_swap_adl {
/**
* @internal
*/
template <typename T>
void swap_impl(T& lhs, T& rhs)
{
@ -18,34 +27,105 @@ void swap_impl(T& lhs, T& rhs)
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Optional_Group Optional Value
* @ingroup Eina_Cxx_Data_Types_Group
*
* @{
*/
/**
* @internal
*/
template <typename T>
void adl_swap(T& lhs, T& rhs)
{
::efl_eina_swap_adl::swap_impl<T>(lhs, rhs);
}
/**
* This class manages an optional contained value, i.e. a value that
* semantically may not be present.
*
* A common use case for optional is the return value of a function that
* may fail. As opposed to other approaches, such as
* <tt>std::pair<T,bool></tt>, optional handles expensive to construct
* objects well and is more readable, as the intent is expressed
* explicitly.
*
* An optional object holding a semantically present value is considered
* to be @em engaged, otherwise it is considered to be @em disengaged.
*/
template <typename T>
struct optional
{
typedef optional<T> _self_type;
typedef optional<T> _self_type; /**< Type for the optional class itself. */
/**
* @brief Create a disengaged object.
*
* This constructor creates a disengaged <tt>eina::optional</tt>
* object, since null pointer is meant to be a valid object type.
*/
optional(std::nullptr_t) : engaged(false)
{}
/**
* @brief Default constructor. Create a disengaged object.
*/
optional() : engaged(false)
{}
/**
* @brief Create an engaged object by moving @p other content.
* @param other R-value reference to the desired type.
*
* This constructor creates an <tt>eina::optional</tt> object in an
* engaged state. The contained value is initialized by moving
* @p other.
*/
optional(T&& other) : engaged(false)
{
_construct(std::move(other));
}
/**
* @brief Create an engaged object by copying @p other content.
* @param other Constant reference to the desired type.
*
* This constructor creates an <tt>eina::optional</tt> object in an
* engaged state. The contained value is initialized by copying
* @p other.
*/
optional(T const& other) : engaged(false)
{
_construct(std::move(other));
}
/**
* @brief Copy constructor. Create an object containing the same value as @p other and in the same state.
* @param other Constant reference to another <tt>eina::optional</tt> object that holds the same value type.
*
* This constructor creates an <tt>eina::optional</tt> object with
* the same engagement state of @p other. If @p other is engaged then
* the contained value of the newly created object is initialized by
* copying the contained value of @p other.
*/
optional(optional<T> const& other)
: engaged(false)
{
if(other.engaged) _construct(*other);
}
/**
* @brief Move constructor. Create an object containing the same value as @p other and in the same state.
* @param other R-value reference to another <tt>eina::optional</tt> object that holds the same value type.
*
* This constructor creates an <tt>eina::optional</tt> object with
* the same engagement state of @p other. If @p other is engaged then
* the contained value of the newly created object is initialized by
* moving the contained value of @p other.
*/
optional(optional<T>&& other)
: engaged(false)
{
@ -53,6 +133,16 @@ struct optional
other._destroy();
}
/**
* @brief Assign new content to the object.
* @param other R-value reference to another <tt>eina::optional</tt> object that holds the same value type.
*
* This operator replaces the current content of the object. If
* @p other is engaged its contained value is moved to this object,
* making <tt>*this</tt> be considered engaged too. If @p other is
* disengaged <tt>*this</tt> is also made disengaged and its
* contained value, if any, is simple destroyed.
*/
_self_type& operator=(optional<T>&& other)
{
_destroy();
@ -62,6 +152,17 @@ struct optional
other._destroy();
return *this;
}
/**
* @brief Assign new content to the object.
* @param other Constant reference to another <tt>eina::optional</tt> object that holds the same value type.
*
* This operator replaces the current content of the object. If
* @p other is engaged its contained value is copied to this object,
* making <tt>*this</tt> be considered engaged too. If @p other is
* disengaged <tt>*this</tt> is also made disengaged and its
* contained value, if any, is simple destroyed.
*/
_self_type& operator=(optional<T>const& other)
{
optional<T> tmp(other);
@ -69,37 +170,80 @@ struct optional
return *this;
}
/**
* @brief Releases the contained value if the object is engaged.
*/
~optional()
{
_destroy();
}
/**
* @brief Convert to @c bool based on whether the object is engaged or not.
* @return @c true if the object is engaged, @c false otherwise.
*/
explicit operator bool() const
{
return is_engaged();
}
/**
* @brief Convert to @c bool based on whether the object is engaged or not.
* @return @c true if the object is disengaged, @c false otherwise.
*/
bool operator!() const
{
bool b ( *this );
return !b;
}
/**
* @brief Access member of the contained value.
* @return Pointer to the contained value, whose member will be accessed.
*/
T* operator->()
{
assert(is_engaged());
return static_cast<T*>(static_cast<void*>(&buffer));
}
/**
* @brief Access constant member of the contained value.
* @return Constant pointer to the contained value, whose member will be accessed.
*/
T const* operator->() const
{
return const_cast<_self_type&>(*this).operator->();
}
/**
* @brief Get the contained value.
* @return Reference to the contained value.
*/
T& operator*() { return get(); }
/**
* @brief Get the contained value.
* @return Constant reference to the contained value.
*/
T const& operator*() const { return get(); }
/**
* @brief Get the contained value.
* @return Reference to the contained value.
*/
T& get() { return *this->operator->(); }
/**
* @brief Get the contained value.
* @return Constant reference to the contained value.
*/
T const& get() const { return *this->operator->(); }
/**
* @brief Swap content with another <tt>eina::optional</tt> object.
* @param other Another <tt>eina::optional</tt> object.
*/
void swap(optional<T>& other)
{
if(is_engaged() && other.is_engaged())
@ -118,11 +262,19 @@ struct optional
}
}
/**
* @brief Check if the object is engaged.
* @return @c true if the object is currently engaged, @c false otherwise.
*/
bool is_engaged() const
{
return engaged;
}
private:
/**
* @internal
*/
template <typename U>
void _construct(U&& object)
{
@ -130,6 +282,10 @@ private:
new (&buffer) T(std::move(object));
engaged = true;
}
/**
* @internal
*/
void _destroy()
{
if(is_engaged())
@ -141,16 +297,36 @@ private:
typedef typename std::aligned_storage
<sizeof(T),std::alignment_of<T>::value>::type buffer_type;
/**
* Member variable for holding the contained value.
*/
buffer_type buffer;
/**
* Flag to tell whether the object is engaged or not.
*/
bool engaged;
};
/**
* @brief Swap content with another <tt>eina::optional</tt> object.
*
*/
template <typename T>
void swap(optional<T>& lhs, optional<T>& rhs)
{
lhs.swap(rhs);
}
/**
* @brief Check if both <tt>eina::optional</tt> object are equal.
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
* @return @c true if both are objects are disengaged of if both objects
* are engaged and contain the same value, @c false in all
* other cases.
*/
template <typename T>
bool operator==(optional<T> const& lhs, optional<T> const& rhs)
{
@ -161,11 +337,28 @@ bool operator==(optional<T> const& lhs, optional<T> const& rhs)
else
return *lhs == *rhs;
}
/**
* @brief Check if the <tt>eina::optional</tt> objects are different.
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
* @return The opposite of @ref operator==(optional<T> const& lhs, optional<T> const& rhs).
*/
template <typename T>
bool operator!=(optional<T> const& lhs, optional<T> const& rhs)
{
return !(lhs == rhs);
}
/**
* @brief Less than comparison between <tt>eina::optional</tt> objects.
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
* @return @c true if both objects are engaged and the contained value
* of @p lhs is less than the contained value of @p rhs, or if
* only @p lhs is disengaged. In all other cases returns
* @c false.
*/
template <typename T>
bool operator<(optional<T> const& lhs, optional<T> const& rhs)
{
@ -178,22 +371,60 @@ bool operator<(optional<T> const& lhs, optional<T> const& rhs)
else
return *lhs < *rhs;
}
/**
* @brief Less than or equal comparison between <tt>eina::optional</tt> objects.
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
* @return @c true if @p lhs is disengaged or if both objects are
* engaged and the contained value of @p lhs is less than or
* equal to the contained value of @p rhs. In all other cases
* returns @c false.
*/
template <typename T>
bool operator<=(optional<T> const& lhs, optional<T> const& rhs)
{
return lhs < rhs || lhs == rhs;
}
/**
* @brief More than comparison between <tt>eina::optional</tt> objects.
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
* @return @c true if both objects are engaged and the contained value
* of @p lhs is more than the contained value of @p rhs, or if
* only @p rhs is disengaged. In all other cases returns
* @c false.
*/
template <typename T>
bool operator>(optional<T> const& lhs, optional<T> const& rhs)
{
return !(lhs <= rhs);
}
/**
* @brief More than or equal comparison between <tt>eina::optional</tt> objects.
* @param lhs <tt>eina::optional</tt> object at the left side of the expression.
* @param rhs <tt>eina::optional</tt> object at the right side of the expression.
* @return @c true if @p rhs is disengaged or if both objects are
* engaged and the contained value of @p lhs is more than or
* equal to the contained value of @p rhs. In all other
* cases returns @c false.
*/
template <typename T>
bool operator>=(optional<T> const& lhs, optional<T> const& rhs)
{
return !(lhs < rhs);
}
/**
* @}
*/
} } // efl::eina
/**
* @}
*/
#endif // EINA_OPTIONAL_HH_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,159 +1,377 @@
#ifndef EINA_RANGE_TYPES_HH_
#define EINA_RANGE_TYPES_HH_
/**
* @addtogroup Eina_Cxx_Content_Access_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Range_Group Range
* @ingroup Eina_Cxx_Content_Access_Group
*
* @{
*/
/**
* @brief Range implementation for immutable collections.
*/
template <typename T, typename Traits>
struct _const_range_template
{
typedef typename Traits::template const_iterator<T>::type const_iterator;
typedef typename Traits::template iterator<T>::type iterator;
typedef T value_type;
typedef T& reference;
typedef T const& const_reference;
typedef T* pointer;
typedef T const* const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef typename Traits::template const_iterator<T>::type const_iterator; /**< Type for constant iterator to the range. */
typedef typename Traits::template iterator<T>::type iterator; /**< Type for iterator to the range. */
typedef T value_type; /**< The type of each element. */
typedef T& reference; /**< Type for a reference to an element. */
typedef T const& const_reference; /**< Type for a constant reference to an element. */
typedef T* pointer; /**< Type for a pointer to an element. */
typedef T const* const_pointer; /**< Type for a constant pointer to an element. */
typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for reverse iterator to the range. */
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; /**< Type for constant reverse iterator to the range. */
typedef std::size_t size_type; /**< Type for size information. */
typedef std::ptrdiff_t difference_type; /**< Type to represent the distance between two iterators. */
typedef typename Traits::template const_native_handle<T>::type native_handle_type;
typedef _const_range_template<T, Traits> _self_type;
typedef typename Traits::template const_native_handle<T>::type native_handle_type; /**< Type for the native handle of the container. */
typedef _const_range_template<T, Traits> _self_type; /**< Type of the range itself. */
/**
* @brief Creates a range object wrapping the given native container handle.
*/
_const_range_template(native_handle_type handle)
: _handle(handle) {}
/**
* @brief Get a constant handle for the native Eina container.
* @return Constant handle for the native Eina container.
*/
native_handle_type native_handle() const { return _handle; }
/**
* @brief Get a constant reference to the last element.
* @return Constant reference to the last element of the range.
*/
value_type const& back() const
{
return Traits::template back<value_type>(_handle);
}
/**
* @brief Get a constant reference to the first element.
* @return Constant reference to the first element of the range.
*/
value_type const& front() const
{
return Traits::template front<value_type>(_handle);
}
/**
* @brief Get a constant iterator pointing to the first element of the range.
* @return Constant iterator to the initial position of the range.
*
* This member function returns a constant iterator pointing to the
* first element of the range. If the range contains no elements the
* returned iterator is the same as the one returned by @ref end() const.
*/
const_iterator begin() const
{
return cbegin();
}
/**
* @brief Get a constant iterator to the position following the last element of the range.
* @return Constant iterator to the final position of the range.
*
* This member function returns a constant iterator to the position
* following the last element in the range. If the range contains no
* elements the returned iterator is the same as the one returned by
* @ref begin() const.
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
const_iterator end() const
{
return cend();
}
/**
* @brief Get a constant reverse iterator pointing to the reverse begin of the range.
* @return Constant reverse iterator pointing to the reverse begin of the range.
*
* This member function works like @ref rbegin() const but is granted
* to return a constant reverse iterator even for a range to a mutable
* collection.
*/
const_reverse_iterator crbegin() const
{
return const_reverse_iterator(Traits::template rbegin<value_type>(_handle));
}
/**
* @brief Get a constant reverse iterator pointing to the reverse end of the range.
* @return Constant reverse iterator pointing to the reverse end of the range.
*
* This member function works like @ref rend() const but is granted to
* return a constant reverse iterator even for range to a mutable
* collection.
*/
const_reverse_iterator crend() const
{
return const_reverse_iterator(Traits::template rend<value_type>(_handle));
}
/**
* @brief Get a constant iterator pointing to the first element of the range.
* @return Constant iterator to the initial position of the range.
*
* This member function works like @ref begin() const but is granted
* to return a constant iterator even for a range to a mutable
* collection.
*/
const_iterator cbegin() const
{
return Traits::template cbegin<value_type>(_handle);
}
/**
* @brief Get a constant iterator to the position following the last element of the range.
* @return Constant iterator to the final position of the range.
*
* This member function works like @ref end() const but is granted to
* return a constant iterator even for a range to a mutable collection.
*/
const_iterator cend() const
{
return Traits::template cend<value_type>(_handle);
}
/**
* @brief Get a constant reverse iterator pointing to the reverse begin of the range.
* @return Constant reverse iterator pointing to the reverse begin of the range.
*
* This member function returns a constant reverse iterator pointing
* to the last element of the range. If the range is empty the
* returned reverse iterator is the same as the one returned by
* @ref rend().
*/
const_reverse_iterator rbegin()
{
return crbegin();
}
/**
* @brief Get a constant reverse iterator pointing to the reverse end of the range.
* @return Constant reverse iterator pointing to the reverse end of the range.
*
* This member function returns a constant reverse iterator pointing
* to the position before the first element of the range. If the range
* is empty the returned iterator is the same as the one returned by
* @ref rbegin().
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
const_reverse_iterator rend()
{
return crend();
}
/**
* @brief Check if the range does not contain any elements.
* @return @c true if there is no elements in the range, @c false otherwise.
*
* This member function returns @c true if the range does not contain
* any elements, otherwise it returns @c false.
*/
bool empty() const
{
return Traits::template empty<value_type>(_handle);
}
/**
* @brief Get the number of elements in the range.
* @return Number of elements in the range.
*
* This member function returns the current number of elements in the
* range.
*/
size_type size() const
{
return Traits::template size<value_type>(_handle);
}
/**
* @brief Swap content with another range of the same type.
* @param other Another range of the same type.
*/
void swap(_self_type& other)
{
std::swap(_handle, other._handle);
}
protected:
/**
* @internal
*/
native_handle_type _handle;
};
/**
* @brief Swap content between two @ref _const_range_template.
* @param lhs First @c _const_range_template object.
* @param rhs Second @c _const_range_template object.
*/
template <typename T, typename Traits>
void swap(_const_range_template<T, Traits>& lhs, _const_range_template<T, Traits>& rhs)
{
lhs.swap(rhs);
}
/**
* @brief Range implementation for mutable collections.
*/
template <typename T, typename Traits>
struct _mutable_range_template : _const_range_template<T, Traits>
{
typedef T value_type;
typedef typename Traits::template iterator<T>::type iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef typename Traits::template native_handle<T>::type native_handle_type;
typedef _const_range_template<T, Traits> _base_type;
typedef T value_type; /**< The type of each element. */
typedef typename Traits::template iterator<T>::type iterator; /**< Type for a iterator to the range. */
typedef std::reverse_iterator<iterator> reverse_iterator; /**< Type for constant reverse iterator to the range. */
typedef typename Traits::template native_handle<T>::type native_handle_type; /**< Type for the native handle of the container. */
typedef _const_range_template<T, Traits> _base_type; /**< Type for the base class. */
/**
* @brief Creates a range object wrapping the given native container handle.
*/
_mutable_range_template(native_handle_type handle)
: _base_type(handle) {}
/**
* @brief Get a constant handle for the native Eina container.
* @return Constant handle for the native Eina container.
*/
native_handle_type native_handle() const
{
return Traits::template native_handle_from_const<T>(_base_type::native_handle());
}
/**
* @brief Get a reference to the last element.
* @return Reference to the last element of the range.
*/
value_type& back() const
{
return Traits::template back<value_type>(native_handle());
}
/**
* @brief Get a reference to the first element.
* @return Reference to the first element of the range.
*/
value_type& front() const
{
return Traits::template front<value_type>(native_handle());
}
/**
* @brief Get an iterator pointing to the first element of the range.
* @return Iterator to the initial position of the range.
*
* This member function returns an iterator pointing to the first
* element of the range. If the range contains no elements the
* returned iterator is the same as the one returned by @ref end() const.
*/
iterator begin() const
{
return Traits::template begin<value_type>(native_handle());
}
/**
* @brief Get an iterator to the position following the last element of the range.
* @return Iterator to the final position of the range.
*
* This member function returns an iterator to the position following
* the last element in the range. If the range contains no elements
* the returned iterator is the same as the one returned by
* @ref begin() const.
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
iterator end() const
{
return Traits::template end<value_type>(native_handle());
}
/**
* @brief Get a reverse iterator pointing to the reverse begin of the range.
* @return Reverse iterator pointing to the reverse begin of the range.
*
* This member function returns a reverse iterator pointing to the
* last element of the range. If the range is empty the returned
* reverse iterator is the same as the one returned by @ref rend().
*/
reverse_iterator rbegin() const
{
return Traits::template rbegin<value_type>(native_handle());
}
/**
* @brief Get a reverse iterator pointing to the reverse end of the range.
* @return Reverse iterator pointing to the reverse end of the range.
*
* This member function returns a reverse iterator pointing to the
* position before the first element of the range. If the range is
* empty the returned iterator is the same as the one returned by
* @ref rbegin().
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
reverse_iterator rend() const
{
return Traits::template rend<value_type>(native_handle());
}
protected:
/**
* @internal
*/
using _base_type::_handle;
};
/**
* Range class.
*
* Provide objects for accessing and/or modifying elements inside a
* container without modifying the container itself.
*/
template <typename T, typename Traits>
struct _range_template : private std::conditional
<std::is_const<T>::value
, _const_range_template<typename std::remove_const<T>::type, Traits>
, _mutable_range_template<T, Traits> >::type
{
typedef std::integral_constant<bool, !std::is_const<T>::value> is_mutable;
typedef typename std::remove_const<T>::type value_type;
typedef std::integral_constant<bool, !std::is_const<T>::value> is_mutable; /**< Type that specifies if the elements can be modified. */
typedef typename std::remove_const<T>::type value_type; /**< The type of each element. */
typedef typename std::conditional<is_mutable::value, _mutable_range_template<value_type, Traits>
, _const_range_template<value_type, Traits> >::type _base_type;
typedef typename _base_type::native_handle_type native_handle_type;
, _const_range_template<value_type, Traits> >::type _base_type; /**< Type for the base class. */
typedef typename _base_type::native_handle_type native_handle_type; /**< Type for the native handle of the container. */
typedef value_type& reference;
typedef value_type const& const_reference;
typedef value_type* pointer;
typedef value_type const* const_pointer;
typedef typename Traits::template const_iterator<T>::type const_iterator;
typedef typename _base_type::const_reverse_iterator const_reverse_iterator;
typedef typename Traits::template iterator<T>::type iterator;
typedef typename _base_type::reverse_iterator reverse_iterator;
typedef typename _base_type::size_type size_type;
typedef typename _base_type::difference_type difference_type;
typedef value_type& reference; /**< Type for a reference to an element. */
typedef value_type const& const_reference; /**< Type for a constant reference to an element. */
typedef value_type* pointer; /**< Type for a pointer to an element. */
typedef value_type const* const_pointer; /**< Type for a constant pointer to an element. */
typedef typename Traits::template const_iterator<T>::type const_iterator; /**< Type for constant iterator to the range. */
typedef typename _base_type::const_reverse_iterator const_reverse_iterator; /**< Type for constant reverse iterator to the range. */
typedef typename Traits::template iterator<T>::type iterator; /**< Type for iterator to the range. */
typedef typename _base_type::reverse_iterator reverse_iterator; /**< Type for reverse iterator to the range. */
typedef typename _base_type::size_type size_type; /**< Type for size information. */
typedef typename _base_type::difference_type difference_type; /**< Type to represent the distance between two iterators. */
/**
* @brief Creates a range object wrapping the given native container handle.
*/
_range_template(native_handle_type handle)
: _base_type(handle)
{}
@ -175,6 +393,14 @@ protected:
using _base_type::_handle;
};
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -3,12 +3,51 @@
#include <functional>
/**
* @addtogroup Eina_Cxx_Tools_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Ref_Group Reference Wrapper
* @ingroup Eina_Cxx_Tools_Group
*
* @{
*/
/**
* @brief Creates a @c reference_wrapper to the given object.
* @return @c reference_wrapper holding a reference to the given object.
*
* Creates the appropriate reference_wrapper type to hold a reference to
* the given object. If the argument is itself a @c reference_wrapper,
* it creates a copy of it instead.
*/
using std::ref;
/**
* @brief Creates a @c reference_wrapper to the given object.
* @return @c reference_wrapper holding a reference to the given object.
*
* Specialized version of @ref ref for @c reference_wrapper to constant
* types.
*/
using std::cref;
/**
* Class that wraps a reference in a copyable, assignable object.
*/
using std::reference_wrapper;
/**
* Get a reference from a @c reference_wrapper. If @p t is already a
* reference just return a reference to @p t.
*
* @{
*/
template <typename T>
T& unref(T& t)
{
@ -21,6 +60,18 @@ T& unref(reference_wrapper<T> t)
return t.get();
}
/**
* @}
*/
/**
* @}
*/
}}
/**
* @}
*/
#endif

View File

@ -7,11 +7,58 @@
#include <cstring>
#include <stdexcept>
/**
* @addtogroup Eina_Cxx_Data_Types_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Stringshare_Group Stringshare
* @ingroup Eina_Cxx_Data_Types_Group
*
* C++ Binding to Eina_Stringshare.
*
* This class allows you to store a single copy of a string, and use in
* multiple places throughout your program.
*
* This is a method to reduce the number of duplicated strings kept in
* memory. It's pretty common for the same strings to be dynamically
* allocated repeatedly between applications and libraries, especially in
* circumstances where you could have multiple copies of a structure that
* allocates the string. So rather than duplicating and freeing these
* strings, you request a read-only pointer to an existing string and
* only incur the overhead of a hash look-up.
*
* It sounds like micro-optimizing, but profiling has shown this can have
* a significant impact as you scale the number of copies up. It improves
* string creation/destruction speed, reduces memory use and decreases
* memory fragmentation, so a win all-around.
*
* @{
*/
/**
* Type for stealing the ownership of a string that was previously shared.
*/
struct steal_stringshare_ref_t {};
/**
* Constant instance of @c steal_stringshare_ref_t for quick reference.
*/
steal_stringshare_ref_t const steal_stringshare_ref = {};
/**
* Stringshare class. It provides an OOP interface to the
* @c Eina_Stringshare functions, and automatically take care of sharing
* the string upon construction and deleting it upon destruction using
* the RAII programming idiom.
*
* It also provides additional member functions to facilitate the access
* to the string content, much like a STL string.
*/
struct stringshare
{
typedef char value_type;
@ -24,17 +71,64 @@ struct stringshare
typedef std::ptrdiff_t difference_type;
typedef std::size_t size_type;
/**
* @brief Default constructor. Creates a new object holding an shared empty string.
* @see stringshare(const char* str)
*/
stringshare()
: _string( ::eina_stringshare_add("") )
{}
/**
* @brief Share an instance of the given string wrapped by the newly created @c stringshare object.
* @param <tt>NULL</tt>-terminated string to be shared.
*
* This constructor creates an <tt>eina::stringshare</tt> object that
* shares the given string and wraps the shared pointer, providing an
* OOP interface to the string content. If the string is already
* shared this constructor simple increment its reference counter and
* wraps the shared pointer.
*
* @see stringshare(char* str, steal_stringshare_ref_t)
*/
stringshare(const char* str)
: _string( ::eina_stringshare_add(str) )
{
}
/**
* @brief Create an <tt>eina::stringshare</tt> that steal the ownership of the given shared string.
* @param str Shared string whose ownership should be stolen.
*
* This constructor creates an <tt>eina::stringshare</tt> object that
* steals the ownership of the given shared string. At destruction
* time, the reference counter for the shared string will be
* decremented.
*
* The second parameter is an empty object of a specific type that
* should be supplied to explicitly inform that this is the intended
* constructor; and to differentiate this from
* @ref stringshare(const char* str).
*
* @warning @p str should be a string that was previously shared (most
* likely by an call to the native @c eina_stringshare_add function).
* If the string is not shared, upon destruction time bad things will
* happen, likely a segmentation fault.
*
* @see stringshare(const char* str)
*/
stringshare(char* str, steal_stringshare_ref_t)
: _string( str )
{
}
/**
* @brief Share the string between the iterator.
* @param i Iterator to the initial position of the string (inclusive).
* @param j Iterator to the final position of the string (exclusive).
* @note The ending position (pointed by @p j) is not considered.
* @see stringshare(const char* str)
*/
template <typename InputIterator>
stringshare(InputIterator i, InputIterator j
, typename eina::enable_if
@ -50,6 +144,14 @@ struct stringshare
}
_string = ::eina_stringshare_add(tmp.c_str());
}
/**
* @brief Share the string between the iterator.
* @param i Iterator to the initial position of the string (inclusive).
* @param j Iterator to the final position of the string (exclusive).
* @note The ending position (pointed by @p j) is not considered.
* @see stringshare(const char* str)
*/
template <typename ContiguousMemoryIterator>
stringshare(ContiguousMemoryIterator i, ContiguousMemoryIterator j
, typename eina::enable_if
@ -58,81 +160,225 @@ struct stringshare
{
}
/**
* @brief Destructor. Delete the shared string.
*
* Decreases the reference counter associated with the shared string.
* If the reference counter reaches 0, the memory associated with the
* string is freed.
*/
~stringshare()
{
::eina_stringshare_del(_string);
}
/**
* @brief Copy constructor. Creates a new <tt>eina::stringshare</tt> associated with the same shared string.
* @param other Another <tt>eina::stringshare</tt>.
*
* This constructor increments the reference counter to the shared
* string associated with @p other.
*
* @see stringshare(const char* str)
*/
stringshare(stringshare const& other)
: _string( eina_stringshare_ref(other._string) )
{}
/**
* @brief Replace the current shared string.
* @param other Another <tt>eina::stringshare</tt>.
*
* This operator replaces the current shared string by the string
* shared by @p other. The reference counter of the older shared
* string is decremented (the string is released if needed) and the
* reference counter of the given shared string is incremented.
*/
stringshare& operator=(stringshare const& other)
{
::eina_stringshare_refplace(&_string, other._string);
return *this;
}
/**
* @brief Replace the current shared string.
* @param c_string <tt>NULL</tt>-terminated string.
*
* This operator replaces the shared string currently associated with
* this object by a shared instance of @p c_string.
*
* @see stringshare(const char* str)
*/
stringshare& operator=(const char* c_string)
{
::eina_stringshare_replace(&_string, c_string);
return *this;
}
/**
* @brief Get a constant iterator pointing to the first character of the string.
* @return Constant iterator to the initial position of the string.
*
* This member function returns a constant iterator pointing to the
* first character of the string. If the string is empty the iterator
* is equal to the one returned by @ref end() const.
*/
const_iterator begin() const
{
return _string;
}
/**
* @brief Get a constant iterator to the position following the last character of the string.
* @return Constant iterator to the final position of the string.
*
* This member function returns an constant iterator to the position
* following the last character in the string. If the string is empty
* the iterator is equal to the one returned by @ref begin().
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
const_iterator end() const
{
return _string + size();
}
/**
* @brief Get a constant reverse iterator pointing to the reverse begin of the string.
* @return Constant reverse iterator pointing to the reverse begin of the string.
*
* This member function returns a constant reverse iterator pointing
* to the last character of the string. If the string is empty the
* returned reverse iterator is the same as the one returned by
* @ref rend() const.
*/
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
/**
* @brief Get a constant reverse iterator pointing to the reverse end of the string.
* @return Constant reverse iterator pointing to the reverse end of the string.
*
* This member function returns a constant reverse iterator pointing
* to the position before the first character of the string. If the
* string is empty the returned iterator is the same as the one
* returned by @ref rbegin() const.
*
* @note Note that attempting to access this position causes undefined
* behavior.
*/
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
/**
* @brief Get a constant iterator pointing to the first character of the string.
* @return Constant iterator to the initial position of the string.
*
* This member function works just like @ref begin() const. But it is
* granted to always return a constant iterator.
*/
const_iterator cbegin() const
{
return begin();
}
/**
* @brief Get a constant iterator to the position following the last character of the string.
* @return Constant iterator to the final position of the string.
*
* This member function works just like @ref end() const. But it is
* granted to always return a constant iterator.
*/
const_iterator cend() const
{
return end();
}
/**
* @brief Get a constant reverse iterator pointing to the reverse begin of the string.
* @return Constant reverse iterator pointing to the reverse begin of the string.
*
* This member function works just like @ref rbegin() const. But it is
* granted to always return a constant reverse iterator.
*/
const_reverse_iterator crbegin() const
{
return rbegin();
}
/**
* @brief Get a constant reverse iterator pointing to the reverse end of the string.
* @return Constant reverse iterator pointing to the reverse end of the string.
*
* This member function works just like @ref rend() const. But it is
* granted to always return a constant reverse iterator.
*/
const_reverse_iterator crend() const
{
return rend();
}
/**
* @brief Get the size of the string.
* @return Number of characters in the string.
*/
size_type size() const
{
return eina_stringshare_strlen(_string);
}
/**
* @brief Alias to @ref size() const.
*/
size_type length() const
{
return size();
}
/**
* @brief Get the maximum number of characters a string can hold.
* @return Maximum number of characters a string can hold.
*/
size_type max_size() const
{
return -1;
}
/**
* @brief Check if the string has no characters.
* @return @c true if the string has no characters, @c false otherwise.
*/
bool empty() const
{
return _string[0] == 0;
}
/**
* @brief Get the character at the given position.
* @param i Position of the character in the string.
* @return Constant reference to the character at the given position.
* @note Do not check if the given position exceeds the string size.
*/
const_reference operator[](size_type i) const
{
return _string[i];
}
/**
* @brief Get the character at the given position.
* @param i Position of the character in the string.
* @return Constant reference to the character at the given position.
* @throw <tt>std::out_of_range</tt> if the given position exceeds the string size.
*
* This member function returns a constant reference to the character
* at the position @p i. If @p i exceeds the string size this function
* will throw a <tt>std::out_of_range</tt>.
*/
const_reference at(size_type i) const
{
if(i < size())
@ -140,66 +386,143 @@ struct stringshare
else
throw std::out_of_range("");
}
/**
* @brief Get the last character of the string.
* @return Constant reference to the last character of the string.
*/
const_reference back() const
{
return _string[size()-1];
}
/**
* @brief Get the first character of the string.
* @return Constant reference to the first character of the string.
*/
const_reference front() const
{
return _string[0];
}
/**
* @brief Swap shared strings with other <tt>eina::stringshare</tt>.
*/
void swap(stringshare& other)
{
std::swap(_string, other._string);
}
/**
* @brief Get the c-like shared string currently associated with the object.
* @return Pointer to the shared string.
* @note The pointer returned may be invalidated by calls to non-const member functions.
*/
const char* c_str() const
{
return _string;
}
/**
* @brief Alias to @ref c_str() const.
*/
const char* data() const
{
return _string;
}
private:
/**
* @internal
*/
Eina_Stringshare* _string;
};
/**
* Specialization of the default template to define the
* <tt>stringshare::const_iterator</tt> as a contiguous iterator.
*/
template <>
struct is_contiguous_iterator<stringshare::const_iterator> : true_type {};
/**
* @brief Check if two <tt>eina::stringshare</tt> objects represent the same string.
* @return @c true if the strings of the objects are equal, @c false otherwise.
*
* This operator checks if two <tt>eina::stringshare</tt> objects
* represent the same string. Because of the nature of the objects,
* this operation falls into a simple pointer comparison, since
* identical strings are represented by the same instance.
*/
inline bool operator==(stringshare const& lhs, stringshare const& rhs)
{
return lhs.c_str() == rhs.c_str();
}
/**
* @brief Check if two <tt>eina::stringshare</tt> objects represent different strings.
* @return @c true if the strings of the objects are different, @c false otherwise.
*
* This function essentially returns the opposite of
* @ref operator==(stringshare const& lhs, stringshare const& rhs).
*/
inline bool operator!=(stringshare const& lhs, stringshare const& rhs)
{
return !(lhs == rhs);
}
/**
* @brief Compare an <tt>eina::stringshare</tt> object with a c-like string.
* @return @c true if the content of the <tt>eina::stringshare</tt>
* string is equal the content of the given string, @c false
* otherwise.
*/
inline bool operator==(stringshare const& lhs, const char* rhs)
{
return lhs.c_str() == rhs || std::strcmp(lhs.c_str(), rhs) == 0;
}
/**
* @brief Compare an <tt>eina::stringshare</tt> object with a c-like string.
* @return @c true if the content of the <tt>eina::stringshare</tt>
* string is different from content of the given string,
* @c false otherwise.
*/
inline bool operator!=(stringshare const& lhs, const char* rhs)
{
return !(lhs == rhs);
}
/**
* @brief Compare an <tt>eina::stringshare</tt> object with a c-like string.
* @return @c true if the content of the <tt>eina::stringshare</tt>
* string is equal the content of the given string, @c false
* otherwise.
*/
inline bool operator==(const char* lhs, stringshare const& rhs)
{
return rhs == lhs;
}
/**
* @brief Compare an <tt>eina::stringshare</tt> object with a c-like string.
* @return @c true if the content of the <tt>eina::stringshare</tt>
* string is different from content of the given string,
* @c false otherwise.
*/
inline bool operator!=(const char* lhs, stringshare const& rhs)
{
return !(lhs == rhs);
}
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -13,23 +13,72 @@
#include <chrono>
#include <mutex>
/**
* @addtogroup Eina_Cxx_Tools_Group Tools
*
* @{
*/
#define EFL_EINA_BOOST_MOVABLE_BUT_NOT_COPYABLE(x)
#define EFL_EINA_BOOST_RV_REF(x) x const&
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Mutex_Group Mutex
* @ingroup Eina_Cxx_Tools_Group
*
* @{
*/
/**
* Provides an OOP interface to the @c Eina_Lock and automatic resource
* allocation and deallocation using the RAII programming idiom.
*
* This class implements mutual exclusion variables (mutexes) in a way
* that strongly resembles the STL <tt>std::mutex</tt>.
*/
struct mutex
{
typedef Eina_Lock* native_handle_type;
typedef Eina_Lock* native_handle_type; /**< Type for the native Eina_Lock pointer. */
/**
* @brief Create a new mutex.
*
* Automatically allocates a new mutex and does any platform dependent
* initialization that is required.
*/
mutex()
{
::eina_lock_new(&_mutex);
}
/**
* @brief Release mutex resources.
*
* Automatically deallocates the mutex and does any platform dependent
* cleanup that is required.
*/
~mutex()
{
::eina_lock_free(&_mutex);
}
/**
* @brief Lock the mutex.
* @throw <tt>eina::system_error</tt> with the code
* <tt>eina::errc::resource_deadlock_would_occur</tt> if the
* operation fails because a deadlock condition exists. If some
* other condition causes the lock to fail (other than the
* mutex being already locked) the error code will be an
* internal Eina error code.
*
* This member function locks the mutex. If the mutex is locked
* already, this call will block until the lock is released. This is
* appropriate in many cases, but consider using @ref try_lock() if
* you don't need to block.
*/
void lock()
{
::Eina_Lock_Result r = ::eina_lock_take(&_mutex);
@ -44,6 +93,20 @@ struct mutex
throw system_error(get_error_code());
}
}
/**
* @brief Attempts to lock the mutex.
* @return @c true if it succeed in locking the mutex, @c false otherwise.
* @throw <tt>eina::system_error</tt> with the code
* <tt>eina::errc::resource_deadlock_would_occur</tt> if the
* operation fails because a deadlock condition exists. If some
* other condition causes the lock to fail (other than the
* mutex being already locked) the error code will be an
* internal Eina error code.
*
* This member function attempts to lock the mutex, identical to
* @ref lock(), but returns immediately if the mutex is already locked.
*/
bool try_lock()
{
::Eina_Lock_Result r = ::eina_lock_take_try(&_mutex);
@ -60,6 +123,21 @@ struct mutex
throw system_error(get_error_code());
}
}
/**
* @brief Unlock the lock.
* @throw <tt>eina::system_error</tt> with the code
* <tt>eina::errc::resource_deadlock_would_occur</tt> if the
* operation fails because a deadlock condition exists. If some
* other condition causes the lock to fail the error code will
* be an internal Eina error code.
*
* This member function will unlock the mutex.
*
* @note If successful, and EINA_HAVE_DEBUG_THREADS is defined, the
* mutex is updated and information about the locking process
* is removed (e.g. thread number and backtrace for POSIX).
*/
void unlock()
{
::Eina_Lock_Result r = ::eina_lock_release(&_mutex);
@ -74,37 +152,114 @@ struct mutex
throw system_error(get_error_code());
}
}
/**
* @brief Print debug information about the mutex.
*
* This member function prints debug information for the mutex. The
* information is platform dependent. On POSIX systems it will print
* the address of mutex, lock state, thread number and a backtrace.
*/
void debug()
{
::eina_lock_debug(&_mutex);
}
/**
* @brief Get a handle for the wrapped @c Eina_Lock.
* @return Handle for the native @c Eina_Lock.
*
* This member function returns the native @c Eina_Lock handle that is
* wrapped inside this object.
*
* @warning It is important to take care when using it, since the
* handle will be automatically released upon object destruction.
*/
native_handle_type native_handle()
{
return &_mutex;
}
private:
/** Disabled copy constructor. **/
mutex(mutex const&) = delete;
/** Disabled assignment operator. **/
mutex& operator=(mutex const&) = delete;
/**
* @internal
*/
Eina_Lock _mutex;
};
/**
* @brief Manage a mutex object by keeping it always locked.
*
* Inherited for the STL object <tt>std::lock_guard</tt>.
*/
using std::lock_guard;
/**
* @brief Manages a mutex object.
*
* Inherited for the STL object <tt>std::unique_lock</tt>. This class
* guarantees an unlocked status on destruction.
*/
using std::unique_lock;
/**
* @}
*/
/**
* @defgroup Eina_Cxx_Condition_Variable_Group Condition Variable
* @ingroup Eina_Cxx_Tools_Group
*
* @{
*/
/**
* Provides an OOP interface to the @c Eina_Condition and automatic
* resource allocation and deallocation using the RAII programming idiom.
*
* This class implements condition variables in a way that strongly
* resembles the STL <tt>std::condition_variable</tt>.
*/
struct condition_variable
{
typedef Eina_Condition* native_handle_type;
typedef Eina_Condition* native_handle_type; /**< Type for the native Eina_Lock pointer. */
/**
* @brief Create a new condition variable.
*
* Automatically allocates a new condition variable and does any
* platform dependent initialization that is required.
*/
condition_variable()
{
::eina_condition_new(&_cond, _mutex.native_handle());
}
/**
* @brief Release the condition variable resources.
*
* Automatically deallocates the condition variable and does any
* platform dependent cleanup that is required.
*/
~condition_variable()
{
::eina_condition_free(&_cond);
}
/**
* @brief Unblock a thread waiting for this condition.
* @throw <tt>eina::system_error</tt> on fail.
*
* This member function unblock a thread waiting on this condition
* variable. If there is more than one thread waiting on this
* condition, one of them will be unblocked, but which one is
* undefined. If you do not know for sure that there is only one
* thread waiting, use @ref notify_all() instead.
*/
void notify_one()
{
eina::unique_lock<eina::mutex> l(_mutex);
@ -112,6 +267,15 @@ struct condition_variable
if(!r)
throw eina::system_error(eina::get_error_code());
}
/**
* @brief Unblock all threads waiting for this condition.
* @throw <tt>eina::system_error</tt> on fail.
*
* This member function unblocks all the threads waiting on the this
* condition. If you know for sure that there is only one thread
* waiting, use @ref notify_one instead to gain a little optimization.
*/
void notify_all()
{
eina::unique_lock<eina::mutex> l(_mutex);
@ -119,6 +283,16 @@ struct condition_variable
if(!r)
throw eina::system_error(eina::get_error_code());
}
/**
* @brief Causes a thread to wait until notified.
* @param lock A lockable object (@c mutex, @c unique_lock, etc) that
* is currently locked by this thread. All concurrent
* calls to wait member functions of this object shall use
* the same lockable object.
*
* This member function makes a thread block until notified.
*/
template <typename Lock>
void wait(Lock& lock)
{
@ -127,47 +301,121 @@ struct condition_variable
::eina_condition_wait(&_cond);
lock.lock();
}
/**
* @brief Causes a thread to wait until notified.
* @param lock A lockable object (@c mutex, @c unique_lock, etc) that
* is currently locked by this thread. All concurrent
* calls to wait member functions of this object shall use
* the same lockable object.
* @param p A callable object or function that takes no arguments and
* returns a value that can be evaluated as a bool. This is
* called repeatedly until it evaluates to true.
*
* This member function only blocks the thread if @p p is evaluated to
* @c false. In this case the thread remains blocked until notified
* and the result of @p p evaluates to @c true.
*/
template <typename Lock, typename Predicate>
void wait(Lock& lock, Predicate p)
{
while(!p())
wait(lock);
}
/**
* @brief Get a handle for the wrapped @c Eina_Condition.
* @return Handle for the native @c Eina_Condition.
*
* This member function returns the native @c Eina_Condition handle
* that is wrapped inside this object.
*
* @warning It is important to take care when using it, since the
* handle will be automatically released upon object destruction.
*/
native_handle_type native_handle()
{
return &_cond;
}
private:
/** Disabled copy constructor. **/
condition_variable(condition_variable const&);
/** Disabled assignment operator. **/
condition_variable& operator=(condition_variable const&);
mutex _mutex;
Eina_Condition _cond;
mutex _mutex; /**< @internal */
Eina_Condition _cond; /**< @internal */
};
/**
* @}
*/
/**
* @defgroup Eina_Cxx_Thread_Group Thread
* @ingroup Eina_Cxx_Tools_Group
*
* @{
*/
/**
* Thread identifier.
*/
struct thread_id
{
/**
* @brief Creates a @c thread_id that represents all non-joinable.
*/
thread_id() noexcept
: _raw(0u)
{
}
/**
* @brief
*/
thread_id(Eina_Thread raw)
: _raw(raw) {}
/**
* @brief Check if two thread identifiers are the same.
* @return @c true if the thread identifiers have the same value.
*/
friend inline bool operator==(thread_id lhs, thread_id rhs)
{
return lhs._raw == rhs._raw;
}
/**
* @brief Check if two thread identifiers are different.
* @return @c true if the thread identifiers have different values.
*/
friend inline bool operator!=(thread_id lhs, thread_id rhs)
{
return lhs._raw != rhs._raw;
}
/**
* @brief Less than comparison of thread identifiers.
* @param lhs @c thread_id at the left side of the expression.
* @param rhs @c thread_id at the right side of the expression.
* @return @c true if @c lhs is less than @c rhs, @c false otherwise.
* @note The order established by relational operators is
* implementation-defined.
*/
friend inline bool operator<(thread_id lhs, thread_id rhs)
{
return std::less<Eina_Thread>()(lhs._raw, rhs._raw);
}
private:
Eina_Thread _raw;
Eina_Thread _raw; /**< @internal */
/**
* @brief Inserts a textual representation in the given stream.
* @param out Output stream where the textual representation will be inserted.
* @param id @c thread_id object.
* @return Reference to the modified <tt>std::basic_ostream</tt> object.
*/
template <typename charT, typename Traits>
friend std::basic_ostream<charT, Traits>&
operator<<(std::basic_ostream<charT, Traits>& out, thread_id id)
@ -176,21 +424,53 @@ private:
}
};
/**
* @brief Less than or equal comparison of thread identifiers.
* @param lhs @c thread_id at the left side of the expression.
* @param rhs @c thread_id at the right side of the expression.
* @return @c true if @c lhs is less than or equal to @c rhs, @c false otherwise.
* @note The order established by relational operators is
* implementation-defined.
*/
inline bool operator<=(thread_id lhs, thread_id rhs)
{
return (lhs == rhs) || lhs < rhs;
}
/**
* @brief More than comparison of thread identifiers.
* @param lhs @c thread_id at the left side of the expression.
* @param rhs @c thread_id at the right side of the expression.
* @return @c true if @c lhs is more than @c rhs, @c false otherwise.
* @note The order established by relational operators is
* implementation-defined.
*/
inline bool operator>(thread_id lhs, thread_id rhs)
{
return !(lhs <= rhs);
}
/**
* @brief More than or equal comparison of thread identifiers.
* @param lhs @c thread_id at the left side of the expression.
* @param rhs @c thread_id at the right side of the expression.
* @return @c true if @c lhs is more than or equal to @c rhs, @c false otherwise.
* @note The order established by relational operators is
* implementation-defined.
*/
inline bool operator>=(thread_id lhs, thread_id rhs)
{
return !(lhs < rhs);
}
/**
* @internal
*/
namespace _detail {
/**
* @internal
*/
struct arguments
{
Eina_Lock mutex;
@ -199,6 +479,9 @@ struct arguments
std::function<void()> function;
};
/**
* @internal
*/
inline void* create_thread(void* data, Eina_Thread)
{
arguments* args = static_cast<arguments*>(data);
@ -217,16 +500,40 @@ inline void* create_thread(void* data, Eina_Thread)
}
/**
* Provides an OOP interface to the @c Eina_Thread and automatic
* resource allocation and deallocation using the RAII programming idiom.
*
* This class implements threads in a way that strongly resembles the
* STL <tt>std::thread</tt>.
*/
struct thread
{
typedef thread_id id;
typedef Eina_Thread native_handle_type;
typedef thread_id id; /**< Type for the thread identifier. */
typedef Eina_Thread native_handle_type; /**< Type for the native Eina_Thread handle. */
/**
* @brief Creates a thread object that does not represent any thread of execution.
*/
thread() noexcept
: _joinable(false), _raw(0u)
{
}
/**
* @brief Creates a thread of execution.
* @param f Pointer to function or callable object to execute in the new thread.
* The return value (if any) is ignored.
* @param args Arguments to pass to the @p f.
*
* This constructor creates a thread object that represents a thread
* of execution. The new thread of execution calls @p f passing
* @p args as arguments (all arguments are copied/moved to
* thread-accessible storage).
*
* Any exceptions thrown during evaluation and copying/moving of the
* arguments are thrown in the current thread, not the new thread.
*/
template <typename F, class ... Args>
explicit thread(F&& f, Args&&... args)
{
@ -264,11 +571,27 @@ struct thread
eina_lock_free(&arguments.mutex);
}
/**
* @brief Move constructor. Transfer the thread of execution to the new object.
* @param other Another thread object to construct this thread object with.
*
* This constructor creates a thread object that acquires the thread
* of execution represented by @p other. This operation does not
* affect the execution of the moved thread, it simply transfers its
* handler.
*
* @note After this call @p other no longer represents a thread of execution.
*/
thread(thread&& other)
: _joinable(other._joinable), _raw(other._raw)
{
}
/**
* @brief Transfer the thread of execution.
* @param other Another thread object to assign to this thread object.
* @note After this call @p other no longer represents a thread of execution.
*/
thread& operator=(thread&& other)
{
_raw = other._raw;
@ -276,20 +599,50 @@ struct thread
return *this;
}
/**
* @brief Destroys the thread object.
*/
~thread()
{
assert(!joinable());
}
/**
* @brief Exchanges the underlying handles of two thread objects.
* @param other Another thread object.
*/
void swap(thread& other) noexcept
{
std::swap(_raw, other._raw);
}
/**
* @brief Check if the thread object identifies an active thread of execution.
* @return @c true if the thread object identifies an active thread of execution, @c false otherwise.
*
* This member function checks if the thread object identifies an
* active thread of execution. A default constructed thread is not
* joinable, as well as a thread that its members join or detach has
* been called.
*
* A thread that has finished executing code, but has not yet been
* joined is still considered an active thread of execution and is
* therefore joinable.
*/
bool joinable() const noexcept
{
return _joinable;
}
/**
* @brief Wait for the thread to finish its execution.
*
* This member function blocks the calling thread until the thread
* identified by this object finishes its execution.
*
* @note A joinable thread becomes not joinable after a call to this
* function.
*/
void join()
{
assert(joinable());
@ -297,30 +650,70 @@ struct thread
_joinable = false;
}
/**
* @brief Detaches the thread from its handle, making it runs independently.
*
* This member function separates the thread of execution from the
* thread object, allowing execution to continue independently.
*
* @note After a call to this function, the thread object becomes
* non-joinable.
*/
void detach()
{
assert(joinable());
_joinable = false;
}
/**
* @brief Returns the identifier of the thread associated with this thread object.
* @return <tt>thread::id</tt> identifying the thread associated with this thread object.
*/
id get_id() const noexcept
{
return id(_raw);
}
/**
* @brief Get a handle for the wrapped @c Eina_Thread.
* @return Handle for the native @c Eina_Thread.
*
* This member function returns the native @c Eina_Thread handle that
* is wrapped inside this object.
*/
native_handle_type native_handle() const
{
return _raw;
}
/**
* @brief Get the number of hardware concurrent threads.
* @return A hint on the number of hardware concurrent threads, or
* @c 0 if the value is not well defined or not computable.
*
* This static member function returns the number of hardware
* concurrent threads.
*
* @note The interpretation of this value is implementation-specific,
* and may be just an approximation.
*/
static unsigned hardware_concurrency() noexcept
{
return ::eina_cpu_count();
}
private:
/** @internal */
bool _joinable;
/** @internal */
Eina_Thread _raw;
};
/**
* @brief Exchanges the underlying handles of two thread objects.
* @param lhs First thread object.
* @param rhs Second thread object.
*/
inline void swap(thread& lhs, thread& rhs)
{
lhs.swap(rhs);
@ -328,22 +721,54 @@ inline void swap(thread& lhs, thread& rhs)
namespace this_thread {
/**
* @brief Return identifier of the current thread.
* @return <tt>thread::id</tt> identifying the current thread.
*/
inline thread::id get_id()
{
return thread::id(eina_thread_self());
}
/**
* @brief Provides a hint to the implementation to reschedule the
* execution of threads, allowing other threads to run.
*/
inline void yield() {}
/**
* @brief Block the execution of the current thread until a specified time point.
* @param abs_time Point in time when the calling thread shall resume its execution.
*
* @note This function may block for longer than until after @p rel_time
* has been reached due to scheduling or resource contention delays.
*/
template <typename Clock, typename Duration>
void sleep_until(std::chrono::time_point<Clock, Duration>const& abs_time);
/**
* @brief Block the execution of the current thread for a specified time duration.
* @param rel_time Time span after which the calling thread shall resume its execution.
*
* @note This function may block for longer than @p rel_time due to
* scheduling or resource contention delays.
*/
template <typename Rep, typename Period>
void sleep_for(std::chrono::duration<Rep, Period>const& rel_time);
}
/**
* @}
*/
} }
/**
* @internal
* Specialization of standard @c hash class to specify that a
* <tt>thread_id</tt> object should be handled as a unsigned long
* @{
*/
namespace std {
template <typename T> struct hash;
@ -352,5 +777,12 @@ struct hash< ::efl::eina::thread_id> : hash<unsigned long>
{};
}
/**
* @}
*/
/**
* @}
*/
#endif

View File

@ -6,8 +6,20 @@
#include <string>
#include <vector>
/**
* @addtogroup Eina_Cxx_Data_Types_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @internal
*
* @{
*/
using std::enable_if;
using std::is_integral;
using std::is_pod;
@ -46,6 +58,14 @@ struct if_ : if_c<U::value, T, F>
{
};
/**
* @}
*/
} }
/**
* @}
*/
#endif

View File

@ -6,8 +6,27 @@
#include <eina_stringshare.hh>
#include <eina_type_traits.hh>
/**
* @addtogroup Eina_Cxx_Data_Types_Group
*
* @{
*/
namespace efl { namespace eina {
/**
* @defgroup Eina_Cxx_Value_Group Generic Value Storage
* @ingroup Eina_Cxx_Data_Types_Group
*
* Abstracts generic data storage and access to it in an extensible
* and efficient way.
*
* It is meant for simple data types, providing uniform access, useful
* to exchange data preserving their types.
*
* @{
*/
template <typename T, typename Enable = void>
struct _eina_value_traits;
@ -17,6 +36,9 @@ struct _eina_value_traits_base;
template <typename T>
struct _eina_value_traits_aux;
/**
* @internal
*/
template <typename T>
struct _eina_value_traits_base
{
@ -51,6 +73,9 @@ struct _eina_value_traits_base
// Indirection for uint64_t. uint64_t can be a typedef for unsigned
// long, so we can't specialize on the same template
/**
* @internal
*/
template <>
struct _eina_value_traits_aux<uint64_t>
: _eina_value_traits_base<uint64_t>
@ -61,11 +86,17 @@ struct _eina_value_traits_aux<uint64_t>
}
};
/**
* @internal
*/
template <typename T, typename Enable>
struct _eina_value_traits : _eina_value_traits_aux<T>
{
};
/**
* @internal
*/
template <>
struct _eina_value_traits<unsigned char>
: _eina_value_traits_base<unsigned char>
@ -76,6 +107,9 @@ struct _eina_value_traits<unsigned char>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<unsigned short>
: _eina_value_traits_base<unsigned short>
@ -86,6 +120,9 @@ struct _eina_value_traits<unsigned short>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<unsigned int>
: _eina_value_traits_base<unsigned int>
@ -96,6 +133,9 @@ struct _eina_value_traits<unsigned int>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<unsigned long>
: _eina_value_traits_base<unsigned long>
@ -106,6 +146,9 @@ struct _eina_value_traits<unsigned long>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<char>
: _eina_value_traits_base<char>
@ -116,6 +159,9 @@ struct _eina_value_traits<char>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<short>
: _eina_value_traits_base<short>
@ -126,6 +172,9 @@ struct _eina_value_traits<short>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<int>
: _eina_value_traits_base<int>
@ -136,6 +185,9 @@ struct _eina_value_traits<int>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<long>
: _eina_value_traits_base<long>
@ -146,6 +198,9 @@ struct _eina_value_traits<long>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<float>
: _eina_value_traits_base<float>
@ -156,6 +211,9 @@ struct _eina_value_traits<float>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<double>
: _eina_value_traits_base<double>
@ -166,6 +224,9 @@ struct _eina_value_traits<double>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<stringshare>
: _eina_value_traits_base<stringshare>
@ -186,6 +247,9 @@ struct _eina_value_traits<stringshare>
}
};
/**
* @internal
*/
template <>
struct _eina_value_traits<std::string>
: _eina_value_traits_base<std::string>
@ -209,6 +273,9 @@ struct _eina_value_traits<std::string>
}
};
/**
* @internal
*/
template <typename T>
struct _eina_value_traits<T[], typename eina::enable_if<eina::is_pod<T>::value>::type>
: _eina_value_traits_base<T[]>
@ -237,8 +304,15 @@ class value;
template <typename T>
T get(value const& v);
/**
* Store generic value
*/
class value
{
/**
* @brief Initialize the <tt>eina::value</tt> with the given argument.
* @param v Argument that the <tt>eina::value</tt> will store.
*/
template <typename T>
void primitive_init(T v)
{
@ -246,67 +320,138 @@ class value
_eina_value_traits<T>::set(_raw, v);
}
public:
/**
* @brief Default constructor. Create an empty generic value storage.
*/
value()
: _raw(_eina_value_traits<char>::create())
{
}
/**
* @brief Create an generic value storage holding the given argument.
* @param v Value to be stored.
*/
template <typename T>
value(T v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a @c char value.
* @param v @c char value to be stored.
*/
value(char v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a @c short value.
* @param v @c short value to be stored.
*/
value(short v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a @c int value.
* @param v @c int value to be stored.
*/
value(int v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a @c long value.
* @param v @c long value to be stored.
*/
value(long v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a <tt>unsigned char</tt> value.
* @param v <tt>unsigned char</tt> value to be stored.
*/
value(unsigned char v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a <tt>unsigned short</tt> value.
* @param v <tt>unsigned short</tt> value to be stored.
*/
value(unsigned short v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a <tt>unsigned int</tt> value.
* @param v <tt>unsigned int</tt> value to be stored.
*/
value(unsigned int v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a <tt>unsigned long</tt> value.
* @param v <tt>unsigned long</tt> value to be stored.
*/
value(unsigned long v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a @c float value.
* @param v @c float value to be stored.
*/
value(float v)
{
primitive_init(v);
}
/**
* @brief Create an generic value storage holding a @c double value.
* @param v @c double value to be stored.
*/
value(double v)
{
primitive_init(v);
}
/**
* @brief Deallocate stored value.
*/
~value()
{
eina_value_free(_raw);
}
/**
* @brief Copy Constructor. Create an generic value storage holding the same value of @p other.
* @param other Another <tt>eina::value</tt> object.
*/
value(value const& other)
: _raw(_eina_value_traits<char>::create())
{
if(!eina_value_copy(const_cast<Eina_Value const*>(other._raw), _raw))
throw eina::system_error(eina::get_error_code());
}
/**
* @brief Assignment operator. Replace the current stored value by the value in @p other.
* @param other Another <tt>eina::value</tt> object.
*/
value& operator=(value const& other)
{
eina_value_flush(_raw);
@ -315,17 +460,41 @@ public:
return *this;
}
/**
* @brief Swap stored values with the given <tt>eina::value</tt> object.
* @param other Another <tt>eina::value</tt> object.
*/
void swap(value& other)
{
std::swap(_raw, other._raw);
}
/**
* @brief Get a handle for the wrapped @c Eina_Value.
* @return Handle for the native @c Eina_Value.
*
* This member function returns the native @c Eina_Value handle that
* is wrapped inside this object.
*
* @warning It is important to take care when using it, since the
* handle will be automatically released upon object destruction.
*/
typedef Eina_Value* native_handle_type;
native_handle_type native_handle() const
{
return _raw;
}
/**
* Type for a constant pointer to an @c Eina_Value_Type.
* Describes the type of the data being stored.
*/
typedef Eina_Value_Type const* type_info_t;
/**
* @brief Get an identifier for the type of the value currently stored.
* @return @c Eina_Value_Type instance or @c NULL if type is invalid.
*/
type_info_t type_info() const
{
return ::eina_value_type_get(_raw);
@ -333,6 +502,21 @@ public:
private:
::Eina_Value* _raw;
/**
* @brief Get the data stored in the given <tt>eina::value</tt>.
* @param v <tt>eina::value</tt> object.
* @param T Type of the value stored.
* @return Copy of the value stored in @p v.
* @throw <tt>eina::system_error</tt> with error the code
* @c EINA_ERROR_VALUE_FAILED if @p T doesn't match the type of
* the value currently stored. Or <tt>eina::system_error</tt>
* with an internal Eina error code if the operation fails for
* another reason.
*
* This function returns the value stored in @p v. The type of the
* value must be specified via the template parameter @p T, and must
* match the current stored value type.
*/
template <typename T>
friend T get(value const& v)
{
@ -340,17 +524,39 @@ private:
}
};
/**
* @brief Swap the stored values between the given <tt>eina::value</tt> objects.
* @param lhs First <tt>eina::value</tt> object.
* @param rhs Second <tt>eina::value</tt> object.
*/
inline void swap(value& lhs, value& rhs)
{
lhs.swap(rhs);
}
/**
* @brief Compare if the stored values are equal.
* @param lhs <tt>eina::value</tt> object at the left side of the expression.
* @param rhs <tt>eina::value</tt> object at the right side of the expression.
* @return @c true if the stored values are of the same type and equals
* in content, @c false otherwise.
*/
inline bool operator==(value const& lhs, value const& rhs)
{
return lhs.type_info() == rhs.type_info()
&& eina_value_compare(lhs.native_handle(), rhs.native_handle()) == 0;
}
/**
* @brief Less than comparison between two <tt>eina::value</tt> objects.
* @param lhs <tt>eina::value</tt> object at the left side of the expression.
* @param rhs <tt>eina::value</tt> object at the right side of the expression.
* @return For objects holding values of the same type, returns @c true
* if @p lhs value is less than @p rhs value. For objects
* holding values of different types, returns @c true if the
* type identifier of @p lhs comes before the type indentifier
* of @p rhs. Returns @c false in all other cases.
*/
inline bool operator<(value const& lhs, value const& rhs)
{
return std::less<Eina_Value_Type const*>()(lhs.type_info(), rhs.type_info())
@ -358,6 +564,16 @@ inline bool operator<(value const& lhs, value const& rhs)
&& eina_value_compare(lhs.native_handle(), rhs.native_handle()) < 0);
}
/**
* @brief More than comparison between two <tt>eina::value</tt> objects.
* @param lhs <tt>eina::value</tt> object at the left side of the expression.
* @param rhs <tt>eina::value</tt> object at the right side of the expression.
* @return For objects holding values of the same type, returns @c true
* if @p lhs value is more than @p rhs value. For objects
* holding values of different types, returns @c true if the
* type identifier of @p lhs comes after the type indentifier
* of @p rhs. Returns @c false in all other cases.
*/
inline bool operator>(value const& lhs, value const& rhs)
{
return std::less<Eina_Value_Type const*>()(rhs.type_info(), lhs.type_info())
@ -365,21 +581,57 @@ inline bool operator>(value const& lhs, value const& rhs)
&& eina_value_compare(lhs.native_handle(), rhs.native_handle()) > 0);
}
/**
* @brief Less than or equal comparison between two <tt>eina::value</tt> objects.
* @param lhs <tt>eina::value</tt> object at the left side of the expression.
* @param rhs <tt>eina::value</tt> object at the right side of the expression.
* @return For objects holding values of the same type, returns @c true
* if @p lhs value is less than or equal to @p rhs value. For
* objects holding values of different types, returns @c true if
* the type identifier of @p lhs comes before the type
* indentifier of @p rhs. Returns @c false in all other cases.
*/
inline bool operator<=(value const& lhs, value const& rhs)
{
return !(lhs > rhs);
}
/**
* @brief More than or equal comparison between two <tt>eina::value</tt> objects.
* @param lhs <tt>eina::value</tt> object at the left side of the expression.
* @param rhs <tt>eina::value</tt> object at the right side of the expression.
* @return For objects holding values of the same type, returns @c true
* if @p lhs value is more than or equal to @p rhs value. For
* objects holding values of different types, returns @c true if
* the type identifier of @p lhs comes after the type
* indentifier of @p rhs. Returns @c false in all other cases.
*/
inline bool operator>=(value const& lhs, value const& rhs)
{
return !(lhs < rhs);
}
/**
* @brief Compare if the stored values are different.
* @param lhs <tt>eina::value</tt> object at the left side of the expression.
* @param rhs <tt>eina::value</tt> object at the right side of the expression.
* @return @c true if the value types are different or if the value of
* @p lhs is different from the value of @rhs, @c false
* otherwise.
*/
inline bool operator!=(value const& lhs, value const& rhs)
{
return !(lhs == rhs);
}
/**
* @}
*/
} }
/**
* @}
*/
#endif