Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:02:00

0001 /*
0002  *  Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
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 <type_traits>
0012 #include <vector>
0013 
0014 #include <H5Tpublic.h>
0015 
0016 #include "H5Object.hpp"
0017 #include "bits/H5Utils.hpp"
0018 
0019 #include "bits/string_padding.hpp"
0020 #include "H5PropertyList.hpp"
0021 
0022 #include "bits/h5_wrapper.hpp"
0023 #include "bits/h5t_wrapper.hpp"
0024 
0025 namespace HighFive {
0026 
0027 
0028 ///
0029 /// \brief Enum of Fundamental data classes
0030 ///
0031 enum class DataTypeClass {
0032     Time = 1 << 1,
0033     Integer = 1 << 2,
0034     Float = 1 << 3,
0035     String = 1 << 4,
0036     BitField = 1 << 5,
0037     Opaque = 1 << 6,
0038     Compound = 1 << 7,
0039     Reference = 1 << 8,
0040     Enum = 1 << 9,
0041     VarLen = 1 << 10,
0042     Array = 1 << 11,
0043     Invalid = 0
0044 };
0045 
0046 inline DataTypeClass operator|(DataTypeClass lhs, DataTypeClass rhs) {
0047     using T = std::underlying_type<DataTypeClass>::type;
0048     return static_cast<DataTypeClass>(static_cast<T>(lhs) | static_cast<T>(rhs));
0049 }
0050 
0051 inline DataTypeClass operator&(DataTypeClass lhs, DataTypeClass rhs) {
0052     using T = std::underlying_type<DataTypeClass>::type;
0053     return static_cast<DataTypeClass>(static_cast<T>(lhs) & static_cast<T>(rhs));
0054 }
0055 
0056 class StringType;
0057 
0058 ///
0059 /// \brief HDF5 Data Type
0060 ///
0061 class DataType: public Object {
0062   public:
0063     bool operator==(const DataType& other) const;
0064 
0065     bool operator!=(const DataType& other) const;
0066 
0067     ///
0068     /// \brief Return the fundamental type.
0069     ///
0070     DataTypeClass getClass() const;
0071 
0072     ///
0073     /// \brief Returns the length (in bytes) of this type elements
0074     ///
0075     /// Notice that the size of variable length sequences may have limited applicability
0076     /// given that it refers to the size of the control structure. For info see
0077     ///   https://support.hdfgroup.org/HDF5/doc/RM/RM_H5T.html#Datatype-GetSize
0078     size_t getSize() const;
0079 
0080     ///
0081     /// \brief Returns a friendly description of the type (e.g. Float32)
0082     ///
0083     std::string string() const;
0084 
0085     ///
0086     /// \brief Returns whether the type is a variable-length string
0087     ///
0088     bool isVariableStr() const;
0089 
0090     ///
0091     /// \brief Returns whether the type is a fixed-length string
0092     ///
0093     bool isFixedLenStr() const;
0094 
0095     ///
0096     /// \brief Returns this datatype as a `StringType`.
0097     ///
0098     StringType asStringType() const;
0099 
0100     ///
0101     /// \brief Check the DataType was default constructed.
0102     ///
0103     bool empty() const noexcept;
0104 
0105     /// \brief Returns whether the type is a Reference
0106     bool isReference() const;
0107 
0108     /// \brief Get the list of properties for creation of this DataType
0109     DataTypeCreateProps getCreatePropertyList() const {
0110         return details::get_plist<DataTypeCreateProps>(*this, H5Tget_create_plist);
0111     }
0112 
0113   protected:
0114     using Object::Object;
0115 
0116     friend class Attribute;
0117     friend class File;
0118     friend class DataSet;
0119     friend class CompoundType;
0120     template <typename Derivate>
0121     friend class NodeTraits;
0122 };
0123 
0124 
0125 enum class CharacterSet : std::underlying_type<H5T_cset_t>::type {
0126     Ascii = H5T_CSET_ASCII,
0127     Utf8 = H5T_CSET_UTF8,
0128 };
0129 
0130 class StringType: public DataType {
0131   public:
0132     ///
0133     /// \brief For stings return the character set.
0134     ///
0135     CharacterSet getCharacterSet() const;
0136 
0137     ///
0138     /// \brief For fixed length stings return the padding.
0139     ///
0140     StringPadding getPadding() const;
0141 
0142   protected:
0143     using DataType::DataType;
0144     friend class DataType;
0145 };
0146 
0147 class FixedLengthStringType: public StringType {
0148   public:
0149     ///
0150     /// \brief Create a fixed length string datatype.
0151     ///
0152     /// The string will be `size` bytes long, regardless whether it's ASCII or
0153     /// UTF8. In particular, a string with `n` UFT8 characters in general
0154     /// requires `4*n` bytes.
0155     ///
0156     /// The string padding is subtle, essentially it's just a hint. While
0157     /// commonly, a null-terminated string is guaranteed to have one `'\0'`
0158     /// which marks the semantic end of the string, this is not enforced by
0159     /// HDF5. In fact, there are HDF5 files that contain strings that claim to
0160     /// be null-terminated but aren't.  The length of the buffer must be at
0161     /// least `size` bytes regardless of the padding. HDF5 will read or write
0162     /// `size` bytes, irrespective of when (if at all) the `\0` occurs.
0163     ///
0164     /// Note that when writing, passing `StringPadding::NullTerminated` is a
0165     /// guarantee to the reader that it contains a `\0`. Therefore, make sure
0166     /// that the string really is null-terminated. Otherwise prefer a
0167     /// null-padded string. This mearly states that the buffer is filled up
0168     /// with 0 or more `\0`.
0169     FixedLengthStringType(size_t size,
0170                           StringPadding padding,
0171                           CharacterSet character_set = CharacterSet::Ascii);
0172 };
0173 
0174 class VariableLengthStringType: public StringType {
0175   public:
0176     ///
0177     /// \brief Create a variable length string HDF5 datatype.
0178     ///
0179     VariableLengthStringType(CharacterSet character_set = CharacterSet::Ascii);
0180 };
0181 
0182 
0183 ///
0184 /// \brief create an HDF5 DataType from a C++ type
0185 ///
0186 ///  Support only basic data type
0187 ///
0188 template <typename T>
0189 class AtomicType: public DataType {
0190   public:
0191     AtomicType();
0192 
0193     using basic_type = T;
0194 };
0195 
0196 
0197 ///
0198 /// \brief Create a compound HDF5 datatype
0199 ///
0200 class CompoundType: public DataType {
0201   public:
0202     ///
0203     /// \brief Use for defining a sub-type of compound type
0204     struct member_def {
0205         member_def(std::string t_name, DataType t_base_type, size_t t_offset = 0)
0206             : name(std::move(t_name))
0207             , base_type(std::move(t_base_type))
0208             , offset(t_offset) {}
0209         std::string name;
0210         DataType base_type;
0211         size_t offset;
0212     };
0213 
0214     CompoundType(const CompoundType& other) = default;
0215 
0216     ///
0217     /// \brief Initializes a compound type from a vector of member definitions
0218     /// \param t_members
0219     /// \param size
0220     inline CompoundType(const std::vector<member_def>& t_members, size_t size = 0)
0221         : members(t_members) {
0222         create(size);
0223     }
0224     inline CompoundType(std::vector<member_def>&& t_members, size_t size = 0)
0225         : members(std::move(t_members)) {
0226         create(size);
0227     }
0228     inline CompoundType(const std::initializer_list<member_def>& t_members, size_t size = 0)
0229         : members(t_members) {
0230         create(size);
0231     }
0232 
0233     ///
0234     /// \brief Initializes a compound type from a DataType
0235     /// \param type
0236     inline CompoundType(DataType&& type)
0237         : DataType(type) {
0238         if (getClass() != DataTypeClass::Compound) {
0239             std::ostringstream ss;
0240             ss << "hid " << _hid << " does not refer to a compound data type";
0241             throw DataTypeException(ss.str());
0242         }
0243         size_t n_members = static_cast<size_t>(detail::h5t_get_nmembers(_hid));
0244         members.reserve(n_members);
0245         for (unsigned i = 0; i < n_members; i++) {
0246             char* name = detail::h5t_get_member_name(_hid, i);
0247             size_t offset = detail::h5t_get_member_offset(_hid, i);
0248             hid_t member_hid = detail::h5t_get_member_type(_hid, i);
0249             DataType member_type{member_hid};
0250             members.emplace_back(std::string(name), member_type, offset);
0251 
0252             detail::h5_free_memory(name);
0253         }
0254     }
0255 
0256     /// \brief Commit datatype into the given Object
0257     /// \param object Location to commit object into
0258     /// \param name Name to give the datatype
0259     inline void commit(const Object& object, const std::string& name) const;
0260 
0261     /// \brief Get read access to the CompoundType members
0262     inline const std::vector<member_def>& getMembers() const noexcept {
0263         return members;
0264     }
0265 
0266   private:
0267     /// A vector of the member_def members of this CompoundType
0268     std::vector<member_def> members;
0269 
0270     /// \brief Automatically create the type from the set of members
0271     ///        using standard struct alignment.
0272     /// \param size Total size of data type
0273     void create(size_t size = 0);
0274 };
0275 
0276 ///
0277 /// \brief Create a enum HDF5 datatype
0278 ///
0279 /// \code{.cpp}
0280 /// enum class Position {
0281 ///     FIRST = 1,
0282 ///     SECOND = 2,
0283 /// };
0284 ///
0285 /// EnumType<Position> create_enum_position() {
0286 ///     return {{"FIRST", Position::FIRST},
0287 ///             {"SECOND", Position::SECOND}};
0288 /// }
0289 ///
0290 /// // You have to register the type inside HighFive
0291 /// HIGHFIVE_REGISTER_TYPE(Position, create_enum_position)
0292 ///
0293 /// void write_first(H5::File& file) {
0294 ///     auto dataset = file.createDataSet("/foo", Position::FIRST);
0295 /// }
0296 /// \endcode
0297 template <typename T>
0298 class EnumType: public DataType {
0299   public:
0300     ///
0301     /// \brief Use for defining a member of enum type
0302     struct member_def {
0303         member_def(const std::string& t_name, T t_value)
0304             : name(t_name)
0305             , value(std::move(t_value)) {}
0306         std::string name;
0307         T value;
0308     };
0309 
0310     EnumType(const EnumType& other) = default;
0311 
0312     EnumType(const std::vector<member_def>& t_members)
0313         : members(t_members) {
0314         static_assert(std::is_enum<T>::value, "EnumType<T>::create takes only enum");
0315         if (members.empty()) {
0316             HDF5ErrMapper::ToException<DataTypeException>(
0317                 "Could not create an enum without members");
0318         }
0319         create();
0320     }
0321 
0322     EnumType(std::initializer_list<member_def> t_members)
0323         : EnumType(std::vector<member_def>(t_members)) {}
0324 
0325     /// \brief Commit datatype into the given Object
0326     /// \param object Location to commit object into
0327     /// \param name Name to give the datatype
0328     void commit(const Object& object, const std::string& name) const;
0329 
0330   private:
0331     std::vector<member_def> members;
0332 
0333     void create();
0334 };
0335 
0336 
0337 /// \brief Create a DataType instance representing type T
0338 template <typename T>
0339 DataType create_datatype();
0340 
0341 
0342 /// \brief Create a DataType instance representing type T and perform a sanity check on its size
0343 template <typename T>
0344 DataType create_and_check_datatype();
0345 
0346 
0347 namespace deprecated {
0348 ///
0349 /// \brief A structure representing a set of fixed-length strings
0350 ///
0351 /// Although fixed-len arrays can be created 'raw' without the need for
0352 /// this structure, to retrieve results efficiently it must be used.
0353 ///
0354 /// \tparam N Size of the string in bytes, including the null character. Note,
0355 ///           that all string must be null-terminated.
0356 ///
0357 template <std::size_t N>
0358 class FixedLenStringArray {
0359   public:
0360     FixedLenStringArray() = default;
0361 
0362     ///
0363     /// \brief Create a FixedStringArray from a raw contiguous buffer.
0364     ///
0365     /// The argument `n_strings` specifies the number of strings.
0366     ///
0367     FixedLenStringArray(const char array[][N], std::size_t n_strings);
0368 
0369     ///
0370     /// \brief Create a FixedStringArray from a sequence of strings.
0371     ///
0372     /// Such conversion involves a copy, original vector is not modified
0373     ///
0374     explicit FixedLenStringArray(const std::vector<std::string>& vec);
0375 
0376     FixedLenStringArray(const std::string* iter_begin, const std::string* iter_end);
0377 
0378     FixedLenStringArray(const std::initializer_list<std::string>&);
0379 
0380     ///
0381     /// \brief Append an std::string to the buffer structure
0382     ///
0383     void push_back(const std::string&);
0384 
0385     void push_back(const std::array<char, N>&);
0386 
0387     ///
0388     /// \brief Retrieve a string from the structure as std::string
0389     ///
0390     std::string getString(std::size_t index) const;
0391 
0392     // Container interface
0393     inline const char* operator[](std::size_t i) const noexcept {
0394         return datavec[i].data();
0395     }
0396     inline const char* at(std::size_t i) const {
0397         return datavec.at(i).data();
0398     }
0399     inline bool empty() const noexcept {
0400         return datavec.empty();
0401     }
0402     inline std::size_t size() const noexcept {
0403         return datavec.size();
0404     }
0405     inline void resize(std::size_t n) {
0406         datavec.resize(n);
0407     }
0408     inline const char* front() const {
0409         return datavec.front().data();
0410     }
0411     inline const char* back() const {
0412         return datavec.back().data();
0413     }
0414     inline char* data() noexcept {
0415         return datavec[0].data();
0416     }
0417     inline const char* data() const noexcept {
0418         return datavec[0].data();
0419     }
0420 
0421   private:
0422     using vector_t = typename std::vector<std::array<char, N>>;
0423 
0424   public:
0425     // Use the underlying iterator
0426     using iterator = typename vector_t::iterator;
0427     using const_iterator = typename vector_t::const_iterator;
0428     using reverse_iterator = typename vector_t::reverse_iterator;
0429     using const_reverse_iterator = typename vector_t::const_reverse_iterator;
0430     using value_type = typename vector_t::value_type;
0431 
0432     inline iterator begin() noexcept {
0433         return datavec.begin();
0434     }
0435     inline iterator end() noexcept {
0436         return datavec.end();
0437     }
0438     inline const_iterator begin() const noexcept {
0439         return datavec.begin();
0440     }
0441     inline const_iterator cbegin() const noexcept {
0442         return datavec.cbegin();
0443     }
0444     inline const_iterator end() const noexcept {
0445         return datavec.end();
0446     }
0447     inline const_iterator cend() const noexcept {
0448         return datavec.cend();
0449     }
0450     inline reverse_iterator rbegin() noexcept {
0451         return datavec.rbegin();
0452     }
0453     inline reverse_iterator rend() noexcept {
0454         return datavec.rend();
0455     }
0456     inline const_reverse_iterator rbegin() const noexcept {
0457         return datavec.rbegin();
0458     }
0459     inline const_reverse_iterator rend() const noexcept {
0460         return datavec.rend();
0461     }
0462 
0463   private:
0464     vector_t datavec;
0465 };
0466 }  // namespace deprecated
0467 
0468 template <size_t N>
0469 using FixedLenStringArray H5_DEPRECATED_USING("Use 'std::vector<std::string>'.") =
0470     deprecated::FixedLenStringArray<N>;
0471 
0472 }  // namespace HighFive
0473 
0474 
0475 /// \brief Macro to extend datatype of HighFive
0476 ///
0477 /// This macro has to be called outside of any namespace.
0478 ///
0479 /// \code{.cpp}
0480 /// namespace app {
0481 /// enum FooBar { FOO = 1, BAR = 2 };
0482 /// EnumType create_enum_foobar() {
0483 ///    return EnumType<FooBar>({{"FOO", FooBar::FOO},
0484 ///                             {"BAR", FooBar::BAR}});
0485 /// }
0486 /// }
0487 ///
0488 /// HIGHFIVE_REGISTER_TYPE(FooBar, ::app::create_enum_foobar)
0489 /// \endcode
0490 #define HIGHFIVE_REGISTER_TYPE(type, function)                    \
0491     template <>                                                   \
0492     inline HighFive::DataType HighFive::create_datatype<type>() { \
0493         return function();                                        \
0494     }
0495 
0496 #include "bits/H5DataType_misc.hpp"