Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-09 09:12:31

0001 /*
0002  *  Copyright (c) 2020 Blue Brain Project
0003  *
0004  *  Distributed under the Boost Software License, Version 1.0.
0005  *    (See accompanying file LICENSE_1_0.txt or copy at
0006  *          http://www.boost.org/LICENSE_1_0.txt)
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 // Find the type of an eventual char array, otherwise void
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     // member data for info depending on the destination dataset type
0066     const bool is_fixed_len_string;
0067     const DataType data_type;
0068     const size_t rank_correction;
0069 };
0070 
0071 // details implementation
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     // Note: constness only refers to constness of the DataType object, which
0079     // is just an ID, we can/will change properties of `dst`.
0080 
0081     // TEMP. CHANGE: Ensure that the character set is properly configured to prevent
0082     // converter issues on HDF5 <=v1.12.0 when loading ASCII strings first.
0083     // See https://github.com/HDFGroup/hdf5/issues/544 for further information.
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         // The StringBuffer ensures that the data is transformed such that it
0109         // matches the datatype of the dataset, i.e. `file_datatype` and
0110         // `mem_datatype` are the same.
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     // In case we are using Fixed-len strings we need to subtract one dimension
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     // We warn. In case they are really not convertible an exception will rise on read/write
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 }  // namespace details
0180 
0181 }  // namespace HighFive