eet-cxx: add implementation for eet C++.
[platform/upstream/efl.git] / src / bindings / eet_cxx / Eet.hh
1 #ifndef EET_HH_
2 #define EET_HH_
3
4 #include <Eet.h>
5
6 #include <eet_type.hh>
7 #include <eet_fold.hh>
8 #include <eet_register.hh>
9
10 #include <type_traits>
11 #include <cassert>
12 #include <stdexcept>
13
14 #include <iostream>
15 #include <array>
16
17 namespace efl { namespace eet { namespace _detail {
18
19 template <typename T>
20 void* _allocate( ::size_t size )
21 {
22   assert(size == sizeof(T));
23   (void)size;
24   return new T();
25 }
26
27 template <typename T>
28 void _deallocate( void* p )
29 {
30   delete static_cast<T*>(p);
31 }
32
33 template <typename T, typename... Args>
34 struct descriptor_type
35 {
36   struct push_back
37   {
38     template <typename A, typename B>
39     struct apply : _mpl::push_back<A, typename _detail::member_type<typename B::member_type>::type> {};
40   };
41
42   typedef typename _mpl::fold< std::tuple<Args...>, push_back
43     , descriptor<T> >::type type;
44 };
45
46 }
47
48 #define EET_CXX_MEMBER(C, I) ::efl::eet::type(#I, &C::I)
49
50 template <typename F>
51 _detail::member_info<F, void> type(const char* name, F f)
52 {
53   typedef typename _detail::member_type<F>::type member_type;
54   static_assert(is_eet_primitive<member_type>::value, "");
55   static_assert(std::is_member_pointer<F>::value, "");
56   return _detail::member_info<F, void>{name, f};
57 }
58
59 template <typename F, typename U, typename... Args>
60 _detail::member_info<F, U, Args...> type(const char* name, F f, descriptor<U, Args...> const& descriptor)
61 {
62   typedef typename _detail::member_type<F>::type member_type;
63   static_assert(!is_eet_primitive<member_type>::value, "");
64   static_assert(std::is_member_pointer<F>::value, "");
65   return _detail::member_info<F, U, Args...>{name, f, &descriptor};
66 }
67
68 struct eet_init
69 {
70   eet_init()
71   {
72     ::eet_init();
73   }
74   ~eet_init()
75   {
76     ::eet_shutdown();
77   }
78 };
79
80 template <typename T, typename... Args>
81 struct descriptor
82 {
83   typedef T object_type;
84
85   descriptor() : _descriptor(nullptr) {}
86   descriptor( ::Eet_Data_Descriptor* descriptor
87               , std::array<_detail::member_desc_info, sizeof...(Args)> member_info)
88     : _descriptor(descriptor), _member_info(member_info)
89   {
90   }
91   descriptor(descriptor&& other)
92     : _descriptor(other._descriptor)
93   {
94     other._descriptor = 0;
95   }
96   descriptor& operator=(descriptor&& other)
97   {
98     if(_descriptor)
99       eet_data_descriptor_free(_descriptor);
100     _descriptor = other._descriptor;
101     other._descriptor = 0;
102     return *this;
103   }
104   ~descriptor()
105   {
106     if(_descriptor)
107       eet_data_descriptor_free(_descriptor);
108   }
109   typedef ::Eet_Data_Descriptor const* const_native_handle_type;
110   typedef ::Eet_Data_Descriptor* native_handle_type;
111   const_native_handle_type native_handle() const
112   {
113     return _descriptor;
114   }
115   native_handle_type native_handle()
116   {
117     return _descriptor;
118   }
119   typedef std::integral_constant<std::size_t, sizeof...(Args)> members;
120
121   std::array<_detail::member_desc_info, sizeof...(Args)> get_member_info() const { return _member_info; }
122 private:
123   ::Eet_Data_Descriptor* _descriptor;
124   typedef descriptor<T, Args...> _self_type;
125   descriptor(descriptor const&) = delete;
126   descriptor& operator=(descriptor const&) = delete;
127   std::array<_detail::member_desc_info, sizeof...(Args)> _member_info;
128 };
129
130 template <typename T, typename... Args>
131 std::unique_ptr<T> read_by_ptr(Eet_File* file, const char* name, descriptor<T, Args...> const& d)
132 {
133   void* p = eet_data_read(file, const_cast<descriptor<T, Args...>&>(d).native_handle(), name);
134   return std::unique_ptr<T>(static_cast<T*>(p));
135 }
136
137 template <typename T, typename... Args>
138 T read(Eet_File* file, const char* name, descriptor<T, Args...> const& d)
139 {
140   typename std::aligned_storage<sizeof(T), alignof(T)>::type buffer;
141   void * p =
142     ::eet_data_read_cipher_buffer
143     (file
144      , const_cast<descriptor<T, Args...>&>(d).native_handle()
145      , name, 0
146      , static_cast<char*>(static_cast<void*>(&buffer))
147      , sizeof(buffer));
148   if(p)
149     {
150       assert(p == &buffer);
151       return *static_cast<T*>(p);
152     }
153   else
154     throw std::runtime_error("");
155 }
156
157 namespace _detail {
158
159 template <typename O>
160 inline void _item_fill(O*, ::Eet_Data_Descriptor*, member_desc_info*) {}
161
162 template <typename O, typename F, typename D, typename... Args, typename... FArgs>
163 inline void _item_fill(O* obj, ::Eet_Data_Descriptor* cls, member_desc_info* offset
164                        , _detail::member_info<F, D, Args...> arg0, FArgs... args)
165 {
166   static_assert(std::is_member_object_pointer<F>::value, "");
167   offset->offset = static_cast<char*>( static_cast<void*>( &(obj ->* arg0.member) ))
168     - static_cast<char*>( static_cast<void*>( obj ) );
169   offset->name = arg0.name;
170   _detail::_item_fill(obj, cls, ++offset, args...);
171 }
172
173 }
174
175 template <typename F, typename D, typename... OArgs, typename... Args>
176 typename _detail::descriptor_type
177 <typename _detail::object_type<F>::type
178  , _detail::member_info<F, D, OArgs...>, Args...
179 >::type make_descriptor(const char* name, _detail::member_info<F, D, OArgs...> a0, Args... args)
180 {
181   typedef F member_pointer;
182   static_assert(std::is_member_object_pointer<member_pointer>::value, "");
183   typedef typename _detail::object_type<member_pointer>::type object_type;
184
185   typedef typename _detail::descriptor_type
186     <object_type, _detail::member_info<F, D, OArgs...>, Args...>::type descriptor_type;
187
188   ::Eet_Data_Descriptor_Class cls
189   {
190       EET_DATA_DESCRIPTOR_CLASS_VERSION
191     , name
192     , sizeof(object_type)
193     , {
194         & _detail::_allocate<object_type>
195       , & _detail::_deallocate<object_type>
196       }
197   };
198   ::Eet_Data_Descriptor* native_handle = eet_data_descriptor_stream_new(&cls);
199   if(!native_handle)
200     throw std::runtime_error("");
201
202   typename std::aligned_storage<sizeof(object_type), alignof(object_type)>::type buffer;
203   object_type* p = static_cast<object_type*>(static_cast<void*>(&buffer));
204
205   std::array<_detail::member_desc_info, sizeof...(Args)+1> offsets;
206   _detail::_item_fill(p, native_handle, &offsets[0], a0, args...);
207   _detail::descriptor_type_register(native_handle, &offsets[0], a0, args...);
208
209   return descriptor_type(native_handle, offsets);
210 }
211
212 } }
213
214 #endif