echelon  0.8.0
type_factory.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_TYPE_FACTORY_HPP
7 #define ECHELON_HDF5_TYPE_FACTORY_HPP
8 
9 #include <echelon/hdf5/type.hpp>
10 #include <echelon/hdf5/type_traits.hpp>
11 #include <echelon/hdf5/precursor/object_reference.hpp>
12 #include <echelon/hdf5/customization_hooks.hpp>
13 #include <echelon/hdf5/static_type_layout.hpp>
14 
15 #include <utility>
16 #include <string>
17 
18 namespace echelon
19 {
20 namespace hdf5
21 {
22 template <typename T>
23 inline typename std::enable_if<is_predefined_hdf5_type<T>::value, type>::type get_hdf5_type();
24 
25 template <typename T>
26 inline typename std::enable_if<is_hdf5_type<T>::value && !is_predefined_hdf5_type<T>::value,
27  type>::type
28 get_hdf5_type();
29 
30 template <typename T>
31 inline typename std::enable_if<!is_hdf5_type<T>::value && !is_trivially_storable<T>(), type>::type
32 get_hdf5_type();
33 
34 template <typename T>
35 inline typename std::enable_if<!is_hdf5_type<T>::value && is_trivially_storable<T>(), type>::type
36 get_hdf5_type();
37 
38 template <typename T>
39 struct hdf5_type_selector
40 {
41  static_assert(sizeof(T) != sizeof(T), "invalid type");
42 };
43 
44 template <>
45 struct hdf5_type_selector<char>
46 {
47  static type get()
48  {
49  return type::char_();
50  }
51 };
52 
53 template <>
54 struct hdf5_type_selector<unsigned char>
55 {
56  static type get()
57  {
58  return type::uchar();
59  }
60 };
61 
62 template <>
63 struct hdf5_type_selector<short>
64 {
65  static type get()
66  {
67  return type::short_();
68  }
69 };
70 
71 template <>
72 struct hdf5_type_selector<unsigned short>
73 {
74  static type get()
75  {
76  return type::ushort();
77  }
78 };
79 
80 template <>
81 struct hdf5_type_selector<int>
82 {
83  static type get()
84  {
85  return type::int_();
86  }
87 };
88 
89 template <>
90 struct hdf5_type_selector<unsigned int>
91 {
92  static type get()
93  {
94  return type::uint();
95  }
96 };
97 
98 template <>
99 struct hdf5_type_selector<long>
100 {
101  static type get()
102  {
103  return type::long_();
104  }
105 };
106 
107 template <>
108 struct hdf5_type_selector<unsigned long>
109 {
110  static type get()
111  {
112  return type::ulong();
113  }
114 };
115 
116 template <>
117 struct hdf5_type_selector<long long>
118 {
119  static type get()
120  {
121  return type::long_long();
122  }
123 };
124 
125 template <>
126 struct hdf5_type_selector<unsigned long long>
127 {
128  static type get()
129  {
130  return type::ulong_long();
131  }
132 };
133 
134 template <>
135 struct hdf5_type_selector<float>
136 {
137  static type get()
138  {
139  return type::float_();
140  }
141 };
142 
143 template <>
144 struct hdf5_type_selector<double>
145 {
146  static type get()
147  {
148  return type::double_();
149  }
150 };
151 
152 template <>
153 struct hdf5_type_selector<bool>
154 {
155  static type get()
156  {
157  return type::uchar();
158  }
159 };
160 
161 template <>
162 struct hdf5_type_selector<std::string>
163 {
164  static type get()
165  {
166  return type::string();
167  }
168 };
169 
170 template <std::size_t N>
171 struct hdf5_type_selector<char[N]>
172 {
173  static type get()
174  {
175  return type::string();
176  }
177 };
178 
179 template <>
180 struct hdf5_type_selector<precursor::object_reference>
181 {
182  static type get()
183  {
184  return type::object_reference();
185  }
186 };
187 
188 template <typename T>
189 struct hdf5_type_selector<T const> : hdf5_type_selector<typename std::remove_cv<T>::type>
190 {
191 };
192 
193 namespace detail
194 {
195 
196 template <typename T, std::size_t I, typename Enable = void>
197 struct add_member_to_layout;
198 
199 template <typename T, std::size_t I>
200 struct add_member_to_layout<T, I,
201  typename std::enable_if<static_type_layout<T>::category ==
202  static_type_layout_category::generic>::type>
203 {
204  static std::size_t eval(type_layout& layout, std::size_t)
205  {
206  const id_offset_pair id_offset = static_type_layout<T>::members()[I];
207 
208  typedef typename std::tuple_element<I, typename static_type_layout<T>::member_types>::type
209  member_type;
210 
211  layout.add_element(id_offset.id, get_hdf5_type<member_type>(), id_offset.offset);
212 
213  return id_offset.offset;
214  }
215 };
216 
217 template <typename T, std::size_t I>
218 struct add_member_to_layout<T, I,
219  typename std::enable_if<static_type_layout<T>::category ==
220  static_type_layout_category::packed>::type>
221 {
222  static std::size_t eval(type_layout& layout, std::size_t current_offset)
223  {
224  const id_size_pair id_size = static_type_layout<T>::members()[I];
225 
226  typedef typename std::tuple_element<I, typename static_type_layout<T>::member_types>::type
227  member_type;
228 
229  layout.add_element(id_size.id, get_hdf5_type<member_type>(), current_offset);
230 
231  return current_offset + id_size.size;
232  }
233 };
234 
235 template <typename T, std::size_t I, std::size_t N, typename Enable = void>
236 struct add_members_to_layout;
237 
238 template <typename T, std::size_t I, std::size_t N>
239 struct add_members_to_layout<T, I, N>
240 {
241  static void eval(type_layout& layout, std::size_t current_offset)
242  {
243  const std::size_t new_offset = add_member_to_layout<T, I>::eval(layout, current_offset);
244 
245  add_members_to_layout<T, I + 1, N>::eval(layout, new_offset);
246  }
247 };
248 
249 template <typename T, std::size_t N>
250 struct add_members_to_layout<T, N, N>
251 {
252  static void eval(type_layout&, std::size_t)
253  {
254  }
255 };
256 }
257 
258 template <typename T>
259 inline typename std::enable_if<is_predefined_hdf5_type<T>::value, type>::type get_hdf5_type()
260 {
261  return hdf5_type_selector<T>::get();
262 }
263 
264 template <typename T>
265 inline typename std::enable_if<is_hdf5_type<T>::value && !is_predefined_hdf5_type<T>::value,
266  type>::type
267 get_hdf5_type()
268 {
269  typedef typename std::remove_reference<typename std::remove_cv<T>::type>::type value_type;
270 
271  type_layout new_layout(static_type_layout<value_type>::size);
272 
273  constexpr std::size_t num_members = static_type_layout<value_type>::num_members;
274 
275  detail::add_members_to_layout<value_type, 0, num_members>::eval(new_layout, 0);
276 
277  return type::compound_type(new_layout);
278 }
279 
280 template <typename T>
281 inline typename std::enable_if<!is_hdf5_type<T>::value && !is_trivially_storable<T>(), type>::type
282 get_hdf5_type()
283 {
284  using lowered_type =
285  typename std::decay<decltype(lower_type_internal(std::declval<T>(), {}))>::type;
286 
287  return get_hdf5_type<lowered_type>();
288 }
289 
290 template <typename T>
291 inline typename std::enable_if<!is_hdf5_type<T>::value && is_trivially_storable<T>(), type>::type
292 get_hdf5_type()
293 {
294  static_assert(is_hdf5_type<T>::value, "T must be a valid HDF5 type");
295 }
296 }
297 }
298 
299 #endif
echelon&#39;s core namespace
Definition: attribute.cpp:10
static type short_()
Returns a handle to the primitive type &#39;short&#39;.
Definition: hdf5/type.cpp:17
static type float_()
Returns a handle to the primitive type &#39;float&#39;.
Definition: hdf5/type.cpp:62
static type object_reference()
Returns a handle to the primitive type &#39;object reference&#39;.
Definition: hdf5/type.cpp:77
static type long_long()
Returns a handle to the primitive type &#39;long long&#39;.
Definition: hdf5/type.cpp:32
static type uchar()
Returns a handle to the primitive type &#39;unsigned char&#39;.
Definition: hdf5/type.cpp:37
static type string()
Returns a handle to the primitive type &#39;string&#39;.
Definition: hdf5/type.cpp:72
static type double_()
Returns a handle to the primitive type &#39;double&#39;.
Definition: hdf5/type.cpp:67
static type int_()
Returns a handle to the primitive type &#39;int&#39;.
Definition: hdf5/type.cpp:22
static type ulong_long()
Returns a handle to the primitive type &#39;unsigned long long&#39;.
Definition: hdf5/type.cpp:57
static type ushort()
Returns a handle to the primitive type &#39;unsigned short&#39;.
Definition: hdf5/type.cpp:42
static type long_()
Returns a handle to the primitive type &#39;long&#39;.
Definition: hdf5/type.cpp:27
static type uint()
Returns a handle to the primitive type &#39;unsigned int&#39;.
Definition: hdf5/type.cpp:47
static type char_()
Returns a handle to the primitive type &#39;char&#39;.
Definition: hdf5/type.cpp:12
static type ulong()
Returns a handle to the primitive type &#39;unsigned long&#39;.
Definition: hdf5/type.cpp:52
static type compound_type(const type_layout &layout)
Creates a new compound type using a given layout.
Definition: hdf5/type.cpp:82