HighFive  2.3.1
HighFive - Header-only C++ HDF5 interface
H5ReadWrite_misc.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Blue Brain Project
3  *
4  * Distributed under the Boost Software License, Version 1.0.
5  * (See accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  */
9 #pragma once
10 
11 #include "H5Tpublic.h"
12 #include "H5Utils.hpp"
13 
14 namespace HighFive {
15 
16 namespace details {
17 
18 template <typename T>
19 struct BufferInfo {
20  using type_no_const = typename std::remove_const<T>::type;
21  using elem_type = typename details::inspector<type_no_const>::base_type;
22  using char_array_t = typename details::type_char_array<type_no_const>::type;
23  static constexpr bool is_char_array = ! std::is_same<char_array_t, void>::value;
24 
25  template <class F>
26  BufferInfo(const DataType& dtype, F getName);
27 
28  // member data for info depending on the destination dataset type
29  const bool is_fixed_len_string;
30  const size_t n_dimensions;
31  const DataType data_type;
32 };
33 
34 // details implementation
35 template <typename SrcStrT>
36 struct string_type_checker {
37  static DataType getDataType(const DataType&, const DataType&);
38 };
39 
40 template <>
41 struct string_type_checker<void> {
42 inline static DataType getDataType(const DataType& element_type, const DataType& dtype) {
43  // TEMP. CHANGE: Ensure that the character set is properly configured to prevent
44  // converter issues on HDF5 <=v1.12.0 when loading ASCII strings first.
45  // See https://github.com/HDFGroup/hdf5/issues/544 for further information.
46  if (H5Tget_class(element_type.getId()) == H5T_STRING &&
47  H5Tget_cset(dtype.getId()) == H5T_CSET_ASCII) {
48  H5Tset_cset(element_type.getId(), H5T_CSET_ASCII);
49  }
50  return element_type;
51 }};
52 
53 template <std::size_t FixedLen>
54 struct string_type_checker<char[FixedLen]> {
55 inline static DataType getDataType(const DataType& element_type, const DataType& dtype) {
56  DataType return_type = (dtype.isFixedLenStr()) ? AtomicType<char[FixedLen]>() : element_type;
57  // TEMP. CHANGE: See string_type_checker<void> definition
58  if (H5Tget_cset(dtype.getId()) == H5T_CSET_ASCII) {
59  H5Tset_cset(return_type.getId(), H5T_CSET_ASCII);
60  }
61  return return_type;
62 }};
63 
64 template <>
65 struct string_type_checker<char*> {
66 inline static DataType getDataType(const DataType&, const DataType& dtype) {
67  if (dtype.isFixedLenStr())
68  throw DataSetException("Can't output variable-length to fixed-length strings");
69  // TEMP. CHANGE: See string_type_checker<void> definition
70  DataType return_type = AtomicType<std::string>();
71  if (H5Tget_cset(dtype.getId()) == H5T_CSET_ASCII) {
72  H5Tset_cset(return_type.getId(), H5T_CSET_ASCII);
73  }
74  return return_type;
75 }};
76 
77 template <typename T>
78 template <class F>
79 BufferInfo<T>::BufferInfo(const DataType& dtype, F getName)
80  : is_fixed_len_string(dtype.isFixedLenStr())
81  // In case we are using Fixed-len strings we need to subtract one dimension
82  , n_dimensions(details::inspector<type_no_const>::recursive_ndim -
83  ((is_fixed_len_string && is_char_array) ? 1 : 0))
84  , data_type(string_type_checker<char_array_t>::getDataType(
85  create_datatype<elem_type>(), dtype)) {
86  if (is_fixed_len_string && std::is_same<elem_type, std::string>::value) {
87  throw DataSetException("Can't output std::string as fixed-length. "
88  "Use raw arrays or FixedLenStringArray");
89  }
90  // We warn. In case they are really not convertible an exception will rise on read/write
91  if (dtype.getClass() != data_type.getClass()) {
92  std::cerr << "HighFive WARNING \""
93  << getName()
94  << "\": data and hdf5 dataset have different types: "
95  << data_type.string() << " -> " << dtype.string() << std::endl;
96  }
97 }
98 
99 } // namespace details
100 
101 } // namespace HighFive
Definition: H5_definitions.hpp:15
DataType create_datatype()
Create a DataType instance representing type T.
Definition: H5DataType_misc.hpp:427