/* * Copyright 2019 by its authors. See AUTHORS. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef EET_HH_ #define EET_HH_ #include #include #include #include #include #include #include #include #include namespace efl { namespace eet { namespace _detail { template void* _allocate( ::size_t size ) { assert(size == sizeof(T)); (void)size; return new T(); } template void _deallocate( void* p ) { delete static_cast(p); } template struct descriptor_type { struct push_back { template struct apply : eina::_mpl::push_back::type> {}; }; typedef typename eina::_mpl::fold< std::tuple, push_back , descriptor >::type type; }; } #define EET_CXX_MEMBER(C, I) ::efl::eet::type(#I, &C::I) template _detail::member_info type(const char* name, F f) { typedef typename _detail::member_type::type member_type; static_assert(is_eet_primitive::value, ""); static_assert(std::is_member_pointer::value, ""); return _detail::member_info{name, f}; } template _detail::member_info type(const char* name, F f, descriptor const& descriptor) { typedef typename _detail::member_type::type member_type; static_assert(!is_eet_primitive::value, ""); static_assert(std::is_member_pointer::value, ""); return _detail::member_info{name, f, &descriptor}; } struct eet_init { eet_init() { ::eet_init(); } ~eet_init() { ::eet_shutdown(); } }; template struct descriptor { typedef T object_type; descriptor() : _descriptor(nullptr) {} descriptor( ::Eet_Data_Descriptor* descriptor_ , std::array<_detail::member_desc_info, sizeof...(Args)> member_info) : _descriptor(descriptor_), _member_info(member_info) { } descriptor(descriptor&& other) : _descriptor(other._descriptor) { other._descriptor = 0; } descriptor& operator=(descriptor&& other) { if(_descriptor) eet_data_descriptor_free(_descriptor); _descriptor = other._descriptor; other._descriptor = 0; return *this; } ~descriptor() { if(_descriptor) eet_data_descriptor_free(_descriptor); } typedef ::Eet_Data_Descriptor const* const_native_handle_type; typedef ::Eet_Data_Descriptor* native_handle_type; const_native_handle_type native_handle() const { return _descriptor; } native_handle_type native_handle() { return _descriptor; } typedef std::integral_constant members; std::array<_detail::member_desc_info, sizeof...(Args)> get_member_info() const { return _member_info; } private: ::Eet_Data_Descriptor* _descriptor; typedef descriptor _self_type; descriptor(descriptor const&) = delete; descriptor& operator=(descriptor const&) = delete; std::array<_detail::member_desc_info, sizeof...(Args)> _member_info; }; template std::unique_ptr read_by_ptr(Eet_File* file, const char* name, descriptor const& d) { void* p = eet_data_read(file, const_cast&>(d).native_handle(), name); return std::unique_ptr(static_cast(p)); } template T read(Eet_File* file, const char* name, descriptor const& d) { typename std::aligned_storage::type buffer; void * p = ::eet_data_read_cipher_buffer (file , const_cast&>(d).native_handle() , name, 0 , static_cast(static_cast(&buffer)) , sizeof(buffer)); if(p) { assert(p == &buffer); return *static_cast(p); } else throw std::runtime_error(""); } namespace _detail { template inline void _item_fill(O*, ::Eet_Data_Descriptor*, member_desc_info*) {} template inline void _item_fill(O* obj, ::Eet_Data_Descriptor* cls, member_desc_info* offset , _detail::member_info arg0, FArgs... args) { static_assert(std::is_member_object_pointer::value, ""); offset->offset = static_cast( static_cast( &(obj ->* arg0.member) )) - static_cast( static_cast( obj ) ); offset->name = arg0.name; _detail::_item_fill(obj, cls, ++offset, args...); } } template typename _detail::descriptor_type ::type , _detail::member_info, Args... >::type make_descriptor(const char* name, _detail::member_info a0, Args... args) { typedef F member_pointer; static_assert(std::is_member_object_pointer::value, ""); typedef typename _detail::object_type::type object_type; typedef typename _detail::descriptor_type , Args...>::type descriptor_type; ::Eet_Data_Descriptor_Class cls; eet_eina_file_data_descriptor_class_set(&cls, sizeof(cls), name, sizeof(object_type)); cls.func.mem_alloc = & _detail::_allocate; cls.func.mem_free = & _detail::_deallocate; ::Eet_Data_Descriptor* native_handle = eet_data_descriptor_stream_new(&cls); if(!native_handle) throw std::runtime_error(""); typename std::aligned_storage::type buffer; object_type* p = static_cast(static_cast(&buffer)); std::array<_detail::member_desc_info, sizeof...(Args)+1> offsets; _detail::_item_fill(p, native_handle, &offsets[0], a0, args...); _detail::descriptor_type_register(native_handle, &offsets[0], a0, args...); return descriptor_type(native_handle, offsets); } } } #endif