Shitload of warnings here as well. On 01/04/14 14:01, Felipe Magno de Almeida wrote: > cedric pushed a commit to branch master. > > http://git.enlightenment.org/core/efl.git/commit/?id=ab3eb4b2d350d017eab6683202663244e11aa518 > > commit ab3eb4b2d350d017eab6683202663244e11aa518 > Author: Felipe Magno de Almeida <fel...@expertisesolutions.com.br> > Date: Tue Apr 1 19:08:07 2014 +0900 > > eet-cxx: add implementation for eet C++. > > Usage example: > > struct type > { > int foo; > float bar; > }; > > type t0; > > auto descriptor = make_descriptor("type", &type::ofo, &type::bar); > > eet_data_write(file, descriptor.native_handle(), "type", &t0, false); > > std::unique_ptr<type> p = read_by_ptr(file, "type", descriptor); > type t = read(file, "type", descriptor); > > @feature > > Reviewers: cedric, smohanty > > Reviewed By: cedric > > CC: savio, cedric > > Differential Revision: https://phab.enlightenment.org/D659 > > Signed-off-by: Cedric BAIL <cedric.b...@free.fr> > --- > configure.ac | 1 + > pc/.gitignore | 1 + > pc/eet-cxx.pc.in | 12 ++ > src/Makefile.am | 1 + > src/Makefile_Eet_Cxx.am | 42 +++++ > src/bindings/eet_cxx/Eet.hh | 214 ++++++++++++++++++++++++ > src/bindings/eet_cxx/eet_composite.hh | 49 ++++++ > src/bindings/eet_cxx/eet_fold.hh | 32 ++++ > src/bindings/eet_cxx/eet_register.hh | 132 +++++++++++++++ > src/bindings/eet_cxx/eet_tuple.hh | 39 +++++ > src/bindings/eet_cxx/eet_type.hh | 78 +++++++++ > src/lib/eet/Eet.h | 37 +++++ > src/lib/eet/eet_data.c | 38 +++++ > src/tests/eet_cxx/eet_cxx_suite.cc | 104 ++++++++++++ > src/tests/eet_cxx/eet_cxx_test_descriptors.cc | 231 > ++++++++++++++++++++++++++ > 15 files changed, 1011 insertions(+) > > diff --git a/configure.ac b/configure.ac > index 4001d29..3642b96 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -4100,6 +4100,7 @@ pc/escape.pc > pc/eina.pc > pc/eina-cxx.pc > pc/eet.pc > +pc/eet-cxx.pc > pc/eo.pc > pc/eolian.pc > pc/evas-fb.pc > diff --git a/pc/.gitignore b/pc/.gitignore > index 658f6cf..ae42f58 100644 > --- a/pc/.gitignore > +++ b/pc/.gitignore > @@ -26,6 +26,7 @@ > /efreet.pc > /eina.pc > /eina-cxx.pc > +/eet-cxx.pc > /eio.pc > /eldbus.pc > /embryo.pc > diff --git a/pc/eet-cxx.pc.in b/pc/eet-cxx.pc.in > new file mode 100644 > index 0000000..2412c48 > --- /dev/null > +++ b/pc/eet-cxx.pc.in > @@ -0,0 +1,12 @@ > +prefix=@prefix@ > +exec_prefix=@exec_prefix@ > +libdir=@libdir@ > +includedir=@includedir@ > + > +Name: Eet C++ > +Description: C++ API for the eet library > +Version: @VERSION@ > +Requires.private: @requirements_pc_eet@ > +Libs: -L${libdir} -leet > +Libs.private: @requirements_libs_eet@ > +Cflags: -I${includedir}/efl-@VMAJ@ -I${includedir}/eet-@VMAJ@ > -I${includedir}/efl-@VMAJ@ -I${includedir}/eet_cxx-@VMAJ@ > -I${includedir}/eet_cxx-@VMAJ@/eet_cxx > diff --git a/src/Makefile.am b/src/Makefile.am > index e277678..f9c2497 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -32,6 +32,7 @@ include Makefile_Escape.am > include Makefile_Eina.am > include Makefile_Eo.am > include Makefile_Eet.am > +include Makefile_Eet_Cxx.am > include Makefile_Eolian.am > include Makefile_Evas.am > include Makefile_Ecore.am > diff --git a/src/Makefile_Eet_Cxx.am b/src/Makefile_Eet_Cxx.am > new file mode 100644 > index 0000000..b2381aa > --- /dev/null > +++ b/src/Makefile_Eet_Cxx.am > @@ -0,0 +1,42 @@ > + > +### Library > + > +installed_eetcxxmainheadersdir = $(includedir)/eet_cxx-@VMAJ@ > +dist_installed_eetcxxmainheaders_DATA = bindings/eet_cxx/Eet.hh > + > +installed_eetcxxheadersdir = $(includedir)/eet_cxx-@VMAJ@/eet_cxx > +dist_installed_eetcxxheaders_DATA = \ > +bindings/eet_cxx/eet_composite.hh \ > +bindings/eet_cxx/eet_fold.hh \ > +bindings/eet_cxx/eet_register.hh \ > +bindings/eet_cxx/eet_tuple.hh \ > +bindings/eet_cxx/eet_type.hh > + > +### Unit tests > + > +if EFL_ENABLE_TESTS > +if HAVE_CXX11 > + > +check_PROGRAMS += tests/eet_cxx/eet_cxx_suite > +TESTS += tests/eet_cxx/eet_cxx_suite > + > +tests_eet_cxx_eet_cxx_suite_SOURCES = \ > +tests/eet_cxx/eet_cxx_suite.cc \ > +tests/eet_cxx/eet_cxx_test_descriptors.cc > + > +tests_eet_cxx_eet_cxx_suite_CPPFLAGS = \ > +-I$(top_builddir)/src/lib/efl \ > +-I$(top_builddir)/src/bindings/eina_cxx \ > +-I$(top_builddir)/src/bindings/eet_cxx \ > +-I$(top_srcdir)/src/bindings/eina_cxx \ > +-I$(top_srcdir)/src/bindings/eet_cxx \ > +-DTESTS_WD=\"`pwd`\" \ > +-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eet_cxx\" \ > +-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eet_cxx\" \ > +@CHECK_CFLAGS@ \ > +@EET_CFLAGS@ > +tests_eet_cxx_eet_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EET_LIBS@ > +tests_eet_cxx_eet_cxx_suite_DEPENDENCIES = @USE_EET_INTERNAL_LIBS@ > + > +endif > +endif > diff --git a/src/bindings/eet_cxx/Eet.hh b/src/bindings/eet_cxx/Eet.hh > new file mode 100644 > index 0000000..f725c68 > --- /dev/null > +++ b/src/bindings/eet_cxx/Eet.hh > @@ -0,0 +1,214 @@ > +#ifndef EET_HH_ > +#define EET_HH_ > + > +#include <Eet.h> > + > +#include <eet_type.hh> > +#include <eet_fold.hh> > +#include <eet_register.hh> > + > +#include <type_traits> > +#include <cassert> > +#include <stdexcept> > + > +#include <iostream> > +#include <array> > + > +namespace efl { namespace eet { namespace _detail { > + > +template <typename T> > +void* _allocate( ::size_t size ) > +{ > + assert(size == sizeof(T)); > + (void)size; > + return new T(); > +} > + > +template <typename T> > +void _deallocate( void* p ) > +{ > + delete static_cast<T*>(p); > +} > + > +template <typename T, typename... Args> > +struct descriptor_type > +{ > + struct push_back > + { > + template <typename A, typename B> > + struct apply : _mpl::push_back<A, typename _detail::member_type<typename > B::member_type>::type> {}; > + }; > + > + typedef typename _mpl::fold< std::tuple<Args...>, push_back > + , descriptor<T> >::type type; > +}; > + > +} > + > +#define EET_CXX_MEMBER(C, I) ::efl::eet::type(#I, &C::I) > + > +template <typename F> > +_detail::member_info<F, void> type(const char* name, F f) > +{ > + typedef typename _detail::member_type<F>::type member_type; > + static_assert(is_eet_primitive<member_type>::value, ""); > + static_assert(std::is_member_pointer<F>::value, ""); > + return _detail::member_info<F, void>{name, f}; > +} > + > +template <typename F, typename U, typename... Args> > +_detail::member_info<F, U, Args...> type(const char* name, F f, > descriptor<U, Args...> const& descriptor) > +{ > + typedef typename _detail::member_type<F>::type member_type; > + static_assert(!is_eet_primitive<member_type>::value, ""); > + static_assert(std::is_member_pointer<F>::value, ""); > + return _detail::member_info<F, U, Args...>{name, f, &descriptor}; > +} > + > +struct eet_init > +{ > + eet_init() > + { > + ::eet_init(); > + } > + ~eet_init() > + { > + ::eet_shutdown(); > + } > +}; > + > +template <typename T, typename... Args> > +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<std::size_t, sizeof...(Args)> members; > + > + std::array<_detail::member_desc_info, sizeof...(Args)> get_member_info() > const { return _member_info; } > +private: > + ::Eet_Data_Descriptor* _descriptor; > + typedef descriptor<T, Args...> _self_type; > + descriptor(descriptor const&) = delete; > + descriptor& operator=(descriptor const&) = delete; > + std::array<_detail::member_desc_info, sizeof...(Args)> _member_info; > +}; > + > +template <typename T, typename... Args> > +std::unique_ptr<T> read_by_ptr(Eet_File* file, const char* name, > descriptor<T, Args...> const& d) > +{ > + void* p = eet_data_read(file, const_cast<descriptor<T, > Args...>&>(d).native_handle(), name); > + return std::unique_ptr<T>(static_cast<T*>(p)); > +} > + > +template <typename T, typename... Args> > +T read(Eet_File* file, const char* name, descriptor<T, Args...> const& d) > +{ > + typename std::aligned_storage<sizeof(T), alignof(T)>::type buffer; > + void * p = > + ::eet_data_read_cipher_buffer > + (file > + , const_cast<descriptor<T, Args...>&>(d).native_handle() > + , name, 0 > + , static_cast<char*>(static_cast<void*>(&buffer)) > + , sizeof(buffer)); > + if(p) > + { > + assert(p == &buffer); > + return *static_cast<T*>(p); > + } > + else > + throw std::runtime_error(""); > +} > + > +namespace _detail { > + > +template <typename O> > +inline void _item_fill(O*, ::Eet_Data_Descriptor*, member_desc_info*) {} > + > +template <typename O, typename F, typename D, typename... Args, typename... > FArgs> > +inline void _item_fill(O* obj, ::Eet_Data_Descriptor* cls, member_desc_info* > offset > + , _detail::member_info<F, D, Args...> arg0, FArgs... > args) > +{ > + static_assert(std::is_member_object_pointer<F>::value, ""); > + offset->offset = static_cast<char*>( static_cast<void*>( &(obj ->* > arg0.member) )) > + - static_cast<char*>( static_cast<void*>( obj ) ); > + offset->name = arg0.name; > + _detail::_item_fill(obj, cls, ++offset, args...); > +} > + > +} > + > +template <typename F, typename D, typename... OArgs, typename... Args> > +typename _detail::descriptor_type > +<typename _detail::object_type<F>::type > + , _detail::member_info<F, D, OArgs...>, Args... > +>::type make_descriptor(const char* name, _detail::member_info<F, D, > OArgs...> a0, Args... args) > +{ > + typedef F member_pointer; > + static_assert(std::is_member_object_pointer<member_pointer>::value, ""); > + typedef typename _detail::object_type<member_pointer>::type object_type; > + > + typedef typename _detail::descriptor_type > + <object_type, _detail::member_info<F, D, OArgs...>, Args...>::type > descriptor_type; > + > + ::Eet_Data_Descriptor_Class cls > + { > + EET_DATA_DESCRIPTOR_CLASS_VERSION > + , name > + , sizeof(object_type) > + , { > + & _detail::_allocate<object_type> > + , & _detail::_deallocate<object_type> > + } > + }; > + ::Eet_Data_Descriptor* native_handle = > eet_data_descriptor_stream_new(&cls); > + if(!native_handle) > + throw std::runtime_error(""); > + > + typename std::aligned_storage<sizeof(object_type), > alignof(object_type)>::type buffer; > + object_type* p = static_cast<object_type*>(static_cast<void*>(&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 > diff --git a/src/bindings/eet_cxx/eet_composite.hh > b/src/bindings/eet_cxx/eet_composite.hh > new file mode 100644 > index 0000000..2c8f6be > --- /dev/null > +++ b/src/bindings/eet_cxx/eet_composite.hh > @@ -0,0 +1,49 @@ > +#ifndef EFL_EET_COMPOSITE_HH_ > +#define EFL_EET_COMPOSITE_HH_ > + > +namespace efl { namespace eet { > + > +template <typename, typename...> struct descriptor; > + > +namespace _detail { > + > +struct member_desc_info > +{ > + const char* name; > + std::size_t offset; > +}; > + > +template <std::size_t E, typename U, typename... Types> > +void descriptor_register_composite_member( ::Eet_Data_Descriptor*, int > + , eet::descriptor<U, > Types...>const* > + , > std::integral_constant<std::size_t, E>) > +{ > +} > + > +template <std::size_t E, typename U, typename... Types, std::size_t I> > +void descriptor_register_composite_member( ::Eet_Data_Descriptor* cls, int > offset_base > + , eet::descriptor<U, > Types...>const* descriptor > + , > std::integral_constant<std::size_t, I> > + , typename std::enable_if<E != > I>::type* = 0) > +{ > + typedef typename std::tuple_element<I, std::tuple<Types...> >::type > member_type; > + eet_data_descriptor_element_add(cls, descriptor->get_member_info()[I].name > + , _eet_type<member_type>::value, > EET_G_UNKNOWN > + , offset_base + > descriptor->get_member_info()[I].offset > + , 0, nullptr, nullptr); > + > + _detail::descriptor_register_composite_member<E> > + (cls, offset_base, descriptor, std::integral_constant<std::size_t, > I+1>()); > +} > + > +template <typename U, typename...Types> > +void descriptor_type_register_composite( ::Eet_Data_Descriptor* cls, > member_desc_info info > + , eet::descriptor<U, > Types...>const* descriptor) > +{ > + _detail::descriptor_register_composite_member<eet::descriptor<U, > Types...>::members::value> > + (cls, info.offset, descriptor, std::integral_constant<std::size_t, > 0u>()); > +} > + > +} } } > + > +#endif > diff --git a/src/bindings/eet_cxx/eet_fold.hh > b/src/bindings/eet_cxx/eet_fold.hh > new file mode 100644 > index 0000000..7ff19ae > --- /dev/null > +++ b/src/bindings/eet_cxx/eet_fold.hh > @@ -0,0 +1,32 @@ > +#ifndef EFL_EET_FOLD_HH_ > +#define EFL_EET_FOLD_HH_ > + > +#include <eet_tuple.hh> > + > +namespace efl { namespace eet { > + > +namespace _mpl { > + > +template <typename T, typename F, typename A0, bool B = std::is_same<T, > std::tuple<> >::value> > +struct fold_impl > +{ > + typedef typename F::template apply<A0, typename std::tuple_element<0, > T>::type>::type result; > + typedef typename fold_impl<typename pop_front<T>::type > + , F, result > + >::type > + type; > +}; > + > +template <typename T, typename F, typename A0> > +struct fold_impl<T, F, A0, true> > +{ > + typedef A0 type; > +}; > + > +template <typename T, typename F, typename A0> > +struct fold : fold_impl<T, F, A0> > +{}; > + > +} } } > + > +#endif > diff --git a/src/bindings/eet_cxx/eet_register.hh > b/src/bindings/eet_cxx/eet_register.hh > new file mode 100644 > index 0000000..e2a5142 > --- /dev/null > +++ b/src/bindings/eet_cxx/eet_register.hh > @@ -0,0 +1,132 @@ > +#ifndef EFL_EET_REGISTER_HH_ > +#define EFL_EET_REGISTER_HH_ > + > +#include <eet_type.hh> > +#include <eet_composite.hh> > + > +namespace efl { namespace eet { > + > +template <typename, typename...> struct descriptor; > + > +namespace _detail { > + > +template <typename T> > +struct member_type; > + > +template <typename T, typename U> > +struct member_type<T(U::*)> > +{ > + typedef T type; > +}; > + > +template <typename T> > +struct object_type; > + > +template <typename T, typename U> > +struct object_type<T(U::*)> > +{ > + typedef U type; > +}; > + > +template <typename F, typename T, typename... Args> > +struct member_info > +{ > + typedef F member_type; > + > + const char* name; > + F member; > + eet::descriptor<T, Args...> const* descriptor; > +}; > + > +template <typename F> > +struct member_info<F, void> > +{ > + typedef F member_type; > + > + const char* name; > + F member; > +}; > + > +template <typename F, typename U, typename... Args> > +void descriptor_type_register_impl > + (std::false_type > + , ::Eet_Data_Descriptor* cls > + , member_desc_info i > + , member_info<F, U, Args...> arg0 > + , typename std::enable_if > + < > + !std::is_pointer<typename _detail::member_type<F>::type>::value > + >::type* = 0) > +{ > + // composition by value > + static_assert(std::is_member_object_pointer<F>::value, ""); > + typedef typename _detail::member_type<F>::type member_type; > + typedef typename _detail::object_type<F>::type object_type; > + static_assert(!std::is_pointer<member_type>::value, ""); > + static_assert(std::is_same<member_type, U>::value, ""); > + static_assert(std::is_pod<member_type>::value, ""); > + > + _detail::descriptor_type_register_composite(cls, i, arg0.descriptor); > +} > + > +template <typename F, typename U, typename... Args> > +void descriptor_type_register_impl > + (std::false_type > + , ::Eet_Data_Descriptor* cls > + , member_desc_info i > + , member_info<F, U, Args...> arg0 > + , typename std::enable_if > + < > + std::is_pointer<typename _detail::member_type<F>::type>::value > + >::type* = 0) > +{ > + // composition by pointer > + static_assert(std::is_member_object_pointer<F>::value, ""); > + typedef typename _detail::member_type<F>::type pointer_member_type; > + typedef typename _detail::object_type<F>::type object_type; > + static_assert(std::is_pointer<pointer_member_type>::value, ""); > + typedef typename std::remove_pointer<pointer_member_type>::type > member_type; > + static_assert(std::is_same<member_type, U>::value, ""); > + > + eet_data_descriptor_element_add > + (cls, i.name > + , EET_T_UNKNOW > + , EET_G_UNKNOWN > + , i.offset > + , 0 > + , nullptr > + , const_cast<descriptor<U, > Args...>*>(arg0.descriptor)->native_handle()); > +} > + > +template <typename F> > +void descriptor_type_register_impl > + (std::true_type, ::Eet_Data_Descriptor* cls > + , member_desc_info i > + , member_info<F, void>) > +{ > + static_assert(std::is_member_object_pointer<F>::value, ""); > + typedef typename _detail::member_type<F>::type member_type; > + typedef typename _detail::object_type<F>::type object_type; > + > + eet_data_descriptor_element_add(cls, i.name, > _eet_type<member_type>::value, EET_G_UNKNOWN > + , i.offset, 0, nullptr, nullptr); > +} > + > +inline void descriptor_type_register( ::Eet_Data_Descriptor*, > member_desc_info*) > +{ > +} > + > +template <typename F, typename D, typename... Args, typename... FArgs> > +void descriptor_type_register( ::Eet_Data_Descriptor* cls, member_desc_info* > i > + , member_info<F, D, Args...> a0, FArgs... > args) > +{ > + static_assert(std::is_member_object_pointer<F>::value, ""); > + typedef typename _detail::member_type<F>::type member_type; > + > + _detail::descriptor_type_register_impl(is_eet_primitive<member_type>(), > cls, *i, a0); > + _detail::descriptor_type_register(cls, ++i, args...); > +} > + > +} } } > + > +#endif > diff --git a/src/bindings/eet_cxx/eet_tuple.hh > b/src/bindings/eet_cxx/eet_tuple.hh > new file mode 100644 > index 0000000..2fbb395 > --- /dev/null > +++ b/src/bindings/eet_cxx/eet_tuple.hh > @@ -0,0 +1,39 @@ > +#ifndef EFL_EET_EET_TUPLE_HH_ > +#define EFL_EET_EET_TUPLE_HH_ > + > +namespace efl { namespace eet { > + > +namespace _mpl { > + > +template <typename A, typename... Args> > +struct push_back; > + > +template <template <typename... Args> class C, typename... Args, typename... > AArgs> > +struct push_back<C<Args...>, AArgs...> > +{ > + typedef C<Args..., AArgs...> type; > +}; > + > +template <typename A, typename... Args> > +struct push_front; > + > +template <template <typename... Args> class C, typename... Args, typename... > AArgs> > +struct push_front<C<Args...>, AArgs...> > +{ > + typedef C<Args..., AArgs...> type; > +}; > + > +template <typename A> > +struct pop_front; > + > +template <template <typename...> class C, typename T, typename... Args> > +struct pop_front<C<T, Args...> > > +{ > + typedef C<Args...> type; > +}; > + > +} > + > +} } > + > +#endif > diff --git a/src/bindings/eet_cxx/eet_type.hh > b/src/bindings/eet_cxx/eet_type.hh > new file mode 100644 > index 0000000..e12bc98 > --- /dev/null > +++ b/src/bindings/eet_cxx/eet_type.hh > @@ -0,0 +1,78 @@ > +#ifndef _EET_TYPE_HH > +#define _EET_TYPE_HH > + > +#include <Eet.h> > +#include <Eina.hh> > + > +#include <type_traits> > + > +namespace efl { namespace eet { > + > +template <typename T> > +struct _eet_type; > + > +template <> > +struct _eet_type<char> : std::integral_constant<int, EET_T_CHAR> > +{}; > + > +template <> > +struct _eet_type<short> : std::integral_constant<int, EET_T_SHORT> > +{}; > + > +template <> > +struct _eet_type<int> : std::integral_constant<int, EET_T_INT> > +{}; > + > +template <> > +struct _eet_type<long long> : std::integral_constant<int, EET_T_LONG_LONG> > +{}; > + > +template <> > +struct _eet_type<float> : std::integral_constant<int, EET_T_FLOAT> > +{}; > + > +template <> > +struct _eet_type<double> : std::integral_constant<int, EET_T_DOUBLE> > +{}; > + > +template <> > +struct _eet_type<unsigned char> : std::integral_constant<int, EET_T_UCHAR> > +{}; > + > +template <> > +struct _eet_type<unsigned short> : std::integral_constant<int, EET_T_USHORT> > +{}; > + > +template <> > +struct _eet_type<unsigned int> : std::integral_constant<int, EET_T_UINT> > +{}; > + > +template <> > +struct _eet_type<unsigned long long> : std::integral_constant<int, > EET_T_ULONG_LONG> > +{}; > + > +template <> > +struct _eet_type<char*> : std::integral_constant<int, EET_T_STRING> > +{}; > + > +template <> > +struct _eet_type<void*> : std::integral_constant<int, EET_T_NULL> > +{}; > + > +template <> > +struct _eet_type<eina::value> : std::integral_constant<int, EET_T_VALUE> > +{}; > + > +template <typename T> > +struct _void { typedef void type; }; > + > +template <typename T, typename Enabler = void> > +struct is_eet_primitive : std::false_type {}; > + > +template <typename T> > +struct is_eet_primitive<T, typename _void<typename _eet_type<T>::type>::type> > + : std::true_type {}; > + > +} } > + > +#endif > diff --git a/src/lib/eet/Eet.h b/src/lib/eet/Eet.h > index ab90733..60e58d4 100644 > --- a/src/lib/eet/Eet.h > +++ b/src/lib/eet/Eet.h > @@ -3528,6 +3528,43 @@ eet_data_read_cipher(Eet_File *ef, > const char *cipher_key); > > /** > + * Read a data structure from an eet file and decodes it into a buffer using > a cipher, > + * @param ef The eet file handle to read from. > + * @param edd The data descriptor handle to use when decoding. > + * @param name The key the data is stored under in the eet file. > + * @param cipher_key The key to use as cipher. > + * @param buffer Buffer > + * @return A pointer to buffer if successful and NULL on error. > + * > + * This function decodes a data structure stored in an eet file, returning > + * a pointer to it if it decoded successfully, or NULL on failure. This > + * can save a programmer dozens of hours of work in writing configuration > + * file parsing and writing code, as eet does all that work for the program > + * and presents a program-friendly data structure, just as the programmer > + * likes. Eet can handle members being added or deleted from the data in > + * storage and safely zero-fills unfilled members if they were not found > + * in the data. It checks sizes and headers whenever it reads data, allowing > + * the programmer to not worry about corrupt data. > + * > + * Once a data structure has been described by the programmer with the > + * fields they wish to save or load, storing or retrieving a data structure > + * from an eet file, or from a chunk of memory is as simple as a single > + * function call. > + * > + * @see eet_data_read_cipher() > + * > + * @since 1.10.0 > + * @ingroup Eet_Data_Cipher_Group > + */ > +EAPI void * > +eet_data_read_cipher_buffer(Eet_File *ef, > + Eet_Data_Descriptor *edd, > + const char *name, > + const char *cipher_key, > + char *buffer, > + int buffer_size); > + > +/** > * Read a data structure from an eet extended attribute and decodes it > using a cipher. > * @param filename The file to extract the extended attribute from. > * @param attribute The attribute to get the data from. > diff --git a/src/lib/eet/eet_data.c b/src/lib/eet/eet_data.c > index ea51ed0..c92a526 100644 > --- a/src/lib/eet/eet_data.c > +++ b/src/lib/eet/eet_data.c > @@ -2284,6 +2284,44 @@ eet_data_read_cipher(Eet_File *ef, > return data_dec; > } > > +EAPI void * > +eet_data_read_cipher_buffer(Eet_File *ef, > + Eet_Data_Descriptor *edd, > + const char *name, > + const char *cipher_key, > + char* buffer, > + int buffer_size) > +{ > + const Eet_Dictionary *ed = NULL; > + const void *data = NULL; > + void *data_dec; > + Eet_Free_Context context; > + int required_free = 0; > + int size; > + > + ed = eet_dictionary_get(ef); > + > + if (!cipher_key) > + data = eet_read_direct(ef, name, &size); > + > + if (!data) > + { > + required_free = 1; > + data = eet_read_cipher(ef, name, &size, cipher_key); > + if (!data) > + return NULL; > + } > + > + eet_free_context_init(&context); > + data_dec = _eet_data_descriptor_decode(&context, ed, edd, data, size, > buffer, buffer_size); > + eet_free_context_shutdown(&context); > + > + if (required_free) > + free((void *)data); > + > + return data_dec; > +} > + > EAPI Eet_Node * > eet_data_node_read_cipher(Eet_File *ef, > const char *name, > diff --git a/src/tests/eet_cxx/eet_cxx_suite.cc > b/src/tests/eet_cxx/eet_cxx_suite.cc > new file mode 100644 > index 0000000..26e658b > --- /dev/null > +++ b/src/tests/eet_cxx/eet_cxx_suite.cc > @@ -0,0 +1,104 @@ > + > +#include "Eet.hh" > +#include <Eina.h> > + > +#include <cassert> > +#include <algorithm> > + > +#include <check.h> > + > +void eet_test_descriptors(TCase* tc); > + > +typedef struct _Eet_Test_Case Eet_Test_Case; > +struct _Eet_Test_Case > +{ > + const char *test_case; > + void (*build)(TCase *tc); > +}; > + > +static const Eet_Test_Case etc[] = { > + { "Descriptors", eet_test_descriptors }, > + { NULL, NULL } > +}; > + > +static void > +_list_tests(void) > +{ > + const Eet_Test_Case *itr = etc; > + fputs("Available Test Cases:\n", stderr); > + for (; itr->test_case; itr++) > + fprintf(stderr, "\t%s\n", itr->test_case); > +} > + > +static Eina_Bool > +_use_test(int argc, const char **argv, const char *test_case) > +{ > + if (argc < 1) > + return 1; > + > + for (; argc > 0; argc--, argv++) > + if (strcmp(test_case, *argv) == 0) > + return 1; > + > + return 0; > +} > + > +Suite * > +eet_build_suite(int argc, const char **argv) > +{ > + TCase *tc; > + Suite *s; > + int i; > + > + s = suite_create("Eet C++"); > + > + for (i = 0; etc[i].test_case; ++i) > + { > + if (!_use_test(argc, argv, etc[i].test_case)) > + continue; > + > + tc = tcase_create(etc[i].test_case); > + tcase_set_timeout(tc, 0); > + > + etc[i].build(tc); > + suite_add_tcase(s, tc); > + } > + > + return s; > +} > + > +int main(int argc, char* argv[]) > +{ > + Suite *s; > + SRunner *sr; > + int i, failed_count; > + > + for (i = 1; i < argc; i++) > + if ((strcmp(argv[i], "-h") == 0) || > + (strcmp(argv[i], "--help") == 0)) > + { > + fprintf(stderr, "Usage:\n\t%s [test_case1 .. [test_caseN]]\n", > + argv[0]); > + _list_tests(); > + return 0; > + } > + else if ((strcmp(argv[i], "-l") == 0) || > + (strcmp(argv[i], "--list") == 0)) > + { > + _list_tests(); > + return 0; > + } > + > + putenv(const_cast<char*>("EFL_RUN_IN_TREE=1")); > + > + s = eet_build_suite(argc - 1, (const char **)argv + 1); > + sr = srunner_create(s); > + > + srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml"); > + > + srunner_run_all(sr, CK_ENV); > + failed_count = srunner_ntests_failed(sr); > + srunner_free(sr); > + > + return (failed_count == 0) ? 0 : 255; > +} > diff --git a/src/tests/eet_cxx/eet_cxx_test_descriptors.cc > b/src/tests/eet_cxx/eet_cxx_test_descriptors.cc > new file mode 100644 > index 0000000..bc21418 > --- /dev/null > +++ b/src/tests/eet_cxx/eet_cxx_test_descriptors.cc > @@ -0,0 +1,231 @@ > + > +#include "Eet.hh" > + > +#include <algorithm> > + > +#include <iostream> > + > +#include <check.h> > + > +struct pod_type > +{ > + int i; > + char c; > +}; > + > +START_TEST(eet_cxx_descriptors) > +{ > + efl::eet::eet_init init; > + > + auto d = efl::eet::make_descriptor > + ("pod_type" > + , efl::eet::type("i", &pod_type::i) > + , efl::eet::type("c", &pod_type::c)); > + static_assert(std::is_same<efl::eet::descriptor<pod_type, int, char>, > decltype(d)>::value, ""); > + > + Eet_File* file = eet_open("/tmp/eet_file_test.eet", > EET_FILE_MODE_READ_WRITE); > + ck_assert(file != 0); > + > + pod_type pod = {1, 2}; > + > + int s = eet_data_write(file, d.native_handle(), "pod", &pod, true); > + std::cout << "bytes written " << s << std::endl; > + ck_assert(s > 0); > + eet_sync(file); > + auto p = efl::eet::read_by_ptr(file, "pod", d); > + ck_assert(p != 0); > + ck_assert(p->i == 1); > + ck_assert(p->c == 2); > + > + eet_close(file); > +} > +END_TEST > + > +int constructors_called = 0 > + , destructors_called = 0; > + > +struct non_pod > +{ > + non_pod() : i(10) > + { > + ++constructors_called; > + } > + non_pod(non_pod const& other) > + : i(other.i) > + { > + ++constructors_called; > + } > + ~non_pod() > + { > + ++destructors_called; > + } > + > + int i; > +}; > + > +START_TEST(eet_cxx_descriptors_non_pod) > +{ > + efl::eet::eet_init init; > + > + auto d = efl::eet::make_descriptor > + ("pod_type", EET_CXX_MEMBER(non_pod, i)); > + static_assert(std::is_same<efl::eet::descriptor<non_pod, int>, > decltype(d)>::value, ""); > + > + { > + Eet_File* file = eet_open("/tmp/eet_file_test.eet", > EET_FILE_MODE_READ_WRITE); > + ck_assert(file != 0); > + > + ::non_pod non_pod; > + > + int s = eet_data_write(file, d.native_handle(), "non_pod", &non_pod, > true); > + std::cout << "bytes written " << s << std::endl; > + ck_assert(s > 0); > + eet_sync(file); > + auto p = efl::eet::read_by_ptr(file, "non_pod", d); > + ck_assert(p != 0); > + ck_assert(p->i == 10); > + > + auto v = efl::eet::read(file, "non_pod", d); > + ck_assert(v.i == 10); > + > + eet_close(file); > + } > + > + std::cout << "constructors called for non pod: " << constructors_called > + << " destructors called for non pod: " << destructors_called << > std::endl; > + > + ck_assert(constructors_called == destructors_called); > +} > +END_TEST > + > +struct pod_composited > +{ > + pod_type* member; > +}; > + > +struct pod_composited_with_non_pod > +{ > + non_pod* member; > +}; > + > +struct pod_value_composited > +{ > + pod_type member; > +}; > + > +START_TEST(eet_cxx_descriptors_composition) > +{ > + efl::eet::eet_init init; > + > + auto pod_descriptor = efl::eet::make_descriptor > + ("pod_type" > + , efl::eet::type("i", &pod_type::i) > + , efl::eet::type("c", &pod_type::c)); > + static_assert(std::is_same<efl::eet::descriptor<pod_type, int, char> > + , decltype(pod_descriptor)>::value, ""); > + > + auto non_pod_descriptor = efl::eet::make_descriptor > + ("non_pod" > + , efl::eet::type("i", &non_pod::i)); > + static_assert(std::is_same<efl::eet::descriptor<non_pod, int> > + , decltype(non_pod_descriptor)>::value, ""); > + > + { > + auto d = efl::eet::make_descriptor > + ("pod_composited", efl::eet::type("pod_composited", > &pod_composited::member, pod_descriptor)); > + static_assert(std::is_same<efl::eet::descriptor<pod_composited, > pod_type*>, decltype(d)>::value, ""); > + > + Eet_File* file = eet_open("/tmp/eet_file_test.eet", > EET_FILE_MODE_READ_WRITE); > + ck_assert(file != 0); > + > + ::pod_composited pod_composited {new pod_type{5, 'a'}}; > + > + int s = eet_data_write(file, d.native_handle(), "foo", &pod_composited, > false); > + ck_assert(s > 0); > + eet_sync(file); > + auto p = efl::eet::read_by_ptr(file, "foo", d); > + ck_assert(p != 0); > + ck_assert(p->member->i == 5); > + ck_assert(p->member->c == 'a'); > + > + delete p->member; > + > + auto v = efl::eet::read(file, "foo", d); > + ck_assert(v.member->i == 5); > + ck_assert(v.member->c == 'a'); > + > + delete v.member; > + > + eet_close(file); > + } > + > + { > + auto d = efl::eet::make_descriptor > + ("pod_composited_with_non_pod", > efl::eet::type("pod_composited_with_non_pod", > &pod_composited_with_non_pod::member, non_pod_descriptor)); > + > static_assert(std::is_same<efl::eet::descriptor<pod_composited_with_non_pod, > non_pod*>, decltype(d)>::value, ""); > + > + Eet_File* file = eet_open("/tmp/eet_file_test.eet", > EET_FILE_MODE_READ_WRITE); > + ck_assert(file != 0); > + > + ::pod_composited_with_non_pod pod_composited_with_non_pod {new non_pod}; > + > + int s = eet_data_write(file, d.native_handle(), "foo", > &pod_composited_with_non_pod, false); > + ck_assert(s > 0); > + eet_sync(file); > + auto p = efl::eet::read_by_ptr(file, "foo", d); > + ck_assert(p != 0); > + ck_assert(p->member->i == 10); > + > + delete p->member; > + > + auto v = efl::eet::read(file, "foo", d); > + ck_assert(v.member->i == 10); > + > + delete v.member; > + > + eet_close(file); > + > + delete pod_composited_with_non_pod.member; > + } > + > + std::cout << "constructors called for non pod: " << constructors_called > + << " destructors called for non pod: " << destructors_called << > std::endl; > + > + ck_assert(constructors_called == destructors_called); > + > + { > + auto d = efl::eet::make_descriptor > + ("pod_value_composited", efl::eet::type("member" > + , > &pod_value_composited::member, pod_descriptor)); > + static_assert(std::is_same<efl::eet::descriptor<pod_value_composited, > pod_type>, decltype(d)>::value, ""); > + > + Eet_File* file = eet_open("/tmp/eet_file_test.eet", > EET_FILE_MODE_READ_WRITE); > + ck_assert(file != 0); > + > + ::pod_value_composited pod_value_composited {{5, 'a'}}; > + > + int s = eet_data_write(file, d.native_handle(), "foo", > &pod_value_composited, false); > + ck_assert(s > 0); > + eet_sync(file); > + auto p = efl::eet::read_by_ptr(file, "foo", d); > + ck_assert(p != 0); > + ck_assert(p->member.i == 5); > + ck_assert(p->member.c == 'a'); > + > + auto v = efl::eet::read(file, "foo", d); > + ck_assert(v.member.i == 5); > + ck_assert(v.member.c == 'a'); > + > + eet_close(file); > + } > + > +} > +END_TEST > + > +void > +eet_test_descriptors(TCase* tc) > +{ > + tcase_add_test(tc, eet_cxx_descriptors); > + tcase_add_test(tc, eet_cxx_descriptors_non_pod); > + tcase_add_test(tc, eet_cxx_descriptors_composition); > +} >
------------------------------------------------------------------------------ _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel