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