Back to home page

EIC code displayed by LXR

 
 

    


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

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. A
0157     /// null-terminated string is guaranteed to have one `'\0'` which marks the
0158     /// semantic end of the string. The length of the buffer must be at least
0159     /// `size` bytes regardless. HDF5 will read or write `size` bytes,
0160     /// irrespective of the when the `\0` occurs.
0161     ///
0162     /// Note that when writing passing `StringPadding::NullTerminated` is a
0163     /// guarantee to the reader that it contains a `\0`. Therefore, make sure
0164     /// that the string really is nullterminated. Otherwise prefer a
0165     /// null-padded string which only means states that the buffer is filled up
0166     /// with 0 or more `\0`.
0167     FixedLengthStringType(size_t size,
0168                           StringPadding padding,
0169                           CharacterSet character_set = CharacterSet::Ascii);
0170 };
0171 
0172 class VariableLengthStringType: public StringType {
0173   public:
0174     ///
0175     /// \brief Create a variable length string HDF5 datatype.
0176     ///
0177     VariableLengthStringType(CharacterSet character_set = CharacterSet::Ascii);
0178 };
0179 
0180 
0181 ///
0182 /// \brief create an HDF5 DataType from a C++ type
0183 ///
0184 ///  Support only basic data type
0185 ///
0186 template <typename T>
0187 class AtomicType: public DataType {
0188   public:
0189     AtomicType();
0190 
0191     using basic_type = T;
0192 };
0193 
0194 
0195 ///
0196 /// \brief Create a compound HDF5 datatype
0197 ///
0198 class CompoundType: public DataType {
0199   public:
0200     ///
0201     /// \brief Use for defining a sub-type of compound type
0202     struct member_def {
0203         member_def(std::string t_name, DataType t_base_type, size_t t_offset = 0)
0204             : name(std::move(t_name))
0205             , base_type(std::move(t_base_type))
0206             , offset(t_offset) {}
0207         std::string name;
0208         DataType base_type;
0209         size_t offset;
0210     };
0211 
0212     CompoundType(const CompoundType& other) = default;
0213 
0214     ///
0215     /// \brief Initializes a compound type from a vector of member definitions
0216     /// \param t_members
0217     /// \param size
0218     inline CompoundType(const std::vector<member_def>& t_members, size_t size = 0)
0219         : members(t_members) {
0220         create(size);
0221     }
0222     inline CompoundType(std::vector<member_def>&& t_members, size_t size = 0)
0223         : members(std::move(t_members)) {
0224         create(size);
0225     }
0226     inline CompoundType(const std::initializer_list<member_def>& t_members, size_t size = 0)
0227         : members(t_members) {
0228         create(size);
0229     }
0230 
0231     ///
0232     /// \brief Initializes a compound type from a DataType
0233     /// \param type
0234     inline CompoundType(DataType&& type)
0235         : DataType(type) {
0236         if (getClass() != DataTypeClass::Compound) {
0237             std::ostringstream ss;
0238             ss << "hid " << _hid << " does not refer to a compound data type";
0239             throw DataTypeException(ss.str());
0240         }
0241         size_t n_members = static_cast<size_t>(detail::h5t_get_nmembers(_hid));
0242         members.reserve(n_members);
0243         for (unsigned i = 0; i < n_members; i++) {
0244             char* name = detail::h5t_get_member_name(_hid, i);
0245             size_t offset = detail::h5t_get_member_offset(_hid, i);
0246             hid_t member_hid = detail::h5t_get_member_type(_hid, i);
0247             DataType member_type{member_hid};
0248             members.emplace_back(std::string(name), member_type, offset);
0249 
0250             detail::h5_free_memory(name);
0251         }
0252     }
0253 
0254     /// \brief Commit datatype into the given Object
0255     /// \param object Location to commit object into
0256     /// \param name Name to give the datatype
0257     inline void commit(const Object& object, const std::string& name) const;
0258 
0259     /// \brief Get read access to the CompoundType members
0260     inline const std::vector<member_def>& getMembers() const noexcept {
0261         return members;
0262     }
0263 
0264   private:
0265     /// A vector of the member_def members of this CompoundType
0266     std::vector<member_def> members;
0267 
0268     /// \brief Automatically create the type from the set of members
0269     ///        using standard struct alignment.
0270     /// \param size Total size of data type
0271     void create(size_t size = 0);
0272 };
0273 
0274 ///
0275 /// \brief Create a enum HDF5 datatype
0276 ///
0277 /// \code{.cpp}
0278 /// enum class Position {
0279 ///     FIRST = 1,
0280 ///     SECOND = 2,
0281 /// };
0282 ///
0283 /// EnumType<Position> create_enum_position() {
0284 ///     return {{"FIRST", Position::FIRST},
0285 ///             {"SECOND", Position::SECOND}};
0286 /// }
0287 ///
0288 /// // You have to register the type inside HighFive
0289 /// HIGHFIVE_REGISTER_TYPE(Position, create_enum_position)
0290 ///
0291 /// void write_first(H5::File& file) {
0292 ///     auto dataset = file.createDataSet("/foo", Position::FIRST);
0293 /// }
0294 /// \endcode
0295 template <typename T>
0296 class EnumType: public DataType {
0297   public:
0298     ///
0299     /// \brief Use for defining a member of enum type
0300     struct member_def {
0301         member_def(const std::string& t_name, T t_value)
0302             : name(t_name)
0303             , value(std::move(t_value)) {}
0304         std::string name;
0305         T value;
0306     };
0307 
0308     EnumType(const EnumType& other) = default;
0309 
0310     EnumType(const std::vector<member_def>& t_members)
0311         : members(t_members) {
0312         static_assert(std::is_enum<T>::value, "EnumType<T>::create takes only enum");
0313         if (members.empty()) {
0314             HDF5ErrMapper::ToException<DataTypeException>(
0315                 "Could not create an enum without members");
0316         }
0317         create();
0318     }
0319 
0320     EnumType(std::initializer_list<member_def> t_members)
0321         : EnumType(std::vector<member_def>(t_members)) {}
0322 
0323     /// \brief Commit datatype into the given Object
0324     /// \param object Location to commit object into
0325     /// \param name Name to give the datatype
0326     void commit(const Object& object, const std::string& name) const;
0327 
0328   private:
0329     std::vector<member_def> members;
0330 
0331     void create();
0332 };
0333 
0334 
0335 /// \brief Create a DataType instance representing type T
0336 template <typename T>
0337 DataType create_datatype();
0338 
0339 
0340 /// \brief Create a DataType instance representing type T and perform a sanity check on its size
0341 template <typename T>
0342 DataType create_and_check_datatype();
0343 
0344 
0345 namespace deprecated {
0346 ///
0347 /// \brief A structure representing a set of fixed-length strings
0348 ///
0349 /// Although fixed-len arrays can be created 'raw' without the need for
0350 /// this structure, to retrieve results efficiently it must be used.
0351 ///
0352 /// \tparam N Size of the string in bytes, including the null character. Note,
0353 ///           that all string must be null-terminated.
0354 ///
0355 template <std::size_t N>
0356 class FixedLenStringArray {
0357   public:
0358     FixedLenStringArray() = default;
0359 
0360     ///
0361     /// \brief Create a FixedStringArray from a raw contiguous buffer.
0362     ///
0363     /// The argument `n_strings` specifies the number of strings.
0364     ///
0365     FixedLenStringArray(const char array[][N], std::size_t n_strings);
0366 
0367     ///
0368     /// \brief Create a FixedStringArray from a sequence of strings.
0369     ///
0370     /// Such conversion involves a copy, original vector is not modified
0371     ///
0372     explicit FixedLenStringArray(const std::vector<std::string>& vec);
0373 
0374     FixedLenStringArray(const std::string* iter_begin, const std::string* iter_end);
0375 
0376     FixedLenStringArray(const std::initializer_list<std::string>&);
0377 
0378     ///
0379     /// \brief Append an std::string to the buffer structure
0380     ///
0381     void push_back(const std::string&);
0382 
0383     void push_back(const std::array<char, N>&);
0384 
0385     ///
0386     /// \brief Retrieve a string from the structure as std::string
0387     ///
0388     std::string getString(std::size_t index) const;
0389 
0390     // Container interface
0391     inline const char* operator[](std::size_t i) const noexcept {
0392         return datavec[i].data();
0393     }
0394     inline const char* at(std::size_t i) const {
0395         return datavec.at(i).data();
0396     }
0397     inline bool empty() const noexcept {
0398         return datavec.empty();
0399     }
0400     inline std::size_t size() const noexcept {
0401         return datavec.size();
0402     }
0403     inline void resize(std::size_t n) {
0404         datavec.resize(n);
0405     }
0406     inline const char* front() const {
0407         return datavec.front().data();
0408     }
0409     inline const char* back() const {
0410         return datavec.back().data();
0411     }
0412     inline char* data() noexcept {
0413         return datavec[0].data();
0414     }
0415     inline const char* data() const noexcept {
0416         return datavec[0].data();
0417     }
0418 
0419   private:
0420     using vector_t = typename std::vector<std::array<char, N>>;
0421 
0422   public:
0423     // Use the underlying iterator
0424     using iterator = typename vector_t::iterator;
0425     using const_iterator = typename vector_t::const_iterator;
0426     using reverse_iterator = typename vector_t::reverse_iterator;
0427     using const_reverse_iterator = typename vector_t::const_reverse_iterator;
0428     using value_type = typename vector_t::value_type;
0429 
0430     inline iterator begin() noexcept {
0431         return datavec.begin();
0432     }
0433     inline iterator end() noexcept {
0434         return datavec.end();
0435     }
0436     inline const_iterator begin() const noexcept {
0437         return datavec.begin();
0438     }
0439     inline const_iterator cbegin() const noexcept {
0440         return datavec.cbegin();
0441     }
0442     inline const_iterator end() const noexcept {
0443         return datavec.end();
0444     }
0445     inline const_iterator cend() const noexcept {
0446         return datavec.cend();
0447     }
0448     inline reverse_iterator rbegin() noexcept {
0449         return datavec.rbegin();
0450     }
0451     inline reverse_iterator rend() noexcept {
0452         return datavec.rend();
0453     }
0454     inline const_reverse_iterator rbegin() const noexcept {
0455         return datavec.rbegin();
0456     }
0457     inline const_reverse_iterator rend() const noexcept {
0458         return datavec.rend();
0459     }
0460 
0461   private:
0462     vector_t datavec;
0463 };
0464 }  // namespace deprecated
0465 
0466 template <size_t N>
0467 using FixedLenStringArray H5_DEPRECATED_USING("Use 'std::vector<std::string>'.") =
0468     deprecated::FixedLenStringArray<N>;
0469 
0470 }  // namespace HighFive
0471 
0472 
0473 /// \brief Macro to extend datatype of HighFive
0474 ///
0475 /// This macro has to be called outside of any namespace.
0476 ///
0477 /// \code{.cpp}
0478 /// namespace app {
0479 /// enum FooBar { FOO = 1, BAR = 2 };
0480 /// EnumType create_enum_foobar() {
0481 ///    return EnumType<FooBar>({{"FOO", FooBar::FOO},
0482 ///                             {"BAR", FooBar::BAR}});
0483 /// }
0484 /// }
0485 ///
0486 /// HIGHFIVE_REGISTER_TYPE(FooBar, ::app::create_enum_foobar)
0487 /// \endcode
0488 #define HIGHFIVE_REGISTER_TYPE(type, function)                    \
0489     template <>                                                   \
0490     inline HighFive::DataType HighFive::create_datatype<type>() { \
0491         return function();                                        \
0492     }
0493 
0494 #include "bits/H5DataType_misc.hpp"