echelon  0.8.0
storage_layer.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_STORAGE_LAYER_HPP
7 #define ECHELON_HDF5_STORAGE_LAYER_HPP
8 
9 #include <echelon/hdf5/customization_hooks.hpp>
10 #include <echelon/hdf5/type_traits.hpp>
11 
12 #include <echelon/hdf5/container_adaption.hpp>
13 
14 #include <echelon/hdf5/precursor/property_list.hpp>
15 #include <echelon/hdf5/precursor/dataspace.hpp>
16 #include <echelon/hdf5/precursor/type.hpp>
17 
18 #include <utility>
19 #include <functional>
20 #include <vector>
21 #include <iterator>
22 #include <algorithm>
23 #include <numeric>
24 #include <cassert>
25 #include <type_traits>
26 #include <exception>
27 
28 #include <boost/format.hpp>
29 
30 
31 namespace echelon
32 {
33 namespace hdf5
34 {
35 
36 class inconsistent_selection_size_exception : public std::exception
37 {
38 public:
39  explicit inconsistent_selection_size_exception(hssize_t mem_selection_size_, hssize_t file_selection_size_)
40  {
41  what_ = str(boost::format("The number of selected elements in the memory space (%1%) and the file space (%2%) differs.") % mem_selection_size_ % file_selection_size_);
42  }
43 
44  const char* what() const noexcept override
45  {
46  return what_.c_str();
47  }
48 
49 private:
50  std::string what_;
51 };
52 
53 template <typename Sink, typename C>
54 inline void write_impl(Sink& sink, const hdf5::precursor::type& datatype,
55  const hdf5::precursor::dataspace& memspace,
56  const hdf5::precursor::dataspace& filespace, const C& container,
57  std::true_type)
58 {
59  static_assert(is_readable_container<C>(),
60  "C does not fulfill the ReadableContainer requirements");
61 
62  using value_type = typename std::decay<decltype(*data_adl(container))>::type;
63 
64  static_assert(is_hdf5_type<value_type>::value, "trivially storable types must be HDF5 types.");
65 
66  sink.write(datatype, memspace, filespace, hdf5::precursor::default_property_list,
67  data_adl(container));
68 }
69 
70 template <typename Sink, typename C>
71 void write(Sink& sink, const hdf5::precursor::type& datatype,
72  const hdf5::precursor::dataspace& memspace, const hdf5::precursor::dataspace& filespace,
73  const C& container);
74 
75 template <typename Sink, typename C>
76 inline void write_impl(Sink& sink, const hdf5::precursor::type& datatype,
77  const hdf5::precursor::dataspace& memspace,
78  const hdf5::precursor::dataspace& filespace, const C& container,
79  std::false_type)
80 {
81  static_assert(is_readable_container<C>(),
82  "C does not fulfill the ReadableContainer requirements");
83 
84  using lowered_type =
85  typename std::decay<decltype(lower_type_internal(*data_adl(container), {}))>::type;
86 
87  std::size_t buffer_size = memspace.select_npoints();
88 
89  std::vector<lowered_type> lowered_buffer(buffer_size);
90 
91  for (std::size_t i = 0; i < buffer_size; ++i)
92  {
93  lowered_buffer[i] = lower_type_internal(data_adl(container)[i], sink);
94  }
95 
96  write(sink, datatype, memspace, filespace, lowered_buffer);
97 }
98 
99 template <typename Sink, typename C>
100 inline void write(Sink& sink, const hdf5::precursor::type& datatype,
101  const hdf5::precursor::dataspace& memspace,
102  const hdf5::precursor::dataspace& filespace, const C& container)
103 {
104  static_assert(is_readable_container<C>(),
105  "C does not fulfill the ReadableContainer requirements");
106 
107  using value_type = typename std::decay<decltype(*data_adl(container))>::type;
108 
109  write_impl(sink, datatype, memspace, filespace, container,
110  std::integral_constant<bool, is_trivially_storable<value_type>()>{});
111 }
112 
113 template <typename Source, typename C>
114 void read(const Source& source, const hdf5::precursor::type& datatype,
115  const hdf5::precursor::dataspace& memspace, const hdf5::precursor::dataspace& filespace,
116  C& container);
117 
118 template <typename Source, typename C>
119 inline void read_impl(const Source& source, const hdf5::precursor::type& datatype,
120  const hdf5::precursor::dataspace& memspace,
121  const hdf5::precursor::dataspace& filespace, C& container, std::true_type)
122 {
123  static_assert(is_container<C>(), "C does not fulfill the Container requirements");
124 
125  using value_type = typename std::decay<decltype(*data_adl(container))>::type;
126 
127  static_assert(is_hdf5_type<value_type>::value, "trivially storable types must be HDF5 types.");
128 
129  auto memory_selection_size = memspace.select_npoints();
130  auto file_selection_size = filespace.select_npoints();
131 
132  if(memory_selection_size != file_selection_size)
133  throw inconsistent_selection_size_exception(memory_selection_size, file_selection_size);
134 
135  source.read(datatype, memspace, filespace, hdf5::precursor::default_property_list,
136  data_adl(container));
137 }
138 
139 template <typename Source, typename C>
140 inline void read_impl(const Source& source, const hdf5::precursor::type& datatype,
141  const hdf5::precursor::dataspace& memspace,
142  const hdf5::precursor::dataspace& filespace, C& container, std::false_type)
143 {
144  static_assert(is_container<C>(), "C does not fulfill the Container requirements");
145 
146  std::vector<hsize_t> mem_shape = memspace.get_simple_extent_dims();
147 
148  using lowered_type =
149  typename std::decay<decltype(lower_type_internal(*data_adl(container), {}))>::type;
150 
151  auto memory_selection_size = memspace.select_npoints();
152  auto file_selection_size = filespace.select_npoints();
153 
154  if(memory_selection_size != file_selection_size)
155  throw inconsistent_selection_size_exception(memory_selection_size, file_selection_size);
156 
157  std::vector<lowered_type> lowered_buffer(memory_selection_size);
158 
159  read(source, datatype, memspace, filespace, lowered_buffer);
160 
161  for (decltype(memory_selection_size) i = 0; i < memory_selection_size; ++i)
162  {
163  data_adl(container)[i] = raise_type_internal(lowered_buffer[i], source);
164  }
165 
166  if (H5Tis_variable_str(datatype.id()) || H5Tget_class(datatype.id()) == H5T_VLEN)
167  {
168  H5Dvlen_reclaim(datatype.id(), memspace.id(), H5P_DEFAULT, lowered_buffer.data());
169  }
170 }
171 
172 template <typename Source, typename C>
173 inline void read(const Source& source, const hdf5::precursor::type& datatype,
174  const hdf5::precursor::dataspace& memspace,
175  const hdf5::precursor::dataspace& filespace, C& container)
176 {
177  static_assert(is_container<C>(), "C does not fulfill the Container requirements");
178 
179  using value_type = typename std::decay<decltype(*data_adl(container))>::type;
180 
181  read_impl(source, datatype, memspace, filespace, container,
182  std::integral_constant<bool, is_trivially_storable<value_type>()>{});
183 }
184 
185 template <typename Sink, typename T>
186 void write(Sink& sink, const T& value);
187 
188 template <typename Sink, typename T>
189 inline void write_impl(Sink& sink, const T& value, std::true_type)
190 {
191  static_assert(is_hdf5_type<T>::value, "trivially storable types must be HDF5 types.");
192 
193  sink.write(&value);
194 }
195 
196 template <typename Sink, typename T>
197 inline void write_impl(Sink& sink, const T& value, std::false_type)
198 {
199  auto lowered_value = lower_type_internal(value, sink);
200 
201  write(sink, lowered_value);
202 }
203 
204 template <typename Sink, typename T>
205 inline void write(Sink& sink, const T& value)
206 {
207  write_impl(sink, value, std::integral_constant<bool, is_trivially_storable<T>()>{});
208 }
209 
210 template <typename Sink, typename T, int N>
211 inline void write(Sink& sink, const T (&value)[N])
212 {
213  using value_type = typename std::decay<T>::type;
214 
215  static_assert(is_trivially_storable<value_type>(),
216  "Storage of arrays of non-trivially storable types is not implemented.");
217 
218  const T* decayed_array = value;
219 
220  sink.write(&decayed_array);
221 }
222 
223 template <typename Source, typename T>
224 inline void read(Source& source, T& value);
225 
226 template <typename Source, typename T>
227 inline void read_impl(Source& source, T& value, std::true_type)
228 {
229  static_assert(is_hdf5_type<T>::value, "trivially storable types must be HDF5 types.");
230 
231  source.read(&value);
232 }
233 
234 template <typename Source, typename T>
235 inline void read_impl(Source& source, T& value, std::false_type)
236 {
237  using lowered_value_type = typename std::decay<decltype(lower_type_internal(value, {}))>::type;
238 
239  lowered_value_type lowered_value;
240 
241  read(source, lowered_value);
242 
243  value = raise_type_internal(lowered_value, source);
244 
245  auto datatype = source.datatype();
246 
247  if (H5Tis_variable_str(datatype.id()) || H5Tget_class(datatype.id()) == H5T_VLEN)
248  {
249 
250  H5Dvlen_reclaim(datatype.id(), hdf5::precursor::dataspace().id(), H5P_DEFAULT,
251  &lowered_value);
252  }
253 }
254 
255 template <typename Source, typename T>
256 inline void read(Source& source, T& value)
257 {
258  using value_type = typename std::decay<T>::type;
259 
260  read_impl(source, value, std::integral_constant<bool, is_trivially_storable<value_type>()>{});
261 }
262 
263 template <typename Source, typename T, int N>
264 inline void read(Source& source, T (&value)[N])
265 {
266  using value_type = typename std::decay<T>::type;
267 
268  static_assert(is_trivially_storable<value_type>(),
269  "Storage of arrays of non-trivially storable types is not implemented.");
270 
271  T* decayed_array = value;
272 
273  source.read(&decayed_array);
274 }
275 }
276 }
277 
278 #endif
echelon&#39;s core namespace
Definition: attribute.cpp:10