summaryrefslogtreecommitdiff
path: root/src/bindings/cxx/eldbus_cxx
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-05-23 12:01:30 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-05-23 15:05:50 -0300
commite3c8b280c639058c54f5576f189d0dc288105fc7 (patch)
treee313fa05bd9d2b2cb88623f6adea2c3b396b66e8 /src/bindings/cxx/eldbus_cxx
parent930f39b91b12b311f40cd96b4cf2e85085b01832 (diff)
c++: Reorganized C++ binding generation
Moved all generation to a single Makefile_Cxx.am file instead of throughout the whole project. And fixed C++ generation on Elementary after elm merge.
Diffstat (limited to 'src/bindings/cxx/eldbus_cxx')
-rw-r--r--src/bindings/cxx/eldbus_cxx/Eldbus.hh13
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_basic.hh150
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_error.hh22
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_freedesktop.hh72
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_integer_sequence.hh41
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_message.hh283
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_message_arguments.hh56
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_proxy_call.hh117
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_raw_tuple.hh30
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_service.hh379
-rw-r--r--src/bindings/cxx/eldbus_cxx/eldbus_signature_traits.hh194
11 files changed, 1357 insertions, 0 deletions
diff --git a/src/bindings/cxx/eldbus_cxx/Eldbus.hh b/src/bindings/cxx/eldbus_cxx/Eldbus.hh
new file mode 100644
index 0000000..67cbaf6
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/Eldbus.hh
@@ -0,0 +1,13 @@
1#ifndef EFL_ELDBUS_HH_
2#define EFL_ELDBUS_HH_
3
4#include <Eina.hh>
5#include <Eldbus.h>
6
7#include <eldbus_basic.hh>
8#include <eldbus_proxy_call.hh>
9#include <eldbus_message.hh>
10#include <eldbus_service.hh>
11#include <eina_integer_sequence.hh>
12
13#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_basic.hh b/src/bindings/cxx/eldbus_cxx/eldbus_basic.hh
new file mode 100644
index 0000000..aa287b4
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_basic.hh
@@ -0,0 +1,150 @@
1#ifndef ELDBUS_CXX_ELDBUS_BASIC_HH
2#define ELDBUS_CXX_ELDBUS_BASIC_HH
3
4#include <Eina.hh>
5#include <Eldbus.h>
6
7#include <eldbus_proxy_call.hh>
8
9namespace efl { namespace eldbus {
10
11struct unknown_t {};
12struct session_t {};
13struct system_t {};
14struct start_t {};
15struct address_t {};
16
17unknown_t const unknown = unknown_t();
18session_t const session = session_t();
19system_t const system = system_t();
20start_t const start = start_t();
21address_t const address = address_t();
22
23struct eldbus_init
24{
25 eldbus_init()
26 {
27 ::eldbus_init();
28 }
29 ~eldbus_init()
30 {
31 ::eldbus_shutdown();
32 }
33};
34
35struct proxy
36{
37 typedef Eldbus_Proxy* native_handle_type;
38 typedef Eldbus_Proxy const* const_native_handle_type;
39
40 proxy(native_handle_type native)
41 : _proxy(native) {}
42
43 template <typename R, typename Callback, typename... Args>
44 void call(const char* method, double timeout, Callback&& callback, Args... args) const
45 {
46 eldbus::_detail::proxy_call<R>(_proxy, method, timeout, std::forward<Callback>(callback), args...);
47 }
48
49 template <typename Callback, typename... Args>
50 void call(const char* method, double timeout, Callback&& callback, Args... args) const
51 {
52 eldbus::_detail::proxy_call<void>(_proxy, method, timeout, std::forward<Callback>(callback), args...);
53 }
54
55 native_handle_type native_handle() { return _proxy; }
56 const_native_handle_type native_handle() const { return _proxy; }
57private:
58 native_handle_type _proxy;
59};
60
61struct object
62{
63 typedef Eldbus_Object* native_handle_type;
64 typedef Eldbus_Object const* const_native_handle_type;
65 object(native_handle_type o)
66 : _object(o) {}
67
68 proxy get_proxy(const char* interface_) const
69 {
70 Eldbus_Proxy* p = eldbus_proxy_get
71 (const_cast<object*>(this)->native_handle(), interface_);
72 if(!p)
73 {
74 eina::error_code ec = eina::get_error_code();
75 assert(!!ec);
76 throw eina::system_error(ec, "eldbus");
77 }
78 return proxy(p);
79 }
80
81 native_handle_type native_handle() { return _object; }
82 const_native_handle_type const_native_handle() { return _object; }
83private:
84 native_handle_type _object;
85};
86
87struct connection
88{
89 typedef Eldbus_Connection* native_handle_type;
90 typedef Eldbus_Connection const* const_native_handle_type;
91
92 explicit connection(native_handle_type connection_)
93 : _connection(connection_) {}
94 ~connection()
95 {
96 eldbus_connection_unref(_connection);
97 }
98 connection(unknown_t)
99 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_UNKNOWN))
100 {
101 _check_connection();
102 }
103 connection(session_t)
104 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION))
105 {
106 _check_connection();
107 }
108 connection(system_t)
109 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM))
110 {
111 _check_connection();
112 }
113 connection(address_t)
114 : _connection(eldbus_connection_get(ELDBUS_CONNECTION_TYPE_ADDRESS))
115 {
116 _check_connection();
117 }
118
119 object get_object(const char* bus, const char* path) const
120 {
121 Eldbus_Object* o = eldbus_object_get
122 (const_cast<connection*>(this)->native_handle(), bus, path);
123 if(!o)
124 {
125 eina::error_code ec = eina::get_error_code();
126 assert(!!ec);
127 throw eina::system_error(ec, "eldbus");
128 }
129 return object(o);
130 }
131
132 native_handle_type native_handle() { return _connection; }
133 const_native_handle_type native_handle() const { return _connection; }
134private:
135 void _check_connection()
136 {
137 if(!_connection)
138 {
139 eina::error_code ec = eina::get_error_code();
140 assert(!!ec);
141 throw eina::system_error(ec, "eldbus");
142 }
143 }
144
145 native_handle_type _connection;
146};
147
148} }
149
150#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_error.hh b/src/bindings/cxx/eldbus_cxx/eldbus_error.hh
new file mode 100644
index 0000000..dad1d1b
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_error.hh
@@ -0,0 +1,22 @@
1#ifndef ELDBUS_ERROR_HH
2#define ELDBUS_ERROR_HH
3
4#include <Eina.hh>
5
6namespace efl { namespace eldbus {
7
8inline Eina_Error call_error_code()
9{
10 static Eina_Error error = eina_error_msg_static_register("Error while making eldbus rpc call");
11 return error;
12}
13
14inline Eina_Error signature_mismatch_error_code()
15{
16 static Eina_Error error = eina_error_msg_static_register("Mismatch function signature and signature specification");
17 return error;
18}
19
20} }
21
22#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_freedesktop.hh b/src/bindings/cxx/eldbus_cxx/eldbus_freedesktop.hh
new file mode 100644
index 0000000..4af8c58
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_freedesktop.hh
@@ -0,0 +1,72 @@
1#ifndef EFL_ELDBUS_CXX_ELDBUS_FREEDESKTOP_HH
2#define EFL_ELDBUS_CXX_ELDBUS_FREEDESKTOP_HH
3
4#include <eldbus_message.hh>
5#include <eldbus_service.hh>
6#include <eldbus_basic.hh>
7#include <eldbus_raw_tuple.hh>
8
9namespace efl { namespace eldbus { namespace _detail {
10
11template <typename Callback, typename... Ins>
12void _callback_wrapper(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
13{
14 Callback* callback(static_cast<Callback*>(data));
15
16 const char* errname, *errmsg;
17 if (eldbus_message_error_get(message, &errname, &errmsg))
18 {
19 std::cout << "error " << errname << " " << errmsg << std::endl;
20 std::tuple<Ins...> tuple;
21 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
22 eina::error_code ec (eldbus::call_error_code(), eina::eina_error_category());
23 eina::call_tuple_unwrap_prefix
24 (*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
25 , ec, msg, pending);
26 }
27
28 typename raw_tuple<std::tuple<Ins...> >::type tuple;
29 if(sizeof...(Ins))
30 {
31 if(!_detail::_init_raw_tuple<0u, std::tuple<Ins...> >
32 (eldbus_message_iter_get(message)
33 , tuple, std::integral_constant<bool, (sizeof...(Ins) == 0)>()))
34 {
35 std::cout << "error init raw tuple" << std::endl;
36 std::tuple<Ins...> tuple_;
37 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
38 eina::error_code ec(eldbus::signature_mismatch_error_code(), eina::eina_error_category());
39 eina::call_tuple_unwrap_prefix
40 (*callback, tuple_, eina::make_index_sequence<sizeof...(Ins)>()
41 , ec, msg, pending);
42 }
43 }
44 std::cout << "OK go" << std::endl;
45 eina::error_code ec;
46 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
47 eina::call_tuple_unwrap_prefix
48 (*callback, tuple, eina::make_index_sequence<sizeof...(Ins)>()
49 , ec, msg, pending);
50}
51
52template <typename F>
53void _free_cb(void* data, const void*)
54{
55 delete static_cast<F*>(data);
56}
57
58}
59
60template <typename... Ins, typename F>
61pending name_request(connection& c, const char* bus, unsigned int flags, F&& function)
62{
63 F* f = new F(std::forward<F>(function));
64 pending r = ::eldbus_name_request(c.native_handle(), bus, flags
65 , &_detail::_callback_wrapper<F, Ins...>, f);
66 eldbus_pending_free_cb_add(r.native_handle(), &_detail::_free_cb<F>, f);
67 return r;
68}
69
70} }
71
72#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_integer_sequence.hh b/src/bindings/cxx/eldbus_cxx/eldbus_integer_sequence.hh
new file mode 100644
index 0000000..282936a
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_integer_sequence.hh
@@ -0,0 +1,41 @@
1#ifndef ELDBUS_CXX_ELDBUS_INTEGER_SEQUENCE_HH
2#define ELDBUS_CXX_ELDBUS_INTEGER_SEQUENCE_HH
3
4namespace efl { namespace eldbus { namespace _detail {
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/cxx/eldbus_cxx/eldbus_message.hh b/src/bindings/cxx/eldbus_cxx/eldbus_message.hh
new file mode 100644
index 0000000..3f9e15d
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_message.hh
@@ -0,0 +1,283 @@
1#ifndef ELDBUS_CXX_ELDBUS_MESSAGE_HH
2#define ELDBUS_CXX_ELDBUS_MESSAGE_HH
3
4#include <Eldbus.h>
5#include <eldbus_signature_traits.hh>
6
7namespace efl { namespace eldbus {
8
9struct message_value
10{
11 message_value() : _iterator(0) {}
12 message_value( ::Eldbus_Message_Iter* iterator) : _iterator(iterator) {}
13
14 template <typename T>
15 T get() const
16 {
17 assert(!!_iterator);
18 std::cout << "trying to read " << _detail::signature_traits<T>::sig
19 << " has " << eldbus_message_iter_signature_get(_iterator) << std::endl;
20 T object;
21 char* c = eldbus_message_iter_signature_get(_iterator);
22 if(c[0] != _detail::signature_traits<T>::sig)
23 throw std::runtime_error("");
24 eldbus_message_iter_arguments_get(_iterator, c, &object);
25 return object;
26 }
27 friend inline bool operator==(message_value const& lhs, message_value const& rhs)
28 {
29 return
30 lhs._iterator == rhs._iterator
31 || (!lhs._iterator && rhs._iterator && std::strlen(eldbus_message_iter_signature_get(rhs._iterator)) == 0)
32 || (!rhs._iterator && lhs._iterator && std::strlen(eldbus_message_iter_signature_get(lhs._iterator)) == 0)
33 ;
34 }
35private:
36 friend struct message_iterator;
37 ::Eldbus_Message_Iter* _iterator;
38};
39
40inline bool operator!=(message_value const& lhs, message_value const& rhs)
41{
42 return !(lhs == rhs);
43}
44
45struct message_iterator
46{
47 typedef message_value value_type;
48 typedef value_type& reference;
49 typedef value_type const& const_reference;
50 typedef value_type* pointer;
51 typedef value_type const* const_pointer;
52 typedef std::ptrdiff_t difference_type;
53 typedef std::size_t size_type;
54 typedef std::input_iterator_tag iterator_category;
55
56 message_iterator()
57 {
58 }
59
60 message_iterator(Eldbus_Message_Iter* iterator)
61 : value(iterator)
62 {}
63
64 reference operator*() const
65 {
66 return const_cast<reference>(value);
67 }
68 pointer operator->() const
69 {
70 return const_cast<pointer>(&value);
71 }
72 message_iterator& operator++()
73 {
74 if(!eldbus_message_iter_next(value._iterator))
75 {
76 value._iterator = 0;
77 }
78 return *this;
79 }
80 message_iterator operator++(int)
81 {
82 message_iterator tmp(*this);
83 ++*this;
84 return tmp;
85 }
86 friend inline bool operator==(message_iterator const& lhs, message_iterator const& rhs)
87 {
88 return lhs.value == rhs.value;
89 }
90private:
91 message_value value;
92};
93
94inline bool operator!=(message_iterator const& lhs, message_iterator const& rhs)
95{
96 return !(lhs == rhs);
97}
98
99struct reply_t {};
100struct error_t {};
101struct method_call_t {};
102
103reply_t const reply = {};
104error_t const error = {};
105method_call_t const method_call = {};
106
107struct const_message
108{
109 explicit const_message(Eldbus_Message const* message) : _message(message)
110 {
111 }
112 const_message(const_message const& other, reply_t)
113 : _message( ::eldbus_message_method_return_new(other.native_handle()))
114 {
115 }
116 const_message(const_message const& other, const char* error_name, const char* error_msg, error_t)
117 : _message( ::eldbus_message_error_new(other.native_handle(), error_name, error_msg))
118 {
119 }
120 const_message(const char* destination, const char* path, const char* iface
121 , const char* method, method_call_t)
122 : _message( ::eldbus_message_method_call_new(destination, path, iface, method))
123 {
124 }
125 const_message(const_message const& other)
126 : _message( ::eldbus_message_ref(const_cast<Eldbus_Message*>(other.native_handle())))
127 {
128 }
129 ~const_message()
130 {
131 eldbus_message_unref(const_cast<Eldbus_Message*>(native_handle()));
132 }
133
134 const char* path_get() const
135 {
136 return ::eldbus_message_path_get(_message);
137 }
138 const char* interface_get() const
139 {
140 return ::eldbus_message_interface_get(_message);
141 }
142 const char* member_get() const
143 {
144 return ::eldbus_message_member_get(_message);
145 }
146 const char* destination_get() const
147 {
148 return ::eldbus_message_destination_get(_message);
149 }
150 const char* sender_get() const
151 {
152 return ::eldbus_message_sender_get(_message);
153 }
154 const char* signature_get() const
155 {
156 return ::eldbus_message_signature_get(_message);
157 }
158 bool operator!() const
159 {
160 bool b (*this);
161 return !b;
162 }
163 explicit operator bool() const
164 {
165 const char* name, * text;
166 return !eldbus_message_error_get(_message, &name, &text);
167 }
168 std::pair<const char*, const char*> error_get() const
169 {
170 const char* name, * text;
171 eldbus_message_error_get(_message, &name, &text);
172 return {name, text};
173 }
174
175 typedef message_iterator const_iterator;
176 typedef const_iterator iterator;
177 typedef Eldbus_Message const* native_handle_type;
178 typedef Eldbus_Message const* const_native_handle_type;
179 const_native_handle_type native_handle() const { return _message; }
180 const_native_handle_type const_native_handle() const { return _message; }
181
182 const_iterator begin() const
183 {
184 return const_iterator( ::eldbus_message_iter_get(_message));
185 }
186 const_iterator end() const
187 {
188 return const_iterator();
189 }
190private:
191 Eldbus_Message const* _message;
192};
193
194struct message : const_message
195{
196 typedef const_message base_type;
197
198 explicit message(Eldbus_Message* message_) : const_message(message_)
199 {
200 }
201 message(const_message const& other, reply_t r)
202 : const_message(other, r)
203 {
204 }
205 message(const_message const& other, const char* error_name, const char* error_msg, error_t e)
206 : const_message(other, error_name, error_msg, e)
207 {
208 }
209 message(const char* destination, const char* path, const char* iface
210 , const char* method, method_call_t m)
211 : const_message(destination, path, iface, method, m)
212 {
213 }
214 message(message const& other)
215 : const_message(static_cast<base_type const&>(other))
216 {
217 }
218 typedef Eldbus_Message* native_handle_type;
219 native_handle_type native_handle() { return const_cast<native_handle_type>(const_message::native_handle()); }
220};
221
222struct const_pending
223{
224 const_pending() : _pending(0) {}
225 const_pending(Eldbus_Pending const* pending) : _pending(pending) {}
226
227 void* data_get(const char* key) const
228 {
229 return ::eldbus_pending_data_get(_pending, key);
230 }
231 const char* destination_get() const
232 {
233 return ::eldbus_pending_destination_get(_pending);
234 }
235 const char* path_get() const
236 {
237 return ::eldbus_pending_path_get(_pending);
238 }
239 const char* interface_get() const
240 {
241 return ::eldbus_pending_interface_get(_pending);
242 }
243 const char* method_get() const
244 {
245 return ::eldbus_pending_method_get(_pending);
246 }
247
248 typedef Eldbus_Pending const* native_handle_type;
249 typedef Eldbus_Pending const* const_native_handle_type;
250 native_handle_type native_handle() const { return _pending; }
251 const_native_handle_type const_native_handle() const { return _pending; }
252private:
253 const_native_handle_type _pending;
254};
255
256struct pending : const_pending
257{
258 pending() : const_pending(0) {}
259 pending(Eldbus_Pending* pending_) : const_pending(pending_) {}
260
261 void data_set(const char* key, const char* data)
262 {
263 ::eldbus_pending_data_set(native_handle(), key, data);
264 }
265 void* data_del(const char* key)
266 {
267 return ::eldbus_pending_data_del(native_handle(), key);
268 }
269 void cancel()
270 {
271 ::eldbus_pending_cancel(native_handle());
272 }
273
274 typedef Eldbus_Pending* native_handle_type;
275 native_handle_type native_handle()
276 {
277 return const_cast<native_handle_type>(const_pending::native_handle());
278 }
279};
280
281} }
282
283#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_message_arguments.hh b/src/bindings/cxx/eldbus_cxx/eldbus_message_arguments.hh
new file mode 100644
index 0000000..6c57b02
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_message_arguments.hh
@@ -0,0 +1,56 @@
1#ifndef ELDBUS_CXX_ELDBUS_MESSAGE_ARGUMENTS_HH
2#define ELDBUS_CXX_ELDBUS_MESSAGE_ARGUMENTS_HH
3
4#include <Eldbus.h>
5
6#include <tuple>
7#include <iostream>
8
9namespace efl { namespace eldbus { namespace _detail {
10
11template <std::size_t I, typename Seq, typename Tuple>
12bool _init_raw_tuple(Eldbus_Message_Iter*, Tuple const&, std::true_type)
13{
14 return true;
15}
16
17template <std::size_t I, typename Seq, typename Tuple>
18bool _init_raw_tuple(Eldbus_Message_Iter* iterator, Tuple const& tuple, std::false_type)
19{
20 typedef signature_traits<typename std::tuple_element<I, Seq>::type> traits;
21 typedef typename traits::value_type element_type;
22
23 char* c = eldbus_message_iter_signature_get(iterator);
24 if(c[0] != signature_traits<element_type>::sig)
25 {
26 return false;
27 }
28
29 eldbus_message_iter_get_and_next(iterator, *c, &std::get<I>(tuple));
30
31 return _init_raw_tuple<I+1, Seq>
32 (iterator, tuple, std::integral_constant<bool, (I+1 == std::tuple_size<Tuple>::value)>());
33}
34
35template <std::size_t I, typename Tuple>
36bool _append_tuple(Eldbus_Message*, Tuple const&, std::true_type)
37{
38 return true;
39}
40
41template <std::size_t I, typename Tuple>
42bool _append_tuple(Eldbus_Message* message, Tuple const& tuple, std::false_type)
43{
44 typedef signature_traits<typename std::tuple_element<I, Tuple>::type> traits;
45
46 char signature[2] = {traits::sig, 0};
47 if(!eldbus_message_arguments_append(message, signature, traits::to_raw(std::get<I>(tuple))))
48 return false;
49
50 return _append_tuple<I+1>
51 (message, tuple, std::integral_constant<bool, (I+1 == std::tuple_size<Tuple>::value)>());
52}
53
54} } }
55
56#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_proxy_call.hh b/src/bindings/cxx/eldbus_cxx/eldbus_proxy_call.hh
new file mode 100644
index 0000000..f06f71a
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_proxy_call.hh
@@ -0,0 +1,117 @@
1#ifndef ELDBUS_PROXY_CALL_HH
2#define ELDBUS_PROXY_CALL_HH
3
4#include <Eina.hh>
5#include <eldbus_error.hh>
6#include <eldbus_signature_traits.hh>
7#include <eldbus_message_arguments.hh>
8#include <eldbus_message.hh>
9#include <eldbus_raw_tuple.hh>
10#include <eina_integer_sequence.hh>
11#include <eina_tuple_unwrap.hh>
12
13#include <tuple>
14
15#include <iostream>
16
17namespace efl { namespace eldbus { namespace _detail {
18
19template <typename T> struct tag {};
20
21template <typename Seq, typename Callback, std::size_t... I>
22void _on_call_impl(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
23{
24 std::unique_ptr<Callback> callback(static_cast<Callback*>(data));
25
26 const char* errname, *errmsg;
27 if (eldbus_message_error_get(message, &errname, &errmsg))
28 {
29 Seq tuple_;
30 ::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
31 eldbus::const_message msg(message);
32 eina::error_code ec (eldbus::call_error_code(), eina::eina_error_category());
33 eina::call_tuple_unwrap_prefix
34 (*callback, tuple_, eina::make_index_sequence<std::tuple_size<Seq>::value>()
35 , ec, msg, pending);
36 }
37
38 typename raw_tuple<Seq>::type tuple;
39 if(std::tuple_size<Seq>::value)
40 {
41 if(!_detail::_init_raw_tuple<0u, Seq>
42 (eldbus_message_iter_get(message)
43 , tuple, std::integral_constant<bool, (std::tuple_size<Seq>::value == 0)>()))
44 {
45 Seq tuple_;
46 ::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
47 eldbus::const_message msg(message);
48 eina::error_code ec(eldbus::signature_mismatch_error_code(), eina::eina_error_category());
49 eina::call_tuple_unwrap_prefix
50 (*callback, tuple_, eina::make_index_sequence<std::tuple_size<Seq>::value>()
51 , ec, msg, pending);
52 }
53 }
54 eina::error_code ec;
55 ::eldbus_message_ref(const_cast<Eldbus_Message*>(message));
56 eldbus::const_message msg(message);
57 eina::call_tuple_unwrap_prefix
58 (*callback, tuple, eina::make_index_sequence<std::tuple_size<Seq>::value>()
59 , ec, msg, pending);
60}
61
62template <typename Seq, typename Callback>
63void _on_call(void* data, Eldbus_Message const* message, Eldbus_Pending* pending)
64{
65 _detail::_on_call_impl<Seq, Callback>(data, message, pending);
66}
67
68template <typename R, typename Callback, typename... Args>
69void proxy_call_impl2(Eldbus_Proxy* proxy, const char* method, double timeout
70 , Callback&& callback, Args const&... args)
71{
72 typedef std::tuple<Args...> tuple_args;
73 char signature[signature_size<tuple_args>::value +1];
74 _detail::init_signature_array<Args...>
75 (signature, eina::make_index_sequence<signature_size<tuple_args>::value +1>());
76
77 Callback* c = new Callback(std::forward<Callback>(callback));
78
79 eldbus_proxy_call(proxy, method, &_on_call<R, Callback>, c, timeout, signature
80 , _detail::to_raw(args)...);
81}
82
83template <typename R, typename Callback, typename... Args>
84void proxy_call_impl(tag<R>, Eldbus_Proxy* proxy, const char* method, double timeout
85 , Callback&& callback, Args const&... args)
86{
87 typedef std::tuple<R> reply_tuple;
88 _detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::forward<Callback>(callback), args...);
89}
90
91template <typename... R, typename Callback, typename... Args>
92void proxy_call_impl(tag<std::tuple<R...> >, Eldbus_Proxy* proxy, const char* method, double timeout
93 , Callback&& callback, Args const&... args)
94{
95 typedef std::tuple<R...> reply_tuple;
96 _detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::forward<Callback>(callback), args...);
97}
98
99template <typename Callback, typename... Args>
100void proxy_call_impl(tag<void>, Eldbus_Proxy* proxy, const char* method, double timeout
101 , Callback&& callback, Args const&... args)
102{
103 typedef std::tuple<> reply_tuple;
104 _detail::proxy_call_impl2<reply_tuple>(proxy, method, timeout, std::forward<Callback>(callback), args...);
105}
106
107template <typename R, typename Callback, typename... Args>
108void proxy_call(Eldbus_Proxy* proxy, const char* method, double timeout
109 , Callback&& callback, Args const&... args)
110{
111 return proxy_call_impl(tag<R>(), proxy, method, timeout, std::forward<Callback>(callback), args...);
112}
113
114} } }
115
116#endif
117
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_raw_tuple.hh b/src/bindings/cxx/eldbus_cxx/eldbus_raw_tuple.hh
new file mode 100644
index 0000000..ee17cfb
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_raw_tuple.hh
@@ -0,0 +1,30 @@
1#ifndef EFL_ELDBUS_CXX_ELDBUS_RAW_TUPLE_HH
2#define EFL_ELDBUS_CXX_ELDBUS_RAW_TUPLE_HH
3
4#include <eldbus_signature_traits.hh>
5
6#include <eina_fold.hh>
7#include <eina_tuple.hh>
8
9namespace efl { namespace eldbus { namespace _detail {
10
11template <typename T>
12struct raw_tuple;
13
14template <typename... T>
15struct raw_tuple<std::tuple<T...> >
16{
17 struct push_back
18 {
19 template <typename L, typename R>
20 struct apply
21 : eina::_mpl::push_back<L, typename signature_traits<R>::raw_type> {};
22 };
23
24 typedef typename eina::_mpl::fold< std::tuple<T...>, push_back
25 , std::tuple<> >::type type;
26};
27
28} } }
29
30#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_service.hh b/src/bindings/cxx/eldbus_cxx/eldbus_service.hh
new file mode 100644
index 0000000..6a4919c
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_service.hh
@@ -0,0 +1,379 @@
1#ifndef ELDBUS_CXX_ELDBUS_SERVICE_HH
2#define ELDBUS_CXX_ELDBUS_SERVICE_HH
3
4#include <array>
5
6namespace efl { namespace eldbus {
7
8struct service_interface
9{
10 service_interface(Eldbus_Service_Interface const* iface)
11 : _iface(iface)
12 {}
13
14 typedef Eldbus_Service_Interface* native_handle_type;
15 typedef Eldbus_Service_Interface const* const_native_handle_type;
16 const_native_handle_type native_handle() { return _iface; }
17 const_native_handle_type native_handle() const { return _iface; }
18private:
19 const_native_handle_type _iface;
20};
21
22namespace service {
23
24template <typename F, typename Ins, typename Outs>
25struct method_specification
26{
27 const char* name;
28 F f;
29
30 typedef F function_type;
31 typedef Ins ins_type;
32 typedef Outs outs_type;
33
34 ins_type ins;
35 outs_type outs;
36};
37
38namespace _detail {
39
40template <typename T>
41struct const_char_type
42{
43 typedef const char* type;
44};
45
46}
47
48template <typename... Args>
49struct ins
50{
51 ins(typename _detail::const_char_type<Args>::type... names) : _names({{names...}}) {}
52
53 static constexpr std::size_t size() { return sizeof...(Args); }
54
55 typedef std::tuple<Args...> types;
56 std::array<const char*, sizeof...(Args)> _names;
57};
58
59template <typename... Args>
60struct outs
61{
62 outs(typename _detail::const_char_type<Args>::type... names) : _names({{names...}}) {}
63
64 static constexpr std::size_t size() { return sizeof...(Args); }
65
66 typedef std::tuple<Args...> types;
67 std::array<const char*, sizeof...(Args)> _names;
68};
69
70void foo(int);
71
72template <typename F, typename Ins, typename Outs>
73method_specification<F, Ins, Outs>
74method(const char* name, F f, Ins ins, Outs outs)
75{
76 return method_specification<F, Ins, Outs>
77 {name, f, ins, outs}
78 ;
79}
80
81template <typename F, typename... Outs>
82method_specification<F, service::ins<>, service::outs<Outs...> >
83method(const char* name, F f, service::outs<Outs...> outs)
84{
85 return method_specification<F, service::ins<>, service::outs<Outs...> >
86 {name, f, service::ins<>(), outs}
87 ;
88}
89
90template <typename F, typename... Ins>
91method_specification<F, service::ins<Ins...>, service::outs<> >
92method(const char* name, F f, service::ins<Ins...> ins)
93{
94 return method_specification<F, service::ins<Ins...>, service::outs<> >
95 {name, f, ins, service::outs<>()}
96 ;
97}
98
99}
100
101template <std::size_t I, std::size_t N, template <typename...> class params
102 , typename ... Args>
103int _fill_method_impl(std::array<Eldbus_Arg_Info, N>& array
104 , params<Args...> const&
105 , std::true_type)
106{
107 array[I] = Eldbus_Arg_Info {0, 0};
108 return 0;
109}
110
111
112template <std::size_t I, std::size_t N, template <typename...> class params
113 , typename ... Args>
114int _fill_method_impl(std::array<Eldbus_Arg_Info, N>& array
115 , params<Args...> const& directional_methods
116 , std::false_type)
117{
118 typedef std::tuple<Args...> params_type;
119 static const char sig[2]
120 = {_detail::signature_traits
121 <
122 typename std::tuple_element<I, params_type>::type
123 >::sig
124 , '\0'
125 };
126 array[I] = {sig
127 , directional_methods._names[I]
128 };
129 return 0;
130}
131
132
133template <std::size_t I, std::size_t N, template <typename...> class params
134 , typename ... Args>
135int _fill_method(std::array<Eldbus_Arg_Info, N>& array
136 , params<Args...> const& directional_methods)
137{
138 _fill_method_impl<I>(array, directional_methods
139 , std::integral_constant<bool, N-1 == I>());
140 return 0;
141}
142
143template <typename... T>
144void _foo(T...) {}
145
146template <std::size_t N, template <typename...> class params, typename ... Args
147 , std::size_t... Seq>
148void _fill_methods_impl(std::array<Eldbus_Arg_Info, N>& array
149 , params<Args...> const& directional_methods
150 , eina::index_sequence<Seq...>
151 )
152{
153 eldbus::_foo(eldbus::_fill_method<Seq>(array, directional_methods) ...);
154}
155
156template <std::size_t N, template <typename...> class params, typename ... Args>
157void _fill_methods(std::array<Eldbus_Arg_Info, N>& array
158 , params<Args...> const& directional_methods)
159{
160 eldbus::_fill_methods_impl(array, directional_methods
161 , eina::make_index_sequence<N>());
162}
163
164template <typename Tuple, std::size_t I>
165void _create_methods_specification(Tuple const&
166 , std::array<Eldbus_Method2, std::tuple_size<Tuple>::value+1>& methods
167 , std::integral_constant<std::size_t, I>
168 , std::true_type)
169{
170 methods[I] = Eldbus_Method2 {{0, 0, 0, 0, 0}, 0};
171};
172
173template <std::size_t, typename T>
174T get_in(Eldbus_Message const* msg)
175{
176 typename _detail::signature_traits<T>::raw_type object;
177
178 const char sig[2] = {_detail::signature_traits<T>::sig, 0};
179 if (!eldbus_message_arguments_get(msg, sig, &object))
180 {
181 printf("eldbus_message_arguments_get() error\n");
182 throw std::runtime_error("");
183 }
184 else
185 {
186 return object;
187 }
188}
189
190template <typename Callable, typename... Ins, typename... Outs
191 , std::size_t... IndexIns, std::size_t... IndexOuts
192 , std::size_t... IndexOuts2>
193Eldbus_Message* _method_callback_call
194(Callable const& callable, service::ins<Ins...> const&, service::outs<Outs...> const&
195 , eina::index_sequence<IndexIns...>, eina::index_sequence<IndexOuts...>
196 , eina::index_sequence<IndexOuts2...>
197 , Eldbus_Service_Interface const* iface, Eldbus_Message const* message
198 , typename std::enable_if
199 <!std::is_void
200 <decltype(callable
201 (*static_cast<eldbus::message*>(nullptr)
202 , *static_cast<eldbus::service_interface*>(nullptr)
203 , std::get<IndexIns>(std::tuple<Ins...>())...
204 , &std::get<IndexOuts2>
205 (*static_cast<std::tuple<Outs...>*>(nullptr))...
206 )
207 )>::value, int>::type)
208{
209 typedef std::tuple<Ins...> tuple_ins;
210 typename _detail::raw_tuple<tuple_ins>::type tuple_ins_raw;
211 _detail::_init_raw_tuple<0u, tuple_ins>
212 (eldbus_message_iter_get(message), tuple_ins_raw
213 , std::integral_constant<bool, (std::tuple_size<tuple_ins>::value == 0u)>());
214
215 std::tuple<Outs...> tuple_outs;
216
217 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
218 eldbus::service_interface siface(iface);
219
220 // If you have an error here, then you probably got your ins<...>
221 // and/or outs<...> different from the arguments of your callable
222 //typedef _detail::signature_traits<result_type> traits;
223 std::get<0u>(tuple_outs) =
224 callable(msg, siface, std::get<IndexIns>(tuple_ins_raw)..., &std::get<IndexOuts2>(tuple_outs)...);
225
226 Eldbus_Message *reply_ = eldbus_message_method_return_new(message);
227 _detail::_append_tuple<0u>(reply_, tuple_outs, std::false_type());
228 return reply_;
229}
230
231template <typename Callable, typename... Ins, typename... Outs
232 , std::size_t... IndexIns, std::size_t... IndexOuts
233 , std::size_t... IndexOuts2>
234Eldbus_Message* _method_callback_call
235(Callable const& callable, service::ins<Ins...> const&, service::outs<Outs...> const&
236 , eina::index_sequence<IndexIns...>, eina::index_sequence<IndexOuts...>
237 , eina::index_sequence<IndexOuts2...>
238 , Eldbus_Service_Interface const* iface, Eldbus_Message const* message
239 , long)
240{
241 typedef std::tuple<Ins...> tuple_ins;
242 typename _detail::raw_tuple<tuple_ins>::type tuple_ins_raw;
243 _detail::_init_raw_tuple<0u, tuple_ins>
244 (eldbus_message_iter_get(message), tuple_ins_raw
245 , std::integral_constant<bool, (std::tuple_size<tuple_ins>::value == 0u)>());
246
247 typedef std::tuple<Outs...> tuple_outs_type;
248 tuple_outs_type tuple_outs;
249
250 eldbus::const_message msg( ::eldbus_message_ref(const_cast<Eldbus_Message*>(message)));
251 eldbus::service_interface siface(iface);
252
253 // If you have an error here, then you probably got your ins<...>
254 // and/or outs<...> different from the arguments of your callable
255 callable(msg, siface, std::get<IndexIns>(tuple_ins_raw)..., &std::get<IndexOuts>(tuple_outs)...);
256
257 Eldbus_Message *reply_ = eldbus_message_method_return_new(message);
258 _detail::_append_tuple<0u>
259 (reply_, tuple_outs
260 , std::integral_constant<bool, std::tuple_size<tuple_outs_type>::value == 0u>());
261 return reply_;
262}
263
264template <typename Callable, typename Ins, typename Outs>
265Eldbus_Message* _method_callback(void* data, Eldbus_Service_Interface const* iface, Eldbus_Message const* msg)
266{
267 std::tuple<Callable, Ins, Outs>*
268 tuple = static_cast<std::tuple<Callable, Ins, Outs>*>(data);
269
270 return _method_callback_call(std::get<0u>(*tuple), std::get<1u>(*tuple), std::get<2u>(*tuple)
271 , eina::make_index_sequence
272 <std::tuple_size<typename Ins::types>::value>()
273 , eina::make_index_sequence
274 <std::tuple_size<typename Outs::types>::value>()
275 , eina::pop_integer_sequence
276 <eina::make_index_sequence<0u>
277 , eina::make_index_sequence
278 <std::tuple_size<typename Outs::types>::value>
279 >()
280 , iface, msg, 0);
281}
282
283template <typename Method>
284void _create_methods_specification_impl(Method const& method, Eldbus_Method2& eldbus_method, std::false_type)
285{
286 std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>*
287 in_params = new std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>;
288
289 eldbus::_fill_methods(*in_params, method.ins);
290
291 std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>*
292 out_params = new std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>;
293
294 eldbus::_fill_methods(*out_params, method.outs);
295
296 eldbus_method = {{method.name, &(*in_params)[0], &(*out_params)[0]
297 , reinterpret_cast<Eldbus_Method_Cb>
298 (static_cast<Eldbus_Method_Data_Cb>
299 (&_method_callback<typename Method::function_type
300 , typename Method::ins_type, typename Method::outs_type>))
301 , ELDBUS_METHOD_FLAG_HAS_DATA}
302 , new std::tuple<typename Method::function_type
303 , typename Method::ins_type, typename Method::outs_type
304 >(std::move(method.f), method.ins, method.outs)};
305}
306
307template <typename Method>
308void _create_methods_specification_impl(Method const& method, Eldbus_Method2& eldbus_method, std::true_type)
309{
310 std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>*
311 in_params = new std::array<Eldbus_Arg_Info, Method::ins_type::size()+1>;
312
313 eldbus::_fill_methods(*in_params, method.ins);
314
315 std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>*
316 out_params = new std::array<Eldbus_Arg_Info, Method::outs_type::size()+1>;
317
318 eldbus::_fill_methods(*out_params, method.outs);
319
320 eldbus_method = {method.name, &(*in_params)[0], &(*out_params)[0], method.f, 0, 0};
321}
322
323template <typename Tuple, std::size_t I>
324void _create_methods_specification(Tuple const& tuple
325 , std::array<Eldbus_Method2, std::tuple_size<Tuple>::value+1>& methods
326 , std::integral_constant<std::size_t, I>
327 , std::false_type)
328{
329 typedef Eldbus_Message*(*function_type)(Eldbus_Service_Interface const*, Eldbus_Message const*);
330
331 typedef typename std::tuple_element<I, Tuple>::type method_type;
332
333 _create_methods_specification_impl(std::get<I>(tuple), methods[I]
334 , std::is_convertible<typename method_type::function_type
335 , function_type>());
336
337 return _create_methods_specification(tuple, methods
338 , std::integral_constant<std::size_t, I+1>()
339 , std::integral_constant<bool, I+1 == std::tuple_size<Tuple>::value>());
340};
341
342template <typename Tuple>
343std::array<Eldbus_Method2, std::tuple_size<Tuple>::value+1> _create_methods_specification
344 (Tuple const& tuple
345 )
346{
347 typedef std::tuple_size<Tuple> tuple_size;
348 std::array<Eldbus_Method2, tuple_size::value+1> array;
349
350 _create_methods_specification(tuple, array
351 , std::integral_constant<std::size_t, 0u>()
352 , std::integral_constant<bool, 0 == std::tuple_size<Tuple>::value>());
353 return array;
354};
355
356template <typename... Args>
357service_interface service_interface_register(connection& c, const char* path
358 , const char* interface
359 , Args... args
360 )
361{
362 std::array<Eldbus_Method2, sizeof...(Args) + 1>* methods
363 = new std::array<Eldbus_Method2, sizeof...(Args) + 1>
364 (
365 _create_methods_specification(std::make_tuple(args...))
366 );
367 Eldbus_Service_Interface_Desc2 description =
368 {
369 {interface, 0, 0, 0, 0, 0}, ELDBUS_INTERFACE_DESCRIPTOR_VERSION, &(*methods)[0]
370 };
371
372 Eldbus_Service_Interface* iface
373 = ::eldbus_service_interface_register2(c.native_handle(), path, &description);
374 return service_interface(iface);
375}
376
377} }
378
379#endif
diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_signature_traits.hh b/src/bindings/cxx/eldbus_cxx/eldbus_signature_traits.hh
new file mode 100644
index 0000000..8f2f324
--- /dev/null
+++ b/src/bindings/cxx/eldbus_cxx/eldbus_signature_traits.hh
@@ -0,0 +1,194 @@
1#ifndef ELDBUS_SIGNATURE_TRAITS_HH_
2#define ELDBUS_SIGNATURE_TRAITS_HH_
3
4#include <eina_fold.hh>
5#include <eina_integer_sequence.hh>
6
7namespace efl { namespace eldbus { namespace _detail {
8
9template <typename T>
10struct signature_traits;
11
12template <>
13struct signature_traits<bool>
14{
15 typedef Eina_Bool raw_type;
16 typedef bool value_type;
17 typedef std::integral_constant<int, 1u> sig_size;
18 static int const sig = 'b';
19
20 static raw_type to_raw(value_type v) { return v ? EINA_TRUE : EINA_FALSE; }
21};
22
23template <>
24struct signature_traits<char>
25{
26 typedef char raw_type;
27 typedef raw_type value_type;
28 typedef std::integral_constant<int, 1u> sig_size;
29 static int const sig = 'y';
30
31 static raw_type to_raw(value_type v) { return v; }
32};
33
34template <>
35struct signature_traits<int16_t>
36{
37 typedef int16_t raw_type;
38 typedef raw_type value_type;
39 typedef std::integral_constant<int, 1u> sig_size;
40 static char const sig = 'n';
41
42 static raw_type to_raw(value_type v) { return v; }
43};
44
45template <>
46struct signature_traits<uint16_t>
47{
48 typedef uint16_t raw_type;
49 typedef raw_type value_type;
50 typedef std::integral_constant<int, 1u> sig_size;
51 static char const sig = 'q';
52
53 static raw_type to_raw(value_type i) { return i; }
54};
55
56template <>
57struct signature_traits<int32_t>
58{
59 typedef int32_t raw_type;
60 typedef raw_type value_type;
61 typedef std::integral_constant<int, 1u> sig_size;
62 static char const sig = 'i';
63
64 static raw_type to_raw(value_type i) { return i; }
65};
66
67template <>
68struct signature_traits<uint32_t>
69{
70 typedef uint32_t raw_type;
71 typedef raw_type value_type;
72 typedef std::integral_constant<int, 1u> sig_size;
73 static char const sig = 'u';
74
75 static raw_type to_raw(value_type i) { return i; }
76};
77
78template <>
79struct signature_traits<int64_t>
80{
81 typedef int64_t raw_type;
82 typedef raw_type value_type;
83 typedef std::integral_constant<int, 1u> sig_size;
84 static char const sig = 'x';
85
86 static raw_type to_raw(value_type i) { return i; }
87};
88
89template <>
90struct signature_traits<uint64_t>
91{
92 typedef uint64_t raw_type;
93 typedef raw_type value_type;
94 typedef std::integral_constant<int, 1u> sig_size;
95 static char const sig = 't';
96
97 static raw_type to_raw(value_type i) { return i; }
98};
99
100template <>
101struct signature_traits<double>
102{
103 typedef double raw_type;
104 typedef raw_type value_type;
105 typedef std::integral_constant<int, 1u> sig_size;
106 static char const sig = 'd';
107
108 static raw_type to_raw(value_type i) { return i; }
109};
110
111template <>
112struct signature_traits<std::string>
113{
114 typedef const char* raw_type;
115 typedef std::string value_type;
116 typedef std::integral_constant<int, 1u> sig_size;
117 static char const sig = 's';
118
119 static raw_type to_raw(std::string const& s) { return s.c_str(); }
120};
121
122template <typename T>
123struct signature_traits<T const> : signature_traits<T>
124{
125};
126
127template <typename T>
128typename signature_traits<T>::raw_type to_raw(T const& object)
129{
130 return signature_traits<T>::to_raw(object);
131}
132
133constexpr std::size_t add(std::size_t N)
134{
135 return N;
136}
137
138constexpr std::size_t add(std::size_t L, std::size_t R)
139{
140 return L + R;
141}
142
143template <typename... T>
144constexpr std::size_t add(std::size_t L, std::size_t R, T ... O)
145{
146 return L + R + add(O...);
147}
148
149template <typename T, typename U>
150struct signature_size_impl;
151
152template <typename T, std::size_t... S>
153struct signature_size_impl<T, eina::index_sequence<S...> >
154 : std::integral_constant
155 <std::size_t
156 , _detail::add
157 (signature_traits<typename std::tuple_element<S, T>::type>::sig_size::value...)>
158{
159
160};
161
162template <typename T>
163struct signature_size : signature_size_impl<T, eina::make_index_sequence<std::tuple_size<T>::value> >
164{
165
166};
167
168template <typename ... T>
169void call_all(T...) {}
170
171template <std::size_t I, typename Tuple, std::size_t N
172 , typename = typename std::enable_if<I != N-1>::type>
173int init_signature(char (&signature)[N])
174{
175 signature[I] = signature_traits<typename std::tuple_element<I, Tuple>::type>::sig;
176 return 0;
177}
178
179template <std::size_t I, typename Tuple>
180int init_signature(char (&signature)[I+1])
181{
182 signature[I] = 0;
183 return 0;
184}
185
186template <typename... Args, std::size_t... S, std::size_t N>
187void init_signature_array(char (&signature)[N], eina::index_sequence<S...>)
188{
189 call_all(_detail::init_signature<S, std::tuple<Args...> >(signature)...);
190}
191
192} } }
193
194#endif