From 3c62836260d3a447a5ce5f746297201d247ab179 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 3 May 2023 19:02:44 +0200 Subject: [PATCH 1/2] Introduce '{Shallow,Deep}CopyBuffer'. This commit introduces the internal notion of buffers. We already need to copy non-contiguous data into a contiguous buffer. This commit simply makes this idea more explicit. The advantage is that each class can focus on its purpose and thereby simplify its code. --- include/highfive/bits/H5Attribute_misc.hpp | 2 +- include/highfive/bits/H5Converter_misc.hpp | 157 +++++++++++------- include/highfive/bits/H5Slice_traits_misc.hpp | 2 +- 3 files changed, 101 insertions(+), 60 deletions(-) diff --git a/include/highfive/bits/H5Attribute_misc.hpp b/include/highfive/bits/H5Attribute_misc.hpp index b453f1a34..ed920eb3f 100644 --- a/include/highfive/bits/H5Attribute_misc.hpp +++ b/include/highfive/bits/H5Attribute_misc.hpp @@ -85,7 +85,7 @@ inline void Attribute::read(T& array) const { auto r = details::data_converter::get_reader(dims, array); read(r.get_pointer(), buffer_info.data_type); // re-arrange results - r.unserialize(); + r.unserialize(array); auto t = create_datatype::base_type>(); auto c = t.getClass(); if (c == DataTypeClass::VarLen || t.isVariableStr()) { diff --git a/include/highfive/bits/H5Converter_misc.hpp b/include/highfive/bits/H5Converter_misc.hpp index 5b60ccb4c..542a950a8 100644 --- a/include/highfive/bits/H5Converter_misc.hpp +++ b/include/highfive/bits/H5Converter_misc.hpp @@ -8,91 +8,132 @@ */ #pragma once +#include + #include "H5Inspector_misc.hpp" +#include "../H5DataType.hpp" namespace HighFive { namespace details { -template -struct Writer { - using hdf5_type = typename inspector::hdf5_type; - const hdf5_type* get_pointer() { - if (vec.empty()) { - return ptr; - } else { - return vec.data(); - } +template +struct enable_shallow_copy: public std::enable_if::is_trivially_copyable, V> {}; + +template +struct enable_deep_copy: public std::enable_if::is_trivially_copyable, V> {}; + +template +struct ShallowCopyBuffer { + using type = unqualified_t; + using hdf5_type = + typename std::conditional::hdf5_type>::type, + typename inspector::hdf5_type>::type; + + ShallowCopyBuffer() = delete; + + explicit ShallowCopyBuffer(typename std::conditional::type val) + : ptr(inspector::data(val)){}; + + hdf5_type* get_pointer() const { + return ptr; + } + + void unserialize(T& val) const { + /* nothing to do. */ } - std::vector vec{}; - const hdf5_type* ptr{nullptr}; + + private: + hdf5_type* ptr; }; -template -struct Reader { +template +struct DeepCopyBuffer { using type = unqualified_t; using hdf5_type = typename inspector::hdf5_type; - Reader(const std::vector& _dims, type& _val) - : dims(_dims) - , val(_val) {} + explicit DeepCopyBuffer(const std::vector& _dims) + : buffer(inspector::getSize(_dims)) + , dims(_dims) {} hdf5_type* get_pointer() { - if (vec.empty()) { - return inspector::data(val); - } else { - return vec.data(); - } + return buffer.data(); } - void unserialize() { - if (!vec.empty()) { - inspector::unserialize(vec.data(), dims, val); - } + hdf5_type const* get_pointer() const { + return buffer.data(); } - std::vector dims{}; - std::vector vec{}; - type& val{}; + void unserialize(T& val) const { + inspector::unserialize(buffer.data(), dims, val); + } + + private: + std::vector buffer; + std::vector dims; }; -struct data_converter { - template - static typename std::enable_if::is_trivially_copyable, Writer>::type serialize( - const typename inspector::type& val) { - Writer w; - w.ptr = inspector::data(val); - return w; - } - template - static typename std::enable_if::is_trivially_copyable, Writer>::type serialize( - const typename inspector::type& val) { - Writer w; - w.vec.resize(inspector::getSizeVal(val)); - inspector::serialize(val, w.vec.data()); - return w; +template +struct Writer; + +template +struct Writer::type>: public ShallowCopyBuffer { + private: + using super = ShallowCopyBuffer; + + public: + explicit Writer(const T& val) + : super(val){}; +}; + +template +struct Writer::type>: public DeepCopyBuffer { + explicit Writer(const T& val) + : DeepCopyBuffer(inspector::getDimensions(val)) { + inspector::serialize(val, this->get_pointer()); } +}; + +template +struct Reader; + +template +struct Reader::type>: ShallowCopyBuffer { + private: + using super = ShallowCopyBuffer; + using type = typename super::type; + + public: + Reader(const std::vector&, type& val) + : super(val) {} +}; + +template +struct Reader::type>: public DeepCopyBuffer { + private: + using super = DeepCopyBuffer; + using type = typename super::type; + + public: + Reader(const std::vector& _dims, type&) + : super(_dims) {} +}; + + +struct data_converter { template - static - typename std::enable_if>::is_trivially_copyable, Reader>::type - get_reader(const std::vector& dims, T& val) { - auto effective_dims = details::squeezeDimensions(dims, inspector::recursive_ndim); - Reader r(effective_dims, val); - inspector::prepare(r.val, effective_dims); - return r; + static Writer serialize(const typename inspector::type& val) { + return Writer(val); } template - static typename std::enable_if>::is_trivially_copyable, - Reader>::type - get_reader(const std::vector& dims, T& val) { + static Reader get_reader(const std::vector& dims, T& val) { + // TODO Use bufferinfo for recursive_ndim auto effective_dims = details::squeezeDimensions(dims, inspector::recursive_ndim); - - Reader r(effective_dims, val); - inspector::prepare(r.val, effective_dims); - r.vec.resize(inspector::getSize(effective_dims)); - return r; + inspector::prepare(val, effective_dims); + return Reader(effective_dims, val); } }; diff --git a/include/highfive/bits/H5Slice_traits_misc.hpp b/include/highfive/bits/H5Slice_traits_misc.hpp index 968a9493f..662c8d03f 100644 --- a/include/highfive/bits/H5Slice_traits_misc.hpp +++ b/include/highfive/bits/H5Slice_traits_misc.hpp @@ -196,7 +196,7 @@ inline void SliceTraits::read(T& array, const DataTransferProps& xfer_ auto r = details::data_converter::get_reader(dims, array); read(r.get_pointer(), buffer_info.data_type, xfer_props); // re-arrange results - r.unserialize(); + r.unserialize(array); auto t = create_datatype::base_type>(); auto c = t.getClass(); if (c == DataTypeClass::VarLen || t.isVariableStr()) { From bf807d2e998de9cbf401c574856e96da33298fe9 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 12 Jul 2023 11:37:47 +0200 Subject: [PATCH 2/2] Update include/highfive/bits/H5Converter_misc.hpp Co-authored-by: Nicolas Cornu --- include/highfive/bits/H5Converter_misc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/highfive/bits/H5Converter_misc.hpp b/include/highfive/bits/H5Converter_misc.hpp index 542a950a8..cfb3e2420 100644 --- a/include/highfive/bits/H5Converter_misc.hpp +++ b/include/highfive/bits/H5Converter_misc.hpp @@ -100,7 +100,7 @@ template struct Reader; template -struct Reader::type>: ShallowCopyBuffer { +struct Reader::type>: public ShallowCopyBuffer { private: using super = ShallowCopyBuffer; using type = typename super::type;