summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2014-02-25 17:24:32 -0300
committerCedric Bail <cedric.bail@free.fr>2014-02-25 18:05:01 -0300
commitf279225a6300063c0bc6a47dedd3036ac72e89a6 (patch)
tree796dadba6c7cfaf301f89b24086a1d05647825b7 /src
parentd63507446fcd9ee1fd90373f5d1207f71cfb8f74 (diff)
eina: add a C++ bindings to Eina @feature.
The goal of this library is to make the life of C++ developers easier when having to manipulate Eina datatype by providing a layer to abstract those data type in C++. Check examples for now. Documentation will come soon, but we are pushing that rather sooner to get feedback on those bindings. As you will notice, this library is just composed of headers. There is no .so and we do think it is better this way. Reducing ABI and API stability issue for applications developers who are the primary target of this binding. Also please note that you will need to have C++11 to use this binding. Signed-off-by: Cedric Bail <cedric.bail@free.fr>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile_Eina_Cxx.am61
-rw-r--r--src/examples/eina_cxx/Makefile.am45
-rw-r--r--src/examples/eina_cxx/eina_cxx_list_01.cc55
-rw-r--r--src/examples/eina_cxx/eina_cxx_thread_01.cc32
-rw-r--r--src/lib/eina_cxx/Eina.hh44
-rw-r--r--src/lib/eina_cxx/eina_accessor.hh214
-rw-r--r--src/lib/eina_cxx/eina_clone_allocators.hh69
-rw-r--r--src/lib/eina_cxx/eina_error.hh105
-rw-r--r--src/lib/eina_cxx/eina_inarray.hh544
-rw-r--r--src/lib/eina_cxx/eina_inlist.hh464
-rw-r--r--src/lib/eina_cxx/eina_iterator.hh101
-rw-r--r--src/lib/eina_cxx/eina_lists_auxiliary.hh28
-rw-r--r--src/lib/eina_cxx/eina_ptrarray.hh486
-rw-r--r--src/lib/eina_cxx/eina_ptrlist.hh495
-rw-r--r--src/lib/eina_cxx/eina_ref.hh26
-rw-r--r--src/lib/eina_cxx/eina_stringshare.hh205
-rw-r--r--src/lib/eina_cxx/eina_thread.hh356
-rw-r--r--src/lib/eina_cxx/eina_type_traits.hh51
-rw-r--r--src/lib/eina_cxx/eina_value.hh371
-rw-r--r--src/tests/eina_cxx/eina_cxx_suite.cc125
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_accessor.cc102
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_eina_value.cc191
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_error.cc72
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_inarray.cc388
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_inlist.cc212
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_iterator.cc34
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_ptrarray.cc180
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_ptrlist.cc212
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_stringshare.cc32
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_thread.cc127
31 files changed, 5430 insertions, 0 deletions
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
56include Makefile_Ethumb.am 56include Makefile_Ethumb.am
57include Makefile_Ethumb_Client.am 57include Makefile_Ethumb_Client.am
58 58
59include Makefile_Eina_Cxx.am
60
59.PHONY: benchmark examples 61.PHONY: benchmark examples
60 62
61BENCHMARK_SUBDIRS = \ 63BENCHMARK_SUBDIRS = \
@@ -71,6 +73,7 @@ benchmark: all-am
71 73
72EXAMPLES_SUBDIRS = \ 74EXAMPLES_SUBDIRS = \
73examples/eina \ 75examples/eina \
76examples/eina_cxx \
74examples/eo \ 77examples/eo \
75examples/eet \ 78examples/eet \
76examples/evas \ 79examples/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 @@
1
2### Library
3
4#lib_LTLIBRARIES += lib/eina/libeina.la
5
6installed_einacxxmainheadersdir = $(includedir)/eina_cxx-@VMAJ@
7dist_installed_einacxxmainheaders_DATA = \
8lib/eina_cxx/Eina.hh
9
10installed_einacxxheadersdir = $(includedir)/eina_cxx-@VMAJ@/eina_cxx
11dist_installed_einacxxheaders_DATA = \
12lib/eina_cxx/eina_accessor.hh \
13lib/eina_cxx/eina_clone_allocators.hh \
14lib/eina_cxx/eina_error.hh \
15lib/eina_cxx/eina_inarray.hh \
16lib/eina_cxx/eina_inlist.hh \
17lib/eina_cxx/eina_iterator.hh \
18lib/eina_cxx/eina_lists_auxiliary.hh \
19lib/eina_cxx/eina_ptrarray.hh \
20lib/eina_cxx/eina_ptrlist.hh \
21lib/eina_cxx/eina_ref.hh \
22lib/eina_cxx/eina_stringshare.hh \
23lib/eina_cxx/eina_thread.hh \
24lib/eina_cxx/eina_type_traits.hh \
25lib/eina_cxx/eina_value.hh
26
27### Unit tests
28
29if EFL_ENABLE_TESTS
30if HAVE_CXX11
31
32check_PROGRAMS += tests/eina_cxx/eina_cxx_suite
33TESTS += tests/eina_cxx/eina_cxx_suite
34
35tests_eina_cxx_eina_cxx_suite_SOURCES = \
36tests/eina_cxx/eina_cxx_suite.cc \
37tests/eina_cxx/eina_cxx_test_inlist.cc \
38tests/eina_cxx/eina_cxx_test_inarray.cc \
39tests/eina_cxx/eina_cxx_test_iterator.cc \
40tests/eina_cxx/eina_cxx_test_ptrarray.cc \
41tests/eina_cxx/eina_cxx_test_ptrlist.cc \
42tests/eina_cxx/eina_cxx_test_stringshare.cc \
43tests/eina_cxx/eina_cxx_test_error.cc \
44tests/eina_cxx/eina_cxx_test_accessor.cc \
45tests/eina_cxx/eina_cxx_test_thread.cc \
46tests/eina_cxx/eina_cxx_test_eina_value.cc
47
48tests_eina_cxx_eina_cxx_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
49-I$(top_builddir)/src/lib/eina_cxx \
50-DTESTS_WD=\"`pwd`\" \
51-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eina_cxx\" \
52-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)/src/tests/eina_cxx\" \
53-DTESTS_BUILD_DIR=PACKAGE_BUILD_DIR \
54@CHECK_CFLAGS@ \
55@EINA_CFLAGS@
56tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@
57tests_eina_cxx_eina_cxx_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
58
59endif
60endif
61
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 @@
1MAINTAINERCLEANFILES = Makefile.in
2
3AM_CPPFLAGS = \
4-I$(top_builddir)/src/lib/efl \
5-I. \
6-I$(top_srcdir)/src/lib/eina \
7-I$(top_builddir)/src/lib/eina \
8-I$(top_srcdir)/src/lib/eina_cxx \
9-I$(top_builddir)/src/lib/eina_cxx
10
11LDADD = $(top_builddir)/src/lib/eina/libeina.la @EINA_LDFLAGS@ @USE_BOOST_SYSTEM_LIBS@ @USE_BOOST_SYSTEM_LDFLAGS@
12AM_CXXFLAGS = @USE_BOOST_CPPFLAGS@
13
14SRCS = \
15eina_cxx_list_01.cc
16
17EXTRA_PROGRAMS = \
18eina_cxx_list_01 \
19eina_cxx_thread_01
20
21eina_cxx_list_01_SOURCES = \
22eina_cxx_list_01.cc
23
24eina_cxx_thread_01_SOURCES = \
25eina_cxx_thread_01.cc
26
27EXTRA_DIST = $(DATA_FILES)
28
29examples: $(EXTRA_PROGRAMS)
30
31clean-local:
32 rm -f $(EXTRA_PROGRAMS)
33
34install-examples:
35 mkdir -p $(datadir)/eina/examples
36 $(install_sh_DATA) -c $(SRCS) $(DATA_FILES) $(datadir)/eina/examples
37
38uninstall-local:
39 for f in $(SRCS) $(DATA_FILES); do \
40 rm -f $(datadir)/eina/examples/$$f ; \
41 done
42
43if ALWAYS_BUILD_EXAMPLES
44noinst_PROGRAMS = $(EXTRA_PROGRAMS)
45endif
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 @@
1//Compile with:
2//gcc -g eina_list_01.c -o eina_list_01 `pkg-config --cflags --libs eina`
3
4#include <stdio.h>
5#include <Eina.hh>
6
7#include <iterator>
8#include <algorithm>
9
10#include <iostream>
11
12template <typename I>
13I next(I i, std::size_t n = 1u)
14{
15 for(;n;--n)
16 ++i;
17}
18
19int main(int argc, char **argv)
20{
21 efl::eina::eina_init eina_init;
22
23 efl::eina::ptr_list<std::string, efl::eina::heap_copy_allocator> list;
24
25 list.push_back("tigh");
26 list.push_back("adar");
27 list.push_back("baltar");
28 list.push_back("roslin");
29
30 for(efl::eina::ptr_list<std::string>::const_iterator
31 first = list.begin(), last = list.end()
32 ;first != last; ++first)
33 std::cout << *first << std::endl;
34
35 efl::eina::ptr_list<std::string>::iterator
36 iterator = ::next(list.begin(), 2u);
37 list.insert(iterator, "cain");
38
39 iterator = std::find(list.begin(), list.end(), "cain");
40 assert(iterator != list.end() && ::next(iterator) != list.end());
41 list.insert(::next(iterator), "zarek");
42
43 list.insert(list.begin(), "adama");
44
45 iterator = std::find(list.begin(), list.end(), "cain");
46 assert(iterator != list.end());
47 list.insert(iterator, "gaeta");
48
49 list.insert(::next(list.begin()), "lampkin");
50
51 for(efl::eina::ptr_list<std::string>::const_iterator
52 first = list.begin(), last = list.end()
53 ;first != last; ++first)
54 std::cout << *first << std::endl;
55}
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 @@
1//Compile with:
2//gcc -g eina_list_01.c -o eina_list_01 `pkg-config --cflags --libs eina`
3
4#include <stdio.h>
5#include <Eina.hh>
6
7#include <iterator>
8#include <algorithm>
9
10#include <iostream>
11
12namespace eina = efl::eina;
13
14void thread1(eina::mutex& m)
15{
16
17}
18
19int main(int argc, char **argv)
20{
21 eina::eina_init eina_init;
22 eina::eina_threads_init threads_init;
23
24 eina::mutex m;
25 eina::condition_variable c;
26
27 eina::unique_lock<eina::mutex> l(m);
28
29 eina::thread thread1(&::thread1, eina::ref(m));
30
31 thread1.join();
32}
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 @@
1#ifndef EINA_HH_
2#define EINA_HH_
3
4#include <eina_iterator.hh>
5#include <eina_ptrarray.hh>
6#include <eina_ptrlist.hh>
7#include <eina_inarray.hh>
8#include <eina_inlist.hh>
9#include <eina_stringshare.hh>
10#include <eina_error.hh>
11#include <eina_accessor.hh>
12#include <eina_thread.hh>
13#include <eina_value.hh>
14#include <eina_ref.hh>
15
16namespace efl { namespace eina {
17
18struct eina_init
19{
20 eina_init()
21 {
22 ::eina_init();
23 }
24 ~eina_init()
25 {
26 ::eina_shutdown();
27 }
28};
29
30struct eina_threads_init
31{
32 eina_threads_init()
33 {
34 ::eina_threads_init();
35 }
36 ~eina_threads_init()
37 {
38 ::eina_threads_shutdown();
39 }
40};
41
42} }
43
44#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 @@
1#ifndef EINA_ACCESSOR_HH_
2#define EINA_ACCESSOR_HH_
3
4#include <Eina.h>
5#include <eina_error.hh>
6
7#include <memory>
8#include <iterator>
9#include <cstdlib>
10#include <cassert>
11
12namespace efl { namespace eina {
13
14template <typename T>
15struct accessor
16{
17 typedef unsigned int key_type;
18 typedef T mapped_type;
19 typedef T value_type;
20 typedef std::size_t size_type;
21
22 accessor() : _impl(0) {}
23 explicit accessor(Eina_Accessor* impl)
24 : _impl(impl)
25 {
26 assert(_impl != 0);
27 }
28 accessor(accessor<T> const& other)
29 : _impl(eina_accessor_clone(other._impl))
30 {}
31 accessor<T>& operator=(accessor<T> const& other)
32 {
33 eina_accessor_free(_impl);
34 _impl = eina_accessor_clone(other._impl);
35 if(!_impl)
36 throw eina::system_error(efl::eina::get_error_code(), "Error cloning accessor");
37 return *this;
38 }
39 ~accessor()
40 {
41 eina_accessor_free(_impl);
42 }
43
44 mapped_type& operator[](size_type i) const
45 {
46 assert(_impl != 0);
47 void* p;
48 if(!eina_accessor_data_get(_impl, i, &p))
49 {
50 eina::error_code ec = efl::eina::get_error_code();
51 throw eina::system_error(ec, "EFL Eina Error");
52 }
53 return *static_cast<mapped_type*>(p);
54 }
55
56 Eina_Accessor* native_handle() const;
57
58 void swap(accessor<T>& other)
59 {
60 std::swap(_impl, other._impl);
61 }
62private:
63 typedef Eina_Accessor*(accessor<T>::*unspecified_bool_type)() const;
64public:
65 operator unspecified_bool_type() const
66 {
67 return native_handle() ? &accessor<T>::native_handle : 0 ;
68 }
69private:
70 Eina_Accessor* _impl;
71};
72
73template <typename U>
74void swap(accessor<U>& lhs, accessor<U>& rhs)
75{
76 lhs.swap(rhs);
77}
78
79template <typename T>
80struct accessor_iterator
81{
82 typedef T value_type;
83 typedef value_type* pointer;
84 typedef value_type& reference;
85 typedef std::ptrdiff_t difference_type;
86 typedef std::random_access_iterator_tag iterator_category;
87
88 accessor_iterator(accessor<T> const& a, unsigned int pos = 0u)
89 : _accessor(a), _index(pos)
90 {}
91
92 accessor_iterator<T>& operator+=(difference_type i)
93 {
94 _index += i;
95 return *this;
96 }
97 accessor_iterator<T>& operator-=(difference_type i)
98 {
99 _index -= i;
100 return *this;
101 }
102 value_type& operator[](difference_type i)
103 {
104 return _accessor[_index + i];
105 }
106 accessor_iterator<T>& operator++()
107 {
108 ++_index;
109 return *this;
110 }
111 accessor_iterator<T>& operator--()
112 {
113 --_index;
114 return *this;
115 }
116 accessor_iterator<T>& operator++(int)
117 {
118 accessor_iterator<T> tmp(*this);
119 ++*this;
120 return tmp;
121 }
122 accessor_iterator<T>& operator--(int)
123 {
124 accessor_iterator<T> tmp(*this);
125 --*this;
126 return tmp;
127 }
128 value_type& operator*() const
129 {
130 return _accessor[_index];
131 }
132 pointer operator->() const
133 {
134 return &**this;
135 }
136 void swap(accessor_iterator<T>& other)
137 {
138 std::swap(_index, other._index);
139 std::swap(_accessor, other._accessor);
140 }
141private:
142 accessor<T> _accessor;
143 unsigned int _index;
144
145 template <typename U>
146 friend bool operator==(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
147 {
148 return lhs._index == rhs._index;
149 }
150
151 template <typename U>
152 friend typename accessor_iterator<U>::difference_type
153 operator-(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
154 {
155 return lhs._index - rhs._index;
156 }
157
158 template <typename U>
159 friend
160 accessor_iterator<U> operator+(accessor_iterator<U> lhs
161 , typename accessor_iterator<U>::difference_type rhs)
162 {
163 lhs._index += rhs;
164 return lhs;
165 }
166
167 template <typename U>
168 friend
169 accessor_iterator<U> operator+(typename accessor_iterator<U>::difference_type lhs
170 , accessor_iterator<U> rhs)
171 {
172 return rhs + lhs;
173 }
174
175 template <typename U>
176 friend bool operator<(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
177 {
178 return lhs._index < rhs._index;
179 }
180
181 template <typename U>
182 friend bool operator<=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
183 {
184 return lhs._index <= rhs._index;
185 }
186};
187
188template <typename U>
189bool operator>=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
190{
191 return !(lhs < rhs);
192}
193
194template <typename U>
195bool operator>(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
196{
197 return !(lhs <= rhs);
198}
199
200template <typename U>
201bool operator!=(accessor_iterator<U> const& lhs, accessor_iterator<U> const& rhs)
202{
203 return !(lhs == rhs);
204}
205
206template <typename U>
207void swap(accessor_iterator<U>& lhs, accessor_iterator<U>& rhs)
208{
209 lhs.swap(rhs);
210}
211
212} }
213
214#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 @@
1#ifndef EINA_CLONE_ALLOCATORS_HH_
2#define EINA_CLONE_ALLOCATORS_HH_
3
4#include <memory>
5
6namespace efl { namespace eina {
7
8struct heap_copy_allocator
9{
10 template <typename T>
11 static T* allocate_clone(T const& v)
12 {
13 return new T(v);
14 }
15
16 template <typename T>
17 static void deallocate_clone(T* p)
18 {
19#ifdef EFL_EINA_CXX11
20 std::default_delete<T>()(p);
21#else
22 delete p;
23#endif
24 }
25};
26
27struct heap_clone_allocator
28{
29 template <typename T>
30 static T* allocate_clone(T const& v)
31 {
32 return new_clone(v);
33 }
34 template <typename T>
35 static void deallocate_clone(T* p)
36 {
37 delete_clone(p);
38 }
39};
40
41struct view_clone_allocator
42{
43 template <typename T>
44 static T* allocate_clone(T const& v)
45 {
46 return const_cast<T*>(&v);
47 }
48 template <typename T>
49 static void deallocate_clone(T* p)
50 {
51 }
52};
53
54struct heap_no_copy_allocator
55{
56 template <typename T>
57 static void deallocate_clone(T* p)
58 {
59#ifdef EFL_EINA_CXX11
60 std::default_delete<T>()(p);
61#else
62 delete p;
63#endif
64 }
65};
66
67} }
68
69#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 @@
1#ifndef _EINA_ERROR_HH
2#define _EINA_ERROR_HH
3
4#include <Eina.h>
5
6#include <system_error>
7
8namespace efl { namespace eina {
9
10using std::errc;
11using std::system_error;
12using std::error_code;
13using std::error_condition;
14typedef std::error_category system_error_category;
15
16inline system_error_category const& get_generic_category()
17{
18 return ::std::generic_category();
19}
20inline system_error_category const& get_system_category()
21{
22 return ::std::system_category();
23}
24
25enum error_type {};
26
27struct error_category : system_error_category
28{
29 const char* name() const throw()
30 {
31 return "eina";
32 }
33
34 bool equivalent(int code, eina::error_condition const& condition) const throw()
35 {
36 return code == condition.value();
37 }
38
39 bool equivalent(eina::error_code const& code, int condition) const throw()
40 {
41 return code.value() == condition;
42 }
43
44 std::string message(int condition) const
45 {
46 const char* e = ::eina_error_msg_get(condition);
47 return e? e : "::eina_error_msg_get returned NULL. No error message available";
48 }
49};
50
51inline eina::system_error_category& eina_error_category()
52{
53 static error_category _error_category;
54 return _error_category;
55}
56
57inline eina::error_code get_error_code()
58{
59 Eina_Error error = eina_error_get();
60 if(error)
61 {
62 eina_error_set(0);
63 return eina::error_code(error, eina_error_category());
64 }
65 else
66 return eina::error_code();
67}
68
69inline eina::error_condition get_error_condition()
70{
71 Eina_Error error = eina_error_get();
72 if(error)
73 {
74 eina_error_set(0);
75 return eina::error_condition(error, eina_error_category());
76 }
77 else
78 return eina::error_condition();
79}
80
81inline error_type get_error_code_enum()
82{
83 return static_cast<error_type>( ::eina_error_get() );
84}
85
86
87inline void throw_on_error()
88{
89 eina::error_code ec = get_error_code();
90 if(ec)
91 {
92 throw eina::system_error(ec, "EFL Eina Error");
93 }
94}
95
96} }
97
98namespace std {
99
100template <> struct is_error_condition_enum< ::efl::eina::error_type> : true_type {};
101template <> struct is_error_code_enum< ::efl::eina::error_type> : true_type {};
102
103}
104
105#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 @@
1#ifndef EINA_INARRAY_HH_
2#define EINA_INARRAY_HH_
3
4#include <Eina.h>
5#include <eina_type_traits.hh>
6
7#include <iterator>
8#include <cstring>
9#include <cassert>
10
11namespace efl { namespace eina {
12
13struct _inarray_common_base
14{
15 typedef std::size_t size_type;
16
17 explicit _inarray_common_base(size_type member_size)
18 : _array( ::eina_inarray_new(member_size, 0) )
19 {
20 }
21 ~_inarray_common_base()
22 {
23 ::eina_inarray_free(_array);
24 }
25
26 size_type size() const
27 {
28 return ::eina_inarray_count(_array);
29 }
30 bool empty() const
31 {
32 return size() == 0u;
33 }
34
35 Eina_Inarray* _array;
36private:
37 _inarray_common_base(_inarray_common_base const& other);
38 _inarray_common_base& operator=(_inarray_common_base const& other);
39};
40
41template <typename T>
42class _pod_inarray : _inarray_common_base
43{
44 typedef _inarray_common_base _base_type;
45public:
46 typedef T value_type;
47 typedef T& reference;
48 typedef T const& const_reference;
49 typedef T* pointer;
50 typedef T const* const_pointer;
51 typedef pointer iterator;
52 typedef const_pointer const_iterator;
53 typedef std::size_t size_type;
54 typedef std::ptrdiff_t difference_type;
55
56 typedef std::reverse_iterator<iterator> reverse_iterator;
57 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
58
59 using _base_type::size;
60 using _base_type::empty;
61
62 _pod_inarray() : _base_type(sizeof(T))
63 {
64 }
65 _pod_inarray(size_type n, value_type const& t) : _base_type(sizeof(T))
66 {
67 while(n--)
68 push_back(t);
69 }
70 template <typename InputIterator>
71 _pod_inarray(InputIterator i, InputIterator const& j
72 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
73 : _base_type(sizeof(T))
74 {
75 while(i != j)
76 {
77 push_back(*i);
78 ++i;
79 }
80 }
81 _pod_inarray(_pod_inarray<T>const& other)
82 : _base_type(sizeof(T))
83 {
84 insert(end(), other.begin(), other.end());
85 }
86 ~_pod_inarray()
87 {
88 }
89 _pod_inarray<T>& operator=(_pod_inarray<T>const& other)
90 {
91 clear();
92 insert(end(), other.begin(), other.end());
93 return *this;
94 }
95 void clear()
96 {
97 ::eina_inarray_flush(_array);
98 }
99 void push_back(T const& value)
100 {
101 eina_inarray_push(_array, &value);
102 }
103 void pop_back()
104 {
105 eina_inarray_pop(_array);
106 }
107 iterator insert(iterator i, value_type const& t)
108 {
109 if(i != end())
110 {
111 T* q = static_cast<iterator>
112 ( ::eina_inarray_alloc_at(_array, i - begin(), 1u));
113 std::memcpy(q, &t, sizeof(t));
114 return q;
115 }
116 else
117 {
118 push_back(t);
119 return end()-1;
120 }
121 }
122 iterator insert(iterator i, size_t n, value_type const& t)
123 {
124 T* q;
125 if(i != end())
126 {
127 q = static_cast<iterator>
128 ( ::eina_inarray_alloc_at(_array, i - &_array->members, n));
129 }
130 else
131 {
132 q = eina_inarray_grow(_array, n);
133 }
134 for(T* p = q; n; --n, ++p)
135 std::memcpy(p, &t, sizeof(t));
136 return q;
137 }
138 template <typename InputIterator>
139 iterator insert(iterator p, InputIterator i, InputIterator j
140 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
141 {
142 size_type n = 0;
143 while(i != j)
144 {
145 p = insert(p, *i);
146 ++p;
147 ++i;
148 ++n;
149 }
150 return p - n;
151 }
152 iterator erase(iterator q)
153 {
154 ::eina_inarray_remove_at(_array, q - begin());
155 return q;
156 }
157 iterator erase(iterator i, iterator j)
158 {
159 while(i != j)
160 {
161 erase(--j);
162 }
163 return i;
164 }
165 template <typename InputIterator>
166 void assign(InputIterator i, InputIterator j
167 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0);
168 void assign(size_type n, value_type const& t);
169 value_type& back()
170 {
171 assert(!empty());
172 return *static_cast<value_type*>(eina_inarray_nth(_array, size()-1u));
173 }
174 value_type const& back() const
175 {
176 return const_cast<_pod_inarray<T>&>(*this).back();
177 }
178 value_type& front()
179 {
180 assert(!empty());
181 return *static_cast<value_type*>(eina_inarray_nth(_array, 0u));
182 }
183 value_type const& front() const
184 {
185 return const_cast<_pod_inarray<T>&>(*this).front();
186 }
187 iterator begin()
188 {
189 return !_array->members ? 0 : static_cast<iterator>(::eina_inarray_nth(_array, 0u));
190 }
191 iterator end()
192 {
193 return !_array->members ? 0 : static_cast<iterator>(::eina_inarray_nth(_array, size()-1)) + 1;
194 }
195 const_iterator begin() const
196 {
197 return const_cast< _pod_inarray<T>&>(*this).begin();
198 }
199 const_iterator end() const
200 {
201 return const_cast< _pod_inarray<T>&>(*this).end();
202 }
203 const_reverse_iterator rbegin() const
204 {
205 return const_reverse_iterator(begin());
206 }
207 const_reverse_iterator rend() const
208 {
209 return const_reverse_iterator(end());
210 }
211 reverse_iterator rbegin()
212 {
213 return reverse_iterator(begin());
214 }
215 reverse_iterator rend()
216 {
217 return reverse_iterator(end());
218 }
219 const_iterator cbegin() const
220 {
221 return begin();
222 }
223 const_iterator cend() const
224 {
225 return end();
226 }
227 const_reverse_iterator crbegin() const
228 {
229 return rbegin();
230 }
231 const_reverse_iterator crend() const
232 {
233 return rend();
234 }
235 void swap(_pod_inarray<T>& other)
236 {
237 std::swap(_array, other._array);
238 }
239 size_type max_size() const { return -1; }
240
241 Eina_Inarray* native_handle()
242 {
243 return this->_array;
244 }
245 Eina_Inarray const* native_handle() const
246 {
247 return this->_array;
248 }
249};
250
251template <typename T>
252class _nonpod_inarray : _inarray_common_base
253{
254 typedef _inarray_common_base _base_type;
255public:
256 typedef T value_type;
257 typedef T& reference;
258 typedef T const& const_reference;
259 typedef T* pointer;
260 typedef T const* const_pointer;
261 typedef pointer iterator;
262 typedef const_pointer const_iterator;
263 typedef std::size_t size_type;
264 typedef std::ptrdiff_t difference_type;
265
266 typedef std::reverse_iterator<iterator> reverse_iterator;
267 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
268
269 using _base_type::size;
270 using _base_type::empty;
271
272 _nonpod_inarray() : _base_type(sizeof(T))
273 {
274 }
275 _nonpod_inarray(size_type n, value_type const& t) : _base_type(sizeof(T))
276 {
277 while(n--)
278 push_back(t);
279 }
280 template <typename InputIterator>
281 _nonpod_inarray(InputIterator i, InputIterator const& j
282 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
283 : _base_type(sizeof(T))
284 {
285 while(i != j)
286 {
287 push_back(*i);
288 ++i;
289 }
290 }
291 _nonpod_inarray(_nonpod_inarray<T>const& other)
292 : _base_type(sizeof(T))
293 {
294 insert(end(), other.begin(), other.end());
295 }
296 ~_nonpod_inarray()
297 {
298 for(T* first = static_cast<T*>(_array->members)
299 , *last = first + _array->len; first != last; ++first)
300 first->~T();
301 }
302 _nonpod_inarray<T>& operator=(_nonpod_inarray<T>const& other)
303 {
304 clear();
305 insert(end(), other.begin(), other.end());
306 return *this;
307 }
308 void clear()
309 {
310 for(T* first = static_cast<T*>(_array->members)
311 , *last = first + _array->len; first != last; ++first)
312 first->~T();
313 ::eina_inarray_flush(_array);
314 }
315 void push_back(T const& value)
316 {
317 insert(end(), 1u, value);
318 }
319 void pop_back()
320 {
321 T* elem = static_cast<T*>(_array->members) + _array->len - 1;
322 elem->~T();
323 eina_inarray_pop(_array);
324 }
325 iterator insert(iterator i, value_type const& t)
326 {
327 return insert(i, 1u, t);
328 }
329 iterator insert(iterator i, size_t n, value_type const& t)
330 {
331 if(_array->max - _array->len >= n)
332 {
333 iterator end = static_cast<T*>(_array->members)
334 + _array->len
335 , last = end + n;
336 _array->len += n;
337 std::reverse_iterator<iterator>
338 dest(last), src(end), src_end(i);
339 for(;src != src_end; ++src)
340 {
341 if(dest.base() <= end)
342 *dest++ = *src;
343 else
344 new (&*dest++) T(*src);
345 }
346 iterator j = i;
347 for(size_type i = 0;i != n;++i)
348 {
349 if(j < end)
350 *j = t;
351 else
352 new (&*j++) T(t);
353 }
354 }
355 else
356 {
357 size_type index = i - static_cast<iterator>(_array->members);
358
359 Eina_Inarray* old_array = eina_inarray_new(_array->member_size, 0);
360 *old_array = *_array;
361 _array->len = _array->max = 0;
362 _array->members = 0;
363 eina_inarray_resize(_array, old_array->len+n);
364 _array->len = old_array->len+n;
365
366 iterator old_first = static_cast<iterator>(old_array->members)
367 , first = begin()
368 , last = first + _array->len;
369 i = index + begin();
370
371 while(first != i)
372 {
373 new (&*first++) T(*old_first);
374 old_first++->~T();
375 }
376 for(size_type i = 0;i != n;++i)
377 new (&*first++) T(t);
378 assert(last - first == _array->len - index - n);
379 while(first != last)
380 {
381 new (&*first++) T(*old_first);
382 old_first++->~T();
383 }
384 }
385 return i;
386 }
387 template <typename InputIterator>
388 iterator insert(iterator p, InputIterator i, InputIterator j
389 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
390 {
391 size_type n = 0;
392 while(i != j)
393 {
394 p = insert(p, *i);
395 ++p;
396 ++i;
397 ++n;
398 }
399 return p - n;
400 }
401 iterator erase(iterator q)
402 {
403 return erase(q, q+1);
404 }
405 iterator erase(iterator i, iterator j)
406 {
407 iterator last = end();
408 iterator k = i, l = j;
409 while(l != last)
410 *k++ = *l++;
411 while(k != last)
412 k++->~T();
413 _array->len -= j - i;
414
415 return i;
416 }
417 template <typename InputIterator>
418 void assign(InputIterator i, InputIterator j
419 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0);
420 void assign(size_type n, value_type const& t);
421 value_type& back()
422 {
423 assert(!empty());
424 return *static_cast<value_type*>(eina_inarray_nth(_array, size()-1u));
425 }
426 value_type const& back() const
427 {
428 return const_cast<_nonpod_inarray<T>&>(*this).back();
429 }
430 value_type& front()
431 {
432 assert(!empty());
433 return *static_cast<value_type*>(eina_inarray_nth(_array, 0u));
434 }
435 value_type const& front() const
436 {
437 return const_cast<_nonpod_inarray<T>&>(*this).front();
438 }
439 iterator begin()
440 {
441 return static_cast<iterator>(_array->members);
442 }
443 iterator end()
444 {
445 return static_cast<iterator>(_array->members) + _array->len;
446 }
447 const_iterator begin() const
448 {
449 return const_cast< _nonpod_inarray<T>&>(*this).begin();
450 }
451 const_iterator end() const
452 {
453 return const_cast< _nonpod_inarray<T>&>(*this).end();
454 }
455 const_reverse_iterator rbegin() const
456 {
457 return const_reverse_iterator(begin());
458 }
459 const_reverse_iterator rend() const
460 {
461 return const_reverse_iterator(end());
462 }
463 reverse_iterator rbegin()
464 {
465 return reverse_iterator(begin());
466 }
467 reverse_iterator rend()
468 {
469 return reverse_iterator(end());
470 }
471 const_iterator cbegin() const
472 {
473 return begin();
474 }
475 const_iterator cend() const
476 {
477 return end();
478 }
479 const_reverse_iterator crbegin() const
480 {
481 return rbegin();
482 }
483 const_reverse_iterator crend() const
484 {
485 return rend();
486 }
487 void swap(_nonpod_inarray<T>& other)
488 {
489 std::swap(_array, other._array);
490 }
491 size_type max_size() const { return -1; }
492
493 Eina_Inarray* native_handle()
494 {
495 return this->_array;
496 }
497 Eina_Inarray const* native_handle() const
498 {
499 return this->_array;
500 }
501};
502
503template <typename T>
504class inarray : public eina::if_<eina::is_pod<T>, _pod_inarray<T>
505 , _nonpod_inarray<T> >::type
506{
507 typedef typename eina::if_<eina::is_pod<T>, _pod_inarray<T>
508 , _nonpod_inarray<T> >::type _base_type;
509public:
510 inarray() : _base_type() {}
511 inarray(typename _base_type::size_type n, typename _base_type::value_type const& t)
512 : _base_type(n, t) {}
513 template <typename InputIterator>
514 inarray(InputIterator i, InputIterator const& j
515 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
516 : _base_type(i, j)
517 {}
518
519};
520
521template <typename T>
522bool operator==(inarray<T> const& lhs, inarray<T> const& rhs)
523{
524 return lhs.size() == rhs.size() &&
525 std::equal(lhs.begin(), lhs.end(), rhs.begin());
526}
527
528template <typename T>
529bool operator!=(inarray<T> const& lhs, inarray<T> const& rhs)
530{
531 return !(lhs == rhs);
532}
533
534template <typename T>
535void swap(inarray<T>& lhs, inarray<T>& rhs)
536{
537 lhs.swap(rhs);
538}
539
540
541
542} }
543
544#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 @@
1#ifndef EINA_INLIST_HH_
2#define EINA_INLIST_HH_
3
4#include <Eina.h>
5#include <eina_lists_auxiliary.hh>
6#include <eina_type_traits.hh>
7#include <eina_accessor.hh>
8
9#include <iterator>
10
11namespace efl { namespace eina {
12
13template <typename T>
14struct _inlist_node
15{
16 EINA_INLIST;
17 T object;
18};
19
20template <typename T>
21_inlist_node<T>* _get_node(Eina_Inlist* l)
22{
23 return static_cast<_inlist_node<T>*>(static_cast<void*>(l));
24}
25
26template <typename T>
27_inlist_node<T> const* _get_node(Eina_Inlist const* l)
28{
29 return const_cast<Eina_Inlist*>(l);
30}
31
32template <typename T>
33Eina_Inlist* _get_list(_inlist_node<T>* n)
34{
35 if(n)
36 return EINA_INLIST_GET(n);
37 else
38 return 0;
39}
40
41template <typename T>
42Eina_Inlist const* _get_list(_inlist_node<T> const* n)
43{
44 return _get_list(const_cast<_inlist_node<T>*>(n));
45}
46
47template <typename T>
48struct _inlist_iterator
49{
50 typedef T value_type;
51 typedef T* pointer;
52 typedef T& reference;
53 typedef std::ptrdiff_t difference_type;
54 typedef std::bidirectional_iterator_tag iterator_category;
55
56 _inlist_iterator() {}
57 explicit _inlist_iterator(_inlist_node<T>* list, _inlist_node<T>* node)
58 : _list(list), _node(node) {}
59
60 _inlist_iterator<T>& operator++()
61 {
62 _node = _get_node<T>(_node->__in_list.next);
63 return *this;
64 }
65 _inlist_iterator<T> operator++(int)
66 {
67 _inlist_iterator<T> tmp(*this);
68 ++*this;
69 return tmp;
70 }
71 _inlist_iterator<T>& operator--()
72 {
73 if(_node)
74 _node = _get_node<T>(_node->__in_list.prev);
75 else
76 _node = _get_node<T>(_list->__in_list.last);
77 return *this;
78 }
79 _inlist_iterator<T> operator--(int)
80 {
81 _inlist_iterator<T> tmp(*this);
82 --*this;
83 return tmp;
84 }
85 T const& operator*() const
86 {
87 return _node->object;
88 }
89 T const* operator->() const
90 {
91 return &_node->object;
92 }
93 _inlist_node<T>* native_handle()
94 {
95 return _node;
96 }
97 _inlist_node<T> const* native_handle() const
98 {
99 return _node;
100 }
101private:
102 _inlist_node<T>* _list;
103 _inlist_node<T>* _node;
104
105 friend bool operator==(_inlist_iterator<T> lhs, _inlist_iterator<T> rhs)
106 {
107 return lhs._node == rhs._node;
108 }
109};
110
111template <typename T>
112bool operator!=(_inlist_iterator<T> lhs, _inlist_iterator<T> rhs)
113{
114 return !(lhs == rhs);
115}
116
117template <typename T, typename Allocator>
118struct _inlist_common_base
119{
120 typedef typename Allocator::template rebind<_inlist_node<T> >::other node_allocator_type;
121 typedef Allocator allocator_type;
122 typedef _inlist_node<T> node_type;
123
124 _inlist_common_base(Allocator allocator)
125 : _impl(allocator) {}
126 _inlist_common_base()
127 {}
128 ~_inlist_common_base()
129 {
130 clear();
131 }
132
133 void clear()
134 {
135 Eina_Inlist* p = _impl._list;
136 Eina_Inlist* q;
137 while(p)
138 {
139 q = p->next;
140
141 _inlist_node<T>* node = _get_node<T>(p);
142 node->~_inlist_node<T>();
143 get_node_allocator().deallocate(node, 1);
144
145 p = q;
146 }
147 _impl._list = 0;
148 }
149 node_allocator_type& get_node_allocator()
150 {
151 return _impl;
152 }
153
154 // For EBO
155 struct _inlist_impl : node_allocator_type
156 {
157 _inlist_impl(Allocator allocator)
158 : node_allocator_type(allocator), _list(0)
159 {}
160 _inlist_impl() : _list(0) {}
161
162 Eina_Inlist* _list;
163 };
164
165 _inlist_impl _impl;
166private:
167 _inlist_common_base(_inlist_common_base const& other);
168 _inlist_common_base& operator=(_inlist_common_base const& other);
169};
170
171template <typename T, typename Allocator = std::allocator<T> >
172class inlist : protected _inlist_common_base<T, Allocator>
173{
174 typedef _inlist_common_base<T, Allocator> _base_type;
175 typedef typename _base_type::node_type _node_type;
176public:
177 typedef typename _base_type::allocator_type allocator_type;
178 typedef typename allocator_type::value_type value_type;
179 typedef typename allocator_type::reference reference;
180 typedef typename allocator_type::const_reference const_reference;
181 typedef _inlist_iterator<T const> const_iterator;
182 typedef _inlist_iterator<T> iterator;
183 typedef typename allocator_type::pointer pointer;
184 typedef typename allocator_type::const_pointer const_pointer;
185 typedef std::size_t size_type;
186 typedef std::ptrdiff_t difference_type;
187
188 typedef std::reverse_iterator<iterator> reverse_iterator;
189 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
190
191 using _base_type::clear;
192
193 inlist() {}
194 inlist(size_type n, value_type const& t)
195 {
196 while(n--)
197 push_back(t);
198 }
199 template <typename InputIterator>
200 inlist(InputIterator i, InputIterator const& j
201 , allocator_type const& alloc = allocator_type()
202 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
203 : _base_type(alloc)
204 {
205 while(i != j)
206 {
207 push_back(*i);
208 ++i;
209 }
210 }
211 inlist(inlist<T, Allocator>const& other)
212 : _base_type()
213 {
214 insert(end(), other.begin(), other.end());
215 }
216 inlist<T, Allocator>& operator=(inlist<T, Allocator>const& other)
217 {
218 clear();
219 insert(end(), other.begin(), other.end());
220 return *this;
221 }
222 size_type size() const
223 {
224 return ::eina_inlist_count(this->_impl._list);
225 }
226 bool empty() const
227 {
228 return this->_impl._list == 0;
229 }
230 allocator_type get_allocator() const
231 {
232 return allocator_type(this->get_node_allocator());
233 }
234 void push_back(T const& value)
235 {
236 _node_type* node ( this->get_node_allocator().allocate(1) );
237 try
238 {
239 new (&node->object) T(value);
240 // eina_inlist_append can't fail
241 this->_impl._list = eina_inlist_append(this->_impl._list, _get_list(node));
242 }
243 catch(...)
244 {
245 this->get_node_allocator().deallocate(node, 1);
246 throw;
247 }
248 }
249 void push_front(T const& value)
250 {
251 _node_type* node ( this->get_node_allocator().allocate(1) );
252 try
253 {
254 new (&node->object) T(value);
255 // eina_inlist_prepend can't fail
256 this->_impl._list = eina_inlist_prepend(this->_impl._list, _get_list(node));
257 }
258 catch(...)
259 {
260 this->get_node_allocator().deallocate(node, 1);
261 throw;
262 }
263 }
264 void pop_back()
265 {
266 this->_impl._list = eina_inlist_remove(this->_impl._list, this->_impl._list->last);
267 }
268 void pop_front()
269 {
270 this->_impl._list = eina_inlist_remove(this->_impl._list, this->_impl._list);
271 }
272 iterator insert(iterator i, value_type const& t)
273 {
274 _node_type* node ( this->get_node_allocator().allocate(1) );
275 try
276 {
277 new (&node->object) T(t);
278 // eina_inlist_prepend_relative can't fail
279 this->_impl._list = _eina_inlist_prepend_relative
280 (this->_impl._list, _get_list(node)
281 , _get_list(i.native_handle()));
282 return iterator(_get_node<T>(this->_impl._list), node);
283 }
284 catch(...)
285 {
286 this->get_node_allocator().deallocate(node, 1);
287 throw;
288 }
289 }
290 iterator insert(iterator i, size_t n, value_type const& t)
291 {
292 iterator r = i;
293 if(n--)
294 r = insert(i, t);
295 while(n--)
296 insert(i, t);
297 return r;
298 }
299
300 template <typename InputIterator>
301 iterator insert(iterator p, InputIterator i, InputIterator j
302 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
303 {
304 iterator r = p;
305 if(i != j)
306 {
307 value_type v = *i;
308 r = insert(p, v);
309 ++i;
310 }
311 while(i != j)
312 {
313 insert(p, *i);
314 ++i;
315 }
316 return r;
317 }
318
319 iterator erase(iterator q)
320 {
321 if(q.native_handle())
322 {
323 iterator r(_get_node<T>(this->_impl._list), _get_node<T>(_get_list(q.native_handle())->next));
324 this->_impl._list = eina_inlist_remove(this->_impl._list, _get_list(q.native_handle()));
325 return r;
326 }
327 else
328 return q;
329 }
330
331 iterator erase(iterator i, iterator j)
332 {
333 while(i != j)
334 i = erase(i);
335 if(j.native_handle())
336 return j;
337 else
338 return end();
339 }
340
341 template <typename InputIterator>
342 void assign(InputIterator i, InputIterator j
343 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
344 {
345 clear();
346 insert(end(), i, j);
347 }
348
349 void assign(size_type n, value_type const& t)
350 {
351 clear();
352 insert(end(), n, t);
353 }
354
355 value_type& back()
356 {
357 return _get_node<T>(this->_impl._list->last)->object;
358 }
359 value_type const& back() const
360 {
361 return const_cast<inlist<T, Allocator>&>(*this).back();
362 }
363 value_type& front()
364 {
365 return _get_node<T>(this->_impl._list)->object;
366 }
367 value_type const& front() const
368 {
369 return const_cast<inlist<T, Allocator>&>(*this).front();
370 }
371 const_iterator begin() const
372 {
373 return const_iterator(_get_node<T const>(this->_impl._list), _get_node<T const>(this->_impl._list));
374 }
375 const_iterator end() const
376 {
377 return const_iterator(_get_node<T const>(this->_impl._list), 0);
378 }
379 iterator begin()
380 {
381 return iterator(_get_node<T>(this->_impl._list), _get_node<T>(this->_impl._list));
382 }
383 iterator end()
384 {
385 return iterator(_get_node<T>(this->_impl._list), 0);
386 }
387 const_reverse_iterator rbegin() const
388 {
389 return const_reverse_iterator(begin());
390 }
391 const_reverse_iterator rend() const
392 {
393 return const_reverse_iterator(end());
394 }
395 reverse_iterator rbegin()
396 {
397 return reverse_iterator(begin());
398 }
399 reverse_iterator rend()
400 {
401 return reverse_iterator(end());
402 }
403 const_iterator cbegin() const
404 {
405 return begin();
406 }
407 const_iterator cend() const
408 {
409 return end();
410 }
411 const_reverse_iterator crbegin() const
412 {
413 return rbegin();
414 }
415 const_reverse_iterator crend() const
416 {
417 return rend();
418 }
419 void swap(inlist<T, Allocator>& other)
420 {
421 std::swap(this->_impl._list, other._impl._list);
422 }
423 size_type max_size() const { return -1; }
424
425 Eina_Inlist* native_handle()
426 {
427 return this->_impl._list;
428 }
429 Eina_Inlist const* native_handle() const
430 {
431 return this->_impl._list;
432 }
433 eina::accessor<T const> accessor() const
434 {
435 return eina::accessor<T const>(eina_inlist_accessor_new(this->_impl._list));
436 }
437 eina::accessor<T> accessor()
438 {
439 return eina::accessor<T>(eina_inlist_accessor_new(this->_impl._list));
440 }
441};
442
443template <typename T, typename Allocator1, typename Allocator2>
444bool operator==(inlist<T, Allocator1> const& lhs, inlist<T, Allocator2> const& rhs)
445{
446 return lhs.size() == rhs.size() &&
447 std::equal(lhs.begin(), lhs.end(), rhs.begin());
448}
449
450template <typename T, typename Allocator1, typename Allocator2>
451bool operator!=(inlist<T, Allocator1> const& lhs, inlist<T, Allocator2> const& rhs)
452{
453 return !(lhs == rhs);
454}
455
456template <typename T, typename Allocator>
457void swap(inlist<T, Allocator>& lhs, inlist<T, Allocator>& rhs)
458{
459 lhs.swap(rhs);
460}
461
462} }
463
464#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 @@
1#ifndef EINA_ITERATOR_HH_
2#define EINA_ITERATOR_HH_
3
4#include <Eina.h>
5
6#include <cstdlib>
7#include <iterator>
8
9namespace efl { namespace eina {
10
11template <typename T>
12struct _common_iterator_base
13{
14private:
15 typedef _common_iterator_base<T> self_type;
16public:
17 typedef T const value_type;
18 typedef value_type* pointer;
19 typedef value_type& reference;
20 typedef std::ptrdiff_t difference_type;
21 typedef std::input_iterator_tag iterator_category;
22
23 _common_iterator_base() {}
24 explicit _common_iterator_base(Eina_Iterator* iterator)
25 : _iterator(iterator) {}
26 ~_common_iterator_base()
27 {
28 if(_iterator)
29 eina_iterator_free(_iterator);
30 }
31 _common_iterator_base(self_type const& other)
32 : _iterator(other._iterator)
33 {
34 other._iterator = 0;
35 }
36 _common_iterator_base& operator=(self_type const& other)
37 {
38 _iterator = other._iterator;
39 other._iterator = 0;
40 return *this;
41 }
42
43protected:
44 mutable Eina_Iterator* _iterator;
45
46 friend inline bool operator==(_common_iterator_base<T> const& lhs, _common_iterator_base<T> const& rhs)
47 {
48 return lhs._iterator == rhs._iterator;
49 }
50 friend inline bool operator!=(_common_iterator_base<T> const& lhs, _common_iterator_base<T> const& rhs)
51 {
52 return !(lhs == rhs);
53 }
54};
55
56template <typename T>
57struct iterator : _common_iterator_base<T const>
58{
59private:
60 typedef _common_iterator_base<T const> base_type;
61 typename base_type::pointer _value;
62 typedef iterator<T> self_type;
63public:
64 typedef typename base_type::value_type value_type;
65 typedef typename base_type::pointer pointer;
66 typedef typename base_type::reference reference;
67 typedef typename base_type::difference_type difference_type;
68 typedef typename base_type::iterator_category iterator_category;
69
70 explicit iterator(Eina_Iterator* iterator = 0)
71 : base_type(iterator)
72 {
73 if(this->_iterator)
74 ++*this;
75 }
76 self_type& operator++()
77 {
78 void* data;
79 Eina_Bool r = ::eina_iterator_next(this->_iterator, &data);
80 if(!r)
81 this->_iterator = 0;
82 _value = static_cast<pointer>(data);
83 return *this;
84 }
85 self_type& operator++(int)
86 {
87 return ++**this;
88 }
89 value_type& operator*() const
90 {
91 return *_value;
92 }
93 pointer operator->() const
94 {
95 return _value;
96 }
97};
98
99} }
100
101#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 @@
1#ifndef _EINA_LISTS_AUXILIARY_HH
2#define _EINA_LISTS_AUXILIARY_HH
3
4#include <Eina.h>
5
6namespace efl { namespace eina {
7
8inline Eina_List* _eina_list_prepend_relative_list(Eina_List* list, const void* data, Eina_List* relative) EINA_ARG_NONNULL(2)
9{
10 if(relative)
11 return ::eina_list_prepend_relative_list(list, data, relative);
12 else
13 return ::eina_list_append(list, data);
14}
15
16inline Eina_Inlist *_eina_inlist_prepend_relative(Eina_Inlist *in_list,
17 Eina_Inlist *in_item,
18 Eina_Inlist *in_relative) EINA_ARG_NONNULL(2)
19{
20 if(in_relative)
21 return ::eina_inlist_prepend_relative(in_list, in_item, in_relative);
22 else
23 return ::eina_inlist_append(in_list, in_item);
24}
25
26} }
27
28#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 @@
1#ifndef EINA_PTRARRAY_HH_
2#define EINA_PTRARRAY_HH_
3
4#include <Eina.h>
5#include <eina_clone_allocators.hh>
6#include <eina_lists_auxiliary.hh>
7#include <eina_type_traits.hh>
8
9#include <memory>
10#include <iterator>
11#include <cstdlib>
12#include <cassert>
13
14namespace efl { namespace eina {
15
16struct _ptr_array_iterator_base
17{
18 _ptr_array_iterator_base() : _ptr(0) {}
19 _ptr_array_iterator_base(void** ptr)
20 : _ptr(ptr)
21 {}
22
23 void** _ptr;
24};
25
26template <typename T>
27struct _ptr_array_iterator : protected _ptr_array_iterator_base
28{
29 typedef T value_type;
30 typedef value_type* pointer;
31 typedef value_type& reference;
32 typedef std::ptrdiff_t difference_type;
33 typedef std::bidirectional_iterator_tag iterator_category;
34
35 _ptr_array_iterator() {}
36 explicit _ptr_array_iterator(void** ptr)
37 : _ptr_array_iterator_base(ptr)
38
39 {
40 }
41 _ptr_array_iterator(_ptr_array_iterator<typename remove_cv<value_type>::type> const& other)
42 : _ptr_array_iterator_base(static_cast<_ptr_array_iterator_base const&>(other))
43 {
44 }
45
46 _ptr_array_iterator<T>& operator++()
47 {
48 ++_ptr;
49 return *this;
50 }
51 _ptr_array_iterator<T> operator++(int)
52 {
53 _ptr_array_iterator<T> tmp(*this);
54 ++*this;
55 return tmp;
56 }
57 _ptr_array_iterator<T>& operator--()
58 {
59 --_ptr;
60 return *this;
61 }
62 _ptr_array_iterator<T> operator--(int)
63 {
64 _ptr_array_iterator<T> tmp(*this);
65 --*this;
66 return tmp;
67 }
68 reference operator*() const
69 {
70 return *static_cast<pointer>(*_ptr);
71 }
72 pointer operator->() const
73 {
74 return &**this;
75 }
76 void** native_handle() const
77 {
78 return _ptr;
79 }
80 friend inline bool operator==(_ptr_array_iterator<T> lhs, _ptr_array_iterator<T> rhs)
81 {
82 return lhs._ptr == rhs._ptr;
83 }
84 friend inline bool operator!=(_ptr_array_iterator<T> lhs, _ptr_array_iterator<T> rhs)
85 {
86 return !(lhs == rhs);
87 }
88 friend inline _ptr_array_iterator<T> operator+(_ptr_array_iterator<T> lhs
89 , difference_type size)
90 {
91 lhs._ptr += size;
92 return lhs;
93 }
94 friend inline _ptr_array_iterator<T> operator-(_ptr_array_iterator<T> lhs
95 , difference_type size)
96 {
97 lhs._ptr -= size;
98 return lhs;
99 }
100 friend inline difference_type operator-(_ptr_array_iterator<T> lhs
101 , _ptr_array_iterator<T> rhs)
102 {
103 return lhs._ptr - rhs._ptr;
104 }
105};
106
107template <typename T, typename CloneAllocator>
108struct _ptr_array_common_base
109{
110 typedef CloneAllocator clone_allocator_type;
111
112 _ptr_array_common_base(CloneAllocator clone_allocator)
113 : _impl(clone_allocator)
114 {}
115 _ptr_array_common_base(Eina_Array* _array)
116 : _impl(_array)
117 {}
118 _ptr_array_common_base() {}
119
120 CloneAllocator& _get_clone_allocator()
121 {
122 return _impl;
123 }
124 CloneAllocator const& _get_clone_allocator() const
125 {
126 return _impl;
127 }
128 void _delete_clone(T const* p)
129 {
130 _get_clone_allocator().deallocate_clone(p);
131 }
132 T* _new_clone(T const& a)
133 {
134 return _get_clone_allocator().allocate_clone(a);
135 }
136
137 struct _ptr_array_impl : CloneAllocator
138 {
139 _ptr_array_impl() : _array( ::eina_array_new(32u) ) {}
140 _ptr_array_impl(CloneAllocator allocator)
141 : clone_allocator_type(allocator), _array( ::eina_array_new(32u)) {}
142
143 Eina_Array* _array;
144 };
145
146 _ptr_array_impl _impl;
147
148private:
149 _ptr_array_common_base(_ptr_array_common_base const& other);
150 _ptr_array_common_base& operator=(_ptr_array_common_base const& other);
151};
152
153template <typename T, typename CloneAllocator = heap_no_copy_allocator>
154class ptr_array : protected _ptr_array_common_base<T, CloneAllocator>
155{
156 typedef _ptr_array_common_base<T, CloneAllocator> _base_type;
157public:
158 typedef T value_type;
159 typedef T& reference;
160 typedef T const& const_reference;
161 typedef _ptr_array_iterator<T const> const_iterator;
162 typedef _ptr_array_iterator<T> iterator;
163 typedef T* pointer;
164 typedef T const* const_pointer;
165 typedef std::size_t size_type;
166 typedef std::ptrdiff_t difference_type;
167 typedef CloneAllocator clone_allocator_type;
168
169 typedef std::reverse_iterator<iterator> reverse_iterator;
170 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
171
172 ptr_array() {}
173 ptr_array(size_type n, const_reference t)
174 {
175 while(n--)
176 push_back(t);
177 }
178 template <typename InputIterator>
179 ptr_array(InputIterator i, InputIterator const& j
180 , clone_allocator_type const& alloc = clone_allocator_type()
181 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
182 : _base_type(alloc)
183 {
184 while(i != j)
185 {
186 push_back(*i);
187 ++i;
188 }
189 }
190 ptr_array(ptr_array<T, CloneAllocator> const& other)
191 : _base_type()
192 {
193 insert(end(), other.begin(), other.end());
194 }
195 template <typename CloneAllocator1>
196 ptr_array(ptr_array<T, CloneAllocator1>const& other)
197 : _base_type()
198 {
199 insert(end(), other.begin(), other.end());
200 }
201 ~ptr_array()
202 {
203 clear();
204 }
205 ptr_array<T, CloneAllocator>& operator=(ptr_array<T, CloneAllocator>const& other)
206 {
207 clear();
208 insert(end(), other.begin(), other.end());
209 return *this;
210 }
211
212 void clear()
213 {
214 for(iterator first = begin(), last = end(); first != last; ++first)
215 this->_delete_clone(&*first);
216 eina_array_flush(this->_impl._array);
217 }
218 std::size_t size() const
219 {
220 return eina_array_count(this->_impl._array);
221 }
222 bool empty() const
223 {
224 return size() == 0u;
225 }
226 clone_allocator_type get_clone_allocator() const
227 {
228 return clone_allocator_type(this->_get_clone_allocator());
229 }
230 void push_back(const_reference a)
231 {
232 push_back(this->_new_clone(a));
233 }
234 void push_back(pointer p)
235 {
236 std::auto_ptr<value_type> p1(p);
237 push_back(p1);
238 }
239 void push_back(std::auto_ptr<T>& p)
240 {
241 if(eina_array_push(this->_impl._array, p.get()))
242 p.release();
243 else
244 throw std::bad_alloc();
245 }
246 void pop_back()
247 {
248 eina_array_pop(this->_impl._array);
249 }
250 iterator insert(iterator i, value_type const& t)
251 {
252 return insert(i, this->_new_clone(t));
253 }
254 iterator insert(iterator i, pointer pv)
255 {
256 std::auto_ptr<value_type> p(pv);
257 return insert(i, p);
258 }
259 iterator insert(iterator i, std::auto_ptr<value_type>& p)
260 {
261 std::size_t j
262 = i.native_handle() - this->_impl._array->data
263 , size = this->size();
264 if(eina_array_push(this->_impl._array, p.get()))
265 {
266 if(size - j)
267 {
268 memmove(
269 this->_impl._array->data + j + 1
270 , this->_impl._array->data + j
271 , (size - j)*sizeof(void*));
272 // PRE: Q:[j, size) = [j+1, size+1)
273 pointer* data = static_cast<pointer*>
274 (static_cast<void*>(this->_impl._array->data));
275 data[j] = p.get();
276 }
277 p.release();
278 return iterator(this->_impl._array->data + j);
279 }
280 else
281 throw std::bad_alloc();
282 }
283 iterator insert(iterator i, size_t n, value_type const& t)
284 {
285 iterator r = i;
286 if(n--)
287 r = insert(i, t);
288 while(n--)
289 insert(i, t);
290 return r;
291 }
292 iterator insert(iterator i, size_t n, pointer p)
293 {
294 iterator r = i;
295 if(n--)
296 r = insert(i, p);
297 while(n--)
298 insert(i, this->_new_clone(p));
299 return r;
300 }
301 template <typename InputIterator>
302 iterator insert(iterator p, InputIterator i, InputIterator j
303 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
304 {
305 size_type index = p.native_handle() - this->_impl._array->data;
306 while(i != j)
307 {
308 p = insert(p, this->_new_clone(*i));
309 ++p;
310 ++i;
311 }
312 return iterator(this->_impl._array->data + index);
313 }
314 iterator erase(iterator q)
315 {
316 size_type size = this->size()
317 , i = q.native_handle() - this->_impl._array->data;
318 memmove(q.native_handle()
319 , q.native_handle() + 1
320 , (size - i - 1)*sizeof(void*));
321 eina_array_pop(this->_impl._array);
322 return q;
323 }
324 iterator erase(iterator i, iterator j)
325 {
326 size_type size = this->size()
327 , distance = std::distance(i, j);
328 memmove(i.native_handle()
329 , j.native_handle()
330 , (size - distance)*sizeof(void*));
331 while(distance--)
332 eina_array_pop(this->_impl._array);
333 return i;
334 }
335 template <typename InputIterator>
336 void assign(InputIterator i, InputIterator j
337 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
338 {
339 clear();
340 insert(end(), i, j);
341 }
342 void assign(size_type n, value_type const& t)
343 {
344 clear();
345 insert(end(), n, t);
346 }
347
348 value_type& back()
349 {
350 return *static_cast<pointer>(this->_impl._array->data[size()-1]);
351 }
352 value_type const& back() const
353 {
354 return const_cast<ptr_array<T, CloneAllocator>&>(*this).back();
355 }
356 value_type& front()
357 {
358 return *static_cast<pointer>(this->_impl._array->data[0]);
359 }
360 value_type const& front() const
361 {
362 return const_cast<ptr_array<T, CloneAllocator>&>(*this).front();
363 }
364
365 const_reference operator[](size_type index) const
366 {
367 pointer data = static_cast<pointer>
368 (this->_impl._array->data[index]);
369 return *data;
370 }
371 reference operator[](size_type index)
372 {
373 return const_cast<reference>
374 (const_cast<ptr_array<T, CloneAllocator>const&>(*this)[index]);
375 }
376
377 const_iterator begin() const
378 {
379 return const_iterator(this->_impl._array->data);
380 }
381 const_iterator end() const
382 {
383 return const_iterator(this->_impl._array->data + size());
384 }
385 iterator begin()
386 {
387 return iterator(this->_impl._array->data);
388 }
389 iterator end()
390 {
391 return iterator(this->_impl._array->data + size());
392 }
393 const_reverse_iterator rbegin() const
394 {
395 return const_reverse_iterator(begin());
396 }
397 const_reverse_iterator rend() const
398 {
399 return const_reverse_iterator(end());
400 }
401 reverse_iterator rbegin()
402 {
403 return reverse_iterator(begin());
404 }
405 reverse_iterator rend()
406 {
407 return reverse_iterator(end());
408 }
409 const_iterator cbegin() const
410 {
411 return begin();
412 }
413 const_iterator cend() const
414 {
415 return end();
416 }
417 const_reverse_iterator crbegin() const
418 {
419 return rbegin();
420 }
421 const_reverse_iterator crend() const
422 {
423 return rend();
424 }
425 eina::iterator<T> ibegin()
426 {
427 return eina::iterator<T>( ::eina_array_iterator_new(this->_impl._array) );
428 }
429 eina::iterator<T> iend()
430 {
431 return eina::iterator<T>();
432 }
433 eina::iterator<T const> ibegin() const
434 {
435 return eina::iterator<T const>( ::eina_array_iterator_new(this->_impl._array) );
436 }
437 eina::iterator<T const> iend() const
438 {
439 return eina::iterator<T const>();
440 }
441 eina::iterator<T const> cibegin() const
442 {
443 return ibegin();
444 }
445 eina::iterator<T const> ciend() const
446 {
447 return iend();
448 }
449 void swap(ptr_array<T, CloneAllocator>& other)
450 {
451 std::swap(this->_impl._array, other._impl._array);
452 }
453 size_type max_size() const { return -1; }
454
455 Eina_Array* native_handle()
456 {
457 return this->_impl._array;
458 }
459 Eina_Array const* native_handle() const
460 {
461 return this->_impl._array;
462 }
463};
464
465template <typename T, typename CloneAllocator1, typename CloneAllocator2>
466bool operator==(ptr_array<T, CloneAllocator1> const& lhs, ptr_array<T, CloneAllocator2> const& rhs)
467{
468 return lhs.size() == rhs.size()
469 && std::equal(lhs.begin(), lhs.end(), rhs.begin());
470}
471
472template <typename T, typename CloneAllocator1, typename CloneAllocator2>
473bool operator!=(ptr_array<T, CloneAllocator1> const& lhs, ptr_array<T, CloneAllocator2> const& rhs)
474{
475 return !(lhs == rhs);
476}
477
478template <typename T, typename CloneAllocator>
479void swap(ptr_array<T, CloneAllocator>& lhs, ptr_array<T, CloneAllocator>& rhs)
480{
481 lhs.swap(rhs);
482}
483
484} }
485
486#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 @@
1#ifndef EINA_LIST_HH_
2#define EINA_LIST_HH_
3
4#include <Eina.h>
5#include <eina_clone_allocators.hh>
6#include <eina_lists_auxiliary.hh>
7#include <eina_type_traits.hh>
8#include <eina_accessor.hh>
9
10#include <memory>
11#include <iterator>
12
13namespace efl { namespace eina {
14
15struct _ptr_list_iterator_base
16{
17 typedef std::ptrdiff_t difference_type;
18 typedef std::bidirectional_iterator_tag iterator_category;
19
20 _ptr_list_iterator_base() : _list(0) {}
21 _ptr_list_iterator_base(Eina_List* list, Eina_List* node)
22 : _list(list), _node(node)
23 {}
24
25protected:
26 Eina_List *_list, *_node;
27};
28
29template <typename T>
30struct _ptr_list_iterator : _ptr_list_iterator_base
31{
32 typedef T value_type;
33 typedef value_type* pointer;
34 typedef value_type& reference;
35
36 _ptr_list_iterator() {}
37 explicit _ptr_list_iterator(Eina_List* list, Eina_List* node)
38 : _ptr_list_iterator_base(list, node)
39 {
40 }
41 _ptr_list_iterator(_ptr_list_iterator<typename remove_cv<value_type>::type> const& other)
42 : _ptr_list_iterator_base(static_cast<_ptr_list_iterator_base const&>(other))
43 {
44 }
45
46 _ptr_list_iterator<T>& operator++()
47 {
48 _node = eina_list_next(_node);
49 return *this;
50 }
51 _ptr_list_iterator<T> operator++(int)
52 {
53 _ptr_list_iterator<T> tmp(*this);
54 ++*this;
55 return tmp;
56 }
57 _ptr_list_iterator<T>& operator--()
58 {
59 if(_node)
60 _node = eina_list_prev(_node);
61 else
62 _node = eina_list_last(_list);
63 return *this;
64 }
65 _ptr_list_iterator<T> operator--(int)
66 {
67 _ptr_list_iterator<T> tmp(*this);
68 --*this;
69 return tmp;
70 }
71 reference operator*() const
72 {
73 void* data = eina_list_data_get(_node);
74 return *static_cast<pointer>(data);
75 }
76 pointer operator->() const
77 {
78 return &**this;
79 }
80 Eina_List* native_handle()
81 {
82 return _node;
83 }
84 Eina_List const* native_handle() const
85 {
86 return _node;
87 }
88 friend inline bool operator==(_ptr_list_iterator<T> lhs, _ptr_list_iterator<T> rhs)
89 {
90 return lhs._node == rhs._node;
91 }
92 friend inline bool operator!=(_ptr_list_iterator<T> lhs, _ptr_list_iterator<T> rhs)
93 {
94 return !(lhs == rhs);
95 }
96};
97
98template <typename T, typename CloneAllocator>
99struct _ptr_list_common_base
100{
101 typedef CloneAllocator clone_allocator_type;
102
103 _ptr_list_common_base(CloneAllocator clone_allocator)
104 : _impl(clone_allocator)
105 {}
106 _ptr_list_common_base(Eina_List* _list)
107 : _impl(_list)
108 {}
109 _ptr_list_common_base() {}
110
111 CloneAllocator& _get_clone_allocator()
112 {
113 return _impl;
114 }
115 CloneAllocator const& _get_clone_allocator() const
116 {
117 return _impl;
118 }
119 void _delete_clone(T const* p)
120 {
121 _get_clone_allocator().deallocate_clone(p);
122 }
123 T* _new_clone(T const& a)
124 {
125 return _get_clone_allocator().allocate_clone(a);
126 }
127
128 struct _ptr_list_impl : CloneAllocator
129 {
130 _ptr_list_impl() : _list(0) {}
131 _ptr_list_impl(CloneAllocator allocator)
132 : clone_allocator_type(allocator), _list(0) {}
133
134 Eina_List* _list;
135 };
136
137 _ptr_list_impl _impl;
138
139private:
140 _ptr_list_common_base(_ptr_list_common_base const& other);
141 _ptr_list_common_base& operator=(_ptr_list_common_base const& other);
142};
143
144template <typename T, typename CloneAllocator = heap_no_copy_allocator>
145class ptr_list : protected _ptr_list_common_base<T, CloneAllocator>
146{
147 typedef _ptr_list_common_base<T, CloneAllocator> _base_type;
148public:
149 typedef T value_type;
150 typedef T& reference;
151 typedef T const& const_reference;
152 typedef _ptr_list_iterator<T const> const_iterator;
153 typedef _ptr_list_iterator<T> iterator;
154 typedef T* pointer;
155 typedef T const* const_pointer;
156 typedef std::size_t size_type;
157 typedef std::ptrdiff_t difference_type;
158 typedef CloneAllocator clone_allocator_type;
159
160 typedef std::reverse_iterator<iterator> reverse_iterator;
161 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
162
163 ptr_list() {}
164 ptr_list(size_type n, const_reference t)
165 {
166 while(n--)
167 push_back(t);
168 }
169 template <typename InputIterator>
170 ptr_list(InputIterator i, InputIterator const& j
171 , clone_allocator_type const& alloc = clone_allocator_type()
172 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
173 : _base_type(alloc)
174 {
175 while(i != j)
176 {
177 push_back(*i);
178 ++i;
179 }
180 }
181 ptr_list(ptr_list<T, CloneAllocator> const& other)
182 : _base_type()
183 {
184 insert(end(), other.begin(), other.end());
185 }
186 template <typename CloneAllocator1>
187 ptr_list(ptr_list<T, CloneAllocator1>const& other)
188 : _base_type()
189 {
190 insert(end(), other.begin(), other.end());
191 }
192 ~ptr_list()
193 {
194 clear();
195 }
196 ptr_list<T, CloneAllocator>& operator=(ptr_list<T, CloneAllocator>const& other)
197 {
198 clear();
199 insert(end(), other.begin(), other.end());
200 return *this;
201 }
202
203 void clear()
204 {
205 for(iterator first = begin(), last = end(); first != last; ++first)
206 this->_delete_clone(&*first);
207 eina_list_free(this->_impl._list);
208 this->_impl._list = 0;
209 }
210 std::size_t size() const
211 {
212 return eina_list_count(this->_impl._list);
213 }
214 bool empty() const
215 {
216 return size() == 0u;
217 }
218 clone_allocator_type get_clone_allocator() const
219 {
220 return clone_allocator_type(this->_get_clone_allocator());
221 }
222 void push_back(const_reference a)
223 {
224 push_back(this->_new_clone(a));
225 }
226 void push_back(pointer p)
227 {
228 std::auto_ptr<value_type> p1(p);
229 push_back(p1);
230 }
231 void push_back(std::auto_ptr<T>& p)
232 {
233 Eina_List* new_list = eina_list_append(this->_impl._list, p.get());
234 if(new_list)
235 {
236 this->_impl._list = new_list;
237 p.release();
238 }
239 else
240 throw std::bad_alloc();
241 }
242 void push_front(const_reference a)
243 {
244 push_front(this->new_clone(a));
245 }
246 void push_front(pointer p)
247 {
248 std::auto_ptr<value_type> p1(p);
249 push_front(p1);
250 }
251 void push_front(std::auto_ptr<T>& p)
252 {
253 Eina_List* new_list = eina_list_prepend(this->_impl._list, p.get());
254 if(new_list)
255 {
256 this->_impl._list = new_list;
257 p.release();
258 }
259 else
260 throw std::bad_alloc();
261 }
262 void pop_back()
263 {
264 this->_impl._list = eina_list_remove_list(this->_impl._list, eina_list_last(this->_impl._list));
265 }
266 void pop_front()
267 {
268 this->_impl._list = eina_list_remove_list(this->_impl._list, this->_impl._list);
269 }
270 iterator insert(iterator i, value_type const& t)
271 {
272 return insert(i, this->_new_clone(t));
273 }
274 iterator insert(iterator i, pointer pv)
275 {
276 std::auto_ptr<value_type> p(pv);
277 return insert(i, p);
278 }
279 iterator insert(iterator i, std::auto_ptr<value_type>& p)
280 {
281 this->_impl._list = _eina_list_prepend_relative_list
282 (this->_impl._list, p.get(), i.native_handle());
283 if(this->_impl._list)
284 p.release();
285 else
286 throw std::bad_alloc();
287 return iterator(this->_impl._list
288 , i.native_handle()
289 ? ::eina_list_prev(i.native_handle())
290 : ::eina_list_last(this->_impl._list)
291 );
292 }
293 iterator insert(iterator i, size_t n, value_type const& t)
294 {
295 iterator r = i;
296 if(n--)
297 r = insert(i, t);
298 while(n--)
299 insert(i, t);
300 return r;
301 }
302 iterator insert(iterator i, size_t n, pointer p)
303 {
304 iterator r = i;
305 if(n--)
306 r = insert(i, p);
307 while(n--)
308 insert(i, this->_new_clone(p));
309 return r;
310 }
311 template <typename InputIterator>
312 iterator insert(iterator p, InputIterator i, InputIterator j
313 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
314 {
315 iterator r = p;
316 if(i != j)
317 {
318 r = insert(p, *i);
319 ++i;
320 }
321 while(i != j)
322 {
323 insert(p, this->_new_clone(*i));
324 ++i;
325 }
326 return r;
327 }
328 iterator erase(iterator q)
329 {
330 if(q.native_handle())
331 {
332 iterator r(this->_impl._list, eina_list_next(q.native_handle()));
333 this->_impl._list = eina_list_remove_list(this->_impl._list, q.native_handle());
334 return r;
335 }
336 else
337 return q;
338 }
339 iterator erase(iterator i, iterator j)
340 {
341 while(i != j)
342 i = erase(i);
343 if(j.native_handle())
344 return j;
345 else
346 return end();
347 }
348 template <typename InputIterator>
349 void assign(InputIterator i, InputIterator j
350 , typename eina::enable_if<!eina::is_integral<InputIterator>::value>::type* = 0)
351 {
352 clear();
353 insert(end(), i, j);
354 }
355 void assign(size_type n, value_type const& t)
356 {
357 clear();
358 insert(end(), n, t);
359 }
360
361 value_type& back()
362 {
363 return *static_cast<pointer>(eina_list_data_get(eina_list_last(this->_impl._list)));
364 }
365 value_type const& back() const
366 {
367 return const_cast<ptr_list<T, CloneAllocator>&>(*this).back();
368 }
369 value_type& front()
370 {
371 return *static_cast<pointer>(eina_list_data_get(this->_impl._list));
372 }
373 value_type const& front() const
374 {
375 return const_cast<ptr_list<T, CloneAllocator>&>(*this).front();
376 }
377
378 const_iterator begin() const
379 {
380 return const_iterator(this->_impl._list, this->_impl._list);
381 }
382 const_iterator end() const
383 {
384 return const_iterator(this->_impl._list, 0);
385 }
386 iterator begin()
387 {
388 return iterator(this->_impl._list, this->_impl._list);
389 }
390 iterator end()
391 {
392 return iterator(this->_impl._list, 0);
393 }
394 const_reverse_iterator rbegin() const
395 {
396 return const_reverse_iterator(begin());
397 }
398 const_reverse_iterator rend() const
399 {
400 return const_reverse_iterator(end());
401 }
402 reverse_iterator rbegin()
403 {
404 return reverse_iterator(begin());
405 }
406 reverse_iterator rend()
407 {
408 return reverse_iterator(end());
409 }
410 const_iterator cbegin() const
411 {
412 return begin();
413 }
414 const_iterator cend() const
415 {
416 return end();
417 }
418 const_reverse_iterator crbegin() const
419 {
420 return rbegin();
421 }
422 const_reverse_iterator crend() const
423 {
424 return rend();
425 }
426 eina::iterator<T> ibegin()
427 {
428 return eina::iterator<T>( ::eina_list_iterator_new(this->_impl._list) );
429 }
430 eina::iterator<T> iend()
431 {
432 return eina::iterator<T>();
433 }
434 eina::iterator<T const> ibegin() const
435 {
436 return eina::iterator<T const>( ::eina_list_iterator_new(this->_impl._list) );
437 }
438 eina::iterator<T const> iend() const
439 {
440 return eina::iterator<T const>();
441 }
442 eina::iterator<T const> cibegin() const
443 {
444 return ibegin();
445 }
446 eina::iterator<T const> ciend() const
447 {
448 return iend();
449 }
450 void swap(ptr_list<T, CloneAllocator>& other)
451 {
452 std::swap(this->_impl._list, other._impl._list);
453 }
454 size_type max_size() const { return -1; }
455
456 Eina_List* native_handle()
457 {
458 return this->_impl._list;
459 }
460 Eina_List const* native_handle() const
461 {
462 return this->_impl._list;
463 }
464 eina::accessor<T const> accessor() const
465 {
466 return eina::accessor<T const>(eina_list_accessor_new(this->_impl._list));
467 }
468 eina::accessor<T> accessor()
469 {
470 return eina::accessor<T>(eina_list_accessor_new(this->_impl._list));
471 }
472};
473
474template <typename T, typename CloneAllocator1, typename CloneAllocator2>
475bool operator==(ptr_list<T, CloneAllocator1> const& lhs, ptr_list<T, CloneAllocator2> const& rhs)
476{
477 return lhs.size() == rhs.size()
478 && std::equal(lhs.begin(), lhs.end(), rhs.begin());
479}
480
481template <typename T, typename CloneAllocator1, typename CloneAllocator2>
482bool operator!=(ptr_list<T, CloneAllocator1> const& lhs, ptr_list<T, CloneAllocator2> const& rhs)
483{
484 return !(lhs == rhs);
485}
486
487template <typename T, typename CloneAllocator>
488void swap(ptr_list<T, CloneAllocator>& lhs, ptr_list<T, CloneAllocator>& rhs)
489{
490 lhs.swap(rhs);
491}
492
493} }
494
495#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 @@
1#ifndef EINA_REF_HH
2#define EINA_REF_HH
3
4#include <functional>
5
6namespace efl { namespace eina {
7
8using std::ref;
9using std::cref;
10using std::reference_wrapper;
11
12template <typename T>
13T& unref(T& t)
14{
15 return t;
16}
17
18template <typename T>
19T& unref(reference_wrapper<T> t)
20{
21 return t.get();
22}
23
24}}
25
26#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 @@
1#ifndef _EINA_STRINGSHARE_HH
2#define _EINA_STRINGSHARE_HH
3
4#include <Eina.h>
5#include <eina_type_traits.hh>
6
7#include <cstring>
8#include <stdexcept>
9
10namespace efl { namespace eina {
11
12struct steal_stringshare_ref_t {};
13steal_stringshare_ref_t const steal_stringshare_ref = {};
14
15struct stringshare
16{
17 typedef char value_type;
18 typedef value_type& reference;
19 typedef value_type const& const_reference;
20 typedef value_type* pointer;
21 typedef value_type const* const_pointer;
22 typedef const_pointer const_iterator;
23 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
24 typedef std::ptrdiff_t difference_type;
25 typedef std::size_t size_type;
26
27 stringshare()
28 : _string( ::eina_stringshare_add("") )
29 {}
30 stringshare(const char* str)
31 : _string( ::eina_stringshare_add(str) )
32 {
33 }
34 stringshare(char* str, steal_stringshare_ref_t)
35 : _string( str )
36 {
37 }
38 template <typename InputIterator>
39 stringshare(InputIterator i, InputIterator j
40 , typename eina::enable_if
41 <!eina::is_integral<InputIterator>::value
42 && !eina::is_contiguous_iterator<InputIterator>::value
43 >::type* = 0)
44 {
45 std::string tmp;
46 while(i != j)
47 {
48 tmp.push_back(*i);
49 ++i;
50 }
51 _string = ::eina_stringshare_add(tmp.c_str());
52 }
53 template <typename ContiguousMemoryIterator>
54 stringshare(ContiguousMemoryIterator i, ContiguousMemoryIterator j
55 , typename eina::enable_if
56 <eina::is_contiguous_iterator<ContiguousMemoryIterator>::value>::type* = 0)
57 : _string( ::eina_stringshare_add_length(&*i, j - i) )
58 {
59 }
60
61 ~stringshare()
62 {
63 ::eina_stringshare_del(_string);
64 }
65
66 stringshare(stringshare const& other)
67 : _string( eina_stringshare_ref(other._string) )
68 {}
69 stringshare& operator=(stringshare const& other)
70 {
71 ::eina_stringshare_refplace(&_string, other._string);
72 return *this;
73 }
74 stringshare& operator=(const char* c_string)
75 {
76 ::eina_stringshare_replace(&_string, c_string);
77 return *this;
78 }
79
80 const_iterator begin() const
81 {
82 return _string;
83 }
84 const_iterator end() const
85 {
86 return _string + size();
87 }
88
89 const_reverse_iterator rbegin() const
90 {
91 return const_reverse_iterator(begin());
92 }
93 const_reverse_iterator rend() const
94 {
95 return const_reverse_iterator(end());
96 }
97
98 const_iterator cbegin() const
99 {
100 return begin();
101 }
102 const_iterator cend() const
103 {
104 return end();
105 }
106 const_reverse_iterator crbegin() const
107 {
108 return rbegin();
109 }
110 const_reverse_iterator crend() const
111 {
112 return rend();
113 }
114
115 size_type size() const
116 {
117 return eina_stringshare_strlen(_string);
118 }
119
120 size_type length() const
121 {
122 return size();
123 }
124 size_type max_size() const
125 {
126 return -1;
127 }
128 bool empty() const
129 {
130 return _string[0] == 0;
131 }
132 const_reference operator[](size_type i) const
133 {
134 return _string[i];
135 }
136 const_reference at(size_type i) const
137 {
138 if(i < size())
139 return (*this)[i];
140 else
141 throw std::out_of_range("");
142 }
143 const_reference back() const
144 {
145 return _string[size()-1];
146 }
147 const_reference front() const
148 {
149 return _string[0];
150 }
151
152 void swap(stringshare& other)
153 {
154 std::swap(_string, other._string);
155 }
156
157 const char* c_str() const
158 {
159 return _string;
160 }
161 const char* data() const
162 {
163 return _string;
164 }
165
166private:
167 Eina_Stringshare* _string;
168};
169
170template <>
171struct is_contiguous_iterator<stringshare::const_iterator> : true_type {};
172
173inline bool operator==(stringshare const& lhs, stringshare const& rhs)
174{
175 return lhs.c_str() == rhs.c_str();
176}
177
178inline bool operator!=(stringshare const& lhs, stringshare const& rhs)
179{
180 return !(lhs == rhs);
181}
182
183inline bool operator==(stringshare const& lhs, const char* rhs)
184{
185 return lhs.c_str() == rhs || std::strcmp(lhs.c_str(), rhs) == 0;
186}
187
188inline bool operator!=(stringshare const& lhs, const char* rhs)
189{
190 return !(lhs == rhs);
191}
192
193inline bool operator==(const char* lhs, stringshare const& rhs)
194{
195 return rhs == lhs;
196}
197
198inline bool operator!=(const char* lhs, stringshare const& rhs)
199{
200 return !(lhs == rhs);
201}
202
203} }
204
205#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 @@
1#ifndef EINA_THREAD_HH_
2#define EINA_THREAD_HH_
3
4#include <Eina.h>
5#include <eina_error.hh>
6
7#include <memory>
8#include <iterator>
9#include <cstdlib>
10#include <cassert>
11#include <iosfwd>
12#include <functional>
13#include <chrono>
14#include <mutex>
15
16#define EFL_EINA_BOOST_MOVABLE_BUT_NOT_COPYABLE(x)
17#define EFL_EINA_BOOST_RV_REF(x) x const&
18
19namespace efl { namespace eina {
20
21struct mutex
22{
23 typedef Eina_Lock* native_handle_type;
24
25 mutex()
26 {
27 ::eina_lock_new(&_mutex);
28 }
29 ~mutex()
30 {
31 ::eina_lock_free(&_mutex);
32 }
33 void lock()
34 {
35 ::Eina_Lock_Result r = ::eina_lock_take(&_mutex);
36 switch(r)
37 {
38 case EINA_LOCK_SUCCEED:
39 return;
40 case EINA_LOCK_DEADLOCK:
41 throw system_error(error_code(int(eina::errc::resource_deadlock_would_occur)
42 , get_generic_category()));
43 default:
44 throw system_error(get_error_code());
45 }
46 }
47 bool try_lock()
48 {
49 ::Eina_Lock_Result r = ::eina_lock_take_try(&_mutex);
50 switch(r)
51 {
52 case EINA_LOCK_SUCCEED:
53 return true;
54 case EINA_LOCK_FAIL:
55 return false;
56 case EINA_LOCK_DEADLOCK:
57 throw system_error(error_code(int(eina::errc::resource_deadlock_would_occur)
58 , get_generic_category()));
59 default:
60 throw system_error(get_error_code());
61 }
62 }
63 void unlock()
64 {
65 ::Eina_Lock_Result r = ::eina_lock_release(&_mutex);
66 switch(r)
67 {
68 case EINA_LOCK_SUCCEED:
69 return;
70 case EINA_LOCK_DEADLOCK:
71 throw system_error(error_code(int(eina::errc::resource_deadlock_would_occur)
72 , get_generic_category()));
73 default:
74 throw system_error(get_error_code());
75 }
76 }
77 void debug()
78 {
79 ::eina_lock_debug(&_mutex);
80 }
81 native_handle_type native_handle()
82 {
83 return &_mutex;
84 }
85private:
86 mutex(mutex const&) = delete;
87 mutex& operator=(mutex const&) = delete;
88
89 Eina_Lock _mutex;
90};
91
92using std::lock_guard;
93using std::unique_lock;
94
95struct condition_variable
96{
97 typedef Eina_Condition* native_handle_type;
98
99 condition_variable()
100 {
101 ::eina_condition_new(&_cond, _mutex.native_handle());
102 }
103 ~condition_variable()
104 {
105 ::eina_condition_free(&_cond);
106 }
107
108 void notify_one()
109 {
110 eina::unique_lock<eina::mutex> l(_mutex);
111 Eina_Bool r = eina_condition_signal(&_cond);
112 if(!r)
113 throw eina::system_error(eina::get_error_code());
114 }
115 void notify_all()
116 {
117 eina::unique_lock<eina::mutex> l(_mutex);
118 Eina_Bool r = eina_condition_broadcast(&_cond);
119 if(!r)
120 throw eina::system_error(eina::get_error_code());
121 }
122 template <typename Lock>
123 void wait(Lock& lock)
124 {
125 eina::unique_lock<eina::mutex> l(_mutex);
126 lock.unlock();
127 ::eina_condition_wait(&_cond);
128 lock.lock();
129 }
130 template <typename Lock, typename Predicate>
131 void wait(Lock& lock, Predicate p)
132 {
133 while(!p())
134 wait(lock);
135 }
136 native_handle_type native_handle()
137 {
138 return &_cond;
139 }
140private:
141 condition_variable(condition_variable const&);
142 condition_variable& operator=(condition_variable const&);
143
144 mutex _mutex;
145 Eina_Condition _cond;
146};
147
148struct thread_id
149{
150 thread_id() noexcept
151 : _raw(0u)
152 {
153 }
154 thread_id(Eina_Thread raw)
155 : _raw(raw) {}
156 friend inline bool operator==(thread_id lhs, thread_id rhs)
157 {
158 return lhs._raw == rhs._raw;
159 }
160 friend inline bool operator!=(thread_id lhs, thread_id rhs)
161 {
162 return lhs._raw != rhs._raw;
163 }
164 friend inline bool operator<(thread_id lhs, thread_id rhs)
165 {
166 return std::less<Eina_Thread>()(lhs._raw, rhs._raw);
167 }
168private:
169 Eina_Thread _raw;
170};
171
172inline bool operator<=(thread_id lhs, thread_id rhs)
173{
174 return (lhs == rhs) || lhs < rhs;
175}
176inline bool operator>(thread_id lhs, thread_id rhs)
177{
178 return !(lhs <= rhs);
179}
180inline bool operator>=(thread_id lhs, thread_id rhs)
181{
182 return !(lhs < rhs);
183}
184
185template <typename charT, typename Traits>
186std::basic_ostream<charT, Traits>&
187operator<<(std::basic_ostream<charT, Traits>& out, thread_id id)
188{
189 return out << id._raw;
190}
191
192namespace _detail {
193
194struct arguments
195{
196 Eina_Lock mutex;
197 Eina_Condition condition;
198 bool started;
199 std::function<void()> function;
200};
201
202inline void* create_thread(void* data, Eina_Thread)
203{
204 arguments* args = static_cast<arguments*>(data);
205
206 eina_lock_take(&args->mutex);
207
208 std::function<void()> f = std::move(args->function);
209
210 args->started = true;
211 eina_condition_signal(&args->condition);
212 eina_lock_release(&args->mutex);
213
214 f();
215 return 0;
216}
217
218}
219
220struct thread
221{
222 typedef thread_id id;
223 typedef Eina_Thread native_handle_type;
224
225 thread() noexcept
226 : _joinable(false), _raw(0u)
227 {
228 }
229
230 template <typename F, class ... Args>
231 explicit thread(F&& f, Args&&... args)
232 {
233 _detail::arguments arguments;
234 arguments.started = false;
235 arguments.function = std::bind(f, args...);
236
237 _joinable = true;
238 Eina_Bool r = ::eina_lock_new(&arguments.mutex);
239 if(!r) throw eina::system_error(eina::get_error_code());
240 r = ::eina_condition_new(&arguments.condition, &arguments.mutex);
241 if(!r) throw eina::system_error(eina::get_error_code());
242
243 if(!eina_thread_create
244 (&_raw, ::EINA_THREAD_NORMAL
245 , -1, &eina::_detail::create_thread, &arguments))
246 {
247 eina_condition_free(&arguments.condition);
248 eina_lock_free(&arguments.mutex);
249 throw eina::system_error(eina::get_error_code());
250 }
251 Eina_Lock_Result lr = ::eina_lock_take(&arguments.mutex);
252 if(lr != EINA_LOCK_SUCCEED)
253 throw eina::system_error(eina::get_error_code());
254 while(!arguments.started)
255 {
256 r = eina_condition_wait(&arguments.condition);
257 if(!r) throw eina::system_error(eina::get_error_code());
258 }
259 lr = eina_lock_release(&arguments.mutex);
260 if(lr != EINA_LOCK_SUCCEED)
261 throw eina::system_error(eina::get_error_code());
262
263 eina_condition_free(&arguments.condition);
264 eina_lock_free(&arguments.mutex);
265 }
266
267 thread(thread&& other)
268 : _joinable(other._joinable), _raw(other._raw)
269 {
270 }
271
272 thread& operator=(thread&& other)
273 {
274 _raw = other._raw;
275 _joinable = other._joinable;
276 return *this;
277 }
278
279 ~thread()
280 {
281 assert(!joinable());
282 }
283
284 void swap(thread& other) noexcept
285 {
286 std::swap(_raw, other._raw);
287 }
288 bool joinable() const noexcept
289 {
290 return _joinable;
291 }
292
293 void join()
294 {
295 assert(joinable());
296 ::eina_thread_join(_raw);
297 _joinable = false;
298 }
299
300 void detach()
301 {
302 assert(joinable());
303 _joinable = false;
304 }
305
306 id get_id() const noexcept
307 {
308 return id(_raw);
309 }
310 native_handle_type native_handle() const
311 {
312 return _raw;
313 }
314
315 static unsigned hardware_concurrency() noexcept
316 {
317 return ::eina_cpu_count();
318 }
319private:
320 bool _joinable;
321 Eina_Thread _raw;
322};
323
324inline void swap(thread& lhs, thread& rhs)
325{
326 lhs.swap(rhs);
327}
328
329namespace this_thread {
330
331inline thread::id get_id()
332{
333 return thread::id(eina_thread_self());
334}
335
336inline void yield() {}
337
338template <typename Clock, typename Duration>
339void sleep_until(std::chrono::time_point<Clock, Duration>const& abs_time);
340
341template <typename Rep, typename Period>
342void sleep_for(std::chrono::duration<Rep, Period>const& rel_time);
343}
344
345} }
346
347namespace std {
348
349template <typename T> struct hash;
350template <>
351struct hash< ::efl::eina::thread_id> : hash<unsigned long>
352{};
353
354}
355
356#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 @@
1#ifndef _EINA_TYPE_TRAITS_HH
2#define _EINA_TYPE_TRAITS_HH
3
4#include <type_traits>
5
6#include <string>
7#include <vector>
8
9namespace efl { namespace eina {
10
11using std::enable_if;
12using std::is_integral;
13using std::is_pod;
14using std::is_const;
15using std::remove_cv;
16using std::true_type;
17using std::false_type;
18using std::remove_pointer;
19using std::remove_reference;
20
21template <typename T, typename Enable = void>
22struct is_contiguous_iterator : false_type {};
23template <>
24struct is_contiguous_iterator<std::string::const_iterator> : true_type {};
25template <>
26struct is_contiguous_iterator<std::string::iterator> : true_type {};
27template <>
28struct is_contiguous_iterator<std::vector<char>::const_iterator> : true_type {};
29template <>
30struct is_contiguous_iterator<std::vector<char>::iterator> : true_type {};
31
32template <bool, typename T, typename F>
33struct if_c
34{
35 typedef T type;
36};
37
38template <typename T, typename F>
39struct if_c<false, T, F>
40{
41 typedef F type;
42};
43
44template <typename U, typename T, typename F>
45struct if_ : if_c<U::value, T, F>
46{
47};
48
49} }
50
51#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 @@
1#ifndef _EFL_EINA_EINA_VALUE_HH
2#define _EFL_EINA_EINA_VALUE_HH
3
4#include <Eina.h>
5
6#include <eina_stringshare.hh>
7#include <eina_type_traits.hh>
8
9namespace efl { namespace eina {
10
11template <typename T>
12struct _eina_value_traits_base;
13
14template <typename T>
15struct _eina_value_traits_aux;
16
17// Indirection for uint64_t. uint64_t can be a typedef for unsigned
18// long, so we can't specialize on the same template
19template <>
20struct _eina_value_traits_aux<uint64_t>
21{
22 static ::Eina_Value_Type const* value_type()
23 {
24 return EINA_VALUE_TYPE_UINT64;
25 }
26};
27
28template <typename T, typename Enable = void>
29struct _eina_value_traits : _eina_value_traits_aux<T>
30{
31};
32
33template <typename T>
34struct _eina_value_traits_base
35{
36 typedef T type;
37
38 static ::Eina_Value* create()
39 {
40 return eina_value_new(_eina_value_traits<T>::value_type());
41 }
42 static void set_type( ::Eina_Value* v)
43 {
44 eina_value_setup(v, _eina_value_traits<T>::value_type());
45 }
46 static void set( ::Eina_Value* v, type c)
47 {
48 ::eina_value_set(v, c);
49 }
50 static type get( ::Eina_Value* v)
51 {
52 if(_eina_value_traits<T>::value_type() == eina_value_type_get(v))
53 {
54 type vv;
55 if(::eina_value_get(v, &vv))
56 return vv;
57 else
58 throw eina::system_error(eina::get_error_code());
59 }
60 else
61 throw eina::system_error(EINA_ERROR_VALUE_FAILED, eina::eina_error_category());
62 }
63};
64
65template <>
66struct _eina_value_traits<unsigned char>
67 : _eina_value_traits_base<unsigned char>
68{
69 static ::Eina_Value_Type const* value_type()
70 {
71 return EINA_VALUE_TYPE_UCHAR;
72 }
73};
74
75template <>
76struct _eina_value_traits<unsigned short>
77 : _eina_value_traits_base<unsigned short>
78{
79 static ::Eina_Value_Type const* value_type()
80 {
81 return EINA_VALUE_TYPE_USHORT;
82 }
83};
84
85template <>
86struct _eina_value_traits<unsigned int>
87 : _eina_value_traits_base<unsigned int>
88{
89 static ::Eina_Value_Type const* value_type()
90 {
91 return EINA_VALUE_TYPE_UINT;
92 }
93};
94
95template <>
96struct _eina_value_traits<unsigned long>
97 : _eina_value_traits_base<unsigned long>
98{
99 static ::Eina_Value_Type const* value_type()
100 {
101 return EINA_VALUE_TYPE_ULONG;
102 }
103};
104
105template <>
106struct _eina_value_traits<char>
107 : _eina_value_traits_base<char>
108{
109 static ::Eina_Value_Type const* value_type()
110 {
111 return EINA_VALUE_TYPE_CHAR;
112 }
113};
114
115template <>
116struct _eina_value_traits<short>
117 : _eina_value_traits_base<short>
118{
119 static ::Eina_Value_Type const* value_type()
120 {
121 return EINA_VALUE_TYPE_SHORT;
122 }
123};
124
125template <>
126struct _eina_value_traits<int>
127 : _eina_value_traits_base<int>
128{
129 static ::Eina_Value_Type const* value_type()
130 {
131 return EINA_VALUE_TYPE_INT;
132 }
133};
134
135template <>
136struct _eina_value_traits<long>
137 : _eina_value_traits_base<long>
138{
139 static ::Eina_Value_Type const* value_type()
140 {
141 return EINA_VALUE_TYPE_LONG;
142 }
143};
144
145template <>
146struct _eina_value_traits<float>
147 : _eina_value_traits_base<float>
148{
149 static ::Eina_Value_Type const* value_type()
150 {
151 return EINA_VALUE_TYPE_FLOAT;
152 }
153};
154
155template <>
156struct _eina_value_traits<double>
157 : _eina_value_traits_base<double>
158{
159 static ::Eina_Value_Type const* value_type()
160 {
161 return EINA_VALUE_TYPE_DOUBLE;
162 }
163};
164
165template <>
166struct _eina_value_traits<stringshare>
167 : _eina_value_traits_base<stringshare>
168{
169 static ::Eina_Value_Type const* value_type()
170 {
171 return EINA_VALUE_TYPE_STRINGSHARE;
172 }
173 static void set( ::Eina_Value* v, type c)
174 {
175 ::eina_value_set(v, c.data());
176 }
177 static type get( ::Eina_Value* v)
178 {
179 char* c_str;
180 ::eina_value_get(v, &c_str);
181 return stringshare(c_str, steal_stringshare_ref);
182 }
183};
184
185template <>
186struct _eina_value_traits<std::string>
187 : _eina_value_traits_base<std::string>
188{
189 typedef typename _eina_value_traits_base<std::string>::type type;
190 static ::Eina_Value_Type const* value_type()
191 {
192 return EINA_VALUE_TYPE_STRING;
193 }
194 static void set( ::Eina_Value* v, type c)
195 {
196 ::eina_value_set(v, c.c_str());
197 }
198 static type get( ::Eina_Value* v)
199 {
200 char* c_str;
201 ::eina_value_get(v, &c_str);
202 std::string r(c_str);
203 ::free(c_str);
204 return r;
205 }
206};
207
208template <typename T>
209struct _eina_value_traits<T[], typename eina::enable_if<eina::is_pod<T>::value>::type>
210 : _eina_value_traits_base<T[]>
211{
212 typedef typename _eina_value_traits_base<T[]>::type type;
213 static ::Eina_Value_Type const* value_type()
214 {
215 return EINA_VALUE_TYPE_ARRAY;
216 }
217 static void set( ::Eina_Value* v, type c)
218 {
219 ::eina_value_set(v, c.c_str());
220 }
221 static type get( ::Eina_Value* v)
222 {
223 char* c_str;
224 ::eina_value_get(v, &c_str);
225 std::string r(c_str);
226 ::free(c_str);
227 return r;
228 }
229};
230
231class eina_value
232{
233 template <typename T>
234 void primitive_init(T v)
235 {
236 _raw = _eina_value_traits<T>::create();
237 _eina_value_traits<T>::set(_raw, v);
238 }
239public:
240 eina_value()
241 : _raw(_eina_value_traits<char>::create())
242 {
243 }
244 eina_value(char v)
245 {
246 primitive_init(v);
247 }
248 eina_value(short v)
249 {
250 primitive_init(v);
251 }
252 eina_value(int v)
253 {
254 primitive_init(v);
255 }
256 eina_value(long v)
257 {
258 primitive_init(v);
259 }
260 eina_value(unsigned char v)
261 {
262 primitive_init(v);
263 }
264 eina_value(unsigned short v)
265 {
266 primitive_init(v);
267 }
268 eina_value(unsigned int v)
269 {
270 primitive_init(v);
271 }
272 eina_value(unsigned long v)
273 {
274 primitive_init(v);
275 }
276 eina_value(float v)
277 {
278 primitive_init(v);
279 }
280 eina_value(double v)
281 {
282 primitive_init(v);
283 }
284
285 ~eina_value()
286 {
287 eina_value_free(_raw);
288 }
289
290 eina_value(eina_value const& other)
291 : _raw(_eina_value_traits<char>::create())
292 {
293 if(!eina_value_copy(const_cast<Eina_Value const*>(other._raw), _raw))
294 throw eina::system_error(eina::get_error_code());
295 }
296 eina_value& operator=(eina_value const& other)
297 {
298 eina_value_flush(_raw);
299 if(!eina_value_copy(const_cast<Eina_Value const*>(other._raw), _raw))
300 throw eina::system_error(eina::get_error_code());
301 return *this;
302 }
303
304 void swap(eina_value& other)
305 {
306 std::swap(_raw, other._raw);
307 }
308
309 typedef Eina_Value* native_handle_type;
310 native_handle_type native_handle() const
311 {
312 return _raw;
313 }
314 typedef Eina_Value_Type const* type_info_t;
315 type_info_t type_info() const
316 {
317 return ::eina_value_type_get(_raw);
318 }
319private:
320 ::Eina_Value* _raw;
321
322 template <typename T>
323 friend T get(eina_value const& v)
324 {
325 return _eina_value_traits<T>::get(v._raw);
326 }
327};
328
329inline void swap(eina_value& lhs, eina_value& rhs)
330{
331 lhs.swap(rhs);
332}
333
334inline bool operator==(eina_value const& lhs, eina_value const& rhs)
335{
336 return lhs.type_info() == rhs.type_info()
337 && eina_value_compare(lhs.native_handle(), rhs.native_handle()) == 0;
338}
339
340inline bool operator<(eina_value const& lhs, eina_value const& rhs)
341{
342 return std::less<Eina_Value_Type const*>()(lhs.type_info(), rhs.type_info())
343 || (lhs.type_info() == rhs.type_info()
344 && eina_value_compare(lhs.native_handle(), rhs.native_handle()) < 0);
345}
346
347inline bool operator>(eina_value const& lhs, eina_value const& rhs)
348{
349 return std::less<Eina_Value_Type const*>()(rhs.type_info(), lhs.type_info())
350 || (rhs.type_info() == lhs.type_info()
351 && eina_value_compare(lhs.native_handle(), rhs.native_handle()) > 0);
352}
353
354inline bool operator<=(eina_value const& lhs, eina_value const& rhs)
355{
356 return !(lhs > rhs);
357}
358
359inline bool operator>=(eina_value const& lhs, eina_value const& rhs)
360{
361 return !(lhs < rhs);
362}
363
364inline bool operator!=(eina_value const& lhs, eina_value const& rhs)
365{
366 return !(lhs == rhs);
367}
368
369} }
370
371#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 @@
1
2#include "Eina.hh"
3
4#include <cassert>
5#include <algorithm>
6
7#include <check.h>
8
9void eina_test_inlist(TCase* tc);
10void eina_test_inarray(TCase* tc);
11void eina_test_ptrlist(TCase* tc);
12void eina_test_ptrarray(TCase* tc);
13void eina_test_iterator(TCase* tc);
14void eina_test_stringshare(TCase* tc);
15void eina_test_error(TCase* tc);
16void eina_test_accessor(TCase* tc);
17void eina_test_thread(TCase* tc);
18void eina_test_eina_value(TCase* tc);
19
20typedef struct _Eina_Test_Case Eina_Test_Case;
21struct _Eina_Test_Case
22{
23 const char *test_case;
24 void (*build)(TCase *tc);
25};
26
27static const Eina_Test_Case etc[] = {
28 { "Ptr_List", eina_test_ptrlist },
29 { "Ptr_Array", eina_test_ptrarray },
30 { "Inlist", eina_test_inlist },
31 { "Inarray", eina_test_inarray },
32 { "Iterator", eina_test_iterator },
33 { "Stringshare", eina_test_stringshare },
34 { "Error", eina_test_error },
35 { "Accessor", eina_test_accessor },
36 { "Thread", eina_test_thread },
37 { "EinaValue", eina_test_eina_value },
38 { NULL, NULL }
39};
40
41static void
42_list_tests(void)
43{
44 const Eina_Test_Case *itr = etc;
45 fputs("Available Test Cases:\n", stderr);
46 for (; itr->test_case; itr++)
47 fprintf(stderr, "\t%s\n", itr->test_case);
48}
49
50static Eina_Bool
51_use_test(int argc, const char **argv, const char *test_case)
52{
53 if (argc < 1)
54 return 1;
55
56 for (; argc > 0; argc--, argv++)
57 if (strcmp(test_case, *argv) == 0)
58 return 1;
59
60 return 0;
61}
62
63Suite *
64eina_build_suite(int argc, const char **argv)
65{