File indexing completed on 2025-04-19 08:55:33
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 std::string DataType::string() const {
0077 return type_class_string(getClass()) + std::to_string(getSize() * 8);
0078 }
0079
0080 inline StringPadding StringType::getPadding() const {
0081 return StringPadding(detail::h5t_get_strpad(_hid));
0082 }
0083
0084 inline CharacterSet StringType::getCharacterSet() const {
0085 return CharacterSet(detail::h5t_get_cset(_hid));
0086 }
0087
0088 inline FixedLengthStringType::FixedLengthStringType(size_t size,
0089 StringPadding padding,
0090 CharacterSet character_set) {
0091 if (size == 0 && padding == StringPadding::NullTerminated) {
0092 throw DataTypeException(
0093 "Fixed-length, null-terminated need at least one byte to store the null-character.");
0094 }
0095
0096 _hid = detail::h5t_copy(H5T_C_S1);
0097
0098 detail::h5t_set_size(_hid, hsize_t(size));
0099 detail::h5t_set_cset(_hid, H5T_cset_t(character_set));
0100 detail::h5t_set_strpad(_hid, H5T_str_t(padding));
0101 }
0102
0103 inline VariableLengthStringType::VariableLengthStringType(CharacterSet character_set) {
0104 _hid = detail::h5t_copy(H5T_C_S1);
0105
0106 detail::h5t_set_size(_hid, H5T_VARIABLE);
0107 detail::h5t_set_cset(_hid, H5T_cset_t(character_set));
0108 }
0109
0110
0111 template <>
0112 inline AtomicType<char>::AtomicType() {
0113 _hid = detail::h5t_copy(H5T_NATIVE_CHAR);
0114 }
0115
0116 template <>
0117 inline AtomicType<signed char>::AtomicType() {
0118 _hid = detail::h5t_copy(H5T_NATIVE_SCHAR);
0119 }
0120
0121 template <>
0122 inline AtomicType<unsigned char>::AtomicType() {
0123 _hid = detail::h5t_copy(H5T_NATIVE_UCHAR);
0124 }
0125
0126
0127 template <>
0128 inline AtomicType<short>::AtomicType() {
0129 _hid = detail::h5t_copy(H5T_NATIVE_SHORT);
0130 }
0131
0132 template <>
0133 inline AtomicType<unsigned short>::AtomicType() {
0134 _hid = detail::h5t_copy(H5T_NATIVE_USHORT);
0135 }
0136
0137
0138 template <>
0139 inline AtomicType<int>::AtomicType() {
0140 _hid = detail::h5t_copy(H5T_NATIVE_INT);
0141 }
0142
0143 template <>
0144 inline AtomicType<unsigned>::AtomicType() {
0145 _hid = detail::h5t_copy(H5T_NATIVE_UINT);
0146 }
0147
0148
0149 template <>
0150 inline AtomicType<long>::AtomicType() {
0151 _hid = detail::h5t_copy(H5T_NATIVE_LONG);
0152 }
0153
0154 template <>
0155 inline AtomicType<unsigned long>::AtomicType() {
0156 _hid = detail::h5t_copy(H5T_NATIVE_ULONG);
0157 }
0158
0159
0160 template <>
0161 inline AtomicType<long long>::AtomicType() {
0162 _hid = detail::h5t_copy(H5T_NATIVE_LLONG);
0163 }
0164
0165 template <>
0166 inline AtomicType<unsigned long long>::AtomicType() {
0167 _hid = detail::h5t_copy(H5T_NATIVE_ULLONG);
0168 }
0169
0170
0171 template <>
0172 inline AtomicType<float>::AtomicType() {
0173 _hid = detail::h5t_copy(H5T_NATIVE_FLOAT);
0174 }
0175
0176 template <>
0177 inline AtomicType<double>::AtomicType() {
0178 _hid = detail::h5t_copy(H5T_NATIVE_DOUBLE);
0179 }
0180
0181 template <>
0182 inline AtomicType<long double>::AtomicType() {
0183 _hid = detail::h5t_copy(H5T_NATIVE_LDOUBLE);
0184 }
0185
0186
0187 template <>
0188 inline AtomicType<std::string>::AtomicType() {
0189 _hid = create_string(H5T_VARIABLE);
0190 }
0191
0192 #if HIGHFIVE_CXX_STD >= 17
0193
0194 template <>
0195 inline AtomicType<std::byte>::AtomicType() {
0196 _hid = detail::h5t_copy(H5T_NATIVE_B8);
0197 }
0198 #endif
0199
0200
0201
0202 template <size_t StrLen>
0203 class AtomicType<char[StrLen]>: public DataType {
0204 public:
0205 inline AtomicType()
0206 : DataType(create_string(StrLen)) {}
0207 };
0208
0209 template <size_t StrLen>
0210 class AtomicType<deprecated::FixedLenStringArray<StrLen>>: public DataType {
0211 public:
0212 inline AtomicType()
0213 : DataType(create_string(StrLen)) {}
0214 };
0215
0216 template <typename T>
0217 class AtomicType<std::complex<T>>: public DataType {
0218 public:
0219 inline AtomicType()
0220 : DataType(
0221 CompoundType({{"r", create_datatype<T>(), 0}, {"i", create_datatype<T>(), sizeof(T)}},
0222 sizeof(std::complex<T>))) {
0223 static_assert(std::is_arithmetic<T>::value,
0224 "std::complex accepts only floating point and integral numbers.");
0225 }
0226 };
0227
0228
0229 inline EnumType<details::Boolean> create_enum_boolean() {
0230 return {{"FALSE", details::Boolean::HighFiveFalse}, {"TRUE", details::Boolean::HighFiveTrue}};
0231 }
0232
0233
0234 template <typename T>
0235 AtomicType<T>::AtomicType() {
0236 static_assert(details::inspector<T>::recursive_ndim == 0,
0237 "Atomic types cant be arrays, except for char[] (fixed-length strings)");
0238 static_assert(details::inspector<T>::recursive_ndim > 0, "Type not supported");
0239 }
0240
0241
0242 namespace deprecated {
0243 template <std::size_t N>
0244 inline FixedLenStringArray<N>::FixedLenStringArray(const char array[][N], std::size_t length) {
0245 datavec.resize(length);
0246 std::memcpy(datavec[0].data(), array[0].data(), N * length);
0247 }
0248
0249 template <std::size_t N>
0250 inline FixedLenStringArray<N>::FixedLenStringArray(const std::string* iter_begin,
0251 const std::string* iter_end) {
0252 datavec.reserve(static_cast<std::size_t>(iter_end - iter_begin));
0253 for (std::string const* it = iter_begin; it != iter_end; ++it) {
0254 push_back(*it);
0255 }
0256 }
0257
0258 template <std::size_t N>
0259 inline FixedLenStringArray<N>::FixedLenStringArray(const std::vector<std::string>& vec)
0260 : FixedLenStringArray(vec.data(), vec.data() + vec.size()) {}
0261
0262 template <std::size_t N>
0263 inline FixedLenStringArray<N>::FixedLenStringArray(
0264 const std::initializer_list<std::string>& init_list)
0265 : FixedLenStringArray(init_list.begin(), init_list.end()) {}
0266
0267 template <std::size_t N>
0268 inline void FixedLenStringArray<N>::push_back(const std::string& src) {
0269 datavec.emplace_back();
0270 const size_t length = std::min(N - 1, src.length());
0271 std::memcpy(datavec.back().data(), src.c_str(), length);
0272 datavec.back()[length] = 0;
0273 }
0274
0275 template <std::size_t N>
0276 inline void FixedLenStringArray<N>::push_back(const std::array<char, N>& src) {
0277 datavec.emplace_back();
0278 std::copy(src.begin(), src.end(), datavec.back().data());
0279 }
0280
0281 template <std::size_t N>
0282 inline std::string FixedLenStringArray<N>::getString(std::size_t i) const {
0283 return std::string(datavec[i].data());
0284 }
0285 }
0286
0287
0288
0289 template <>
0290 inline AtomicType<Reference>::AtomicType() {
0291 _hid = detail::h5t_copy(H5T_STD_REF_OBJ);
0292 }
0293
0294 inline size_t find_first_atomic_member_size(hid_t hid) {
0295
0296 if (detail::h5t_get_class(hid) == H5T_COMPOUND) {
0297 auto number_of_members = detail::h5t_get_nmembers(hid);
0298 if (number_of_members == -1) {
0299 throw DataTypeException("Cannot get members of CompoundType with hid: " +
0300 std::to_string(hid));
0301 }
0302 if (number_of_members == 0) {
0303 throw DataTypeException("No members defined for CompoundType with hid: " +
0304 std::to_string(hid));
0305 }
0306
0307 auto member_type = detail::h5t_get_member_type(hid, 0);
0308 auto size = find_first_atomic_member_size(member_type);
0309 detail::h5t_close(member_type);
0310 return size;
0311 } else if (detail::h5t_get_class(hid) == H5T_STRING) {
0312 return 1;
0313 }
0314 return detail::h5t_get_size(hid);
0315 }
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333 #define _H5_STRUCT_PADDING(current_size, member_size) \
0334 (((member_size) >= (current_size)) \
0335 ? (((member_size) - (current_size)) % (member_size)) \
0336 : ((((member_size) - (((current_size) - (member_size)) % (member_size)))) % \
0337 (member_size)))
0338
0339 inline void CompoundType::create(size_t size) {
0340 if (size == 0) {
0341 size_t current_size = 0, max_atomic_size = 0;
0342
0343
0344 for (auto& member: members) {
0345 size_t member_size = detail::h5t_get_size(member.base_type.getId());
0346
0347 if (member_size == 0) {
0348 throw DataTypeException("Cannot get size of DataType with hid: " +
0349 std::to_string(member.base_type.getId()));
0350 }
0351
0352 size_t first_atomic_size = find_first_atomic_member_size(member.base_type.getId());
0353
0354
0355
0356
0357 member.offset = current_size + _H5_STRUCT_PADDING(current_size, first_atomic_size);
0358
0359
0360 current_size = member.offset + member_size;
0361
0362
0363
0364 max_atomic_size = std::max(max_atomic_size, first_atomic_size);
0365 }
0366
0367 size = current_size + _H5_STRUCT_PADDING(current_size, max_atomic_size);
0368 }
0369
0370
0371 _hid = detail::h5t_create(H5T_COMPOUND, size);
0372
0373
0374 for (const auto& member: members) {
0375 detail::h5t_insert(_hid, member.name.c_str(), member.offset, member.base_type.getId());
0376 }
0377 }
0378
0379 #undef _H5_STRUCT_PADDING
0380
0381 inline void CompoundType::commit(const Object& object, const std::string& name) const {
0382 detail::h5t_commit2(
0383 object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
0384 }
0385
0386 template <typename T>
0387 inline void EnumType<T>::create() {
0388
0389 _hid = detail::h5t_enum_create(AtomicType<typename std::underlying_type<T>::type>{}.getId());
0390
0391
0392 for (const auto& member: members) {
0393 detail::h5t_enum_insert(_hid, member.name.c_str(), &(member.value));
0394 }
0395 }
0396
0397 template <typename T>
0398 inline void EnumType<T>::commit(const Object& object, const std::string& name) const {
0399 detail::h5t_commit2(
0400 object.getId(), name.c_str(), getId(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
0401 }
0402
0403 namespace {
0404
0405 inline hid_t create_string(size_t length) {
0406 hid_t _hid = detail::h5t_copy(H5T_C_S1);
0407 detail::h5t_set_size(_hid, length);
0408 detail::h5t_set_cset(_hid, H5T_CSET_UTF8);
0409 return _hid;
0410 }
0411
0412
0413 inline DataTypeClass convert_type_class(const H5T_class_t& tclass) {
0414 switch (tclass) {
0415 case H5T_TIME:
0416 return DataTypeClass::Time;
0417 case H5T_INTEGER:
0418 return DataTypeClass::Integer;
0419 case H5T_FLOAT:
0420 return DataTypeClass::Float;
0421 case H5T_STRING:
0422 return DataTypeClass::String;
0423 case H5T_BITFIELD:
0424 return DataTypeClass::BitField;
0425 case H5T_OPAQUE:
0426 return DataTypeClass::Opaque;
0427 case H5T_COMPOUND:
0428 return DataTypeClass::Compound;
0429 case H5T_REFERENCE:
0430 return DataTypeClass::Reference;
0431 case H5T_ENUM:
0432 return DataTypeClass::Enum;
0433 case H5T_VLEN:
0434 return DataTypeClass::VarLen;
0435 case H5T_ARRAY:
0436 return DataTypeClass::Array;
0437 case H5T_NO_CLASS:
0438 case H5T_NCLASSES:
0439 default:
0440 return DataTypeClass::Invalid;
0441 }
0442 }
0443
0444
0445 inline std::string type_class_string(DataTypeClass tclass) {
0446 switch (tclass) {
0447 case DataTypeClass::Time:
0448 return "Time";
0449 case DataTypeClass::Integer:
0450 return "Integer";
0451 case DataTypeClass::Float:
0452 return "Float";
0453 case DataTypeClass::String:
0454 return "String";
0455 case DataTypeClass::BitField:
0456 return "BitField";
0457 case DataTypeClass::Opaque:
0458 return "Opaque";
0459 case DataTypeClass::Compound:
0460 return "Compound";
0461 case DataTypeClass::Reference:
0462 return "Reference";
0463 case DataTypeClass::Enum:
0464 return "Enum";
0465 case DataTypeClass::VarLen:
0466 return "Varlen";
0467 case DataTypeClass::Array:
0468 return "Array";
0469 default:
0470 return "(Invalid)";
0471 }
0472 }
0473
0474 }
0475
0476
0477
0478 template <typename T>
0479 inline DataType create_datatype() {
0480 return AtomicType<T>();
0481 }
0482
0483
0484
0485 template <typename T>
0486 inline DataType create_and_check_datatype() {
0487 DataType t = create_datatype<T>();
0488 if (t.empty()) {
0489 throw DataTypeException("Type given to create_and_check_datatype is not valid");
0490 }
0491
0492
0493 if (t.isVariableStr()) {
0494 return t;
0495 }
0496
0497
0498
0499 if (t.isReference() || t.isFixedLenStr()) {
0500 return t;
0501 }
0502 if (sizeof(T) != t.getSize()) {
0503 std::ostringstream ss;
0504 ss << "Size of array type " << sizeof(T) << " != that of memory datatype " << t.getSize()
0505 << std::endl;
0506 throw DataTypeException(ss.str());
0507 }
0508
0509 return t;
0510 }
0511
0512 }
0513 HIGHFIVE_REGISTER_TYPE(HighFive::details::Boolean, HighFive::create_enum_boolean)
0514
0515 namespace HighFive {
0516
0517 template <>
0518 inline DataType create_datatype<bool>() {
0519 return create_datatype<HighFive::details::Boolean>();
0520 }
0521
0522 }
0523
0524 #ifdef H5_USE_HALF_FLOAT
0525 #include <highfive/half_float.hpp>
0526 #endif