summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile_Eina_Cxx.am7
-rw-r--r--src/bindings/eina_cxx/Eina.hh2
-rw-r--r--src/bindings/eina_cxx/eina_integer_sequence.hh41
-rw-r--r--src/bindings/eina_cxx/eina_optional.hh199
-rw-r--r--src/tests/eina_cxx/eina_cxx_suite.cc2
-rw-r--r--src/tests/eina_cxx/eina_cxx_test_optional.cc142
6 files changed, 391 insertions, 2 deletions
diff --git a/src/Makefile_Eina_Cxx.am b/src/Makefile_Eina_Cxx.am
index d82493af13..1e3265612e 100644
--- a/src/Makefile_Eina_Cxx.am
+++ b/src/Makefile_Eina_Cxx.am
@@ -1,20 +1,22 @@
1 1
2### Library 2### Library
3 3
4installed_einacxxmainheadersdir = $(includedir)/eina_cxx-@VMAJ@ 4installed_einacxxmainheadersdir = $(includedir)/eina-cxx-@VMAJ@
5dist_installed_einacxxmainheaders_DATA = \ 5dist_installed_einacxxmainheaders_DATA = \
6bindings/eina_cxx/Eina.hh 6bindings/eina_cxx/Eina.hh
7 7
8installed_einacxxheadersdir = $(includedir)/eina_cxx-@VMAJ@/eina_cxx 8installed_einacxxheadersdir = $(includedir)/eina-cxx-@VMAJ@/eina-cxx
9dist_installed_einacxxheaders_DATA = \ 9dist_installed_einacxxheaders_DATA = \
10bindings/eina_cxx/eina_accessor.hh \ 10bindings/eina_cxx/eina_accessor.hh \
11bindings/eina_cxx/eina_clone_allocators.hh \ 11bindings/eina_cxx/eina_clone_allocators.hh \
12bindings/eina_cxx/eina_error.hh \ 12bindings/eina_cxx/eina_error.hh \
13bindings/eina_cxx/eina_inarray.hh \ 13bindings/eina_cxx/eina_inarray.hh \
14bindings/eina_cxx/eina_inlist.hh \ 14bindings/eina_cxx/eina_inlist.hh \
15bindings/eina_cxx/eina_integer_sequence.hh \
15bindings/eina_cxx/eina_iterator.hh \ 16bindings/eina_cxx/eina_iterator.hh \
16bindings/eina_cxx/eina_lists_auxiliary.hh \ 17bindings/eina_cxx/eina_lists_auxiliary.hh \
17bindings/eina_cxx/eina_log.hh \ 18bindings/eina_cxx/eina_log.hh \
19bindings/eina_cxx/eina_optional.hh \
18bindings/eina_cxx/eina_ptrarray.hh \ 20bindings/eina_cxx/eina_ptrarray.hh \
19bindings/eina_cxx/eina_ptrlist.hh \ 21bindings/eina_cxx/eina_ptrlist.hh \
20bindings/eina_cxx/eina_range_types.hh \ 22bindings/eina_cxx/eina_range_types.hh \
@@ -44,6 +46,7 @@ tests/eina_cxx/eina_cxx_test_stringshare.cc \
44tests/eina_cxx/eina_cxx_test_error.cc \ 46tests/eina_cxx/eina_cxx_test_error.cc \
45tests/eina_cxx/eina_cxx_test_accessor.cc \ 47tests/eina_cxx/eina_cxx_test_accessor.cc \
46tests/eina_cxx/eina_cxx_test_thread.cc \ 48tests/eina_cxx/eina_cxx_test_thread.cc \
49tests/eina_cxx/eina_cxx_test_optional.cc \
47tests/eina_cxx/eina_cxx_test_value.cc 50tests/eina_cxx/eina_cxx_test_value.cc
48 51
49tests_eina_cxx_eina_cxx_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \ 52tests_eina_cxx_eina_cxx_suite_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
diff --git a/src/bindings/eina_cxx/Eina.hh b/src/bindings/eina_cxx/Eina.hh
index 37741b642f..9ba0ca3ebc 100644
--- a/src/bindings/eina_cxx/Eina.hh
+++ b/src/bindings/eina_cxx/Eina.hh
@@ -13,6 +13,8 @@
13#include <eina_value.hh> 13#include <eina_value.hh>
14#include <eina_ref.hh> 14#include <eina_ref.hh>
15#include <eina_log.hh> 15#include <eina_log.hh>
16#include <eina_optional.hh>
17#include <eina_integer_sequence.hh>
16 18
17namespace efl { namespace eina { 19namespace efl { namespace eina {
18 20
diff --git a/src/bindings/eina_cxx/eina_integer_sequence.hh b/src/bindings/eina_cxx/eina_integer_sequence.hh
new file mode 100644
index 0000000000..4ec17621f7
--- /dev/null
+++ b/src/bindings/eina_cxx/eina_integer_sequence.hh
@@ -0,0 +1,41 @@
1#ifndef EINA_CXX_EINA_INTEGER_SEQUENCE_HH
2#define EINA_CXX_EINA_INTEGER_SEQUENCE_HH
3
4namespace efl { namespace eina {
5
6template <typename T, T... Ints>
7struct integer_sequence
8{
9 typedef T value_type;
10 static constexpr std::size_t size() { return sizeof...(Ints); }
11 typedef integer_sequence<T, Ints...> type;
12};
13
14template<class S1, class S2> struct concat;
15
16template<typename T, T... I1, T... I2>
17struct concat<integer_sequence<T, I1...>, integer_sequence<T, I2...> >
18 : integer_sequence<T, I1..., (sizeof...(I1)+I2)...> {};
19
20template<class S1, class S2>
21using Concat = typename concat<S1, S2>::type;
22
23template<typename T, T N> struct gen_seq;
24template<typename T, T N> using make_integer_sequence = typename gen_seq<T, N>::type;
25
26template<typename T, T N>
27struct gen_seq : Concat<make_integer_sequence<T, N/2>
28 , make_integer_sequence<T, N - N/2>>{};
29
30template<> struct gen_seq<std::size_t, 0> : integer_sequence<std::size_t>{};
31template<> struct gen_seq<std::size_t, 1> : integer_sequence<std::size_t, 0>{};
32
33template <std::size_t... I>
34using index_sequence = integer_sequence<std::size_t, I...>;
35
36template <std::size_t I>
37using make_index_sequence = make_integer_sequence<std::size_t, I>;
38
39} }
40
41#endif
diff --git a/src/bindings/eina_cxx/eina_optional.hh b/src/bindings/eina_cxx/eina_optional.hh
new file mode 100644
index 0000000000..e6d853f1bb
--- /dev/null
+++ b/src/bindings/eina_cxx/eina_optional.hh
@@ -0,0 +1,199 @@
1#ifndef EINA_OPTIONAL_HH_
2#define EINA_OPTIONAL_HH_
3
4#include <cstddef>
5#include <algorithm>
6#include <utility>
7
8namespace efl_eina_swap_adl {
9
10template <typename T>
11void swap_impl(T& lhs, T& rhs)
12{
13 using namespace std;
14 swap(lhs, rhs);
15}
16
17}
18
19namespace efl { namespace eina {
20
21template <typename T>
22void adl_swap(T& lhs, T& rhs)
23{
24 ::efl_eina_swap_adl::swap_impl<T>(lhs, rhs);
25}
26
27template <typename T>
28struct optional
29{
30 typedef optional<T> _self_type;
31
32 optional(std::nullptr_t) : engaged(false)
33 {}
34 optional() : engaged(false)
35 {}
36 optional(T&& other) : engaged(false)
37 {
38 _construct(std::move(other));
39 }
40 optional(T const& other) : engaged(false)
41 {
42 _construct(std::move(other));
43 }
44 optional(optional<T> const& other)
45 : engaged(false)
46 {
47 if(other.engaged) _construct(*other);
48 }
49 optional(optional<T>&& other)
50 : engaged(false)
51 {
52 _construct(std::move(*other));
53 other._destroy();
54 }
55
56 _self_type& operator=(optional<T>&& other)
57 {
58 _destroy();
59 engaged = other.engaged;
60 if(engaged)
61 _construct(std::move(*other));
62 other._destroy();
63 return *this;
64 }
65 _self_type& operator=(optional<T>const& other)
66 {
67 optional<T> tmp(other);
68 tmp.swap(*this);
69 return *this;
70 }
71
72 ~optional()
73 {
74 _destroy();
75 }
76
77 explicit operator bool() const
78 {
79 return is_engaged();
80 }
81 bool operator!() const
82 {
83 bool b ( *this );
84 return !b;
85 }
86
87 T* operator->()
88 {
89 assert(is_engaged());
90 return static_cast<T*>(static_cast<void*>(&buffer));
91 }
92 T const* operator->() const
93 {
94 return const_cast<_self_type&>(*this).operator->();
95 }
96
97 T& operator*() { return get(); }
98 T const& operator*() const { return get(); }
99
100 T& get() { return *this->operator->(); }
101 T const& get() const { return *this->operator->(); }
102
103 void swap(optional<T>& other)
104 {
105 if(is_engaged() && other.is_engaged())
106 {
107 eina::adl_swap(**this, *other);
108 }
109 else if(is_engaged())
110 {
111 other._construct(std::move(**this));
112 _destroy();
113 }
114 else if(other.is_engaged())
115 {
116 _construct(std::move(*other));
117 other._destroy();
118 }
119 }
120
121 bool is_engaged() const
122 {
123 return engaged;
124 }
125private:
126 template <typename U>
127 void _construct(U&& object)
128 {
129 assert(!is_engaged());
130 new (&buffer) T(std::move(object));
131 engaged = true;
132 }
133 void _destroy()
134 {
135 if(is_engaged())
136 {
137 static_cast<T*>(static_cast<void*>(&buffer))->~T();
138 engaged = false;
139 }
140 }
141
142 typedef typename std::aligned_storage
143 <sizeof(T),std::alignment_of<T>::value>::type buffer_type;
144 buffer_type buffer;
145 bool engaged;
146};
147
148template <typename T>
149void swap(optional<T>& lhs, optional<T>& rhs)
150{
151 lhs.swap(rhs);
152}
153
154template <typename T>
155bool operator==(optional<T> const& lhs, optional<T> const& rhs)
156{
157 if(!lhs && !rhs)
158 return true;
159 else if(!lhs || !rhs)
160 return false;
161 else
162 return *lhs == *rhs;
163}
164template <typename T>
165bool operator!=(optional<T> const& lhs, optional<T> const& rhs)
166{
167 return !(lhs == rhs);
168}
169template <typename T>
170bool operator<(optional<T> const& lhs, optional<T> const& rhs)
171{
172 if(!lhs && !rhs)
173 return false;
174 else if(!lhs)
175 return true;
176 else if(!rhs)
177 return false;
178 else
179 return *lhs < *rhs;
180}
181template <typename T>
182bool operator<=(optional<T> const& lhs, optional<T> const& rhs)
183{
184 return lhs < rhs || lhs == rhs;
185}
186template <typename T>
187bool operator>(optional<T> const& lhs, optional<T> const& rhs)
188{
189 return !(lhs <= rhs);
190}
191template <typename T>
192bool operator>=(optional<T> const& lhs, optional<T> const& rhs)
193{
194 return !(lhs < rhs);
195}
196
197} } // efl::eina
198
199#endif // EINA_OPTIONAL_HH_
diff --git a/src/tests/eina_cxx/eina_cxx_suite.cc b/src/tests/eina_cxx/eina_cxx_suite.cc
index 4ef8a9f45d..942d539512 100644
--- a/src/tests/eina_cxx/eina_cxx_suite.cc
+++ b/src/tests/eina_cxx/eina_cxx_suite.cc
@@ -15,6 +15,7 @@ void eina_test_stringshare(TCase* tc);
15void eina_test_error(TCase* tc); 15void eina_test_error(TCase* tc);
16void eina_test_accessor(TCase* tc); 16void eina_test_accessor(TCase* tc);
17void eina_test_thread(TCase* tc); 17void eina_test_thread(TCase* tc);
18void eina_test_optional(TCase* tc);
18void eina_test_value(TCase* tc); 19void eina_test_value(TCase* tc);
19void eina_test_log(TCase* tc); 20void eina_test_log(TCase* tc);
20 21
@@ -35,6 +36,7 @@ static const Eina_Test_Case etc[] = {
35 { "Error", eina_test_error }, 36 { "Error", eina_test_error },
36 { "Accessor", eina_test_accessor }, 37 { "Accessor", eina_test_accessor },
37 { "Thread", eina_test_thread }, 38 { "Thread", eina_test_thread },
39 { "Optional", eina_test_optional },
38 { "Value", eina_test_value }, 40 { "Value", eina_test_value },
39 { "Log", eina_test_log }, 41 { "Log", eina_test_log },
40 { NULL, NULL } 42 { NULL, NULL }
diff --git a/src/tests/eina_cxx/eina_cxx_test_optional.cc b/src/tests/eina_cxx/eina_cxx_test_optional.cc
new file mode 100644
index 0000000000..a809f6622a
--- /dev/null
+++ b/src/tests/eina_cxx/eina_cxx_test_optional.cc
@@ -0,0 +1,142 @@
1
2#include "Eina.hh"
3
4#include <algorithm>
5
6#include <check.h>
7
8#include <iostream>
9
10std::size_t nonpod_constructed = 0u
11 , nonpod_destructed = 0u;
12
13struct nonpod
14{
15 nonpod() { nonpod_constructed++; }
16 nonpod(nonpod const&) { nonpod_constructed++; }
17 nonpod(nonpod&&) { nonpod_constructed++; }
18 ~nonpod() { nonpod_destructed++; }
19};
20
21START_TEST(eina_cxx_optional_constructors)
22{
23 namespace eina = efl::eina;
24
25 eina::eina_init init;
26
27 {
28 eina::optional<int> optional;
29 ck_assert(!optional);
30 }
31
32 {
33 eina::optional<int> optional(nullptr);
34 ck_assert(!optional);
35 }
36
37 {
38 eina::optional<int> optional(5);
39 ck_assert(!!optional);
40 ck_assert(*optional == 5);
41 }
42
43 {
44 eina::optional<nonpod> optional;
45 ck_assert(!optional);
46 ck_assert(::nonpod_constructed == 0u);
47 }
48
49 {
50 ::nonpod object;
51 eina::optional<nonpod> optional(object);
52 ck_assert(!!optional);
53 }
54 std::cout << "nonpod_constructed " << nonpod_constructed
55 << " nonpod_destructed " << nonpod_destructed << std::endl;
56 ck_assert(::nonpod_constructed == ::nonpod_destructed);
57}
58END_TEST
59
60START_TEST(eina_cxx_optional_rel_ops)
61{
62 namespace eina = efl::eina;
63
64 eina::eina_init init;
65
66 eina::optional<int> empty;
67 eina::optional<int> one(1);
68 eina::optional<int> two(2);
69 eina::optional<int> one_again(1);
70
71 ck_assert(empty == empty);
72 ck_assert(one == one);
73 ck_assert(one == one_again);
74 ck_assert(one <= one_again);
75 ck_assert(one >= one_again);
76 ck_assert(empty < one);
77 ck_assert(one >= empty);
78 ck_assert(one > empty);
79 ck_assert(one < two);
80 ck_assert(one <= two);
81 ck_assert(two > one);
82 ck_assert(two >= one);
83 ck_assert(!(empty < empty));
84 ck_assert(!(one < one_again));
85 ck_assert(empty != one);
86 ck_assert(!(one != one));
87 ck_assert(!(one != one_again));
88}
89END_TEST
90
91START_TEST(eina_cxx_optional_assignment)
92{
93 namespace eina = efl::eina;
94
95 eina::eina_init init;
96
97 eina::optional<int> a;
98 eina::optional<int> b(1);
99 eina::optional<int> c(2);
100 eina::optional<int> d(1);
101
102 assert(!a); assert(b); assert(c); assert(d);
103
104 a = a;
105 ck_assert(a == a);
106 ck_assert(!a);
107
108 assert(!a); assert(b); assert(c); assert(d);
109
110 b = a;
111 ck_assert(b == a);
112 ck_assert(b != d);
113 ck_assert(!b);
114
115 assert(!a); assert(!b); assert(c); assert(d);
116
117 a = d;
118 ck_assert(a == d);
119 ck_assert(a != b);
120 ck_assert(!!a);
121 ck_assert(*a == 1);
122
123 assert(a); assert(!b); assert(c); assert(d);
124
125 c = d;
126
127 ck_assert(c == d);
128 ck_assert(c != b);
129 ck_assert(!!c);
130 ck_assert(*c == 1);
131
132 assert(a); assert(!b); assert(c); assert(d);
133}
134END_TEST
135
136void
137eina_test_optional(TCase* tc)
138{
139 tcase_add_test(tc, eina_cxx_optional_constructors);
140 tcase_add_test(tc, eina_cxx_optional_rel_ops);
141 tcase_add_test(tc, eina_cxx_optional_assignment);
142}