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.bail@free.fr>
This commit is contained in:
Felipe Magno de Almeida 2014-04-01 19:08:07 +09:00 committed by Cedric BAIL
parent b218c13fb7
commit ab3eb4b2d3
15 changed files with 1011 additions and 0 deletions

View File

@ -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

1
pc/.gitignore vendored
View File

@ -26,6 +26,7 @@
/efreet.pc
/eina.pc
/eina-cxx.pc
/eet-cxx.pc
/eio.pc
/eldbus.pc
/embryo.pc

12
pc/eet-cxx.pc.in Normal file
View File

@ -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

View File

@ -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

42
src/Makefile_Eet_Cxx.am Normal file
View File

@ -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

214
src/bindings/eet_cxx/Eet.hh Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -3527,6 +3527,43 @@ eet_data_read_cipher(Eet_File *ef,
const char *name,
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.

View File

@ -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,

View File

@ -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;
}

View File

@ -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);
}