File indexing completed on 2026-09-23 09:14:20
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <string>
0012 #include <complex>
0013 #include <cstring>
0014 #if HIGHFIVE_CXX_STD >= 17
0015 #include <cstddef>
0016 #endif
0017
0018 #include <H5Ppublic.h>
0019
0020 #include "H5Inspector_misc.hpp"
0021 #include "h5t_wrapper.hpp"
0022 #include "h5i_wrapper.hpp"
0023
0024 namespace HighFive {
0025
0026 namespace {
0027 inline DataTypeClass convert_type_class(const H5T_class_t& tclass);
0028 inline std::string type_class_string(DataTypeClass);
0029 inline hid_t create_string(std::size_t length);
0030 }
0031
0032 inline bool DataType::empty() const noexcept {
0033 return _hid == H5I_INVALID_HID;
0034 }
0035
0036 inline DataTypeClass DataType::getClass() const {
0037 return convert_type_class(detail::h5t_get_class(_hid));
0038 }
0039
0040 inline size_t DataType::getSize() const {
0041 return detail::h5t_get_size(_hid);
0042 }
0043
0044 inline bool DataType::operator==(const DataType& other) const {
0045 return detail::h5t_equal(_hid, other._hid) > 0;
0046 }
0047
0048 inline bool DataType::operator!=(const DataType& other) const {
0049 return !(*this == other);
0050 }
0051
0052 inline bool DataType::isVariableStr() const {
0053 return detail::h5t_is_variable_str(_hid) > 0;
0054 }
0055
0056 inline bool DataType::isFixedLenStr() const {
0057 return getClass() == DataTypeClass::String && !isVariableStr();
0058 }
0059
0060 inline bool DataType::isReference() const {
0061 return detail::h5t_equal(_hid, H5T_STD_REF_OBJ) > 0;
0062 }
0063
0064 inline StringType DataType::asStringType() const {
0065 if (getClass() != DataTypeClass::String) {
0066 throw DataTypeException("Invalid conversion to StringType.");
0067 }
0068
0069 if (isValid()) {
0070 detail::h5i_inc_ref(_hid);
0071 }
0072
0073 return StringType(_hid);
0074 }
0075
0076 inline IntegerType DataType::asIntegerType() const {
0077 if (getClass() != DataTypeClass::Integer) {
0078 throw DataTypeException("Invalid conversion to IntegerType.");
0079 }
0080
0081 if (isValid()) {
0082 detail::h5i_inc_ref(_hid);
0083 }
0084
0085 return IntegerType(_hid);
0086 }
0087
0088 inline std::string DataType::string() const {
0089 return type_class_string(getClass()) + std::to_string(getSize() * 8);
0090 }
0091
0092 inline StringPadding StringType::getPadding() const {
0093 return StringPadding(detail::h5t_get_strpad(_hid));
0094 }
0095
0096 inline CharacterSet StringType::getCharacterSet() const {
0097 return CharacterSet(detail::h5t_get_cset(_hid));
0098 }
0099
0100 inline FixedLengthStringType::FixedLengthStringType(size_t size,
0101 StringPadding padding,
0102 CharacterSet character_set) {
0103 if (size == 0 && padding == StringPadding::NullTerminated) {
0104 throw DataTypeException(
0105 "Fixed-length, null-terminated need at least one byte to store the null-character.");
0106 }
0107
0108 _hid = detail::h5t_copy(H5T_C_S1);
0109
0110 detail::h5t_set_size(_hid, hsize_t(size));
0111 detail::h5t_set_cset(_hid, H5T_cset_t(character_set));
0112 detail::h5t_set_strpad(_hid, H5T_str_t(padding));
0113 }
0114
0115 inline VariableLengthStringType::VariableLengthStringType(CharacterSet character_set) {
0116 _hid = detail::h5t_copy(H5T_C_S1);
0117
0118 detail::h5t_set_size(_hid, H5T_VARIABLE);
0119 detail::h5t_set_cset(_hid, H5T_cset_t(character_set));
0120 }
0121
0122
0123 template <>
0124 inline AtomicType<char>::AtomicType() {
0125 _hid = detail::h5t_copy(H5T_NATIVE_CHAR);
0126 }
0127
0128 template <>
0129 inline AtomicType<signed char>::AtomicType() {
0130 _hid = detail::h5t_copy(H5T_NATIVE_SCHAR);
0131 }
0132
0133 template <>
0134 inline AtomicType<unsigned char>::AtomicType() {
0135 _hid = detail::h5t_copy(H5T_NATIVE_UCHAR);
0136 }
0137
0138
0139 template <>
0140 inline AtomicType<short>::AtomicType() {
0141 _hid = detail::h5t_copy(H5T_NATIVE_SHORT);
0142 }
0143
0144 template <>
0145 inline AtomicType<unsigned short>::AtomicType() {
0146 _hid = detail::h5t_copy(H5T_NATIVE_USHORT);
0147 }
0148
0149
0150 template <>
0151 inline AtomicType<int>::AtomicType() {
0152 _hid = detail::h5t_copy(H5T_NATIVE_INT);
0153 }
0154
0155 template <>
0156 inline AtomicType<unsigned>::AtomicType() {
0157 _hid = detail::h5t_copy(H5T_NATIVE_UINT);
0158 }
0159
0160
0161 template <>
0162 inline AtomicType<long>::AtomicType() {
0163 _hid = detail::h5t_copy(H5T_NATIVE_LONG);
0164 }
0165
0166 template <>
0167 inline AtomicType<unsigned long>::AtomicType() {
0168 _hid = detail::h5t_copy(H5T_NATIVE_ULONG);
0169 }
0170
0171
0172 template <>
0173 inline AtomicType<long long>::AtomicType() {
0174 _hid = detail::h5t_copy(H5T_NATIVE_LLONG);
0175 }
0176
0177 template <>
0178 inline AtomicType<unsigned long long>::AtomicType() {
0179 _hid = detail::h5t_copy(H5T_NATIVE_ULLONG);
0180 }
0181
0182
0183 template <>
0184 inline AtomicType<float>::AtomicType() {
0185 _hid = detail::h5t_copy(H5T_NATIVE_FLOAT);
0186 }
0187
0188 template <>
0189 inline AtomicType<double>::AtomicType() {
0190 _hid = detail::h5t_copy(H5T_NATIVE_DOUBLE);
0191 }
0192
0193 template <>
0194 inline AtomicType<long double>::AtomicType() {
0195 _hid = detail::h5t_copy(H5T_NATIVE_LDOUBLE);
0196 }
0197
0198
0199 template <>
0200 inline AtomicType<std::string>::AtomicType() {
0201 _hid = create_string(H5T_VARIABLE);
0202 }
0203
0204 #if HIGHFIVE_CXX_STD >= 17
0205
0206 template <>
0207 inline AtomicType<std::byte>::AtomicType() {
0208 _hid = detail::h5t_copy(H5T_NATIVE_B8);
0209 }
0210 #endif
0211
0212
0213
0214 template <size_t StrLen>
0215 class AtomicType<char[StrLen]>: public DataType {
0216 public:
0217 inline AtomicType()
0218 : DataType(create_string(StrLen)) {}
0219 };
0220
0221 template <typename T>
0222 class AtomicType<std::complex<T>>: public DataType {
0223 public:
0224 inline AtomicType()
0225 : DataType(
0226 CompoundType({{"r", create_datatype<T>(), 0}, {"i", create_datatype<T>(), sizeof(T)}},
0227 sizeof(std::complex<T>))) {
0228 static_assert(std::is_arithmetic<T>::value,
0229 "std::complex accepts only floating point and integral numbers.");
0230 }
0231 };
0232
0233
0234 inline EnumType<details::Boolean> create_enum_boolean() {
0235 return {{"FALSE", details::Boolean::HighFiveFalse}, {"TRUE", details::Boolean::HighFiveTrue}};
0236 }
0237
0238
0239 namespace detail {
0240 template <class T>
0241 struct FalseType {
0242 static constexpr const bool value = false;
0243 };
0244 }
0245
0246
0247 template <typename T>
0248 AtomicType<T>::AtomicType() {
0249
0250 static_assert(
0251 ::HighFive::detail::FalseType<T>::value,
0252 "Missing specialization of AtomicType<T>. Therefore, type T is not supported by HighFive.");
0253 }
0254
0255
0256
0257
0258 template <>
0259 inline AtomicType<Reference>::AtomicType() {
0260 _hid = detail::h5t_copy(H5T_STD_REF_OBJ);
0261 }
0262
0263 inline size_t find_first_atomic_member_size(hid_t hid) {
0264
0265 if (detail::h5t_get_class(hid) == H5T_COMPOUND) {
0266 auto number_of_members = detail::h5t_get_nmembers(hid);
0267 if (number_of_members == -1) {
0268 throw DataTypeException("Cannot get members of CompoundType with hid: " +
0269 std::to_string(hid));
0270 }
0271 if (number_of_members == 0) {
0272 throw DataTypeException("No members defined for CompoundType with hid: " +
0273 std::to_string(hid));
0274 }
0275
0276 auto member_type = detail::h5t_get_member_type(hid, 0);
0277 auto size = find_first_atomic_member_size(member_type);
0278 detail::h5t_close(member_type);
0279 return size;
0280 } else if (detail::h5t_get_class(hid) == H5T_STRING) {
0281 return 1;
0282 }
0283 return detail::h5t_get_size(hid);
0284 }
0285
0286 namespace detail {
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303 inline size_t struct_padding(size_t current_size, size_t member_size) {
0304 if (member_size == 0) {
0305 throw DataTypeException("Unexpected `member_size == 0`.");
0306 }
0307
0308 return member_size >= current_size
0309 ? (member_size - current_size) % member_size
0310 : ((member_size - ((current_size - member_size) % member_size))) % member_size;
0311 }
0312 }
0313
0314 inline void CompoundType::create(size_t size) {
0315 if (size == 0) {
0316 size_t current_size = 0, max_atomic_size = 0;
0317
0318
0319 for (auto& member: members) {
0320 size_t member_size = detail::h5t_get_size(member.base_type.getId());
0321
0322 if (member_size == 0) {
0323 throw DataTypeException("Cannot get size of DataType with hid: " +
0324 std::to_string(member.base_type.getId()));
0325 }
0326
0327 size_t first_atomic_size = find_first_atomic_member_size(member.base_type.getId());
0328
0329
0330
0331
0332 member.offset = current_size + detail::struct_padding(current_size, first_atomic_size);
0333
0334
0335 current_size = member.offset + member_size;
0336
0337
0338
0339 max_atomic_size = std::max(max_atomic_size, first_atomic_size);
0340 }
0341
0342 size = current_size + detail::struct_padding(current_size, max_atomic_size);
0343 }
0344
0345
0346 _hid = detail::h5t_create(H5T_COMPOUND, size);
0347
0348
0349 for (const auto& member: members) {
0350 detail::h5t_insert(_hid, member.name.c_str(), member.offset, member.base_type.getId());
0351 }
0352 }
0353
0354 inline void CompoundType::commit(const Object& object, const std::string& name) const {
0355 detail::h5t_commit2(
0356 object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
0357 }
0358
0359 template <typename T>
0360 inline void EnumType<T>::create() {
0361
0362 _hid = detail::h5t_enum_create(AtomicType<typename std::underlying_type<T>::type>{}.getId());
0363
0364
0365 for (const auto& member: members) {
0366 detail::h5t_enum_insert(_hid, member.name.c_str(), &(member.value));
0367 }
0368 }
0369
0370 template <typename T>
0371 inline void EnumType<T>::commit(const Object& object, const std::string& name) const {
0372 detail::h5t_commit2(
0373 object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
0374 }
0375
0376 namespace {
0377
0378 inline hid_t create_string(size_t length) {
0379 hid_t _hid = detail::h5t_copy(H5T_C_S1);
0380 detail::h5t_set_size(_hid, length);
0381 detail::h5t_set_cset(_hid, H5T_CSET_UTF8);
0382 return _hid;
0383 }
0384
0385
0386 inline DataTypeClass convert_type_class(const H5T_class_t& tclass) {
0387 switch (tclass) {
0388 case H5T_TIME:
0389 return DataTypeClass::Time;
0390 case H5T_INTEGER:
0391 return DataTypeClass::Integer;
0392 case H5T_FLOAT:
0393 return DataTypeClass::Float;
0394 case H5T_STRING:
0395 return DataTypeClass::String;
0396 case H5T_BITFIELD:
0397 return DataTypeClass::BitField;
0398 case H5T_OPAQUE:
0399 return DataTypeClass::Opaque;
0400 case H5T_COMPOUND:
0401 return DataTypeClass::Compound;
0402 case H5T_REFERENCE:
0403 return DataTypeClass::Reference;
0404 case H5T_ENUM:
0405 return DataTypeClass::Enum;
0406 case H5T_VLEN:
0407 return DataTypeClass::VarLen;
0408 case H5T_ARRAY:
0409 return DataTypeClass::Array;
0410 case H5T_NO_CLASS:
0411 case H5T_NCLASSES:
0412 default:
0413 return DataTypeClass::Invalid;
0414 }
0415 }
0416
0417
0418 inline std::string type_class_string(DataTypeClass tclass) {
0419 switch (tclass) {
0420 case DataTypeClass::Time:
0421 return "Time";
0422 case DataTypeClass::Integer:
0423 return "Integer";
0424 case DataTypeClass::Float:
0425 return "Float";
0426 case DataTypeClass::String:
0427 return "String";
0428 case DataTypeClass::BitField:
0429 return "BitField";
0430 case DataTypeClass::Opaque:
0431 return "Opaque";
0432 case DataTypeClass::Compound:
0433 return "Compound";
0434 case DataTypeClass::Reference:
0435 return "Reference";
0436 case DataTypeClass::Enum:
0437 return "Enum";
0438 case DataTypeClass::VarLen:
0439 return "Varlen";
0440 case DataTypeClass::Array:
0441 return "Array";
0442 default:
0443 return "(Invalid)";
0444 }
0445 }
0446
0447 }
0448
0449
0450
0451 template <typename T>
0452 inline DataType create_datatype() {
0453 return AtomicType<T>();
0454 }
0455
0456
0457
0458 template <typename T>
0459 inline DataType create_and_check_datatype() {
0460 DataType t = create_datatype<T>();
0461 if (t.empty()) {
0462 throw DataTypeException("Type given to create_and_check_datatype is not valid");
0463 }
0464
0465
0466 if (t.isVariableStr()) {
0467 return t;
0468 }
0469
0470
0471
0472 if (t.isReference() || t.isFixedLenStr()) {
0473 return t;
0474 }
0475 if (sizeof(T) != t.getSize()) {
0476 std::ostringstream ss;
0477 ss << "Size of array type " << sizeof(T) << " != that of memory datatype " << t.getSize()
0478 << std::endl;
0479 throw DataTypeException(ss.str());
0480 }
0481
0482 return t;
0483 }
0484
0485 }
0486 HIGHFIVE_REGISTER_TYPE(HighFive::details::Boolean, HighFive::create_enum_boolean)
0487
0488 namespace HighFive {
0489
0490 template <>
0491 inline DataType create_datatype<bool>() {
0492 return create_datatype<HighFive::details::Boolean>();
0493 }
0494
0495 }