File indexing completed on 2026-09-09 09:12:31
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <H5Tpublic.h>
0012 #include "H5Inspector_misc.hpp"
0013 #include "H5Utils.hpp"
0014
0015 namespace HighFive {
0016
0017 namespace details {
0018
0019 template <typename T>
0020 using unqualified_t = typename std::remove_const<typename std::remove_reference<T>::type>::type;
0021
0022
0023 template <typename T>
0024 struct type_char_array {
0025 using type = typename std::conditional<
0026 std::is_same<typename inspector<T>::base_type, std::string>::value,
0027 std::string,
0028 void>::type;
0029 static constexpr bool is_char_array = false;
0030 };
0031
0032 template <typename T>
0033 struct type_char_array<T*> {
0034 using type = typename std::conditional<std::is_same<unqualified_t<T>, char>::value,
0035 char*,
0036 typename type_char_array<T>::type>::type;
0037 static constexpr bool is_char_array = true;
0038 };
0039
0040 template <typename T, std::size_t N>
0041 struct type_char_array<T[N]> {
0042 using type = typename std::conditional<std::is_same<unqualified_t<T>, char>::value,
0043 char[N],
0044 typename type_char_array<T>::type>::type;
0045 static constexpr bool is_char_array = true;
0046 };
0047
0048 template <typename T>
0049 struct BufferInfo {
0050 using type_no_const = typename std::remove_const<T>::type;
0051 using elem_type = typename details::inspector<type_no_const>::base_type;
0052 using char_array_t = typename details::type_char_array<type_no_const>::type;
0053 static constexpr bool is_char_array = details::type_char_array<type_no_const>::is_char_array;
0054
0055 enum class Operation { read, write };
0056 const Operation op;
0057
0058 template <class F>
0059 BufferInfo(const DataType& file_data_type, F getName, Operation _op);
0060
0061 size_t getRank(const T& array) const;
0062 size_t getMinRank() const;
0063 size_t getMaxRank() const;
0064
0065
0066 const bool is_fixed_len_string;
0067 const DataType data_type;
0068 const size_t rank_correction;
0069 };
0070
0071
0072 template <typename SrcStrT>
0073 struct string_type_checker {
0074 static DataType getDataType(const DataType&, const DataType&);
0075 };
0076
0077 inline void enforce_ascii_hack(const DataType& dst, const DataType& src) {
0078
0079
0080
0081
0082
0083
0084
0085 bool is_dst_string = detail::h5t_get_class(dst.getId()) == H5T_STRING;
0086 bool is_src_string = detail::h5t_get_class(src.getId()) == H5T_STRING;
0087
0088 if (is_dst_string && is_src_string) {
0089 if (detail::h5t_get_cset(src.getId()) == H5T_CSET_ASCII) {
0090 detail::h5t_set_cset(dst.getId(), H5T_CSET_ASCII);
0091 }
0092 }
0093 }
0094
0095 template <>
0096 struct string_type_checker<void> {
0097 inline static DataType getDataType(const DataType& element_type, const DataType& dtype) {
0098 if (detail::h5t_get_class(element_type.getId()) == H5T_STRING) {
0099 enforce_ascii_hack(element_type, dtype);
0100 }
0101 return element_type;
0102 }
0103 };
0104
0105 template <>
0106 struct string_type_checker<std::string> {
0107 inline static DataType getDataType(const DataType&, const DataType& file_datatype) {
0108
0109
0110
0111 return file_datatype;
0112 }
0113 };
0114
0115 template <std::size_t FixedLen>
0116 struct string_type_checker<char[FixedLen]> {
0117 inline static DataType getDataType(const DataType& element_type, const DataType& dtype) {
0118 DataType return_type = (dtype.isFixedLenStr()) ? AtomicType<char[FixedLen]>()
0119 : element_type;
0120 enforce_ascii_hack(return_type, dtype);
0121 return return_type;
0122 }
0123 };
0124
0125 template <>
0126 struct string_type_checker<char*> {
0127 inline static DataType getDataType(const DataType&, const DataType& dtype) {
0128 if (dtype.isFixedLenStr()) {
0129 throw DataSetException("Can't output variable-length to fixed-length strings");
0130 }
0131 DataType return_type = AtomicType<std::string>();
0132 enforce_ascii_hack(return_type, dtype);
0133 return return_type;
0134 }
0135 };
0136
0137 template <typename T>
0138 template <class F>
0139 BufferInfo<T>::BufferInfo(const DataType& file_data_type, F getName, Operation _op)
0140 : op(_op)
0141 , is_fixed_len_string(file_data_type.isFixedLenStr())
0142
0143 , data_type(string_type_checker<char_array_t>::getDataType(create_datatype<elem_type>(),
0144 file_data_type))
0145 , rank_correction((is_fixed_len_string && is_char_array) ? 1 : 0) {
0146
0147 if (file_data_type.getClass() != data_type.getClass()) {
0148 HIGHFIVE_LOG_WARN(getName() + "\": data and hdf5 dataset have different types: " +
0149 data_type.string() + " -> " + file_data_type.string());
0150 } else if ((file_data_type.getClass() & data_type.getClass()) == DataTypeClass::Float) {
0151 HIGHFIVE_LOG_WARN_IF(
0152 (op == Operation::read) && (file_data_type.getSize() > data_type.getSize()),
0153 getName() + "\": hdf5 dataset has higher floating point precision than data on read: " +
0154 file_data_type.string() + " -> " + data_type.string());
0155
0156 HIGHFIVE_LOG_WARN_IF(
0157 (op == Operation::write) && (file_data_type.getSize() < data_type.getSize()),
0158 getName() +
0159 "\": data has higher floating point precision than hdf5 dataset on write: " +
0160 data_type.string() + " -> " + file_data_type.string());
0161 }
0162 }
0163
0164 template <typename T>
0165 size_t BufferInfo<T>::getRank(const T& array) const {
0166 return details::inspector<type_no_const>::getRank(array) - rank_correction;
0167 }
0168
0169 template <typename T>
0170 size_t BufferInfo<T>::getMinRank() const {
0171 return details::inspector<T>::min_ndim - rank_correction;
0172 }
0173
0174 template <typename T>
0175 size_t BufferInfo<T>::getMaxRank() const {
0176 return details::inspector<T>::max_ndim - rank_correction;
0177 }
0178
0179 }
0180
0181 }