Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-19 08:55:34

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 "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 // Find the type of an eventual char array, otherwise void
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     // member data for info depending on the destination dataset type
0061     const bool is_fixed_len_string;
0062     const size_t n_dimensions;
0063     const DataType data_type;
0064 };
0065 
0066 // details implementation
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     // Note: constness only refers to constness of the DataType object, which
0074     // is just an ID, we can/will change properties of `dst`.
0075 
0076     // TEMP. CHANGE: Ensure that the character set is properly configured to prevent
0077     // converter issues on HDF5 <=v1.12.0 when loading ASCII strings first.
0078     // See https://github.com/HDFGroup/hdf5/issues/544 for further information.
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         // The StringBuffer ensures that the data is transformed such that it
0104         // matches the datatype of the dataset, i.e. `file_datatype` and
0105         // `mem_datatype` are the same.
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     // In case we are using Fixed-len strings we need to subtract one dimension
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     // We warn. In case they are really not convertible an exception will rise on read/write
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 }  // namespace details
0161 
0162 }  // namespace HighFive