echelon  0.8.0
adapt_type.hpp
1 // Copyright (c) 2012-2014 Christopher Hinz
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef ECHELON_HDF5_ADAPT_TYPE_HPP
7 #define ECHELON_HDF5_ADAPT_TYPE_HPP
8 
9 #include <echelon/hdf5/type.hpp>
10 #include <echelon/hdf5/type_traits_fwd.hpp>
11 #include <echelon/hdf5/static_type_layout.hpp>
12 
13 #include <cstddef>
14 #include <utility>
15 #include <tuple>
16 
17 #include <boost/mpl/bool.hpp>
18 
19 #include <boost/preprocessor/seq/transform.hpp>
20 #include <boost/preprocessor/seq/to_tuple.hpp>
21 
22 #include <boost/preprocessor/stringize.hpp>
23 
24 #define ECHELON_TUPLE_TO_VARIADIC_(...) __VA_ARGS__
25 
26 #define ECHELON_TUPLE_TO_VARIADIC(ARG) ECHELON_TUPLE_TO_VARIADIC_ ARG
27 
28 #define ECHELON_CREATE_ID_OFFSET_PAIR(d, data, value) \
29  id_offset_pair(BOOST_PP_STRINGIZE(value), offsetof(data, value))
30 
31 #define ECHELON_PROCESS_MEMBER_LIST(TYPE_NAME, MEMBERS) \
32  { \
33  ECHELON_TUPLE_TO_VARIADIC(BOOST_PP_SEQ_TO_TUPLE( \
34  BOOST_PP_SEQ_TRANSFORM(ECHELON_CREATE_ID_OFFSET_PAIR, TYPE_NAME, MEMBERS))) \
35  }
36 
37 #define ECHELON_GET_MEMBER_TYPE(d, data, value) decltype(data::value)
38 
39 #define ECHELON_GET_MEMBER_TYPES(TYPE_NAME, MEMBERS) \
40  ECHELON_TUPLE_TO_VARIADIC(BOOST_PP_SEQ_TO_TUPLE( \
41  BOOST_PP_SEQ_TRANSFORM(ECHELON_GET_MEMBER_TYPE, TYPE_NAME, MEMBERS)))
42 
43 #define ECHELON_ADAPT_COMPOUND_TYPE(TYPE_NAME, MEMBERS) \
44  namespace echelon \
45  { \
46  template <> \
47  struct static_type_layout<TYPE_NAME> \
48  { \
49  static constexpr static_type_layout_category category = \
50  static_type_layout_category::generic; \
51  typedef std::tuple<ECHELON_GET_MEMBER_TYPES(TYPE_NAME, MEMBERS)> member_types; \
52  static const char* name() \
53  { \
54  return BOOST_PP_STRINGIZE(TYPE_NAME); \
55  } \
56  static constexpr std::size_t size = sizeof(TYPE_NAME); \
57  static const id_offset_pair* members() \
58  { \
59  static constexpr id_offset_pair members_[] = \
60  ECHELON_PROCESS_MEMBER_LIST(TYPE_NAME, MEMBERS); \
61  return members_; \
62  } \
63  static constexpr std::size_t num_members = std::tuple_size<member_types>::value; \
64  }; \
65  \
66  template <> \
67  struct is_hdf5_type<TYPE_NAME> : boost::mpl::true_ \
68  { \
69  }; \
70  }
71 
72 #define ECHELON_CREATE_ID_SIZE_PAIR__(d, data, TYPE, NAME) \
73  id_size_pair(BOOST_PP_STRINGIZE(NAME), sizeof(TYPE))
74 
75 #define ECHELON_CREATE_ID_SIZE_PAIR_(d, data, ...) \
76  ECHELON_CREATE_ID_SIZE_PAIR__(d, data, __VA_ARGS__)
77 
78 #define ECHELON_CREATE_ID_SIZE_PAIR(d, data, value) \
79  ECHELON_CREATE_ID_SIZE_PAIR_(d, data, ECHELON_TUPLE_TO_VARIADIC(value))
80 
81 #define ECHELON_PROCESS_PACKED_MEMBER_LIST(TYPE_NAME, MEMBERS) \
82  { \
83  ECHELON_TUPLE_TO_VARIADIC(BOOST_PP_SEQ_TO_TUPLE( \
84  BOOST_PP_SEQ_TRANSFORM(ECHELON_CREATE_ID_SIZE_PAIR, TYPE_NAME, MEMBERS))) \
85  }
86 
87 #define ECHELON_GET_PACKED_MEMBER_TYPE__(d, data, TYPE, NAME) TYPE
88 
89 #define ECHELON_GET_PACKED_MEMBER_TYPE_(d, data, ...) \
90  ECHELON_GET_PACKED_MEMBER_TYPE__(d, data, __VA_ARGS__)
91 
92 #define ECHELON_GET_PACKED_MEMBER_TYPE(d, data, value) \
93  ECHELON_GET_PACKED_MEMBER_TYPE_(d, data, ECHELON_TUPLE_TO_VARIADIC(value))
94 
95 #define ECHELON_GET_PACKED_MEMBER_TYPES(MEMBERS) \
96  ECHELON_TUPLE_TO_VARIADIC( \
97  BOOST_PP_SEQ_TO_TUPLE(BOOST_PP_SEQ_TRANSFORM(ECHELON_GET_PACKED_MEMBER_TYPE, _, MEMBERS)))
98 
99 #define ECHELON_ADAPT_PACKED_COMPOUND_TYPE(TYPE_NAME, MEMBERS) \
100  namespace echelon \
101  { \
102  namespace hdf5 \
103  { \
104  template <> \
105  struct static_type_layout<TYPE_NAME> \
106  { \
107  static constexpr static_type_layout_category category = \
108  static_type_layout_category::packed; \
109  typedef std::tuple<ECHELON_GET_PACKED_MEMBER_TYPES(MEMBERS)> member_types; \
110  static const char* name() \
111  { \
112  return BOOST_PP_STRINGIZE(TYPE_NAME); \
113  } \
114  static constexpr std::size_t size = sizeof(TYPE_NAME); \
115  static const id_size_pair* members() \
116  { \
117  static constexpr id_size_pair members_[] = \
118  ECHELON_PROCESS_PACKED_MEMBER_LIST(TYPE_NAME, MEMBERS); \
119  return members_; \
120  } \
121  static constexpr std::size_t num_members = std::tuple_size<member_types>::value; \
122  }; \
123  \
124  template <> \
125  struct is_hdf5_type<TYPE_NAME> : boost::mpl::true_ \
126  { \
127  }; \
128  } \
129  }
130 
131 #endif