diff --git a/Makefile.am b/Makefile.am index f4b62572a6..db28c44ec2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -119,6 +119,7 @@ endif pkgconfig_DATA += \ pc/eina.pc \ +pc/eina-cxx.pc \ pc/eo.pc \ pc/eet.pc \ pc/evas.pc \ diff --git a/configure.ac b/configure.ac index 8f4023e2de..6f95066c93 100644 --- a/configure.ac +++ b/configure.ac @@ -890,6 +890,21 @@ EFL_LIB_END([Eina]) #### End of Eina +#### Eina CXX +EFL_LIB_START([Eina_Cxx]) + +AX_CXX_COMPILE_STDCXX_11([ext]) +if test "x${HAVE_CXX11}" -a "x1"; then + have_cxx11="yes" +else + have_cxx11="no" +fi + +AM_CONDITIONAL([HAVE_CXX11], [test "x${have_cxx11}" -a "xyes"]) + +EFL_LIB_END([Eina_Cxx]) +#### End of Eina CXX + #### Eet EFL_LIB_START([Eet]) @@ -3927,6 +3942,7 @@ src/Makefile src/benchmarks/eina/Makefile src/benchmarks/eo/Makefile src/examples/eina/Makefile +src/examples/eina_cxx/Makefile src/examples/eet/Makefile src/examples/eo/Makefile src/examples/evas/Makefile @@ -3945,6 +3961,7 @@ spec/efl.spec pc/evil.pc pc/escape.pc pc/eina.pc +pc/eina-cxx.pc pc/eet.pc pc/eo.pc pc/evas-fb.pc @@ -4075,6 +4092,7 @@ echo " Threads.......: ${efl_have_threads} (${features_thread})" echo " Cryptography..: ${build_crypto}" echo " X11...........: ${with_x11}" echo " OpenGL........: ${with_opengl}" +echo " C++11.........: ${have_cxx11}" echo "Evas............: yes (${features_evas})" echo " Engines.......: ${features_evas_engine}" echo " Image Loaders.: ${features_evas_loader}" diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4 new file mode 100644 index 0000000000..af37acdb5c --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_11.m4 @@ -0,0 +1,133 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++11 +# standard; if necessary, add switches to CXXFLAGS to enable support. +# +# The first argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The second argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline C++11 support is required and that the macro +# should error out if no mode with that support is found. If specified +# 'optional', then configuration proceeds regardless, after defining +# HAVE_CXX11 if and only if a supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 3 + +m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; +]) + +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl + m4_if([$1], [], [], + [$1], [ext], [], + [$1], [noext], [], + [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl + m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], + [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], + [$2], [optional], [ax_cxx_compile_cxx11_required=false], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++11 features by default, + ax_cv_cxx_compile_cxx11, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ax_cv_cxx_compile_cxx11=yes], + [ax_cv_cxx_compile_cxx11=no])]) + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + m4_if([$1], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$1], [ext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) + fi + else + if test x$ac_success = xno; then + HAVE_CXX11=0 + AC_MSG_NOTICE([No compiler with C++11 support was found]) + else + HAVE_CXX11=1 + AC_DEFINE(HAVE_CXX11,1, + [define if the compiler supports basic C++11 syntax]) + fi + + AC_SUBST(HAVE_CXX11) + fi +]) diff --git a/pc/.gitignore b/pc/.gitignore index b6178fb51b..1daef65f9c 100644 --- a/pc/.gitignore +++ b/pc/.gitignore @@ -24,6 +24,7 @@ /efreet-trash.pc /efreet.pc /eina.pc +/eina-cxx.pc /eio.pc /eldbus.pc /embryo.pc diff --git a/pc/eina-cxx.pc.in b/pc/eina-cxx.pc.in new file mode 100644 index 0000000000..c6571fa4ae --- /dev/null +++ b/pc/eina-cxx.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Eina C++ +Description: A C++ binding for the Eina library +Requires.private: @requirements_pc_eina@ +Version: @VERSION@ +Libs: -L${libdir} -leina @requirements_public_libs_eina@ +Libs.private: @requirements_libs_eina@ +Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eina-@VMAJ@ -I${includedir}/eina-@VMAJ@/eina -I${includedir}/eina_cxx-@VMAJ@ -I${includedir}/eina_cxx-@VMAJ@/eina_cxx diff --git a/src/Makefile.am b/src/Makefile.am index e797d57820..9abc8a919d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,8 @@ include Makefile_Emotion.am include Makefile_Ethumb.am include Makefile_Ethumb_Client.am +include Makefile_Eina_Cxx.am + .PHONY: benchmark examples BENCHMARK_SUBDIRS = \ @@ -71,6 +73,7 @@ benchmark: all-am EXAMPLES_SUBDIRS = \ examples/eina \ +examples/eina_cxx \ examples/eo \ examples/eet \ examples/evas \ diff --git a/src/Makefile_Eina_Cxx.am b/src/Makefile_Eina_Cxx.am new file mode 100644 index 0000000000..fa4888da41 --- /dev/null +++ b/src/Makefile_Eina_Cxx.am @@ -0,0 +1,61 @@ + +### Library + +#lib_LTLIBRARIES += lib/eina/libeina.la + +installed_einacxxmainheadersdir = $(includedir)/eina_cxx-@VMAJ@ +dist_installed_einacxxmainheaders_DATA = \ +lib/eina_cxx/Eina.hh + +installed_einacxxheadersdir = $(includedir)/eina_cxx-@VMAJ@/eina_cxx +dist_installed_einacxxheaders_DATA = \ +lib/eina_cxx/eina_accessor.hh \ +lib/eina_cxx/eina_clone_allocators.hh \ +lib/eina_cxx/eina_error.hh \ +lib/eina_cxx/eina_inarray.hh \ +lib/eina_cxx/eina_inlist.hh \ +lib/eina_cxx/eina_iterator.hh \ +lib/eina_cxx/eina_lists_auxiliary.hh \ +lib/eina_cxx/eina_ptrarray.hh \ +lib/eina_cxx/eina_ptrlist.hh \ +lib/eina_cxx/eina_ref.hh \ +lib/eina_cxx/eina_stringshare.hh \ +lib/eina_cxx/eina_thread.hh \ +lib/eina_cxx/eina_type_traits.hh \ +lib/eina_cxx/eina_value.hh + +### Unit tests + +if EFL_ENABLE_TESTS +if HAVE_CXX11 + +check_PROGRAMS += tests/eina_cxx/eina_cxx_suite +TESTS += tests/eina_cxx/eina_cxx_suite + +tests_eina_cxx_eina_cxx_suite_SOURCES = \ +tests/eina_cxx/eina_cxx_suite.cc \ +tests/eina_cxx/eina_cxx_test_inlist.cc \ +tests/eina_cxx/eina_cxx_test_inarray.cc \ +tests/eina_cxx/eina_cxx_test_iterator.cc \ +tests/eina_cxx/eina_cxx_test_ptrarray.cc \ +tests/eina_cxx/eina_cxx_test_ptrlist.cc \ +tests/eina_cxx/eina_cxx_test_stringshare.cc \ +tests/eina_cxx/eina_cxx_test_error.cc \ +tests/eina_cxx/eina_cxx_test_accessor.cc \ +tests/eina_cxx/eina_cxx_test_thread.cc \ +tests/eina_cxx/eina_cxx_test_eina_value.cc + +tests_eina_cxx_eina_cxx_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \ +-I$(top_builddir)/src/lib/eina_cxx \ +-DTESTS_WD=\"`pwd`\" \ +-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eina_cxx\" \ +-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)/src/tests/eina_cxx\" \ +-DTESTS_BUILD_DIR=PACKAGE_BUILD_DIR \ +@CHECK_CFLAGS@ \ +@EINA_CFLAGS@ +tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ +tests_eina_cxx_eina_cxx_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ + +endif +endif + diff --git a/src/examples/eina_cxx/Makefile.am b/src/examples/eina_cxx/Makefile.am new file mode 100644 index 0000000000..6f784b08a1 --- /dev/null +++ b/src/examples/eina_cxx/Makefile.am @@ -0,0 +1,45 @@ +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I$(top_builddir)/src/lib/efl \ +-I. \ +-I$(top_srcdir)/src/lib/eina \ +-I$(top_builddir)/src/lib/eina \ +-I$(top_srcdir)/src/lib/eina_cxx \ +-I$(top_builddir)/src/lib/eina_cxx + +LDADD = $(top_builddir)/src/lib/eina/libeina.la @EINA_LDFLAGS@ @USE_BOOST_SYSTEM_LIBS@ @USE_BOOST_SYSTEM_LDFLAGS@ +AM_CXXFLAGS = @USE_BOOST_CPPFLAGS@ + +SRCS = \ +eina_cxx_list_01.cc + +EXTRA_PROGRAMS = \ +eina_cxx_list_01 \ +eina_cxx_thread_01 + +eina_cxx_list_01_SOURCES = \ +eina_cxx_list_01.cc + +eina_cxx_thread_01_SOURCES = \ +eina_cxx_thread_01.cc + +EXTRA_DIST = $(DATA_FILES) + +examples: $(EXTRA_PROGRAMS) + +clean-local: + rm -f $(EXTRA_PROGRAMS) + +install-examples: + mkdir -p $(datadir)/eina/examples + $(install_sh_DATA) -c $(SRCS) $(DATA_FILES) $(datadir)/eina/examples + +uninstall-local: + for f in $(SRCS) $(DATA_FILES); do \ + rm -f $(datadir)/eina/examples/$$f ; \ + done + +if ALWAYS_BUILD_EXAMPLES +noinst_PROGRAMS = $(EXTRA_PROGRAMS) +endif diff --git a/src/examples/eina_cxx/eina_cxx_list_01.cc b/src/examples/eina_cxx/eina_cxx_list_01.cc new file mode 100644 index 0000000000..b451ef1553 --- /dev/null +++ b/src/examples/eina_cxx/eina_cxx_list_01.cc @@ -0,0 +1,55 @@ +//Compile with: +//gcc -g eina_list_01.c -o eina_list_01 `pkg-config --cflags --libs eina` + +#include +#include + +#include +#include + +#include + +template +I next(I i, std::size_t n = 1u) +{ + for(;n;--n) + ++i; +} + +int main(int argc, char **argv) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list; + + list.push_back("tigh"); + list.push_back("adar"); + list.push_back("baltar"); + list.push_back("roslin"); + + for(efl::eina::ptr_list::const_iterator + first = list.begin(), last = list.end() + ;first != last; ++first) + std::cout << *first << std::endl; + + efl::eina::ptr_list::iterator + iterator = ::next(list.begin(), 2u); + list.insert(iterator, "cain"); + + iterator = std::find(list.begin(), list.end(), "cain"); + assert(iterator != list.end() && ::next(iterator) != list.end()); + list.insert(::next(iterator), "zarek"); + + list.insert(list.begin(), "adama"); + + iterator = std::find(list.begin(), list.end(), "cain"); + assert(iterator != list.end()); + list.insert(iterator, "gaeta"); + + list.insert(::next(list.begin()), "lampkin"); + + for(efl::eina::ptr_list::const_iterator + first = list.begin(), last = list.end() + ;first != last; ++first) + std::cout << *first << std::endl; +} diff --git a/src/examples/eina_cxx/eina_cxx_thread_01.cc b/src/examples/eina_cxx/eina_cxx_thread_01.cc new file mode 100644 index 0000000000..6ce329f3e5 --- /dev/null +++ b/src/examples/eina_cxx/eina_cxx_thread_01.cc @@ -0,0 +1,32 @@ +//Compile with: +//gcc -g eina_list_01.c -o eina_list_01 `pkg-config --cflags --libs eina` + +#include +#include + +#include +#include + +#include + +namespace eina = efl::eina; + +void thread1(eina::mutex& m) +{ + +} + +int main(int argc, char **argv) +{ + eina::eina_init eina_init; + eina::eina_threads_init threads_init; + + eina::mutex m; + eina::condition_variable c; + + eina::unique_lock l(m); + + eina::thread thread1(&::thread1, eina::ref(m)); + + thread1.join(); +} diff --git a/src/lib/eina_cxx/Eina.hh b/src/lib/eina_cxx/Eina.hh new file mode 100644 index 0000000000..7e7e985c16 --- /dev/null +++ b/src/lib/eina_cxx/Eina.hh @@ -0,0 +1,44 @@ +#ifndef EINA_HH_ +#define EINA_HH_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace efl { namespace eina { + +struct eina_init +{ + eina_init() + { + ::eina_init(); + } + ~eina_init() + { + ::eina_shutdown(); + } +}; + +struct eina_threads_init +{ + eina_threads_init() + { + ::eina_threads_init(); + } + ~eina_threads_init() + { + ::eina_threads_shutdown(); + } +}; + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_accessor.hh b/src/lib/eina_cxx/eina_accessor.hh new file mode 100644 index 0000000000..b389b31bf7 --- /dev/null +++ b/src/lib/eina_cxx/eina_accessor.hh @@ -0,0 +1,214 @@ +#ifndef EINA_ACCESSOR_HH_ +#define EINA_ACCESSOR_HH_ + +#include +#include + +#include +#include +#include +#include + +namespace efl { namespace eina { + +template +struct accessor +{ + typedef unsigned int key_type; + typedef T mapped_type; + typedef T value_type; + typedef std::size_t size_type; + + accessor() : _impl(0) {} + explicit accessor(Eina_Accessor* impl) + : _impl(impl) + { + assert(_impl != 0); + } + accessor(accessor const& other) + : _impl(eina_accessor_clone(other._impl)) + {} + accessor& operator=(accessor const& other) + { + eina_accessor_free(_impl); + _impl = eina_accessor_clone(other._impl); + if(!_impl) + throw eina::system_error(efl::eina::get_error_code(), "Error cloning accessor"); + return *this; + } + ~accessor() + { + eina_accessor_free(_impl); + } + + mapped_type& operator[](size_type i) const + { + assert(_impl != 0); + void* p; + if(!eina_accessor_data_get(_impl, i, &p)) + { + eina::error_code ec = efl::eina::get_error_code(); + throw eina::system_error(ec, "EFL Eina Error"); + } + return *static_cast(p); + } + + Eina_Accessor* native_handle() const; + + void swap(accessor& other) + { + std::swap(_impl, other._impl); + } +private: + typedef Eina_Accessor*(accessor::*unspecified_bool_type)() const; +public: + operator unspecified_bool_type() const + { + return native_handle() ? &accessor::native_handle : 0 ; + } +private: + Eina_Accessor* _impl; +}; + +template +void swap(accessor& lhs, accessor& rhs) +{ + lhs.swap(rhs); +} + +template +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; + + accessor_iterator(accessor const& a, unsigned int pos = 0u) + : _accessor(a), _index(pos) + {} + + accessor_iterator& operator+=(difference_type i) + { + _index += i; + return *this; + } + accessor_iterator& operator-=(difference_type i) + { + _index -= i; + return *this; + } + value_type& operator[](difference_type i) + { + return _accessor[_index + i]; + } + accessor_iterator& operator++() + { + ++_index; + return *this; + } + accessor_iterator& operator--() + { + --_index; + return *this; + } + accessor_iterator& operator++(int) + { + accessor_iterator tmp(*this); + ++*this; + return tmp; + } + accessor_iterator& operator--(int) + { + accessor_iterator tmp(*this); + --*this; + return tmp; + } + value_type& operator*() const + { + return _accessor[_index]; + } + pointer operator->() const + { + return &**this; + } + void swap(accessor_iterator& other) + { + std::swap(_index, other._index); + std::swap(_accessor, other._accessor); + } +private: + accessor _accessor; + unsigned int _index; + + template + friend bool operator==(accessor_iterator const& lhs, accessor_iterator const& rhs) + { + return lhs._index == rhs._index; + } + + template + friend typename accessor_iterator::difference_type + operator-(accessor_iterator const& lhs, accessor_iterator const& rhs) + { + return lhs._index - rhs._index; + } + + template + friend + accessor_iterator operator+(accessor_iterator lhs + , typename accessor_iterator::difference_type rhs) + { + lhs._index += rhs; + return lhs; + } + + template + friend + accessor_iterator operator+(typename accessor_iterator::difference_type lhs + , accessor_iterator rhs) + { + return rhs + lhs; + } + + template + friend bool operator<(accessor_iterator const& lhs, accessor_iterator const& rhs) + { + return lhs._index < rhs._index; + } + + template + friend bool operator<=(accessor_iterator const& lhs, accessor_iterator const& rhs) + { + return lhs._index <= rhs._index; + } +}; + +template +bool operator>=(accessor_iterator const& lhs, accessor_iterator const& rhs) +{ + return !(lhs < rhs); +} + +template +bool operator>(accessor_iterator const& lhs, accessor_iterator const& rhs) +{ + return !(lhs <= rhs); +} + +template +bool operator!=(accessor_iterator const& lhs, accessor_iterator const& rhs) +{ + return !(lhs == rhs); +} + +template +void swap(accessor_iterator& lhs, accessor_iterator& rhs) +{ + lhs.swap(rhs); +} + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_clone_allocators.hh b/src/lib/eina_cxx/eina_clone_allocators.hh new file mode 100644 index 0000000000..6f7aba49eb --- /dev/null +++ b/src/lib/eina_cxx/eina_clone_allocators.hh @@ -0,0 +1,69 @@ +#ifndef EINA_CLONE_ALLOCATORS_HH_ +#define EINA_CLONE_ALLOCATORS_HH_ + +#include + +namespace efl { namespace eina { + +struct heap_copy_allocator +{ + template + static T* allocate_clone(T const& v) + { + return new T(v); + } + + template + static void deallocate_clone(T* p) + { +#ifdef EFL_EINA_CXX11 + std::default_delete()(p); +#else + delete p; +#endif + } +}; + +struct heap_clone_allocator +{ + template + static T* allocate_clone(T const& v) + { + return new_clone(v); + } + template + static void deallocate_clone(T* p) + { + delete_clone(p); + } +}; + +struct view_clone_allocator +{ + template + static T* allocate_clone(T const& v) + { + return const_cast(&v); + } + template + static void deallocate_clone(T* p) + { + } +}; + +struct heap_no_copy_allocator +{ + template + static void deallocate_clone(T* p) + { +#ifdef EFL_EINA_CXX11 + std::default_delete()(p); +#else + delete p; +#endif + } +}; + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_error.hh b/src/lib/eina_cxx/eina_error.hh new file mode 100644 index 0000000000..1199e694b9 --- /dev/null +++ b/src/lib/eina_cxx/eina_error.hh @@ -0,0 +1,105 @@ +#ifndef _EINA_ERROR_HH +#define _EINA_ERROR_HH + +#include + +#include + +namespace efl { namespace eina { + +using std::errc; +using std::system_error; +using std::error_code; +using std::error_condition; +typedef std::error_category system_error_category; + +inline system_error_category const& get_generic_category() +{ + return ::std::generic_category(); +} +inline system_error_category const& get_system_category() +{ + return ::std::system_category(); +} + +enum error_type {}; + +struct error_category : system_error_category +{ + const char* name() const throw() + { + return "eina"; + } + + bool equivalent(int code, eina::error_condition const& condition) const throw() + { + return code == condition.value(); + } + + bool equivalent(eina::error_code const& code, int condition) const throw() + { + return code.value() == condition; + } + + std::string message(int condition) const + { + const char* e = ::eina_error_msg_get(condition); + return e? e : "::eina_error_msg_get returned NULL. No error message available"; + } +}; + +inline eina::system_error_category& eina_error_category() +{ + static error_category _error_category; + return _error_category; +} + +inline eina::error_code get_error_code() +{ + Eina_Error error = eina_error_get(); + if(error) + { + eina_error_set(0); + return eina::error_code(error, eina_error_category()); + } + else + return eina::error_code(); +} + +inline eina::error_condition get_error_condition() +{ + Eina_Error error = eina_error_get(); + if(error) + { + eina_error_set(0); + return eina::error_condition(error, eina_error_category()); + } + else + return eina::error_condition(); +} + +inline error_type get_error_code_enum() +{ + return static_cast( ::eina_error_get() ); +} + + +inline void throw_on_error() +{ + eina::error_code ec = get_error_code(); + if(ec) + { + throw eina::system_error(ec, "EFL Eina Error"); + } +} + +} } + +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 diff --git a/src/lib/eina_cxx/eina_inarray.hh b/src/lib/eina_cxx/eina_inarray.hh new file mode 100644 index 0000000000..3619358bad --- /dev/null +++ b/src/lib/eina_cxx/eina_inarray.hh @@ -0,0 +1,544 @@ +#ifndef EINA_INARRAY_HH_ +#define EINA_INARRAY_HH_ + +#include +#include + +#include +#include +#include + +namespace efl { namespace eina { + +struct _inarray_common_base +{ + typedef std::size_t size_type; + + explicit _inarray_common_base(size_type member_size) + : _array( ::eina_inarray_new(member_size, 0) ) + { + } + ~_inarray_common_base() + { + ::eina_inarray_free(_array); + } + + size_type size() const + { + return ::eina_inarray_count(_array); + } + bool empty() const + { + return size() == 0u; + } + + Eina_Inarray* _array; +private: + _inarray_common_base(_inarray_common_base const& other); + _inarray_common_base& operator=(_inarray_common_base const& other); +}; + +template +class _pod_inarray : _inarray_common_base +{ + typedef _inarray_common_base _base_type; +public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T* pointer; + typedef T const* const_pointer; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + using _base_type::size; + using _base_type::empty; + + _pod_inarray() : _base_type(sizeof(T)) + { + } + _pod_inarray(size_type n, value_type const& t) : _base_type(sizeof(T)) + { + while(n--) + push_back(t); + } + template + _pod_inarray(InputIterator i, InputIterator const& j + , typename eina::enable_if::value>::type* = 0) + : _base_type(sizeof(T)) + { + while(i != j) + { + push_back(*i); + ++i; + } + } + _pod_inarray(_pod_inarrayconst& other) + : _base_type(sizeof(T)) + { + insert(end(), other.begin(), other.end()); + } + ~_pod_inarray() + { + } + _pod_inarray& operator=(_pod_inarrayconst& other) + { + clear(); + insert(end(), other.begin(), other.end()); + return *this; + } + void clear() + { + ::eina_inarray_flush(_array); + } + void push_back(T const& value) + { + eina_inarray_push(_array, &value); + } + void pop_back() + { + eina_inarray_pop(_array); + } + iterator insert(iterator i, value_type const& t) + { + if(i != end()) + { + T* q = static_cast + ( ::eina_inarray_alloc_at(_array, i - begin(), 1u)); + std::memcpy(q, &t, sizeof(t)); + return q; + } + else + { + push_back(t); + return end()-1; + } + } + iterator insert(iterator i, size_t n, value_type const& t) + { + T* q; + if(i != end()) + { + q = static_cast + ( ::eina_inarray_alloc_at(_array, i - &_array->members, n)); + } + else + { + q = eina_inarray_grow(_array, n); + } + for(T* p = q; n; --n, ++p) + std::memcpy(p, &t, sizeof(t)); + return q; + } + template + iterator insert(iterator p, InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + size_type n = 0; + while(i != j) + { + p = insert(p, *i); + ++p; + ++i; + ++n; + } + return p - n; + } + iterator erase(iterator q) + { + ::eina_inarray_remove_at(_array, q - begin()); + return q; + } + iterator erase(iterator i, iterator j) + { + while(i != j) + { + erase(--j); + } + return i; + } + template + void assign(InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0); + void assign(size_type n, value_type const& t); + value_type& back() + { + assert(!empty()); + return *static_cast(eina_inarray_nth(_array, size()-1u)); + } + value_type const& back() const + { + return const_cast<_pod_inarray&>(*this).back(); + } + value_type& front() + { + assert(!empty()); + return *static_cast(eina_inarray_nth(_array, 0u)); + } + value_type const& front() const + { + return const_cast<_pod_inarray&>(*this).front(); + } + iterator begin() + { + return !_array->members ? 0 : static_cast(::eina_inarray_nth(_array, 0u)); + } + iterator end() + { + return !_array->members ? 0 : static_cast(::eina_inarray_nth(_array, size()-1)) + 1; + } + const_iterator begin() const + { + return const_cast< _pod_inarray&>(*this).begin(); + } + const_iterator end() const + { + return const_cast< _pod_inarray&>(*this).end(); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(end()); + } + reverse_iterator rbegin() + { + return reverse_iterator(begin()); + } + reverse_iterator rend() + { + return reverse_iterator(end()); + } + const_iterator cbegin() const + { + return begin(); + } + const_iterator cend() const + { + return end(); + } + const_reverse_iterator crbegin() const + { + return rbegin(); + } + const_reverse_iterator crend() const + { + return rend(); + } + void swap(_pod_inarray& other) + { + std::swap(_array, other._array); + } + size_type max_size() const { return -1; } + + Eina_Inarray* native_handle() + { + return this->_array; + } + Eina_Inarray const* native_handle() const + { + return this->_array; + } +}; + +template +class _nonpod_inarray : _inarray_common_base +{ + typedef _inarray_common_base _base_type; +public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T* pointer; + typedef T const* const_pointer; + typedef pointer iterator; + typedef const_pointer const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + using _base_type::size; + using _base_type::empty; + + _nonpod_inarray() : _base_type(sizeof(T)) + { + } + _nonpod_inarray(size_type n, value_type const& t) : _base_type(sizeof(T)) + { + while(n--) + push_back(t); + } + template + _nonpod_inarray(InputIterator i, InputIterator const& j + , typename eina::enable_if::value>::type* = 0) + : _base_type(sizeof(T)) + { + while(i != j) + { + push_back(*i); + ++i; + } + } + _nonpod_inarray(_nonpod_inarrayconst& other) + : _base_type(sizeof(T)) + { + insert(end(), other.begin(), other.end()); + } + ~_nonpod_inarray() + { + for(T* first = static_cast(_array->members) + , *last = first + _array->len; first != last; ++first) + first->~T(); + } + _nonpod_inarray& operator=(_nonpod_inarrayconst& other) + { + clear(); + insert(end(), other.begin(), other.end()); + return *this; + } + void clear() + { + for(T* first = static_cast(_array->members) + , *last = first + _array->len; first != last; ++first) + first->~T(); + ::eina_inarray_flush(_array); + } + void push_back(T const& value) + { + insert(end(), 1u, value); + } + void pop_back() + { + T* elem = static_cast(_array->members) + _array->len - 1; + elem->~T(); + eina_inarray_pop(_array); + } + iterator insert(iterator i, value_type const& t) + { + return insert(i, 1u, t); + } + iterator insert(iterator i, size_t n, value_type const& t) + { + if(_array->max - _array->len >= n) + { + iterator end = static_cast(_array->members) + + _array->len + , last = end + n; + _array->len += n; + std::reverse_iterator + dest(last), src(end), src_end(i); + for(;src != src_end; ++src) + { + if(dest.base() <= end) + *dest++ = *src; + else + new (&*dest++) T(*src); + } + iterator j = i; + for(size_type i = 0;i != n;++i) + { + if(j < end) + *j = t; + else + new (&*j++) T(t); + } + } + else + { + size_type index = i - static_cast(_array->members); + + Eina_Inarray* old_array = eina_inarray_new(_array->member_size, 0); + *old_array = *_array; + _array->len = _array->max = 0; + _array->members = 0; + eina_inarray_resize(_array, old_array->len+n); + _array->len = old_array->len+n; + + iterator old_first = static_cast(old_array->members) + , first = begin() + , last = first + _array->len; + i = index + begin(); + + while(first != i) + { + new (&*first++) T(*old_first); + old_first++->~T(); + } + for(size_type i = 0;i != n;++i) + new (&*first++) T(t); + assert(last - first == _array->len - index - n); + while(first != last) + { + new (&*first++) T(*old_first); + old_first++->~T(); + } + } + return i; + } + template + iterator insert(iterator p, InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + size_type n = 0; + while(i != j) + { + p = insert(p, *i); + ++p; + ++i; + ++n; + } + return p - n; + } + iterator erase(iterator q) + { + return erase(q, q+1); + } + iterator erase(iterator i, iterator j) + { + iterator last = end(); + iterator k = i, l = j; + while(l != last) + *k++ = *l++; + while(k != last) + k++->~T(); + _array->len -= j - i; + + return i; + } + template + void assign(InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0); + void assign(size_type n, value_type const& t); + value_type& back() + { + assert(!empty()); + return *static_cast(eina_inarray_nth(_array, size()-1u)); + } + value_type const& back() const + { + return const_cast<_nonpod_inarray&>(*this).back(); + } + value_type& front() + { + assert(!empty()); + return *static_cast(eina_inarray_nth(_array, 0u)); + } + value_type const& front() const + { + return const_cast<_nonpod_inarray&>(*this).front(); + } + iterator begin() + { + return static_cast(_array->members); + } + iterator end() + { + return static_cast(_array->members) + _array->len; + } + const_iterator begin() const + { + return const_cast< _nonpod_inarray&>(*this).begin(); + } + const_iterator end() const + { + return const_cast< _nonpod_inarray&>(*this).end(); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(end()); + } + reverse_iterator rbegin() + { + return reverse_iterator(begin()); + } + reverse_iterator rend() + { + return reverse_iterator(end()); + } + const_iterator cbegin() const + { + return begin(); + } + const_iterator cend() const + { + return end(); + } + const_reverse_iterator crbegin() const + { + return rbegin(); + } + const_reverse_iterator crend() const + { + return rend(); + } + void swap(_nonpod_inarray& other) + { + std::swap(_array, other._array); + } + size_type max_size() const { return -1; } + + Eina_Inarray* native_handle() + { + return this->_array; + } + Eina_Inarray const* native_handle() const + { + return this->_array; + } +}; + +template +class inarray : public eina::if_, _pod_inarray + , _nonpod_inarray >::type +{ + typedef typename eina::if_, _pod_inarray + , _nonpod_inarray >::type _base_type; +public: + inarray() : _base_type() {} + inarray(typename _base_type::size_type n, typename _base_type::value_type const& t) + : _base_type(n, t) {} + template + inarray(InputIterator i, InputIterator const& j + , typename eina::enable_if::value>::type* = 0) + : _base_type(i, j) + {} + +}; + +template +bool operator==(inarray const& lhs, inarray const& rhs) +{ + return lhs.size() == rhs.size() && + std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator!=(inarray const& lhs, inarray const& rhs) +{ + return !(lhs == rhs); +} + +template +void swap(inarray& lhs, inarray& rhs) +{ + lhs.swap(rhs); +} + + + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_inlist.hh b/src/lib/eina_cxx/eina_inlist.hh new file mode 100644 index 0000000000..168b262c53 --- /dev/null +++ b/src/lib/eina_cxx/eina_inlist.hh @@ -0,0 +1,464 @@ +#ifndef EINA_INLIST_HH_ +#define EINA_INLIST_HH_ + +#include +#include +#include +#include + +#include + +namespace efl { namespace eina { + +template +struct _inlist_node +{ + EINA_INLIST; + T object; +}; + +template +_inlist_node* _get_node(Eina_Inlist* l) +{ + return static_cast<_inlist_node*>(static_cast(l)); +} + +template +_inlist_node const* _get_node(Eina_Inlist const* l) +{ + return const_cast(l); +} + +template +Eina_Inlist* _get_list(_inlist_node* n) +{ + if(n) + return EINA_INLIST_GET(n); + else + return 0; +} + +template +Eina_Inlist const* _get_list(_inlist_node const* n) +{ + return _get_list(const_cast<_inlist_node*>(n)); +} + +template +struct _inlist_iterator +{ + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + _inlist_iterator() {} + explicit _inlist_iterator(_inlist_node* list, _inlist_node* node) + : _list(list), _node(node) {} + + _inlist_iterator& operator++() + { + _node = _get_node(_node->__in_list.next); + return *this; + } + _inlist_iterator operator++(int) + { + _inlist_iterator tmp(*this); + ++*this; + return tmp; + } + _inlist_iterator& operator--() + { + if(_node) + _node = _get_node(_node->__in_list.prev); + else + _node = _get_node(_list->__in_list.last); + return *this; + } + _inlist_iterator operator--(int) + { + _inlist_iterator tmp(*this); + --*this; + return tmp; + } + T const& operator*() const + { + return _node->object; + } + T const* operator->() const + { + return &_node->object; + } + _inlist_node* native_handle() + { + return _node; + } + _inlist_node const* native_handle() const + { + return _node; + } +private: + _inlist_node* _list; + _inlist_node* _node; + + friend bool operator==(_inlist_iterator lhs, _inlist_iterator rhs) + { + return lhs._node == rhs._node; + } +}; + +template +bool operator!=(_inlist_iterator lhs, _inlist_iterator rhs) +{ + return !(lhs == rhs); +} + +template +struct _inlist_common_base +{ + typedef typename Allocator::template rebind<_inlist_node >::other node_allocator_type; + typedef Allocator allocator_type; + typedef _inlist_node node_type; + + _inlist_common_base(Allocator allocator) + : _impl(allocator) {} + _inlist_common_base() + {} + ~_inlist_common_base() + { + clear(); + } + + void clear() + { + Eina_Inlist* p = _impl._list; + Eina_Inlist* q; + while(p) + { + q = p->next; + + _inlist_node* node = _get_node(p); + node->~_inlist_node(); + get_node_allocator().deallocate(node, 1); + + p = q; + } + _impl._list = 0; + } + node_allocator_type& get_node_allocator() + { + return _impl; + } + + // For EBO + struct _inlist_impl : node_allocator_type + { + _inlist_impl(Allocator allocator) + : node_allocator_type(allocator), _list(0) + {} + _inlist_impl() : _list(0) {} + + Eina_Inlist* _list; + }; + + _inlist_impl _impl; +private: + _inlist_common_base(_inlist_common_base const& other); + _inlist_common_base& operator=(_inlist_common_base const& other); +}; + +template > +class inlist : protected _inlist_common_base +{ + typedef _inlist_common_base _base_type; + typedef typename _base_type::node_type _node_type; +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 const_iterator; + typedef _inlist_iterator 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 std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + using _base_type::clear; + + inlist() {} + inlist(size_type n, value_type const& t) + { + while(n--) + push_back(t); + } + template + inlist(InputIterator i, InputIterator const& j + , allocator_type const& alloc = allocator_type() + , typename eina::enable_if::value>::type* = 0) + : _base_type(alloc) + { + while(i != j) + { + push_back(*i); + ++i; + } + } + inlist(inlistconst& other) + : _base_type() + { + insert(end(), other.begin(), other.end()); + } + inlist& operator=(inlistconst& other) + { + clear(); + insert(end(), other.begin(), other.end()); + return *this; + } + size_type size() const + { + return ::eina_inlist_count(this->_impl._list); + } + bool empty() const + { + return this->_impl._list == 0; + } + allocator_type get_allocator() const + { + return allocator_type(this->get_node_allocator()); + } + void push_back(T const& value) + { + _node_type* node ( this->get_node_allocator().allocate(1) ); + try + { + new (&node->object) T(value); + // eina_inlist_append can't fail + this->_impl._list = eina_inlist_append(this->_impl._list, _get_list(node)); + } + catch(...) + { + this->get_node_allocator().deallocate(node, 1); + throw; + } + } + void push_front(T const& value) + { + _node_type* node ( this->get_node_allocator().allocate(1) ); + try + { + new (&node->object) T(value); + // eina_inlist_prepend can't fail + this->_impl._list = eina_inlist_prepend(this->_impl._list, _get_list(node)); + } + catch(...) + { + this->get_node_allocator().deallocate(node, 1); + throw; + } + } + void pop_back() + { + this->_impl._list = eina_inlist_remove(this->_impl._list, this->_impl._list->last); + } + void pop_front() + { + this->_impl._list = eina_inlist_remove(this->_impl._list, this->_impl._list); + } + iterator insert(iterator i, value_type const& t) + { + _node_type* node ( this->get_node_allocator().allocate(1) ); + try + { + new (&node->object) T(t); + // eina_inlist_prepend_relative can't fail + this->_impl._list = _eina_inlist_prepend_relative + (this->_impl._list, _get_list(node) + , _get_list(i.native_handle())); + return iterator(_get_node(this->_impl._list), node); + } + catch(...) + { + this->get_node_allocator().deallocate(node, 1); + throw; + } + } + iterator insert(iterator i, size_t n, value_type const& t) + { + iterator r = i; + if(n--) + r = insert(i, t); + while(n--) + insert(i, t); + return r; + } + + template + iterator insert(iterator p, InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + iterator r = p; + if(i != j) + { + value_type v = *i; + r = insert(p, v); + ++i; + } + while(i != j) + { + insert(p, *i); + ++i; + } + return r; + } + + iterator erase(iterator q) + { + if(q.native_handle()) + { + iterator r(_get_node(this->_impl._list), _get_node(_get_list(q.native_handle())->next)); + this->_impl._list = eina_inlist_remove(this->_impl._list, _get_list(q.native_handle())); + return r; + } + else + return q; + } + + iterator erase(iterator i, iterator j) + { + while(i != j) + i = erase(i); + if(j.native_handle()) + return j; + else + return end(); + } + + template + void assign(InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + clear(); + insert(end(), i, j); + } + + void assign(size_type n, value_type const& t) + { + clear(); + insert(end(), n, t); + } + + value_type& back() + { + return _get_node(this->_impl._list->last)->object; + } + value_type const& back() const + { + return const_cast&>(*this).back(); + } + value_type& front() + { + return _get_node(this->_impl._list)->object; + } + value_type const& front() const + { + return const_cast&>(*this).front(); + } + const_iterator begin() const + { + return const_iterator(_get_node(this->_impl._list), _get_node(this->_impl._list)); + } + const_iterator end() const + { + return const_iterator(_get_node(this->_impl._list), 0); + } + iterator begin() + { + return iterator(_get_node(this->_impl._list), _get_node(this->_impl._list)); + } + iterator end() + { + return iterator(_get_node(this->_impl._list), 0); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(end()); + } + reverse_iterator rbegin() + { + return reverse_iterator(begin()); + } + reverse_iterator rend() + { + return reverse_iterator(end()); + } + const_iterator cbegin() const + { + return begin(); + } + const_iterator cend() const + { + return end(); + } + const_reverse_iterator crbegin() const + { + return rbegin(); + } + const_reverse_iterator crend() const + { + return rend(); + } + void swap(inlist& other) + { + std::swap(this->_impl._list, other._impl._list); + } + size_type max_size() const { return -1; } + + Eina_Inlist* native_handle() + { + return this->_impl._list; + } + Eina_Inlist const* native_handle() const + { + return this->_impl._list; + } + eina::accessor accessor() const + { + return eina::accessor(eina_inlist_accessor_new(this->_impl._list)); + } + eina::accessor accessor() + { + return eina::accessor(eina_inlist_accessor_new(this->_impl._list)); + } +}; + +template +bool operator==(inlist const& lhs, inlist const& rhs) +{ + return lhs.size() == rhs.size() && + std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator!=(inlist const& lhs, inlist const& rhs) +{ + return !(lhs == rhs); +} + +template +void swap(inlist& lhs, inlist& rhs) +{ + lhs.swap(rhs); +} + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_iterator.hh b/src/lib/eina_cxx/eina_iterator.hh new file mode 100644 index 0000000000..d10401c0c0 --- /dev/null +++ b/src/lib/eina_cxx/eina_iterator.hh @@ -0,0 +1,101 @@ +#ifndef EINA_ITERATOR_HH_ +#define EINA_ITERATOR_HH_ + +#include + +#include +#include + +namespace efl { namespace eina { + +template +struct _common_iterator_base +{ +private: + typedef _common_iterator_base self_type; +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; + + _common_iterator_base() {} + explicit _common_iterator_base(Eina_Iterator* iterator) + : _iterator(iterator) {} + ~_common_iterator_base() + { + if(_iterator) + eina_iterator_free(_iterator); + } + _common_iterator_base(self_type const& other) + : _iterator(other._iterator) + { + other._iterator = 0; + } + _common_iterator_base& operator=(self_type const& other) + { + _iterator = other._iterator; + other._iterator = 0; + return *this; + } + +protected: + mutable Eina_Iterator* _iterator; + + friend inline bool operator==(_common_iterator_base const& lhs, _common_iterator_base const& rhs) + { + return lhs._iterator == rhs._iterator; + } + friend inline bool operator!=(_common_iterator_base const& lhs, _common_iterator_base const& rhs) + { + return !(lhs == rhs); + } +}; + +template +struct iterator : _common_iterator_base +{ +private: + typedef _common_iterator_base base_type; + typename base_type::pointer _value; + typedef iterator self_type; +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; + + explicit iterator(Eina_Iterator* iterator = 0) + : base_type(iterator) + { + if(this->_iterator) + ++*this; + } + self_type& operator++() + { + void* data; + Eina_Bool r = ::eina_iterator_next(this->_iterator, &data); + if(!r) + this->_iterator = 0; + _value = static_cast(data); + return *this; + } + self_type& operator++(int) + { + return ++**this; + } + value_type& operator*() const + { + return *_value; + } + pointer operator->() const + { + return _value; + } +}; + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_lists_auxiliary.hh b/src/lib/eina_cxx/eina_lists_auxiliary.hh new file mode 100644 index 0000000000..ebcbfd6016 --- /dev/null +++ b/src/lib/eina_cxx/eina_lists_auxiliary.hh @@ -0,0 +1,28 @@ +#ifndef _EINA_LISTS_AUXILIARY_HH +#define _EINA_LISTS_AUXILIARY_HH + +#include + +namespace efl { namespace eina { + +inline Eina_List* _eina_list_prepend_relative_list(Eina_List* list, const void* data, Eina_List* relative) EINA_ARG_NONNULL(2) +{ + if(relative) + return ::eina_list_prepend_relative_list(list, data, relative); + else + return ::eina_list_append(list, data); +} + +inline Eina_Inlist *_eina_inlist_prepend_relative(Eina_Inlist *in_list, + Eina_Inlist *in_item, + Eina_Inlist *in_relative) EINA_ARG_NONNULL(2) +{ + if(in_relative) + return ::eina_inlist_prepend_relative(in_list, in_item, in_relative); + else + return ::eina_inlist_append(in_list, in_item); +} + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_ptrarray.hh b/src/lib/eina_cxx/eina_ptrarray.hh new file mode 100644 index 0000000000..7b0e88b6ed --- /dev/null +++ b/src/lib/eina_cxx/eina_ptrarray.hh @@ -0,0 +1,486 @@ +#ifndef EINA_PTRARRAY_HH_ +#define EINA_PTRARRAY_HH_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace efl { namespace eina { + +struct _ptr_array_iterator_base +{ + _ptr_array_iterator_base() : _ptr(0) {} + _ptr_array_iterator_base(void** ptr) + : _ptr(ptr) + {} + + void** _ptr; +}; + +template +struct _ptr_array_iterator : protected _ptr_array_iterator_base +{ + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + _ptr_array_iterator() {} + explicit _ptr_array_iterator(void** ptr) + : _ptr_array_iterator_base(ptr) + + { + } + _ptr_array_iterator(_ptr_array_iterator::type> const& other) + : _ptr_array_iterator_base(static_cast<_ptr_array_iterator_base const&>(other)) + { + } + + _ptr_array_iterator& operator++() + { + ++_ptr; + return *this; + } + _ptr_array_iterator operator++(int) + { + _ptr_array_iterator tmp(*this); + ++*this; + return tmp; + } + _ptr_array_iterator& operator--() + { + --_ptr; + return *this; + } + _ptr_array_iterator operator--(int) + { + _ptr_array_iterator tmp(*this); + --*this; + return tmp; + } + reference operator*() const + { + return *static_cast(*_ptr); + } + pointer operator->() const + { + return &**this; + } + void** native_handle() const + { + return _ptr; + } + friend inline bool operator==(_ptr_array_iterator lhs, _ptr_array_iterator rhs) + { + return lhs._ptr == rhs._ptr; + } + friend inline bool operator!=(_ptr_array_iterator lhs, _ptr_array_iterator rhs) + { + return !(lhs == rhs); + } + friend inline _ptr_array_iterator operator+(_ptr_array_iterator lhs + , difference_type size) + { + lhs._ptr += size; + return lhs; + } + friend inline _ptr_array_iterator operator-(_ptr_array_iterator lhs + , difference_type size) + { + lhs._ptr -= size; + return lhs; + } + friend inline difference_type operator-(_ptr_array_iterator lhs + , _ptr_array_iterator rhs) + { + return lhs._ptr - rhs._ptr; + } +}; + +template +struct _ptr_array_common_base +{ + typedef CloneAllocator clone_allocator_type; + + _ptr_array_common_base(CloneAllocator clone_allocator) + : _impl(clone_allocator) + {} + _ptr_array_common_base(Eina_Array* _array) + : _impl(_array) + {} + _ptr_array_common_base() {} + + CloneAllocator& _get_clone_allocator() + { + return _impl; + } + CloneAllocator const& _get_clone_allocator() const + { + return _impl; + } + void _delete_clone(T const* p) + { + _get_clone_allocator().deallocate_clone(p); + } + T* _new_clone(T const& a) + { + return _get_clone_allocator().allocate_clone(a); + } + + struct _ptr_array_impl : CloneAllocator + { + _ptr_array_impl() : _array( ::eina_array_new(32u) ) {} + _ptr_array_impl(CloneAllocator allocator) + : clone_allocator_type(allocator), _array( ::eina_array_new(32u)) {} + + Eina_Array* _array; + }; + + _ptr_array_impl _impl; + +private: + _ptr_array_common_base(_ptr_array_common_base const& other); + _ptr_array_common_base& operator=(_ptr_array_common_base const& other); +}; + +template +class ptr_array : protected _ptr_array_common_base +{ + typedef _ptr_array_common_base _base_type; +public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef _ptr_array_iterator const_iterator; + typedef _ptr_array_iterator iterator; + typedef T* pointer; + typedef T const* const_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef CloneAllocator clone_allocator_type; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + ptr_array() {} + ptr_array(size_type n, const_reference t) + { + while(n--) + push_back(t); + } + template + ptr_array(InputIterator i, InputIterator const& j + , clone_allocator_type const& alloc = clone_allocator_type() + , typename eina::enable_if::value>::type* = 0) + : _base_type(alloc) + { + while(i != j) + { + push_back(*i); + ++i; + } + } + ptr_array(ptr_array const& other) + : _base_type() + { + insert(end(), other.begin(), other.end()); + } + template + ptr_array(ptr_arrayconst& other) + : _base_type() + { + insert(end(), other.begin(), other.end()); + } + ~ptr_array() + { + clear(); + } + ptr_array& operator=(ptr_arrayconst& other) + { + clear(); + insert(end(), other.begin(), other.end()); + return *this; + } + + void clear() + { + for(iterator first = begin(), last = end(); first != last; ++first) + this->_delete_clone(&*first); + eina_array_flush(this->_impl._array); + } + std::size_t size() const + { + return eina_array_count(this->_impl._array); + } + bool empty() const + { + return size() == 0u; + } + clone_allocator_type get_clone_allocator() const + { + return clone_allocator_type(this->_get_clone_allocator()); + } + void push_back(const_reference a) + { + push_back(this->_new_clone(a)); + } + void push_back(pointer p) + { + std::auto_ptr p1(p); + push_back(p1); + } + void push_back(std::auto_ptr& p) + { + if(eina_array_push(this->_impl._array, p.get())) + p.release(); + else + throw std::bad_alloc(); + } + void pop_back() + { + eina_array_pop(this->_impl._array); + } + iterator insert(iterator i, value_type const& t) + { + return insert(i, this->_new_clone(t)); + } + iterator insert(iterator i, pointer pv) + { + std::auto_ptr p(pv); + return insert(i, p); + } + iterator insert(iterator i, std::auto_ptr& p) + { + std::size_t j + = i.native_handle() - this->_impl._array->data + , size = this->size(); + if(eina_array_push(this->_impl._array, p.get())) + { + if(size - j) + { + memmove( + this->_impl._array->data + j + 1 + , this->_impl._array->data + j + , (size - j)*sizeof(void*)); + // PRE: Q:[j, size) = [j+1, size+1) + pointer* data = static_cast + (static_cast(this->_impl._array->data)); + data[j] = p.get(); + } + p.release(); + return iterator(this->_impl._array->data + j); + } + else + throw std::bad_alloc(); + } + iterator insert(iterator i, size_t n, value_type const& t) + { + iterator r = i; + if(n--) + r = insert(i, t); + while(n--) + insert(i, t); + return r; + } + iterator insert(iterator i, size_t n, pointer p) + { + iterator r = i; + if(n--) + r = insert(i, p); + while(n--) + insert(i, this->_new_clone(p)); + return r; + } + template + iterator insert(iterator p, InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + size_type index = p.native_handle() - this->_impl._array->data; + while(i != j) + { + p = insert(p, this->_new_clone(*i)); + ++p; + ++i; + } + return iterator(this->_impl._array->data + index); + } + iterator erase(iterator q) + { + size_type size = this->size() + , i = q.native_handle() - this->_impl._array->data; + memmove(q.native_handle() + , q.native_handle() + 1 + , (size - i - 1)*sizeof(void*)); + eina_array_pop(this->_impl._array); + return q; + } + iterator erase(iterator i, iterator j) + { + size_type size = this->size() + , distance = std::distance(i, j); + memmove(i.native_handle() + , j.native_handle() + , (size - distance)*sizeof(void*)); + while(distance--) + eina_array_pop(this->_impl._array); + return i; + } + template + void assign(InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + clear(); + insert(end(), i, j); + } + void assign(size_type n, value_type const& t) + { + clear(); + insert(end(), n, t); + } + + value_type& back() + { + return *static_cast(this->_impl._array->data[size()-1]); + } + value_type const& back() const + { + return const_cast&>(*this).back(); + } + value_type& front() + { + return *static_cast(this->_impl._array->data[0]); + } + value_type const& front() const + { + return const_cast&>(*this).front(); + } + + const_reference operator[](size_type index) const + { + pointer data = static_cast + (this->_impl._array->data[index]); + return *data; + } + reference operator[](size_type index) + { + return const_cast + (const_castconst&>(*this)[index]); + } + + const_iterator begin() const + { + return const_iterator(this->_impl._array->data); + } + const_iterator end() const + { + return const_iterator(this->_impl._array->data + size()); + } + iterator begin() + { + return iterator(this->_impl._array->data); + } + iterator end() + { + return iterator(this->_impl._array->data + size()); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(end()); + } + reverse_iterator rbegin() + { + return reverse_iterator(begin()); + } + reverse_iterator rend() + { + return reverse_iterator(end()); + } + const_iterator cbegin() const + { + return begin(); + } + const_iterator cend() const + { + return end(); + } + const_reverse_iterator crbegin() const + { + return rbegin(); + } + const_reverse_iterator crend() const + { + return rend(); + } + eina::iterator ibegin() + { + return eina::iterator( ::eina_array_iterator_new(this->_impl._array) ); + } + eina::iterator iend() + { + return eina::iterator(); + } + eina::iterator ibegin() const + { + return eina::iterator( ::eina_array_iterator_new(this->_impl._array) ); + } + eina::iterator iend() const + { + return eina::iterator(); + } + eina::iterator cibegin() const + { + return ibegin(); + } + eina::iterator ciend() const + { + return iend(); + } + void swap(ptr_array& other) + { + std::swap(this->_impl._array, other._impl._array); + } + size_type max_size() const { return -1; } + + Eina_Array* native_handle() + { + return this->_impl._array; + } + Eina_Array const* native_handle() const + { + return this->_impl._array; + } +}; + +template +bool operator==(ptr_array const& lhs, ptr_array const& rhs) +{ + return lhs.size() == rhs.size() + && std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator!=(ptr_array const& lhs, ptr_array const& rhs) +{ + return !(lhs == rhs); +} + +template +void swap(ptr_array& lhs, ptr_array& rhs) +{ + lhs.swap(rhs); +} + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_ptrlist.hh b/src/lib/eina_cxx/eina_ptrlist.hh new file mode 100644 index 0000000000..b9132872b7 --- /dev/null +++ b/src/lib/eina_cxx/eina_ptrlist.hh @@ -0,0 +1,495 @@ +#ifndef EINA_LIST_HH_ +#define EINA_LIST_HH_ + +#include +#include +#include +#include +#include + +#include +#include + +namespace efl { namespace eina { + +struct _ptr_list_iterator_base +{ + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + _ptr_list_iterator_base() : _list(0) {} + _ptr_list_iterator_base(Eina_List* list, Eina_List* node) + : _list(list), _node(node) + {} + +protected: + Eina_List *_list, *_node; +}; + +template +struct _ptr_list_iterator : _ptr_list_iterator_base +{ + typedef T value_type; + typedef value_type* pointer; + typedef value_type& reference; + + _ptr_list_iterator() {} + explicit _ptr_list_iterator(Eina_List* list, Eina_List* node) + : _ptr_list_iterator_base(list, node) + { + } + _ptr_list_iterator(_ptr_list_iterator::type> const& other) + : _ptr_list_iterator_base(static_cast<_ptr_list_iterator_base const&>(other)) + { + } + + _ptr_list_iterator& operator++() + { + _node = eina_list_next(_node); + return *this; + } + _ptr_list_iterator operator++(int) + { + _ptr_list_iterator tmp(*this); + ++*this; + return tmp; + } + _ptr_list_iterator& operator--() + { + if(_node) + _node = eina_list_prev(_node); + else + _node = eina_list_last(_list); + return *this; + } + _ptr_list_iterator operator--(int) + { + _ptr_list_iterator tmp(*this); + --*this; + return tmp; + } + reference operator*() const + { + void* data = eina_list_data_get(_node); + return *static_cast(data); + } + pointer operator->() const + { + return &**this; + } + Eina_List* native_handle() + { + return _node; + } + Eina_List const* native_handle() const + { + return _node; + } + friend inline bool operator==(_ptr_list_iterator lhs, _ptr_list_iterator rhs) + { + return lhs._node == rhs._node; + } + friend inline bool operator!=(_ptr_list_iterator lhs, _ptr_list_iterator rhs) + { + return !(lhs == rhs); + } +}; + +template +struct _ptr_list_common_base +{ + typedef CloneAllocator clone_allocator_type; + + _ptr_list_common_base(CloneAllocator clone_allocator) + : _impl(clone_allocator) + {} + _ptr_list_common_base(Eina_List* _list) + : _impl(_list) + {} + _ptr_list_common_base() {} + + CloneAllocator& _get_clone_allocator() + { + return _impl; + } + CloneAllocator const& _get_clone_allocator() const + { + return _impl; + } + void _delete_clone(T const* p) + { + _get_clone_allocator().deallocate_clone(p); + } + T* _new_clone(T const& a) + { + return _get_clone_allocator().allocate_clone(a); + } + + struct _ptr_list_impl : CloneAllocator + { + _ptr_list_impl() : _list(0) {} + _ptr_list_impl(CloneAllocator allocator) + : clone_allocator_type(allocator), _list(0) {} + + Eina_List* _list; + }; + + _ptr_list_impl _impl; + +private: + _ptr_list_common_base(_ptr_list_common_base const& other); + _ptr_list_common_base& operator=(_ptr_list_common_base const& other); +}; + +template +class ptr_list : protected _ptr_list_common_base +{ + typedef _ptr_list_common_base _base_type; +public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef _ptr_list_iterator const_iterator; + typedef _ptr_list_iterator iterator; + typedef T* pointer; + typedef T const* const_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef CloneAllocator clone_allocator_type; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + ptr_list() {} + ptr_list(size_type n, const_reference t) + { + while(n--) + push_back(t); + } + template + ptr_list(InputIterator i, InputIterator const& j + , clone_allocator_type const& alloc = clone_allocator_type() + , typename eina::enable_if::value>::type* = 0) + : _base_type(alloc) + { + while(i != j) + { + push_back(*i); + ++i; + } + } + ptr_list(ptr_list const& other) + : _base_type() + { + insert(end(), other.begin(), other.end()); + } + template + ptr_list(ptr_listconst& other) + : _base_type() + { + insert(end(), other.begin(), other.end()); + } + ~ptr_list() + { + clear(); + } + ptr_list& operator=(ptr_listconst& other) + { + clear(); + insert(end(), other.begin(), other.end()); + return *this; + } + + void clear() + { + for(iterator first = begin(), last = end(); first != last; ++first) + this->_delete_clone(&*first); + eina_list_free(this->_impl._list); + this->_impl._list = 0; + } + std::size_t size() const + { + return eina_list_count(this->_impl._list); + } + bool empty() const + { + return size() == 0u; + } + clone_allocator_type get_clone_allocator() const + { + return clone_allocator_type(this->_get_clone_allocator()); + } + void push_back(const_reference a) + { + push_back(this->_new_clone(a)); + } + void push_back(pointer p) + { + std::auto_ptr p1(p); + push_back(p1); + } + void push_back(std::auto_ptr& p) + { + Eina_List* new_list = eina_list_append(this->_impl._list, p.get()); + if(new_list) + { + this->_impl._list = new_list; + p.release(); + } + else + throw std::bad_alloc(); + } + void push_front(const_reference a) + { + push_front(this->new_clone(a)); + } + void push_front(pointer p) + { + std::auto_ptr p1(p); + push_front(p1); + } + void push_front(std::auto_ptr& p) + { + Eina_List* new_list = eina_list_prepend(this->_impl._list, p.get()); + if(new_list) + { + this->_impl._list = new_list; + p.release(); + } + else + throw std::bad_alloc(); + } + void pop_back() + { + this->_impl._list = eina_list_remove_list(this->_impl._list, eina_list_last(this->_impl._list)); + } + void pop_front() + { + this->_impl._list = eina_list_remove_list(this->_impl._list, this->_impl._list); + } + iterator insert(iterator i, value_type const& t) + { + return insert(i, this->_new_clone(t)); + } + iterator insert(iterator i, pointer pv) + { + std::auto_ptr p(pv); + return insert(i, p); + } + iterator insert(iterator i, std::auto_ptr& p) + { + this->_impl._list = _eina_list_prepend_relative_list + (this->_impl._list, p.get(), i.native_handle()); + if(this->_impl._list) + p.release(); + else + throw std::bad_alloc(); + return iterator(this->_impl._list + , i.native_handle() + ? ::eina_list_prev(i.native_handle()) + : ::eina_list_last(this->_impl._list) + ); + } + iterator insert(iterator i, size_t n, value_type const& t) + { + iterator r = i; + if(n--) + r = insert(i, t); + while(n--) + insert(i, t); + return r; + } + iterator insert(iterator i, size_t n, pointer p) + { + iterator r = i; + if(n--) + r = insert(i, p); + while(n--) + insert(i, this->_new_clone(p)); + return r; + } + template + iterator insert(iterator p, InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + iterator r = p; + if(i != j) + { + r = insert(p, *i); + ++i; + } + while(i != j) + { + insert(p, this->_new_clone(*i)); + ++i; + } + return r; + } + iterator erase(iterator q) + { + if(q.native_handle()) + { + iterator r(this->_impl._list, eina_list_next(q.native_handle())); + this->_impl._list = eina_list_remove_list(this->_impl._list, q.native_handle()); + return r; + } + else + return q; + } + iterator erase(iterator i, iterator j) + { + while(i != j) + i = erase(i); + if(j.native_handle()) + return j; + else + return end(); + } + template + void assign(InputIterator i, InputIterator j + , typename eina::enable_if::value>::type* = 0) + { + clear(); + insert(end(), i, j); + } + void assign(size_type n, value_type const& t) + { + clear(); + insert(end(), n, t); + } + + value_type& back() + { + return *static_cast(eina_list_data_get(eina_list_last(this->_impl._list))); + } + value_type const& back() const + { + return const_cast&>(*this).back(); + } + value_type& front() + { + return *static_cast(eina_list_data_get(this->_impl._list)); + } + value_type const& front() const + { + return const_cast&>(*this).front(); + } + + const_iterator begin() const + { + return const_iterator(this->_impl._list, this->_impl._list); + } + const_iterator end() const + { + return const_iterator(this->_impl._list, 0); + } + iterator begin() + { + return iterator(this->_impl._list, this->_impl._list); + } + iterator end() + { + return iterator(this->_impl._list, 0); + } + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(end()); + } + reverse_iterator rbegin() + { + return reverse_iterator(begin()); + } + reverse_iterator rend() + { + return reverse_iterator(end()); + } + const_iterator cbegin() const + { + return begin(); + } + const_iterator cend() const + { + return end(); + } + const_reverse_iterator crbegin() const + { + return rbegin(); + } + const_reverse_iterator crend() const + { + return rend(); + } + eina::iterator ibegin() + { + return eina::iterator( ::eina_list_iterator_new(this->_impl._list) ); + } + eina::iterator iend() + { + return eina::iterator(); + } + eina::iterator ibegin() const + { + return eina::iterator( ::eina_list_iterator_new(this->_impl._list) ); + } + eina::iterator iend() const + { + return eina::iterator(); + } + eina::iterator cibegin() const + { + return ibegin(); + } + eina::iterator ciend() const + { + return iend(); + } + void swap(ptr_list& other) + { + std::swap(this->_impl._list, other._impl._list); + } + size_type max_size() const { return -1; } + + Eina_List* native_handle() + { + return this->_impl._list; + } + Eina_List const* native_handle() const + { + return this->_impl._list; + } + eina::accessor accessor() const + { + return eina::accessor(eina_list_accessor_new(this->_impl._list)); + } + eina::accessor accessor() + { + return eina::accessor(eina_list_accessor_new(this->_impl._list)); + } +}; + +template +bool operator==(ptr_list const& lhs, ptr_list const& rhs) +{ + return lhs.size() == rhs.size() + && std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator!=(ptr_list const& lhs, ptr_list const& rhs) +{ + return !(lhs == rhs); +} + +template +void swap(ptr_list& lhs, ptr_list& rhs) +{ + lhs.swap(rhs); +} + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_ref.hh b/src/lib/eina_cxx/eina_ref.hh new file mode 100644 index 0000000000..887a21f769 --- /dev/null +++ b/src/lib/eina_cxx/eina_ref.hh @@ -0,0 +1,26 @@ +#ifndef EINA_REF_HH +#define EINA_REF_HH + +#include + +namespace efl { namespace eina { + +using std::ref; +using std::cref; +using std::reference_wrapper; + +template +T& unref(T& t) +{ + return t; +} + +template +T& unref(reference_wrapper t) +{ + return t.get(); +} + +}} + +#endif diff --git a/src/lib/eina_cxx/eina_stringshare.hh b/src/lib/eina_cxx/eina_stringshare.hh new file mode 100644 index 0000000000..9638547c90 --- /dev/null +++ b/src/lib/eina_cxx/eina_stringshare.hh @@ -0,0 +1,205 @@ +#ifndef _EINA_STRINGSHARE_HH +#define _EINA_STRINGSHARE_HH + +#include +#include + +#include +#include + +namespace efl { namespace eina { + +struct steal_stringshare_ref_t {}; +steal_stringshare_ref_t const steal_stringshare_ref = {}; + +struct stringshare +{ + typedef char value_type; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef value_type* pointer; + typedef value_type const* const_pointer; + typedef const_pointer const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + + stringshare() + : _string( ::eina_stringshare_add("") ) + {} + stringshare(const char* str) + : _string( ::eina_stringshare_add(str) ) + { + } + stringshare(char* str, steal_stringshare_ref_t) + : _string( str ) + { + } + template + stringshare(InputIterator i, InputIterator j + , typename eina::enable_if + ::value + && !eina::is_contiguous_iterator::value + >::type* = 0) + { + std::string tmp; + while(i != j) + { + tmp.push_back(*i); + ++i; + } + _string = ::eina_stringshare_add(tmp.c_str()); + } + template + stringshare(ContiguousMemoryIterator i, ContiguousMemoryIterator j + , typename eina::enable_if + ::value>::type* = 0) + : _string( ::eina_stringshare_add_length(&*i, j - i) ) + { + } + + ~stringshare() + { + ::eina_stringshare_del(_string); + } + + stringshare(stringshare const& other) + : _string( eina_stringshare_ref(other._string) ) + {} + stringshare& operator=(stringshare const& other) + { + ::eina_stringshare_refplace(&_string, other._string); + return *this; + } + stringshare& operator=(const char* c_string) + { + ::eina_stringshare_replace(&_string, c_string); + return *this; + } + + const_iterator begin() const + { + return _string; + } + const_iterator end() const + { + return _string + size(); + } + + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator rend() const + { + return const_reverse_iterator(end()); + } + + const_iterator cbegin() const + { + return begin(); + } + const_iterator cend() const + { + return end(); + } + const_reverse_iterator crbegin() const + { + return rbegin(); + } + const_reverse_iterator crend() const + { + return rend(); + } + + size_type size() const + { + return eina_stringshare_strlen(_string); + } + + size_type length() const + { + return size(); + } + size_type max_size() const + { + return -1; + } + bool empty() const + { + return _string[0] == 0; + } + const_reference operator[](size_type i) const + { + return _string[i]; + } + const_reference at(size_type i) const + { + if(i < size()) + return (*this)[i]; + else + throw std::out_of_range(""); + } + const_reference back() const + { + return _string[size()-1]; + } + const_reference front() const + { + return _string[0]; + } + + void swap(stringshare& other) + { + std::swap(_string, other._string); + } + + const char* c_str() const + { + return _string; + } + const char* data() const + { + return _string; + } + +private: + Eina_Stringshare* _string; +}; + +template <> +struct is_contiguous_iterator : true_type {}; + +inline bool operator==(stringshare const& lhs, stringshare const& rhs) +{ + return lhs.c_str() == rhs.c_str(); +} + +inline bool operator!=(stringshare const& lhs, stringshare const& rhs) +{ + return !(lhs == rhs); +} + +inline bool operator==(stringshare const& lhs, const char* rhs) +{ + return lhs.c_str() == rhs || std::strcmp(lhs.c_str(), rhs) == 0; +} + +inline bool operator!=(stringshare const& lhs, const char* rhs) +{ + return !(lhs == rhs); +} + +inline bool operator==(const char* lhs, stringshare const& rhs) +{ + return rhs == lhs; +} + +inline bool operator!=(const char* lhs, stringshare const& rhs) +{ + return !(lhs == rhs); +} + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_thread.hh b/src/lib/eina_cxx/eina_thread.hh new file mode 100644 index 0000000000..bb630a5d27 --- /dev/null +++ b/src/lib/eina_cxx/eina_thread.hh @@ -0,0 +1,356 @@ +#ifndef EINA_THREAD_HH_ +#define EINA_THREAD_HH_ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFL_EINA_BOOST_MOVABLE_BUT_NOT_COPYABLE(x) +#define EFL_EINA_BOOST_RV_REF(x) x const& + +namespace efl { namespace eina { + +struct mutex +{ + typedef Eina_Lock* native_handle_type; + + mutex() + { + ::eina_lock_new(&_mutex); + } + ~mutex() + { + ::eina_lock_free(&_mutex); + } + void lock() + { + ::Eina_Lock_Result r = ::eina_lock_take(&_mutex); + switch(r) + { + case EINA_LOCK_SUCCEED: + return; + case EINA_LOCK_DEADLOCK: + throw system_error(error_code(int(eina::errc::resource_deadlock_would_occur) + , get_generic_category())); + default: + throw system_error(get_error_code()); + } + } + bool try_lock() + { + ::Eina_Lock_Result r = ::eina_lock_take_try(&_mutex); + switch(r) + { + case EINA_LOCK_SUCCEED: + return true; + case EINA_LOCK_FAIL: + return false; + case EINA_LOCK_DEADLOCK: + throw system_error(error_code(int(eina::errc::resource_deadlock_would_occur) + , get_generic_category())); + default: + throw system_error(get_error_code()); + } + } + void unlock() + { + ::Eina_Lock_Result r = ::eina_lock_release(&_mutex); + switch(r) + { + case EINA_LOCK_SUCCEED: + return; + case EINA_LOCK_DEADLOCK: + throw system_error(error_code(int(eina::errc::resource_deadlock_would_occur) + , get_generic_category())); + default: + throw system_error(get_error_code()); + } + } + void debug() + { + ::eina_lock_debug(&_mutex); + } + native_handle_type native_handle() + { + return &_mutex; + } +private: + mutex(mutex const&) = delete; + mutex& operator=(mutex const&) = delete; + + Eina_Lock _mutex; +}; + +using std::lock_guard; +using std::unique_lock; + +struct condition_variable +{ + typedef Eina_Condition* native_handle_type; + + condition_variable() + { + ::eina_condition_new(&_cond, _mutex.native_handle()); + } + ~condition_variable() + { + ::eina_condition_free(&_cond); + } + + void notify_one() + { + eina::unique_lock l(_mutex); + Eina_Bool r = eina_condition_signal(&_cond); + if(!r) + throw eina::system_error(eina::get_error_code()); + } + void notify_all() + { + eina::unique_lock l(_mutex); + Eina_Bool r = eina_condition_broadcast(&_cond); + if(!r) + throw eina::system_error(eina::get_error_code()); + } + template + void wait(Lock& lock) + { + eina::unique_lock l(_mutex); + lock.unlock(); + ::eina_condition_wait(&_cond); + lock.lock(); + } + template + void wait(Lock& lock, Predicate p) + { + while(!p()) + wait(lock); + } + native_handle_type native_handle() + { + return &_cond; + } +private: + condition_variable(condition_variable const&); + condition_variable& operator=(condition_variable const&); + + mutex _mutex; + Eina_Condition _cond; +}; + +struct thread_id +{ + thread_id() noexcept + : _raw(0u) + { + } + thread_id(Eina_Thread raw) + : _raw(raw) {} + friend inline bool operator==(thread_id lhs, thread_id rhs) + { + return lhs._raw == rhs._raw; + } + friend inline bool operator!=(thread_id lhs, thread_id rhs) + { + return lhs._raw != rhs._raw; + } + friend inline bool operator<(thread_id lhs, thread_id rhs) + { + return std::less()(lhs._raw, rhs._raw); + } +private: + Eina_Thread _raw; +}; + +inline bool operator<=(thread_id lhs, thread_id rhs) +{ + return (lhs == rhs) || lhs < rhs; +} +inline bool operator>(thread_id lhs, thread_id rhs) +{ + return !(lhs <= rhs); +} +inline bool operator>=(thread_id lhs, thread_id rhs) +{ + return !(lhs < rhs); +} + +template +std::basic_ostream& +operator<<(std::basic_ostream& out, thread_id id) +{ + return out << id._raw; +} + +namespace _detail { + +struct arguments +{ + Eina_Lock mutex; + Eina_Condition condition; + bool started; + std::function function; +}; + +inline void* create_thread(void* data, Eina_Thread) +{ + arguments* args = static_cast(data); + + eina_lock_take(&args->mutex); + + std::function f = std::move(args->function); + + args->started = true; + eina_condition_signal(&args->condition); + eina_lock_release(&args->mutex); + + f(); + return 0; +} + +} + +struct thread +{ + typedef thread_id id; + typedef Eina_Thread native_handle_type; + + thread() noexcept + : _joinable(false), _raw(0u) + { + } + + template + explicit thread(F&& f, Args&&... args) + { + _detail::arguments arguments; + arguments.started = false; + arguments.function = std::bind(f, args...); + + _joinable = true; + Eina_Bool r = ::eina_lock_new(&arguments.mutex); + if(!r) throw eina::system_error(eina::get_error_code()); + r = ::eina_condition_new(&arguments.condition, &arguments.mutex); + if(!r) throw eina::system_error(eina::get_error_code()); + + if(!eina_thread_create + (&_raw, ::EINA_THREAD_NORMAL + , -1, &eina::_detail::create_thread, &arguments)) + { + eina_condition_free(&arguments.condition); + eina_lock_free(&arguments.mutex); + throw eina::system_error(eina::get_error_code()); + } + Eina_Lock_Result lr = ::eina_lock_take(&arguments.mutex); + if(lr != EINA_LOCK_SUCCEED) + throw eina::system_error(eina::get_error_code()); + while(!arguments.started) + { + r = eina_condition_wait(&arguments.condition); + if(!r) throw eina::system_error(eina::get_error_code()); + } + lr = eina_lock_release(&arguments.mutex); + if(lr != EINA_LOCK_SUCCEED) + throw eina::system_error(eina::get_error_code()); + + eina_condition_free(&arguments.condition); + eina_lock_free(&arguments.mutex); + } + + thread(thread&& other) + : _joinable(other._joinable), _raw(other._raw) + { + } + + thread& operator=(thread&& other) + { + _raw = other._raw; + _joinable = other._joinable; + return *this; + } + + ~thread() + { + assert(!joinable()); + } + + void swap(thread& other) noexcept + { + std::swap(_raw, other._raw); + } + bool joinable() const noexcept + { + return _joinable; + } + + void join() + { + assert(joinable()); + ::eina_thread_join(_raw); + _joinable = false; + } + + void detach() + { + assert(joinable()); + _joinable = false; + } + + id get_id() const noexcept + { + return id(_raw); + } + native_handle_type native_handle() const + { + return _raw; + } + + static unsigned hardware_concurrency() noexcept + { + return ::eina_cpu_count(); + } +private: + bool _joinable; + Eina_Thread _raw; +}; + +inline void swap(thread& lhs, thread& rhs) +{ + lhs.swap(rhs); +} + +namespace this_thread { + +inline thread::id get_id() +{ + return thread::id(eina_thread_self()); +} + +inline void yield() {} + +template +void sleep_until(std::chrono::time_pointconst& abs_time); + +template +void sleep_for(std::chrono::durationconst& rel_time); +} + +} } + +namespace std { + +template struct hash; +template <> +struct hash< ::efl::eina::thread_id> : hash +{}; + +} + +#endif diff --git a/src/lib/eina_cxx/eina_type_traits.hh b/src/lib/eina_cxx/eina_type_traits.hh new file mode 100644 index 0000000000..bd22457de3 --- /dev/null +++ b/src/lib/eina_cxx/eina_type_traits.hh @@ -0,0 +1,51 @@ +#ifndef _EINA_TYPE_TRAITS_HH +#define _EINA_TYPE_TRAITS_HH + +#include + +#include +#include + +namespace efl { namespace eina { + +using std::enable_if; +using std::is_integral; +using std::is_pod; +using std::is_const; +using std::remove_cv; +using std::true_type; +using std::false_type; +using std::remove_pointer; +using std::remove_reference; + +template +struct is_contiguous_iterator : false_type {}; +template <> +struct is_contiguous_iterator : true_type {}; +template <> +struct is_contiguous_iterator : true_type {}; +template <> +struct is_contiguous_iterator::const_iterator> : true_type {}; +template <> +struct is_contiguous_iterator::iterator> : true_type {}; + +template +struct if_c +{ + typedef T type; +}; + +template +struct if_c +{ + typedef F type; +}; + +template +struct if_ : if_c +{ +}; + +} } + +#endif diff --git a/src/lib/eina_cxx/eina_value.hh b/src/lib/eina_cxx/eina_value.hh new file mode 100644 index 0000000000..aee5b853c2 --- /dev/null +++ b/src/lib/eina_cxx/eina_value.hh @@ -0,0 +1,371 @@ +#ifndef _EFL_EINA_EINA_VALUE_HH +#define _EFL_EINA_EINA_VALUE_HH + +#include + +#include +#include + +namespace efl { namespace eina { + +template +struct _eina_value_traits_base; + +template +struct _eina_value_traits_aux; + +// Indirection for uint64_t. uint64_t can be a typedef for unsigned +// long, so we can't specialize on the same template +template <> +struct _eina_value_traits_aux +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_UINT64; + } +}; + +template +struct _eina_value_traits : _eina_value_traits_aux +{ +}; + +template +struct _eina_value_traits_base +{ + typedef T type; + + static ::Eina_Value* create() + { + return eina_value_new(_eina_value_traits::value_type()); + } + static void set_type( ::Eina_Value* v) + { + eina_value_setup(v, _eina_value_traits::value_type()); + } + static void set( ::Eina_Value* v, type c) + { + ::eina_value_set(v, c); + } + static type get( ::Eina_Value* v) + { + if(_eina_value_traits::value_type() == eina_value_type_get(v)) + { + type vv; + if(::eina_value_get(v, &vv)) + return vv; + else + throw eina::system_error(eina::get_error_code()); + } + else + throw eina::system_error(EINA_ERROR_VALUE_FAILED, eina::eina_error_category()); + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_UCHAR; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_USHORT; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_UINT; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_ULONG; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_CHAR; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_SHORT; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_INT; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_LONG; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_FLOAT; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_DOUBLE; + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_STRINGSHARE; + } + static void set( ::Eina_Value* v, type c) + { + ::eina_value_set(v, c.data()); + } + static type get( ::Eina_Value* v) + { + char* c_str; + ::eina_value_get(v, &c_str); + return stringshare(c_str, steal_stringshare_ref); + } +}; + +template <> +struct _eina_value_traits + : _eina_value_traits_base +{ + typedef typename _eina_value_traits_base::type type; + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_STRING; + } + static void set( ::Eina_Value* v, type c) + { + ::eina_value_set(v, c.c_str()); + } + static type get( ::Eina_Value* v) + { + char* c_str; + ::eina_value_get(v, &c_str); + std::string r(c_str); + ::free(c_str); + return r; + } +}; + +template +struct _eina_value_traits::value>::type> + : _eina_value_traits_base +{ + typedef typename _eina_value_traits_base::type type; + static ::Eina_Value_Type const* value_type() + { + return EINA_VALUE_TYPE_ARRAY; + } + static void set( ::Eina_Value* v, type c) + { + ::eina_value_set(v, c.c_str()); + } + static type get( ::Eina_Value* v) + { + char* c_str; + ::eina_value_get(v, &c_str); + std::string r(c_str); + ::free(c_str); + return r; + } +}; + +class eina_value +{ + template + void primitive_init(T v) + { + _raw = _eina_value_traits::create(); + _eina_value_traits::set(_raw, v); + } +public: + eina_value() + : _raw(_eina_value_traits::create()) + { + } + eina_value(char v) + { + primitive_init(v); + } + eina_value(short v) + { + primitive_init(v); + } + eina_value(int v) + { + primitive_init(v); + } + eina_value(long v) + { + primitive_init(v); + } + eina_value(unsigned char v) + { + primitive_init(v); + } + eina_value(unsigned short v) + { + primitive_init(v); + } + eina_value(unsigned int v) + { + primitive_init(v); + } + eina_value(unsigned long v) + { + primitive_init(v); + } + eina_value(float v) + { + primitive_init(v); + } + eina_value(double v) + { + primitive_init(v); + } + + ~eina_value() + { + eina_value_free(_raw); + } + + eina_value(eina_value const& other) + : _raw(_eina_value_traits::create()) + { + if(!eina_value_copy(const_cast(other._raw), _raw)) + throw eina::system_error(eina::get_error_code()); + } + eina_value& operator=(eina_value const& other) + { + eina_value_flush(_raw); + if(!eina_value_copy(const_cast(other._raw), _raw)) + throw eina::system_error(eina::get_error_code()); + return *this; + } + + void swap(eina_value& other) + { + std::swap(_raw, other._raw); + } + + typedef Eina_Value* native_handle_type; + native_handle_type native_handle() const + { + return _raw; + } + typedef Eina_Value_Type const* type_info_t; + type_info_t type_info() const + { + return ::eina_value_type_get(_raw); + } +private: + ::Eina_Value* _raw; + + template + friend T get(eina_value const& v) + { + return _eina_value_traits::get(v._raw); + } +}; + +inline void swap(eina_value& lhs, eina_value& rhs) +{ + lhs.swap(rhs); +} + +inline bool operator==(eina_value const& lhs, eina_value const& rhs) +{ + return lhs.type_info() == rhs.type_info() + && eina_value_compare(lhs.native_handle(), rhs.native_handle()) == 0; +} + +inline bool operator<(eina_value const& lhs, eina_value const& rhs) +{ + return std::less()(lhs.type_info(), rhs.type_info()) + || (lhs.type_info() == rhs.type_info() + && eina_value_compare(lhs.native_handle(), rhs.native_handle()) < 0); +} + +inline bool operator>(eina_value const& lhs, eina_value const& rhs) +{ + return std::less()(rhs.type_info(), lhs.type_info()) + || (rhs.type_info() == lhs.type_info() + && eina_value_compare(lhs.native_handle(), rhs.native_handle()) > 0); +} + +inline bool operator<=(eina_value const& lhs, eina_value const& rhs) +{ + return !(lhs > rhs); +} + +inline bool operator>=(eina_value const& lhs, eina_value const& rhs) +{ + return !(lhs < rhs); +} + +inline bool operator!=(eina_value const& lhs, eina_value const& rhs) +{ + return !(lhs == rhs); +} + +} } + +#endif diff --git a/src/tests/eina_cxx/eina_cxx_suite.cc b/src/tests/eina_cxx/eina_cxx_suite.cc new file mode 100644 index 0000000000..a9c20dc61a --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_suite.cc @@ -0,0 +1,125 @@ + +#include "Eina.hh" + +#include +#include + +#include + +void eina_test_inlist(TCase* tc); +void eina_test_inarray(TCase* tc); +void eina_test_ptrlist(TCase* tc); +void eina_test_ptrarray(TCase* tc); +void eina_test_iterator(TCase* tc); +void eina_test_stringshare(TCase* tc); +void eina_test_error(TCase* tc); +void eina_test_accessor(TCase* tc); +void eina_test_thread(TCase* tc); +void eina_test_eina_value(TCase* tc); + +typedef struct _Eina_Test_Case Eina_Test_Case; +struct _Eina_Test_Case +{ + const char *test_case; + void (*build)(TCase *tc); +}; + +static const Eina_Test_Case etc[] = { + { "Ptr_List", eina_test_ptrlist }, + { "Ptr_Array", eina_test_ptrarray }, + { "Inlist", eina_test_inlist }, + { "Inarray", eina_test_inarray }, + { "Iterator", eina_test_iterator }, + { "Stringshare", eina_test_stringshare }, + { "Error", eina_test_error }, + { "Accessor", eina_test_accessor }, + { "Thread", eina_test_thread }, + { "EinaValue", eina_test_eina_value }, + { NULL, NULL } +}; + +static void +_list_tests(void) +{ + const Eina_Test_Case *itr = etc; + fputs("Available Test Cases:\n", stderr); + for (; itr->test_case; itr++) + fprintf(stderr, "\t%s\n", itr->test_case); +} + +static Eina_Bool +_use_test(int argc, const char **argv, const char *test_case) +{ + if (argc < 1) + return 1; + + for (; argc > 0; argc--, argv++) + if (strcmp(test_case, *argv) == 0) + return 1; + + return 0; +} + +Suite * +eina_build_suite(int argc, const char **argv) +{ + TCase *tc; + Suite *s; + int i; + + s = suite_create("Eina"); + + for (i = 0; etc[i].test_case; ++i) + { + if (!_use_test(argc, argv, etc[i].test_case)) + continue; + + tc = tcase_create(etc[i].test_case); + tcase_set_timeout(tc, 0); + + etc[i].build(tc); + suite_add_tcase(s, tc); + } + + return s; +} + +int main(int argc, char* argv[]) +{ + Suite *s; + SRunner *sr; + int i, failed_count; + + for (i = 1; i < argc; i++) + if ((strcmp(argv[i], "-h") == 0) || + (strcmp(argv[i], "--help") == 0)) + { + fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n", + argv[0]); + _list_tests(); + return 0; + } + else if ((strcmp(argv[i], "-l") == 0) || + (strcmp(argv[i], "--list") == 0)) + { + _list_tests(); + return 0; + } + + putenv(const_cast("EFL_RUN_IN_TREE=1")); + + s = eina_build_suite(argc - 1, (const char **)argv + 1); + sr = srunner_create(s); + + srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml"); + + eina_init(); + + srunner_run_all(sr, CK_ENV); + failed_count = srunner_ntests_failed(sr); + srunner_free(sr); + + eina_shutdown(); + + return (failed_count == 0) ? 0 : 255; +} diff --git a/src/tests/eina_cxx/eina_cxx_test_accessor.cc b/src/tests/eina_cxx/eina_cxx_test_accessor.cc new file mode 100644 index 0000000000..21ad5e09da --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_accessor.cc @@ -0,0 +1,102 @@ + +#include "Eina.hh" + +#include + +#include + +START_TEST(eina_cxx_accessor_indexing) +{ + efl::eina::ptr_list list; + list.push_back(new int(5)); + list.push_back(new int(10)); + list.push_back(new int(15)); + list.push_back(new int(20)); + + efl::eina::accessor accessor(list.accessor()); + + ck_assert(accessor[0] == 5); + ck_assert(accessor[1] == 10); + ck_assert(accessor[2] == 15); + ck_assert(accessor[3] == 20); +} +END_TEST + +START_TEST(eina_cxx_accessor_iterator) +{ + efl::eina::ptr_list list; + list.push_back(new int(5)); + list.push_back(new int(10)); + list.push_back(new int(15)); + list.push_back(new int(20)); + + std::size_t pos = 0u; + for(efl::eina::accessor_iterator first (list.accessor()) + , last (list.accessor(), list.size()); first != last; ++first, ++pos) + { + ck_assert(pos != 0u || *first == 5); + ck_assert(pos != 1u || *first == 10); + ck_assert(pos != 2u || *first == 15); + ck_assert(pos != 3u || *first == 20); + } +} +END_TEST + +START_TEST(eina_cxx_accessor_relops) +{ + efl::eina::ptr_list list; + list.push_back(new int(5)); + list.push_back(new int(10)); + list.push_back(new int(15)); + list.push_back(new int(20)); + + efl::eina::accessor_iterator first (list.accessor()) + , second(list.accessor(), 1u) + , third(list.accessor(), 2u) + , fourth(list.accessor(), 3u) + ; + ck_assert(!(first < first)); ck_assert(first < second); + ck_assert(first < third); ck_assert(first < fourth); + ck_assert(!(second < first)); ck_assert(!(second < second)); + ck_assert(second < third); ck_assert(second < fourth); + ck_assert(!(third < first)); ck_assert(!(third < second)); + ck_assert(!(third < third)); ck_assert(third < fourth); + ck_assert(!(fourth < first)); ck_assert(!(fourth < second)); + ck_assert(!(fourth < third)); ck_assert(!(fourth < fourth)); + + ck_assert(first <= first); ck_assert(first <= second); + ck_assert(first <= third); ck_assert(first <= fourth); + ck_assert(!(second <= first)); ck_assert(second <= second); + ck_assert(second <= third); ck_assert(second <= fourth); + ck_assert(!(third <= first)); ck_assert(!(third <= second)); + ck_assert(third <= third); ck_assert(third <= fourth); + ck_assert(!(fourth <= first)); ck_assert(!(fourth <= second)); + ck_assert(!(fourth <= third)); ck_assert(fourth <= fourth); + + ck_assert(!(first > first)); ck_assert(!(first > second)); + ck_assert(!(first > third)); ck_assert(!(first > fourth)); + ck_assert(second > first); ck_assert(!(second > second)); + ck_assert(!(second > third)); ck_assert(!(second > fourth)); + ck_assert(third > first); ck_assert(third > second); + ck_assert(!(third > third)); ck_assert(!(third > fourth)); + ck_assert(fourth > first); ck_assert(fourth > second); + ck_assert(fourth > third); ck_assert(!(fourth > fourth)); + + ck_assert(first >= first); ck_assert(!(first >= second)); + ck_assert(!(first >= third)); ck_assert(!(first >= fourth)); + ck_assert(second >= first); ck_assert(second >= second); + ck_assert(!(second >= third)); ck_assert(!(second >= fourth)); + ck_assert(third >= first); ck_assert(third >= second); + ck_assert(third >= third); ck_assert(!(third >= fourth)); + ck_assert(fourth >= first); ck_assert(fourth >= second); + ck_assert(fourth >= third); ck_assert(fourth >= fourth); +} +END_TEST + +void +eina_test_accessor(TCase* tc) +{ + tcase_add_test(tc, eina_cxx_accessor_indexing); + tcase_add_test(tc, eina_cxx_accessor_iterator); + tcase_add_test(tc, eina_cxx_accessor_relops); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_eina_value.cc b/src/tests/eina_cxx/eina_cxx_test_eina_value.cc new file mode 100644 index 0000000000..f9ddd2e6d4 --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_eina_value.cc @@ -0,0 +1,191 @@ + +#include "Eina.hh" + +#include + +START_TEST(eina_cxx_eina_value_constructors) +{ + efl::eina::eina_init init; + + efl::eina::eina_value v; + + char c = 'c'; + efl::eina::eina_value vchar(c); + + short s = 5; + efl::eina::eina_value vshort(s); + + efl::eina::eina_value vint(5); + + efl::eina::eina_value vlong(5l); + + unsigned char uc = 'b'; + efl::eina::eina_value vuchar(uc); + + unsigned short us = 5; + efl::eina::eina_value vushort(us); + + efl::eina::eina_value vuint(5u); + + efl::eina::eina_value vulong(5ul); + + efl::eina::eina_value vu64(uint64_t(5ul)); + + efl::eina::eina_value vfloat(5.0f); + + efl::eina::eina_value vdouble(5.0); +} +END_TEST + +START_TEST(eina_cxx_eina_value_get) +{ + efl::eina::eina_init init; + + char c = 'c'; + efl::eina::eina_value vchar(c); + ck_assert(efl::eina::get(vchar) == 'c'); + + short s = 5; + efl::eina::eina_value vshort(s); + ck_assert(efl::eina::get(vshort) == 5); + + efl::eina::eina_value vint(6); + ck_assert(efl::eina::get(vint) == 6); + + efl::eina::eina_value vlong(7l); + ck_assert(efl::eina::get(vlong) == 7l); + + unsigned char uc = 'b'; + efl::eina::eina_value vuchar(uc); + ck_assert(efl::eina::get(vuchar) == 'b'); + + unsigned short us = 8; + efl::eina::eina_value vushort(us); + ck_assert(efl::eina::get(vushort) == 8); + + efl::eina::eina_value vuint(9u); + ck_assert(efl::eina::get(vuint) == 9u); + + efl::eina::eina_value vulong(10ul); + ck_assert(efl::eina::get(vulong) == 10ul); + + efl::eina::eina_value vu64((uint64_t)10ul); + ck_assert(efl::eina::get(vu64) == 10ul); + + efl::eina::eina_value vfloat(11.0f); + ck_assert(efl::eina::get(vfloat) == 11.0f); + + efl::eina::eina_value vdouble(12.0); + ck_assert(efl::eina::get(vdouble) == 12.0f); +} +END_TEST + +START_TEST(eina_cxx_eina_value_wrong_get) +{ + efl::eina::eina_init init; + + char c = 'c'; + efl::eina::eina_value vchar(c); + try + { + efl::eina::get(vchar); + std::abort(); + } + catch(efl::eina::system_error const&) + { + } +} +END_TEST + +START_TEST(eina_cxx_eina_value_comparison_operators) +{ + efl::eina::eina_init init; + + efl::eina::eina_value v; + + char c = 5; + efl::eina::eina_value vchar(c); + + short s = 5; + efl::eina::eina_value vshort(s); + + efl::eina::eina_value vint(5); + + efl::eina::eina_value vlong(5l); + + unsigned char uc = 5; + efl::eina::eina_value vuchar(uc); + + unsigned short us = 5; + efl::eina::eina_value vushort(us); + + efl::eina::eina_value vuint(5u); + + efl::eina::eina_value vulong(5ul); + + efl::eina::eina_value vu64((uint64_t)5ul); + + efl::eina::eina_value vfloat(5.0f); + + efl::eina::eina_value vdouble(5.0); + + ck_assert(vchar == vchar); + ck_assert(vshort == vshort); + ck_assert(vint == vint); + ck_assert(vlong == vlong); + ck_assert(vuchar == vuchar); + ck_assert(vushort == vushort); + ck_assert(vuint == vuint); + ck_assert(vulong == vulong); + ck_assert(vu64 == vu64); + ck_assert(vfloat == vfloat); + ck_assert(vdouble == vdouble); + + ck_assert(vchar != vshort); + ck_assert(vshort != vint); + ck_assert(vint != vlong); + ck_assert(vlong != vuchar); + ck_assert(vuchar != vushort); + ck_assert(vushort != vuint); + ck_assert(vuint != vulong); + ck_assert(vulong != vfloat); + ck_assert(vfloat != vdouble); + ck_assert(vdouble != vchar); + + ck_assert(vchar != vuchar); + ck_assert(vshort != vushort); + ck_assert(vint != vuint); + ck_assert(vlong != vulong); + ck_assert(vfloat != vdouble); + ck_assert(vdouble != vfloat); +} +END_TEST + +START_TEST(eina_cxx_eina_value_copying) +{ + char c = 5; + + efl::eina::eina_value vchar(c); + efl::eina::eina_value vchar2(vchar); + ck_assert(vchar == vchar2); + ck_assert(efl::eina::get(vchar) == 5); + ck_assert(efl::eina::get(vchar2) == 5); + + efl::eina::eina_value vint(10); + vchar = vint; + ck_assert(vchar != vchar2); + ck_assert(vint == vchar); + ck_assert(efl::eina::get(vchar) == 10); + ck_assert(efl::eina::get(vint) == 10); +} +END_TEST + +void +eina_test_eina_value(TCase* tc) +{ + tcase_add_test(tc, eina_cxx_eina_value_constructors); + tcase_add_test(tc, eina_cxx_eina_value_get); + tcase_add_test(tc, eina_cxx_eina_value_wrong_get); + tcase_add_test(tc, eina_cxx_eina_value_comparison_operators); + tcase_add_test(tc, eina_cxx_eina_value_copying); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_error.cc b/src/tests/eina_cxx/eina_cxx_test_error.cc new file mode 100644 index 0000000000..fb3a6aa7ae --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_error.cc @@ -0,0 +1,72 @@ + +#include "Eina.hh" + +#include + +Eina_Error my_error, my_error_2; + +START_TEST(eina_cxx_get_error) +{ + efl::eina::eina_init eina_init; + + my_error = ::eina_error_msg_static_register("Message 1"); + + ::eina_error_set(0); + + efl::eina::error_code ec1 = efl::eina::get_error_code(); + ck_assert(!ec1); + + ::eina_error_set(my_error); + + efl::eina::error_code ec2 = efl::eina::get_error_code(); + ck_assert(!!ec2); + + ck_assert(ec2.message() == "Message 1"); + + ::eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + + efl::eina::error_code ec3 = efl::eina::get_error_code(); + ck_assert(!!ec3); + + ck_assert(ec3.message() == "Out of memory"); +} +END_TEST + +START_TEST(eina_cxx_throw_on_error) +{ + efl::eina::eina_init eina_init; + + ::eina_error_set(my_error_2); + my_error_2 = ::eina_error_msg_static_register("Message 2"); + + ::eina_error_set(0); + try + { + efl::eina::throw_on_error(); + } + catch(std::exception const&) + { + std::abort(); + } + + ::eina_error_set(my_error_2); + try + { + efl::eina::throw_on_error(); + std::abort(); + } + catch(efl::eina::system_error const& e) + { + ck_assert(e.code().value() == my_error_2); + ck_assert(e.code().message() == "Message 2"); + ck_assert(!efl::eina::get_error_code()); + } +} +END_TEST + +void +eina_test_error(TCase *tc) +{ + tcase_add_test(tc, eina_cxx_get_error); + tcase_add_test(tc, eina_cxx_throw_on_error); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_inarray.cc b/src/tests/eina_cxx/eina_cxx_test_inarray.cc new file mode 100644 index 0000000000..d2e526c45b --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_inarray.cc @@ -0,0 +1,388 @@ + +#include "Eina.hh" + +#include +#include + +#include + +#include + +START_TEST(eina_cxx_inarray_pod_push_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::inarray array; + + array.push_back(5); + array.push_back(10); + array.push_back(15); + + int result[] = {5, 10, 15}; + + ck_assert(array.size() == 3); + ck_assert(std::equal(array.begin(), array.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_inarray_pod_pop_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::inarray array; + + array.push_back(5); + array.push_back(10); + array.push_back(15); + array.pop_back(); + + int result[] = {5, 10}; + + ck_assert(array.size() == 2); + ck_assert(std::equal(array.begin(), array.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_inarray_pod_insert) +{ + efl::eina::eina_init eina_init; + + efl::eina::inarray array; + + efl::eina::inarray::iterator it; + + it = array.insert(array.end(), 5); // first element + ck_assert(it != array.end()); + ++it; + ck_assert(it == array.end()); + + it = array.insert(array.end(), 10); // equivalent to push_back + ck_assert(it != array.end()); + ++it; + ck_assert(it == array.end()); + + it = array.insert(array.begin(), 15); // equivalent to push_front + ck_assert(it == array.begin()); + + it = array.end(); + --it; + array.insert(it, 20); // insert before the last element + + int result[] = {15, 5, 20, 10}; + + ck_assert(array.size() == 4); + ck_assert(std::equal(array.begin(), array.end(), result)); + + efl::eina::inarray array2; + it = array2.insert(array2.end(), array.begin(), array.end()); + ck_assert(it == array2.begin()); + ck_assert(array == array2); + + efl::eina::inarray array3; + array3.push_back(1); + it = array3.insert(array3.end(), array.begin(), array.end()); + ck_assert(array3.size() == 5); + ck_assert(array3.front() == 1); + it = array3.begin(); + ++it; + ck_assert(std::equal(it, array3.end(), array.begin())); + + efl::eina::inarray array4; + array4.push_back(1); + it = array4.insert(array4.begin(), array.begin(), array.end()); + ck_assert(array4.size() == 5); + ck_assert(array4.back() == 1); + ck_assert(std::equal(array.begin(), array.end(), array4.begin())); +} +END_TEST + +START_TEST(eina_cxx_inarray_pod_constructors) +{ + efl::eina::eina_init eina_init; + + efl::eina::inarray array1; + ck_assert(array1.empty()); + + efl::eina::inarray array2(10, 5); + ck_assert(array2.size() == 10); + ck_assert(std::find_if(array2.begin(), array2.end() + , std::not1(std::bind1st(std::equal_to(), 5))) == array2.end()); + + efl::eina::inarray array3(array2); + ck_assert(array2 == array3); + + efl::eina::inarray array4(array2.begin(), array2.end()); + ck_assert(array2 == array4); +} +END_TEST + +START_TEST(eina_cxx_inarray_pod_erase) +{ + efl::eina::eina_init eina_init; + + efl::eina::inarray array1; + array1.push_back(5); + array1.push_back(10); + array1.push_back(15); + array1.push_back(20); + array1.push_back(25); + array1.push_back(30); + + efl::eina::inarray::iterator it = array1.begin(), it2; + + it = array1.erase(it); + ck_assert(it == array1.begin()); + ck_assert(array1.size() == 5); + ck_assert(array1.front() == 10); + + it = array1.begin() + 1; + ck_assert(*it == 15); + it = array1.erase(it); + ck_assert(*it == 20); + ck_assert(array1.size() == 4); + + it = array1.end() - 1; + it = array1.erase(it); + ck_assert(it == array1.end()); + ck_assert(array1.size() == 3); + ck_assert(array1.back() == 25); + + it = array1.begin() + 1; + it2 = array1.end() - 1; + it = array1.erase(it, it2); + it2 = array1.end() -1; + ck_assert(it == it2); + ck_assert(array1.size() == 2); + ck_assert(array1.front() == 10); + ck_assert(array1.back() == 25); +} +END_TEST + +unsigned int constructors_called = 0u; +unsigned int destructors_called = 0u; + +struct non_pod +{ + non_pod(int x) + : x(new int(x)) + { + ++::constructors_called; + } + ~non_pod() + { + ++::destructors_called; + delete x; + } + non_pod(non_pod const& other) + { + ++::constructors_called; + x = new int(*other.x); + } + non_pod& operator=(non_pod const& other) + { + delete x; + x = new int(*other.x); + return *this; + } + + int* x; +}; + +bool operator==(non_pod lhs, non_pod rhs) +{ + return *lhs.x == *rhs.x; +} + +START_TEST(eina_cxx_inarray_nonpod_push_back) +{ + efl::eina::eina_init eina_init; + { + efl::eina::inarray array; + + array.push_back(5); + array.push_back(10); + array.push_back(15); + + int result[] = {5, 10, 15}; + + ck_assert(array.size() == 3); + ck_assert(std::equal(array.begin(), array.end(), result)); + } + std::cout << "constructors called " << ::constructors_called + << "\ndestructors called " << ::destructors_called << std::endl; + ck_assert(::constructors_called == ::destructors_called); + ::constructors_called = ::destructors_called = 0; +} +END_TEST + +START_TEST(eina_cxx_inarray_nonpod_pop_back) +{ + { + efl::eina::eina_init eina_init; + + efl::eina::inarray array; + + array.push_back(5); + array.push_back(10); + array.push_back(15); + array.pop_back(); + + int result[] = {5, 10}; + + ck_assert(array.size() == 2); + ck_assert(std::equal(array.begin(), array.end(), result)); + } + std::cout << "constructors called " << ::constructors_called + << "\ndestructors called " << ::destructors_called << std::endl; + ck_assert(::constructors_called == ::destructors_called); + ::constructors_called = ::destructors_called = 0; +} +END_TEST + +START_TEST(eina_cxx_inarray_nonpod_insert) +{ + { + efl::eina::eina_init eina_init; + + efl::eina::inarray array; + + efl::eina::inarray::iterator it; + + it = array.insert(array.end(), 5); // first element + ck_assert(it != array.end()); + ++it; + ck_assert(it == array.end()); + + it = array.insert(array.end(), 10); // equivalent to push_back + ck_assert(it != array.end()); + ++it; + ck_assert(it == array.end()); + + it = array.insert(array.begin(), 15); // equivalent to push_front + ck_assert(it == array.begin()); + + it = array.end(); + --it; + array.insert(it, 20); // insert before the last element + + int result[] = {15, 5, 20, 10}; + + ck_assert(array.size() == 4); + ck_assert(std::equal(array.begin(), array.end(), result)); + + efl::eina::inarray array2; + it = array2.insert(array2.end(), array.begin(), array.end()); + ck_assert(it == array2.begin()); + ck_assert(array == array2); + + efl::eina::inarray array3; + array3.push_back(1); + it = array3.insert(array3.end(), array.begin(), array.end()); + ck_assert(array3.size() == 5); + ck_assert(array3.front() == 1); + it = array3.begin(); + ++it; + ck_assert(std::equal(it, array3.end(), array.begin())); + + efl::eina::inarray array4; + array4.push_back(1); + it = array4.insert(array4.begin(), array.begin(), array.end()); + ck_assert(array4.size() == 5); + ck_assert(array4.back() == 1); + ck_assert(std::equal(array.begin(), array.end(), array4.begin())); + } + std::cout << "constructors called " << ::constructors_called + << "\ndestructors called " << ::destructors_called << std::endl; + ck_assert(::constructors_called == ::destructors_called); + ::constructors_called = ::destructors_called = 0; +} +END_TEST + +START_TEST(eina_cxx_inarray_nonpod_constructors) +{ + { + efl::eina::eina_init eina_init; + + efl::eina::inarray array1; + ck_assert(array1.empty()); + + efl::eina::inarray array2(10, 5); + ck_assert(array2.size() == 10); + ck_assert(std::find_if(array2.begin(), array2.end() + , std::not1(std::bind1st(std::equal_to(), 5))) == array2.end()); + + efl::eina::inarray array3(array2); + ck_assert(array2 == array3); + + efl::eina::inarray array4(array2.begin(), array2.end()); + ck_assert(array2 == array4); + } + std::cout << "constructors called " << ::constructors_called + << "\ndestructors called " << ::destructors_called << std::endl; + ck_assert(::constructors_called == ::destructors_called); + ::constructors_called = ::destructors_called = 0; +} +END_TEST + +START_TEST(eina_cxx_inarray_nonpod_erase) +{ + { + efl::eina::eina_init eina_init; + + efl::eina::inarray array1; + array1.push_back(5); + array1.push_back(10); + array1.push_back(15); + array1.push_back(20); + array1.push_back(25); + array1.push_back(30); + + efl::eina::inarray::iterator it = array1.begin(), it2; + + it = array1.erase(it); + ck_assert(it == array1.begin()); + ck_assert(array1.size() == 5); + ck_assert(array1.front() == 10); + + it = array1.begin() + 1; + ck_assert(*it == 15); + it = array1.erase(it); + ck_assert(*it == 20); + ck_assert(array1.size() == 4); + + it = array1.end() - 1; + it = array1.erase(it); + ck_assert(it == array1.end()); + ck_assert(array1.size() == 3); + ck_assert(array1.back() == 25); + + it = array1.begin() + 1; + it2 = array1.end() - 1; + it = array1.erase(it, it2); + it2 = array1.end() -1; + ck_assert(it == it2); + ck_assert(array1.size() == 2); + ck_assert(array1.front() == 10); + ck_assert(array1.back() == 25); + } + std::cout << "constructors called " << ::constructors_called + << "\ndestructors called " << ::destructors_called << std::endl; + ck_assert(::constructors_called == ::destructors_called); + ::constructors_called = ::destructors_called = 0; +} +END_TEST + +void +eina_test_inarray(TCase *tc) +{ + tcase_add_test(tc, eina_cxx_inarray_pod_push_back); + tcase_add_test(tc, eina_cxx_inarray_pod_pop_back); + tcase_add_test(tc, eina_cxx_inarray_pod_insert); + tcase_add_test(tc, eina_cxx_inarray_pod_erase); + tcase_add_test(tc, eina_cxx_inarray_pod_constructors); + tcase_add_test(tc, eina_cxx_inarray_nonpod_push_back); + tcase_add_test(tc, eina_cxx_inarray_nonpod_pop_back); + tcase_add_test(tc, eina_cxx_inarray_nonpod_insert); + tcase_add_test(tc, eina_cxx_inarray_nonpod_erase); + tcase_add_test(tc, eina_cxx_inarray_nonpod_constructors); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_inlist.cc b/src/tests/eina_cxx/eina_cxx_test_inlist.cc new file mode 100644 index 0000000000..09934f3f04 --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_inlist.cc @@ -0,0 +1,212 @@ + +#include "Eina.hh" + +#include +#include + +#include + +START_TEST(eina_cxx_inlist_push_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::inlist list; + + list.push_back(5); + list.push_back(10); + list.push_back(15); + + int result[] = {5, 10, 15}; + + ck_assert(list.size() == 3); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_inlist_pop_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::inlist list; + + list.push_back(5); + list.push_back(10); + list.push_back(15); + list.pop_back(); + + int result[] = {5, 10}; + + ck_assert(list.size() == 2); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_inlist_push_front) +{ + efl::eina::eina_init eina_init; + + efl::eina::inlist list; + + list.push_front(5); + list.push_front(10); + list.push_front(15); + + int result[] = {15, 10, 5}; + + ck_assert(list.size() == 3); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_inlist_pop_front) +{ + efl::eina::eina_init eina_init; + + efl::eina::inlist list; + + list.push_front(5); + list.push_front(10); + list.push_front(15); + list.pop_front(); + + int result[] = {10, 5}; + + ck_assert(list.size() == 2); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_inlist_insert) +{ + efl::eina::eina_init eina_init; + + efl::eina::inlist list; + + efl::eina::inlist::iterator it; + + it = list.insert(list.end(), 5); // first element + ck_assert(it != list.end()); + ++it; + ck_assert(it == list.end()); + + it = list.insert(list.end(), 10); // equivalent to push_back + ck_assert(it != list.end()); + ++it; + ck_assert(it == list.end()); + + it = list.insert(list.begin(), 15); // equivalent to push_front + ck_assert(it == list.begin()); + + it = list.end(); + --it; + list.insert(it, 20); // insert before the last element + + int result[] = {15, 5, 20, 10}; + + ck_assert(list.size() == 4); + ck_assert(std::equal(list.begin(), list.end(), result)); + + efl::eina::inlist list2; + it = list2.insert(list2.end(), list.begin(), list.end()); + ck_assert(it == list2.begin()); + ck_assert(list == list2); + + efl::eina::inlist list3; + list3.push_back(1); + it = list3.insert(list3.end(), list.begin(), list.end()); + ck_assert(list3.size() == 5); + ck_assert(list3.front() == 1); + it = list3.begin(); + ++it; + ck_assert(std::equal(it, list3.end(), list.begin())); + + efl::eina::inlist list4; + list4.push_back(1); + it = list4.insert(list4.begin(), list.begin(), list.end()); + ck_assert(list4.size() == 5); + ck_assert(list4.back() == 1); + ck_assert(std::equal(list.begin(), list.end(), list4.begin())); +} +END_TEST + +START_TEST(eina_cxx_inlist_constructors) +{ + efl::eina::eina_init eina_init; + + efl::eina::inlist list1; + ck_assert(list1.empty()); + + efl::eina::inlist list2(10, 5); + ck_assert(list2.size() == 10); + ck_assert(std::find_if(list2.begin(), list2.end() + , std::not1(std::bind1st(std::equal_to(), 5))) == list2.end()); + + efl::eina::inlist list3(list2); + ck_assert(list2 == list3); + + efl::eina::inlist list4(list2.begin(), list2.end()); + ck_assert(list2 == list4); +} +END_TEST + +START_TEST(eina_cxx_inlist_erase) +{ + efl::eina::eina_init eina_init; + + efl::eina::inlist list1; + list1.push_back(5); + list1.push_back(10); + list1.push_back(15); + list1.push_back(20); + list1.push_back(25); + list1.push_back(30); + + efl::eina::inlist::iterator it = list1.begin(), it2; + + it = list1.erase(it); + ck_assert(it == list1.begin()); + ck_assert(list1.size() == 5); + ck_assert(list1.front() == 10); + + it = list1.begin(); + it2 = list1.begin(); + ++it; + ++it2; ++it2; + ck_assert(*it2 == 20); + it = list1.erase(it); + ck_assert(it == it2); + ck_assert(list1.size() == 4); + ck_assert(*it2 == 20); + + it = list1.end(); + --it; + it = list1.erase(it); + ck_assert(it == list1.end()); + ck_assert(list1.size() == 3); + ck_assert(list1.back() == 25); + + it = list1.begin(); + ++it; + it2 = list1.end(); + --it2; + it = list1.erase(it, it2); + it2 = list1.end(); + --it2; + ck_assert(it == it2); + ck_assert(list1.size() == 2); + ck_assert(list1.front() == 10); + ck_assert(list1.back() == 25); +} +END_TEST + +void +eina_test_inlist(TCase *tc) +{ + tcase_add_test(tc, eina_cxx_inlist_push_back); + tcase_add_test(tc, eina_cxx_inlist_push_front); + tcase_add_test(tc, eina_cxx_inlist_pop_back); + tcase_add_test(tc, eina_cxx_inlist_pop_front); + tcase_add_test(tc, eina_cxx_inlist_insert); + tcase_add_test(tc, eina_cxx_inlist_erase); + tcase_add_test(tc, eina_cxx_inlist_constructors); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_iterator.cc b/src/tests/eina_cxx/eina_cxx_test_iterator.cc new file mode 100644 index 0000000000..ee4b356a7b --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_iterator.cc @@ -0,0 +1,34 @@ + +#include "Eina.hh" + +#include + +#include + +START_TEST(eina_cxx_iterator_equal) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list; + ck_assert(list.size() == 0); + ck_assert(list.empty()); + + list.push_back(new int(5)); + list.push_back(new int(10)); + list.push_back(new int(15)); + list.push_back(new int(20)); + + efl::eina::iterator iterator = list.ibegin() + , last_iterator = list.iend(); + + int result[] = {5, 10, 15, 20}; + + ck_assert(std::equal(iterator, last_iterator, result)); +} +END_TEST + +void +eina_test_iterator(TCase *tc) +{ + tcase_add_test(tc, eina_cxx_iterator_equal); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_ptrarray.cc b/src/tests/eina_cxx/eina_cxx_test_ptrarray.cc new file mode 100644 index 0000000000..4e9a13b933 --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_ptrarray.cc @@ -0,0 +1,180 @@ + +#include "Eina.hh" + +#include + +#include + +START_TEST(eina_cxx_ptrarray_push_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_array array; + + array.push_back(new int(5)); + array.push_back(new int(10)); + array.push_back(new int(15)); + + int result[] = {5, 10, 15}; + + ck_assert(array.size() == 3); + ck_assert(std::equal(array.begin(), array.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_ptrarray_pop_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_array array; + + array.push_back(new int(5)); + array.push_back(new int(10)); + array.push_back(new int(15)); + array.pop_back(); + + int result[] = {5, 10}; + + ck_assert(array.size() == 2); + ck_assert(std::equal(array.begin(), array.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_ptrarray_insert) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_array array; + ck_assert(std::distance(array.begin(), array.end()) == 0u); + + efl::eina::ptr_array::iterator it; + + it = array.insert(array.end(), new int(5)); // first element + ck_assert(it != array.end()); + ++it; + ck_assert(it == array.end()); + ck_assert(array[0] == 5); + ck_assert(std::distance(array.begin(), array.end()) == 1u); + + it = array.insert(array.end(), new int(10)); // equivalent to push_back + ck_assert(it != array.end()); + ++it; + ck_assert(it == array.end()); + ck_assert(array[0] == 5); + ck_assert(array[1] == 10); + ck_assert(std::distance(array.begin(), array.end()) == 2u); + + it = array.insert(array.begin(), new int(15)); // equivalent to push_front + ck_assert(it == array.begin()); + + ck_assert(array[1] == 5); + ck_assert(array[2] == 10); + ck_assert(array[0] == 15); + ck_assert(std::distance(array.begin(), array.end()) == 3u); + + array.insert(array.end() - 1, new int(20)); // insert before the last element + ck_assert(array[0] == 15); + ck_assert(array[1] == 5); + ck_assert(array[2] == 20); + ck_assert(array[3] == 10); + ck_assert(std::distance(array.begin(), array.end()) == 4u); + + int result[] = {15, 5, 20, 10}; + + ck_assert(array.size() == 4); + ck_assert(std::distance(array.begin(), array.end()) == 4u); + ck_assert(std::equal(array.begin(), array.end(), result)); + + efl::eina::ptr_array array2; + it = array2.insert(array2.end(), array.begin(), array.end()); + ck_assert(it == array2.begin()); + ck_assert(array == array2); + + + efl::eina::ptr_array array3; + array3.push_back(1); + it = array3.insert(array3.end(), array.begin(), array.end()); + ck_assert(array3.size() == 5); + ck_assert(array3.front() == 1); + it = array3.begin(); + ++it; + ck_assert(std::equal(it, array3.end(), array.begin())); + + efl::eina::ptr_array array4; + array4.push_back(1); + it = array4.insert(array4.begin(), array.begin(), array.end()); + ck_assert(array4.size() == 5); + ck_assert(array4.back() == 1); + ck_assert(std::equal(array.begin(), array.end(), array4.begin())); +} +END_TEST + +START_TEST(eina_cxx_ptrarray_constructors) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_array array1; + ck_assert(array1.empty()); + + efl::eina::ptr_array array2(10, 5); + ck_assert(array2.size() == 10); + ck_assert(std::find_if(array2.begin(), array2.end() + , std::not1(std::bind1st(std::equal_to(), 5))) == array2.end()); + + efl::eina::ptr_array array3(array2); + ck_assert(array2 == array3); + + efl::eina::ptr_array array4 + (array2.begin(), array2.end()); + ck_assert(array2 == array4); +} +END_TEST + +START_TEST(eina_cxx_ptrarray_erase) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_array array1; + array1.push_back(new int(5)); + array1.push_back(new int(10)); + array1.push_back(new int(15)); + array1.push_back(new int(20)); + array1.push_back(new int(25)); + array1.push_back(new int(30)); + + int result[] = {5, 10, 15, 20, 25, 30}; + ck_assert(std::equal(array1.begin(), array1.end(), result)); + + efl::eina::ptr_array::iterator it = array1.erase(array1.begin()); + ck_assert(it == array1.begin()); + ck_assert(array1.size() == 5); + ck_assert(array1.front() == 10); + + ck_assert(std::equal(array1.begin(), array1.end(), &result[1])); + + it = array1.erase(array1.begin() + 1); + ck_assert(*it == 20); + ck_assert(array1.size() == 4); + + it = array1.erase(array1.end() - 1); + ck_assert(it == array1.end()); + ck_assert(array1.size() == 3); + ck_assert(array1.back() == 25); + + it = array1.erase(array1.begin() + 1, array1.end() - 1); + ck_assert(it == array1.end() - 1); + ck_assert(array1.size() == 2); + ck_assert(array1.front() == 10); + ck_assert(array1.back() == 25); +} +END_TEST + +void +eina_test_ptrarray(TCase* tc) +{ + tcase_add_test(tc, eina_cxx_ptrarray_push_back); + tcase_add_test(tc, eina_cxx_ptrarray_pop_back); + tcase_add_test(tc, eina_cxx_ptrarray_insert); + tcase_add_test(tc, eina_cxx_ptrarray_constructors); + tcase_add_test(tc, eina_cxx_ptrarray_erase); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc b/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc new file mode 100644 index 0000000000..c95adc3b21 --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc @@ -0,0 +1,212 @@ + +#include "Eina.hh" + +#include + +#include + +START_TEST(eina_cxx_ptrlist_push_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list; + + list.push_back(new int(5)); + list.push_back(new int(10)); + list.push_back(new int(15)); + + int result[] = {5, 10, 15}; + + ck_assert(list.size() == 3); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_ptrlist_pop_back) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list; + + list.push_back(new int(5)); + list.push_back(new int(10)); + list.push_back(new int(15)); + list.pop_back(); + + int result[] = {5, 10}; + + ck_assert(list.size() == 2); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_ptrlist_push_front) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list; + + list.push_front(new int(5)); + list.push_front(new int(10)); + list.push_front(new int(15)); + + int result[] = {15, 10, 5}; + + ck_assert(list.size() == 3); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_ptrlist_pop_front) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list; + + list.push_front(new int(5)); + list.push_front(new int(10)); + list.push_front(new int(15)); + list.pop_front(); + + int result[] = {10, 5}; + + ck_assert(list.size() == 2); + ck_assert(std::equal(list.begin(), list.end(), result)); +} +END_TEST + +START_TEST(eina_cxx_ptrlist_insert) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list; + + efl::eina::ptr_list::iterator it; + + it = list.insert(list.end(), new int(5)); // first element + ck_assert(it != list.end()); + ++it; + ck_assert(it == list.end()); + + it = list.insert(list.end(), new int(10)); // equivalent to push_back + ck_assert(it != list.end()); + ++it; + ck_assert(it == list.end()); + + it = list.insert(list.begin(), new int(15)); // equivalent to push_front + ck_assert(it == list.begin()); + + it = list.end(); + --it; + list.insert(it, new int(20)); // insert before the last element + + int result[] = {15, 5, 20, 10}; + + ck_assert(list.size() == 4); + ck_assert(std::equal(list.begin(), list.end(), result)); + + efl::eina::ptr_list list2; + it = list2.insert(list2.end(), list.begin(), list.end()); + ck_assert(it == list2.begin()); + ck_assert(list == list2); + + efl::eina::ptr_list list3; + list3.push_back(1); + it = list3.insert(list3.end(), list.begin(), list.end()); + ck_assert(list3.size() == 5); + ck_assert(list3.front() == 1); + it = list3.begin(); + ++it; + ck_assert(std::equal(it, list3.end(), list.begin())); + + efl::eina::ptr_list list4; + list4.push_back(1); + it = list4.insert(list4.begin(), list.begin(), list.end()); + ck_assert(list4.size() == 5); + ck_assert(list4.back() == 1); + ck_assert(std::equal(list.begin(), list.end(), list4.begin())); +} +END_TEST + +START_TEST(eina_cxx_ptrlist_constructors) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list1; + ck_assert(list1.empty()); + + efl::eina::ptr_list list2(10, 5); + ck_assert(list2.size() == 10); + ck_assert(std::find_if(list2.begin(), list2.end() + , std::not1(std::bind1st(std::equal_to(), 5))) == list2.end()); + + efl::eina::ptr_list list3(list2); + ck_assert(list2 == list3); + + efl::eina::ptr_list list4 + (list2.begin(), list2.end()); + ck_assert(list2 == list4); +} +END_TEST + +START_TEST(eina_cxx_ptrlist_erase) +{ + efl::eina::eina_init eina_init; + + efl::eina::ptr_list list1; + list1.push_back(new int(5)); + list1.push_back(new int(10)); + list1.push_back(new int(15)); + list1.push_back(new int(20)); + list1.push_back(new int(25)); + list1.push_back(new int(30)); + + efl::eina::ptr_list::iterator it = list1.begin(), it2; + + it = list1.erase(it); + ck_assert(it == list1.begin()); + ck_assert(list1.size() == 5); + ck_assert(list1.front() == 10); + + it = list1.begin(); + it2 = list1.begin(); + ++it; + ++it2; ++it2; + ck_assert(*it2 == 20); + it = list1.erase(it); + ck_assert(it == it2); + ck_assert(list1.size() == 4); + ck_assert(*it2 == 20); + + it = list1.end(); + --it; + it = list1.erase(it); + ck_assert(it == list1.end()); + ck_assert(list1.size() == 3); + ck_assert(list1.back() == 25); + + it = list1.begin(); + ++it; + it2 = list1.end(); + --it2; + it = list1.erase(it, it2); + it2 = list1.end(); + --it2; + ck_assert(it == it2); + ck_assert(list1.size() == 2); + ck_assert(list1.front() == 10); + ck_assert(list1.back() == 25); +} +END_TEST + +void +eina_test_ptrlist(TCase* tc) +{ + tcase_add_test(tc, eina_cxx_ptrlist_push_back); + tcase_add_test(tc, eina_cxx_ptrlist_pop_back); + tcase_add_test(tc, eina_cxx_ptrlist_push_front); + tcase_add_test(tc, eina_cxx_ptrlist_pop_front); + tcase_add_test(tc, eina_cxx_ptrlist_insert); + tcase_add_test(tc, eina_cxx_ptrlist_constructors); + tcase_add_test(tc, eina_cxx_ptrlist_erase); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_stringshare.cc b/src/tests/eina_cxx/eina_cxx_test_stringshare.cc new file mode 100644 index 0000000000..1215431712 --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_stringshare.cc @@ -0,0 +1,32 @@ + +#include "Eina.hh" + +#include +#include + +#include + +START_TEST(eina_cxx_stringshare_constructors) +{ + efl::eina::eina_init eina_init; + + efl::eina::stringshare string1; + ck_assert(string1.empty()); + + efl::eina::stringshare string2("string"); + ck_assert(string2.size() == 6); + ck_assert(string2 == "string"); + + efl::eina::stringshare string3(string2); + ck_assert(string2 == string3); + + efl::eina::stringshare string4(string3.begin(), string3.end()); + ck_assert(string2 == string3); +} +END_TEST + +void +eina_test_stringshare(TCase *tc) +{ + tcase_add_test(tc, eina_cxx_stringshare_constructors); +} diff --git a/src/tests/eina_cxx/eina_cxx_test_thread.cc b/src/tests/eina_cxx/eina_cxx_test_thread.cc new file mode 100644 index 0000000000..1a749359b2 --- /dev/null +++ b/src/tests/eina_cxx/eina_cxx_test_thread.cc @@ -0,0 +1,127 @@ + +#include "Eina.hh" + +#include + +#include + +bool no_args = false + , args_1 = false + , args_2 = false; + +void thread_no_args() +{ + no_args = true; +} + +struct test +{ + int x; +}; + +void thread_1_arg(int a0) +{ + args_1 = true; + ck_assert(a0 == 5); +} + +void thread_2_arg(int a0, test t) +{ + args_2 = true; + ck_assert(a0 == 5); + ck_assert(t.x == 10); +} + +START_TEST(eina_cxx_thread_constructors) +{ + efl::eina::eina_init init; + efl::eina::eina_threads_init threads_init; + { + efl::eina::thread default_constructed_thread; + ck_assert(default_constructed_thread.get_id() == efl::eina::thread::id()); + } + + { + efl::eina::thread thread_no_args(&::thread_no_args); + thread_no_args.join(); + ck_assert( ::no_args); + } + + { + efl::eina::thread thread_1_arg(&::thread_1_arg, 5); + thread_1_arg.join(); + ck_assert( ::args_1); + } + + { + test t = {10}; + efl::eina::thread thread_2_arg(&::thread_2_arg, 5, t); + thread_2_arg.join(); + ck_assert( ::args_2); + } +} +END_TEST + +START_TEST(eina_cxx_thread_mutexes) +{ + efl::eina::mutex m; + + { + efl::eina::unique_lock lock1(m); + ck_assert(lock1.owns_lock()); + + lock1.unlock(); + ck_assert(!lock1.owns_lock()); + + ck_assert(lock1.try_lock()); + ck_assert(lock1.owns_lock()); + lock1.unlock(); + + lock1.lock(); + ck_assert(lock1.owns_lock()); + } + + { + efl::eina::lock_guard lock1(m); + } +} +END_TEST + +bool b = false; + +void condition_thread(efl::eina::mutex& condition_mutex + , efl::eina::condition_variable& condition_condition) +{ + efl::eina::unique_lock l( condition_mutex); + b = true; + condition_condition.notify_one(); +} + +START_TEST(eina_cxx_thread_conditional) +{ + efl::eina::mutex m; + + efl::eina::mutex condition_mutex; + efl::eina::condition_variable condition_condition; + + efl::eina::unique_lock l( condition_mutex); + efl::eina::thread thread(&condition_thread, std::ref(condition_mutex), std::ref(condition_condition)); + + while(!b) + { + ck_assert(l.owns_lock()); + condition_condition.wait(l); + ck_assert(l.owns_lock()); + } + + thread.join(); +} +END_TEST + +void +eina_test_thread(TCase* tc) +{ + tcase_add_test(tc, eina_cxx_thread_constructors); + tcase_add_test(tc, eina_cxx_thread_mutexes); + tcase_add_test(tc, eina_cxx_thread_conditional); +}