21 static constexpr bool value =
22 std::is_same<typename inspector<T>::base_type, std::string>::value;
25template <
class T,
class V =
void>
26struct enable_shallow_copy
27 :
public std::enable_if<!is_std_string<T>::value && inspector<T>::is_trivially_copyable, V> {};
29template <
class T,
class V =
void>
30struct enable_deep_copy
31 :
public std::enable_if<!is_std_string<T>::value && !inspector<T>::is_trivially_copyable, V> {};
33template <
class T,
class V =
void>
34struct enable_string_copy:
public std::enable_if<is_std_string<T>::value, V> {};
37template <
typename T,
bool IsReadOnly>
38struct ShallowCopyBuffer {
39 using type = unqualified_t<T>;
41 typename std::conditional<IsReadOnly,
42 typename std::add_const<typename inspector<T>::hdf5_type>::type,
43 typename inspector<T>::hdf5_type>::type;
45 ShallowCopyBuffer() =
delete;
47 explicit ShallowCopyBuffer(
typename std::conditional<IsReadOnly, const T&, T&>::type val)
48 : ptr(inspector<T>::data(val)){};
50 hdf5_type* getPointer()
const {
54 hdf5_type* begin()
const {
58 void unserialize(T& )
const {
67struct DeepCopyBuffer {
68 using type = unqualified_t<T>;
69 using hdf5_type =
typename inspector<type>::hdf5_type;
71 explicit DeepCopyBuffer(
const std::vector<size_t>& _dims)
72 : buffer(inspector<T>::
getSize(_dims))
75 hdf5_type* getPointer() {
79 hdf5_type
const* getPointer()
const {
87 hdf5_type
const* begin()
const {
91 void unserialize(T& val)
const {
92 inspector<type>::unserialize(buffer.data(), dims, val);
96 std::vector<hdf5_type> buffer;
97 std::vector<size_t> dims;
100enum class BufferMode { Read, Write };
106inline size_t char_buffer_size(
char const*
const str,
size_t max_string_length) {
107 for (
size_t i = 0; i <= max_string_length; ++i) {
108 if (str[i] ==
'\0') {
113 return max_string_length;
164template <
typename T, BufferMode buffer_mode>
166 using type = unqualified_t<T>;
167 using hdf5_type =
typename inspector<type>::hdf5_type;
171 StringView(StringBuffer<T, buffer_mode>& _buffer,
size_t _i)
182 void assign(
char const* data,
size_t length,
StringPadding pad) {
183 if (buffer.isVariableLengthString()) {
185 buffer.variable_length_pointers[i] = data;
187 buffer.variable_length_buffer[i] = std::string(data, length);
188 buffer.variable_length_pointers[i] = buffer.variable_length_buffer[i].data();
190 }
else if (buffer.isFixedLengthString()) {
193 if (length > buffer.string_length) {
194 throw std::invalid_argument(
"String length too big.");
197 memcpy(&buffer.fixed_length_buffer[i * buffer.string_size], data, length);
202 StringBuffer<T, buffer_mode>& buffer;
207 class StringConstView {
209 StringConstView(
const StringBuffer<T, buffer_mode>& _buffer,
size_t _i)
216 char const* data()
const {
217 if (buffer.isVariableLengthString()) {
218 return buffer.variable_length_pointers[i];
220 return &buffer.fixed_length_buffer[i * buffer.string_size];
230 size_t length()
const {
231 if (buffer.isNullTerminated()) {
232 return char_buffer_size(data(), buffer.string_length);
234 return buffer.string_length;
239 const StringBuffer<T, buffer_mode>& buffer;
246 Iterator(StringBuffer<T, buffer_mode>& _buffer,
size_t _pos)
250 Iterator operator+(
size_t n_strings)
const {
251 return Iterator(buffer, pos + n_strings);
254 void operator+=(
size_t n_strings) {
258 StringView operator*() {
259 return StringView(buffer, pos);
262 StringConstView operator*()
const {
263 return StringConstView(buffer, pos);
267 StringBuffer<T, buffer_mode>& buffer;
271 StringBuffer(std::vector<size_t> _dims,
const DataType& _file_datatype)
272 : file_datatype(_file_datatype.asStringType())
273 , padding(file_datatype.getPadding())
274 , string_size(file_datatype.isVariableStr() ? size_t(-1) : file_datatype.
getSize())
275 , string_length(string_size - size_t(isNullTerminated()))
277 if (string_size == 0 && isNullTerminated()) {
278 throw DataTypeException(
279 "Fixed-length, null-terminated need at least one byte to store the "
284 if (isVariableLengthString()) {
285 variable_length_buffer.resize(n_strings);
286 variable_length_pointers.resize(n_strings);
289 fixed_length_buffer.assign(n_strings * string_size, pad);
293 bool isVariableLengthString()
const {
294 return file_datatype.isVariableStr();
297 bool isFixedLengthString()
const {
298 return file_datatype.isFixedLenStr();
301 bool isNullTerminated()
const {
307 if (file_datatype.isVariableStr()) {
308 return variable_length_pointers.data();
310 return fixed_length_buffer.data();
315 return Iterator(*
this, 0ul);
318 void unserialize(T& val) {
319 inspector<type>::unserialize(begin(), dims, val);
323 StringType file_datatype;
327 size_t string_length;
328 std::vector<size_t> dims;
330 std::vector<char> fixed_length_buffer;
331 std::vector<std::string> variable_length_buffer;
333 typename std::conditional<buffer_mode == BufferMode::Write, const char, char>::type*>
334 variable_length_pointers;
338template <
typename T,
typename Enable =
void>
342struct Writer<T, typename enable_shallow_copy<T>::type>:
public ShallowCopyBuffer<T, true> {
344 using super = ShallowCopyBuffer<T, true>;
347 explicit Writer(
const T& val,
const DataType& )
352struct Writer<T, typename enable_deep_copy<T>::type>:
public DeepCopyBuffer<T> {
353 explicit Writer(
const T& val,
const DataType& )
354 : DeepCopyBuffer<T>(inspector<T>::getDimensions(val)) {
355 inspector<T>::serialize(val, this->begin());
360struct Writer<T, typename enable_string_copy<T>::type>:
public StringBuffer<T, BufferMode::Write> {
361 explicit Writer(
const T& val,
const DataType& _file_datatype)
362 : StringBuffer<T, BufferMode::Write>(inspector<T>::getDimensions(val), _file_datatype) {
363 inspector<T>::serialize(val, this->begin());
367template <
typename T,
typename Enable =
void>
371struct Reader<T, typename enable_shallow_copy<T>::type>:
public ShallowCopyBuffer<T, false> {
373 using super = ShallowCopyBuffer<T, false>;
374 using type =
typename super::type;
377 Reader(
const std::vector<size_t>&, type& val,
const DataType& )
382struct Reader<T, typename enable_deep_copy<T>::type>:
public DeepCopyBuffer<T> {
384 using super = DeepCopyBuffer<T>;
385 using type =
typename super::type;
388 Reader(
const std::vector<size_t>& _dims, type&,
const DataType& )
394struct Reader<T, typename enable_string_copy<T>::type>:
public StringBuffer<T, BufferMode::Write> {
396 explicit Reader(
const std::vector<size_t>& _dims,
398 const DataType& _file_datatype)
399 : StringBuffer<T, BufferMode::Write>(_dims, _file_datatype) {}
402struct data_converter {
403 template <
typename T>
404 static Writer<T> serialize(
const typename inspector<T>::type& val,
405 const DataType& file_datatype) {
406 return Writer<T>(val, file_datatype);
409 template <
typename T>
410 static Reader<T> get_reader(
const std::vector<size_t>& dims,
412 const DataType& file_datatype) {
414 auto effective_dims = details::squeezeDimensions(dims, inspector<T>::recursive_ndim);
415 inspector<T>::prepare(val, effective_dims);
416 return Reader<T>(effective_dims, val, file_datatype);
size_t getSize(const File &file, const std::string &path)
Get the size of an existing DataSet in an open HDF5 file.
Definition H5Easy_public.hpp:82
Definition H5_definitions.hpp:22
StringPadding
Definition string_padding.hpp:7
size_t compute_total_size(const std::vector< size_t > &dims)
Definition H5Inspector_decl.hpp:10