Warning, file /include/highfive/bits/H5Converter_misc.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <type_traits>
0012
0013 #include "H5Inspector_misc.hpp"
0014 #include "../H5DataType.hpp"
0015
0016 namespace HighFive {
0017 namespace details {
0018
0019 template <class T>
0020 struct is_std_string {
0021 static constexpr bool value =
0022 std::is_same<typename inspector<T>::base_type, std::string>::value;
0023 };
0024
0025 template <class T, class V = void>
0026 struct enable_shallow_copy
0027 : public std::enable_if<!is_std_string<T>::value && inspector<T>::is_trivially_copyable, V> {};
0028
0029 template <class T, class V = void>
0030 struct enable_deep_copy
0031 : public std::enable_if<!is_std_string<T>::value && !inspector<T>::is_trivially_copyable, V> {};
0032
0033 template <class T, class V = void>
0034 struct enable_string_copy: public std::enable_if<is_std_string<T>::value, V> {};
0035
0036
0037 template <typename T, bool IsReadOnly>
0038 struct ShallowCopyBuffer {
0039 using type = unqualified_t<T>;
0040 using hdf5_type =
0041 typename std::conditional<IsReadOnly,
0042 typename std::add_const<typename inspector<T>::hdf5_type>::type,
0043 typename inspector<T>::hdf5_type>::type;
0044
0045 ShallowCopyBuffer() = delete;
0046
0047 explicit ShallowCopyBuffer(typename std::conditional<IsReadOnly, const T&, T&>::type val)
0048 : ptr(inspector<T>::data(val)){};
0049
0050 hdf5_type* getPointer() const {
0051 return ptr;
0052 }
0053
0054 hdf5_type* begin() const {
0055 return getPointer();
0056 }
0057
0058 void unserialize(T& ) const {
0059
0060 }
0061
0062 private:
0063 hdf5_type* ptr;
0064 };
0065
0066 template <class T>
0067 struct DeepCopyBuffer {
0068 using type = unqualified_t<T>;
0069 using hdf5_type = typename inspector<type>::hdf5_type;
0070
0071 explicit DeepCopyBuffer(const std::vector<size_t>& _dims)
0072 : buffer(inspector<T>::getSize(_dims))
0073 , dims(_dims) {}
0074
0075 hdf5_type* getPointer() {
0076 return buffer.data();
0077 }
0078
0079 hdf5_type const* getPointer() const {
0080 return buffer.data();
0081 }
0082
0083 hdf5_type* begin() {
0084 return getPointer();
0085 }
0086
0087 hdf5_type const* begin() const {
0088 return getPointer();
0089 }
0090
0091 void unserialize(T& val) const {
0092 inspector<type>::unserialize(buffer.data(), dims, val);
0093 }
0094
0095 private:
0096 std::vector<hdf5_type> buffer;
0097 std::vector<size_t> dims;
0098 };
0099
0100 enum class BufferMode { Read, Write };
0101
0102
0103
0104
0105
0106 inline size_t char_buffer_length(char const* const str, size_t max_string_size) {
0107 for (size_t i = 0; i < max_string_size; ++i) {
0108 if (str[i] == '\0') {
0109 return i;
0110 }
0111 }
0112
0113 return max_string_size;
0114 }
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 template <typename T, BufferMode buffer_mode>
0165 struct StringBuffer {
0166 using type = unqualified_t<T>;
0167 using hdf5_type = typename inspector<type>::hdf5_type;
0168
0169 class StringView {
0170 public:
0171 StringView(StringBuffer<T, buffer_mode>& _buffer, size_t _i)
0172 : buffer(_buffer)
0173 , i(_i) {}
0174
0175
0176
0177
0178
0179
0180
0181
0182 void assign(char const* data, size_t length, StringPadding pad) {
0183 if (buffer.isVariableLengthString()) {
0184 if (pad == StringPadding::NullTerminated) {
0185 buffer.variable_length_pointers[i] = data;
0186 } else {
0187 buffer.variable_length_buffer[i] = std::string(data, length);
0188 buffer.variable_length_pointers[i] = buffer.variable_length_buffer[i].data();
0189 }
0190 } else if (buffer.isFixedLengthString()) {
0191
0192
0193 if (length > buffer.string_max_length) {
0194 throw std::invalid_argument("String length too big.");
0195 }
0196
0197 memcpy(&buffer.fixed_length_buffer[i * buffer.string_size], data, length);
0198 }
0199 }
0200
0201 private:
0202 StringBuffer<T, buffer_mode>& buffer;
0203 size_t i;
0204 };
0205
0206
0207 class StringConstView {
0208 public:
0209 StringConstView(const StringBuffer<T, buffer_mode>& _buffer, size_t _i)
0210 : buffer(_buffer)
0211 , i(_i) {}
0212
0213
0214
0215
0216 char const* data() const {
0217 if (buffer.isVariableLengthString()) {
0218 return buffer.variable_length_pointers[i];
0219 } else {
0220 return &buffer.fixed_length_buffer[i * buffer.string_size];
0221 }
0222 }
0223
0224
0225
0226
0227
0228
0229
0230 size_t length() const {
0231 if (buffer.isNullTerminated()) {
0232 return char_buffer_length(data(), buffer.string_size);
0233 } else {
0234 return buffer.string_max_length;
0235 }
0236 }
0237
0238 private:
0239 const StringBuffer<T, buffer_mode>& buffer;
0240 size_t i;
0241 };
0242
0243
0244 class Iterator {
0245 public:
0246 Iterator(StringBuffer<T, buffer_mode>& _buffer, size_t _pos)
0247 : buffer(_buffer)
0248 , pos(_pos) {}
0249
0250 Iterator operator+(size_t n_strings) const {
0251 return Iterator(buffer, pos + n_strings);
0252 }
0253
0254 void operator+=(size_t n_strings) {
0255 pos += n_strings;
0256 }
0257
0258 StringView operator*() {
0259 return StringView(buffer, pos);
0260 }
0261
0262 StringConstView operator*() const {
0263 return StringConstView(buffer, pos);
0264 }
0265
0266 private:
0267 StringBuffer<T, buffer_mode>& buffer;
0268 size_t pos;
0269 };
0270
0271 StringBuffer(std::vector<size_t> _dims, const DataType& _file_datatype)
0272 : file_datatype(_file_datatype.asStringType())
0273 , padding(file_datatype.getPadding())
0274 , string_size(file_datatype.isVariableStr() ? size_t(-1) : file_datatype.getSize())
0275 , string_max_length(string_size - size_t(isNullTerminated()))
0276 , dims(_dims) {
0277 if (string_size == 0 && isNullTerminated()) {
0278 throw DataTypeException(
0279 "Fixed-length, null-terminated need at least one byte to store the "
0280 "null-character.");
0281 }
0282
0283 auto n_strings = compute_total_size(dims);
0284 if (isVariableLengthString()) {
0285 variable_length_buffer.resize(n_strings);
0286 variable_length_pointers.resize(n_strings);
0287 } else {
0288 char pad = padding == StringPadding::SpacePadded ? ' ' : '\0';
0289 fixed_length_buffer.assign(n_strings * string_size, pad);
0290 }
0291 }
0292
0293 bool isVariableLengthString() const {
0294 return file_datatype.isVariableStr();
0295 }
0296
0297 bool isFixedLengthString() const {
0298 return file_datatype.isFixedLenStr();
0299 }
0300
0301 bool isNullTerminated() const {
0302 return file_datatype.getPadding() == StringPadding::NullTerminated;
0303 }
0304
0305
0306 void* getPointer() {
0307 if (file_datatype.isVariableStr()) {
0308 return variable_length_pointers.data();
0309 } else {
0310 return fixed_length_buffer.data();
0311 }
0312 }
0313
0314 Iterator begin() {
0315 return Iterator(*this, 0ul);
0316 }
0317
0318 void unserialize(T& val) {
0319 inspector<type>::unserialize(begin(), dims, val);
0320 }
0321
0322 private:
0323 StringType file_datatype;
0324 StringPadding padding;
0325
0326
0327 size_t string_size;
0328
0329 size_t string_max_length;
0330 std::vector<size_t> dims;
0331
0332 std::vector<char> fixed_length_buffer;
0333 std::vector<std::string> variable_length_buffer;
0334 std::vector<
0335 typename std::conditional<buffer_mode == BufferMode::Write, const char, char>::type*>
0336 variable_length_pointers;
0337 };
0338
0339
0340 template <typename T, typename Enable = void>
0341 struct Writer;
0342
0343 template <typename T>
0344 struct Writer<T, typename enable_shallow_copy<T>::type>: public ShallowCopyBuffer<T, true> {
0345 private:
0346 using super = ShallowCopyBuffer<T, true>;
0347
0348 public:
0349 explicit Writer(const T& val, const DataType& )
0350 : super(val){};
0351 };
0352
0353 template <typename T>
0354 struct Writer<T, typename enable_deep_copy<T>::type>: public DeepCopyBuffer<T> {
0355 explicit Writer(const T& val, const DataType& )
0356 : DeepCopyBuffer<T>(inspector<T>::getDimensions(val)) {
0357 inspector<T>::serialize(val, this->begin());
0358 }
0359 };
0360
0361 template <typename T>
0362 struct Writer<T, typename enable_string_copy<T>::type>: public StringBuffer<T, BufferMode::Write> {
0363 explicit Writer(const T& val, const DataType& _file_datatype)
0364 : StringBuffer<T, BufferMode::Write>(inspector<T>::getDimensions(val), _file_datatype) {
0365 inspector<T>::serialize(val, this->begin());
0366 }
0367 };
0368
0369 template <typename T, typename Enable = void>
0370 struct Reader;
0371
0372 template <typename T>
0373 struct Reader<T, typename enable_shallow_copy<T>::type>: public ShallowCopyBuffer<T, false> {
0374 private:
0375 using super = ShallowCopyBuffer<T, false>;
0376 using type = typename super::type;
0377
0378 public:
0379 Reader(const std::vector<size_t>&, type& val, const DataType& )
0380 : super(val) {}
0381 };
0382
0383 template <typename T>
0384 struct Reader<T, typename enable_deep_copy<T>::type>: public DeepCopyBuffer<T> {
0385 private:
0386 using super = DeepCopyBuffer<T>;
0387 using type = typename super::type;
0388
0389 public:
0390 Reader(const std::vector<size_t>& _dims, type&, const DataType& )
0391 : super(_dims) {}
0392 };
0393
0394
0395 template <typename T>
0396 struct Reader<T, typename enable_string_copy<T>::type>: public StringBuffer<T, BufferMode::Write> {
0397 public:
0398 explicit Reader(const std::vector<size_t>& _dims,
0399 const T& ,
0400 const DataType& _file_datatype)
0401 : StringBuffer<T, BufferMode::Write>(_dims, _file_datatype) {}
0402 };
0403
0404 struct data_converter {
0405 template <typename T>
0406 static Writer<T> serialize(const typename inspector<T>::type& val,
0407 const DataType& file_datatype) {
0408 return Writer<T>(val, file_datatype);
0409 }
0410
0411 template <typename T>
0412 static Reader<T> get_reader(const std::vector<size_t>& dims,
0413 T& val,
0414 const DataType& file_datatype) {
0415
0416 auto effective_dims = details::squeezeDimensions(dims, inspector<T>::recursive_ndim);
0417 inspector<T>::prepare(val, effective_dims);
0418 return Reader<T>(effective_dims, val, file_datatype);
0419 }
0420 };
0421
0422 }
0423 }