HighFive 2.10.0
HighFive - Header-only C++ HDF5 interface
Loading...
Searching...
No Matches
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
14namespace HighFive {
15
16namespace details {
17
18template <typename T>
19using unqualified_t = typename std::remove_const<typename std::remove_reference<T>::type>::type;
20
21// Find the type of an eventual char array, otherwise void
22template <typename T>
23struct type_char_array {
24 using type = typename std::conditional<
25 std::is_same<typename inspector<T>::base_type, std::string>::value,
26 std::string,
27 void>::type;
28 static constexpr bool is_char_array = false;
29};
30
31template <typename T>
32struct type_char_array<T*> {
33 using type = typename std::conditional<std::is_same<unqualified_t<T>, char>::value,
34 char*,
35 typename type_char_array<T>::type>::type;
36 static constexpr bool is_char_array = true;
37};
38
39template <typename T, std::size_t N>
40struct type_char_array<T[N]> {
41 using type = typename std::conditional<std::is_same<unqualified_t<T>, char>::value,
42 char[N],
43 typename type_char_array<T>::type>::type;
44 static constexpr bool is_char_array = true;
45};
46
47template <typename T>
48struct BufferInfo {
49 using type_no_const = typename std::remove_const<T>::type;
50 using elem_type = typename details::inspector<type_no_const>::base_type;
51 using char_array_t = typename details::type_char_array<type_no_const>::type;
52 static constexpr bool is_char_array = details::type_char_array<type_no_const>::is_char_array;
53
54 enum class Operation { read, write };
55 const Operation op;
56
57 template <class F>
58 BufferInfo(const DataType& dtype, F getName, Operation _op);
59
60 // member data for info depending on the destination dataset type
61 const bool is_fixed_len_string;
62 const size_t n_dimensions;
63 const DataType data_type;
64};
65
66// details implementation
67template <typename SrcStrT>
68struct string_type_checker {
69 static DataType getDataType(const DataType&, const DataType&);
70};
71
72inline void enforce_ascii_hack(const DataType& dst, const DataType& src) {
73 // Note: constness only refers to constness of the DataType object, which
74 // is just an ID, we can/will change properties of `dst`.
75
76 // TEMP. CHANGE: Ensure that the character set is properly configured to prevent
77 // converter issues on HDF5 <=v1.12.0 when loading ASCII strings first.
78 // See https://github.com/HDFGroup/hdf5/issues/544 for further information.
79
80 bool is_dst_string = detail::h5t_get_class(dst.getId()) == H5T_STRING;
81 bool is_src_string = detail::h5t_get_class(src.getId()) == H5T_STRING;
82
83 if (is_dst_string && is_src_string) {
84 if (detail::h5t_get_cset(src.getId()) == H5T_CSET_ASCII) {
85 detail::h5t_set_cset(dst.getId(), H5T_CSET_ASCII);
86 }
87 }
88}
89
90template <>
91struct string_type_checker<void> {
92 inline static DataType getDataType(const DataType& element_type, const DataType& dtype) {
93 if (detail::h5t_get_class(element_type.getId()) == H5T_STRING) {
94 enforce_ascii_hack(element_type, dtype);
95 }
96 return element_type;
97 }
98};
99
100template <>
101struct string_type_checker<std::string> {
102 inline static DataType getDataType(const DataType&, const DataType& file_datatype) {
103 // The StringBuffer ensures that the data is transformed such that it
104 // matches the datatype of the dataset, i.e. `file_datatype` and
105 // `mem_datatype` are the same.
106 return file_datatype;
107 }
108};
109
110template <std::size_t FixedLen>
111struct string_type_checker<char[FixedLen]> {
112 inline static DataType getDataType(const DataType& element_type, const DataType& dtype) {
113 DataType return_type = (dtype.isFixedLenStr()) ? AtomicType<char[FixedLen]>()
114 : element_type;
115 enforce_ascii_hack(return_type, dtype);
116 return return_type;
117 }
118};
119
120template <>
121struct string_type_checker<char*> {
122 inline static DataType getDataType(const DataType&, const DataType& dtype) {
123 if (dtype.isFixedLenStr()) {
124 throw DataSetException("Can't output variable-length to fixed-length strings");
125 }
126 DataType return_type = AtomicType<std::string>();
127 enforce_ascii_hack(return_type, dtype);
128 return return_type;
129 }
130};
131
132template <typename T>
133template <class F>
134BufferInfo<T>::BufferInfo(const DataType& file_data_type, F getName, Operation _op)
135 : op(_op)
136 , is_fixed_len_string(file_data_type.isFixedLenStr())
137 // In case we are using Fixed-len strings we need to subtract one dimension
138 , n_dimensions(details::inspector<type_no_const>::recursive_ndim -
139 ((is_fixed_len_string && is_char_array) ? 1 : 0))
140 , data_type(string_type_checker<char_array_t>::getDataType(create_datatype<elem_type>(),
141 file_data_type)) {
142 // We warn. In case they are really not convertible an exception will rise on read/write
143 if (file_data_type.getClass() != data_type.getClass()) {
144 HIGHFIVE_LOG_WARN(getName() + "\": data and hdf5 dataset have different types: " +
145 data_type.string() + " -> " + file_data_type.string());
146 } else if ((file_data_type.getClass() & data_type.getClass()) == DataTypeClass::Float) {
148 (op == Operation::read) && (file_data_type.getSize() > data_type.getSize()),
149 getName() + "\": hdf5 dataset has higher floating point precision than data on read: " +
150 file_data_type.string() + " -> " + data_type.string());
151
153 (op == Operation::write) && (file_data_type.getSize() < data_type.getSize()),
154 getName() +
155 "\": data has higher floating point precision than hdf5 dataset on write: " +
156 data_type.string() + " -> " + file_data_type.string());
157 }
158}
159
160} // namespace details
161
162} // namespace HighFive
#define HIGHFIVE_LOG_WARN_IF(cond, message)
Definition H5Utility.hpp:193
#define HIGHFIVE_LOG_WARN(message)
Definition H5Utility.hpp:189
Definition H5_definitions.hpp:22
DataType create_datatype()
Create a DataType instance representing type T.
Definition H5DataType_misc.hpp:479
typename std::remove_const< typename std::remove_reference< T >::type >::type unqualified_t
Definition H5Inspector_decl.hpp:15