Skip to content

Commit

Permalink
Pass dimensions to 'serialize'.
Browse files Browse the repository at this point in the history
By passing the dimensions to `serialize` allows serializing nested
pointers. This was previously not possible because, we didn't know how
many elements the pointer pointed to.

The logic for obtaining the dimensions of the array is:

  * When creating/opening the array the memspace is set to be the same
    as the filespace.

  * Performing a selection either leads to a simple (packed)
    multi-dimensional memspace; or to a one-dimensional memspace.

Therefore, if we perform a write without selection, we know the
dimensions the input array must have. If we perform a selection we again
know the dimensions the input buffer needs to have.
  • Loading branch information
1uc committed Jan 30, 2024
1 parent 3ea8154 commit 4e43b51
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 29 deletions.
3 changes: 2 additions & 1 deletion include/highfive/bits/H5Attribute_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ inline void Attribute::read(T* array) const {
template <typename T>
inline void Attribute::write(const T& buffer) {
const DataSpace& mem_space = getMemSpace();
auto dims = mem_space.getDimensions();

if (mem_space.getElementCount() == 0) {
return;
Expand All @@ -138,7 +139,7 @@ inline void Attribute::write(const T& buffer) {
<< " into dataset of dimensions " << mem_space.getNumberDimensions();
throw DataSpaceException(ss.str());
}
auto w = details::data_converter::serialize<T>(buffer, file_datatype);
auto w = details::data_converter::serialize<T>(buffer, dims, file_datatype);
write_raw(w.getPointer(), buffer_info.data_type);
}

Expand Down
17 changes: 9 additions & 8 deletions include/highfive/bits/H5Converter_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,23 +344,23 @@ struct Writer<T, typename enable_shallow_copy<T>::type>: public ShallowCopyBuffe
using super = ShallowCopyBuffer<T, true>;

public:
explicit Writer(const T& val, const DataType& /* file_datatype */)
explicit Writer(const T& val, const std::vector<size_t>& /* dims */, const DataType& /* file_datatype */)
: super(val){};
};

template <typename T>
struct Writer<T, typename enable_deep_copy<T>::type>: public DeepCopyBuffer<T> {
explicit Writer(const T& val, const DataType& /* file_datatype */)
: DeepCopyBuffer<T>(inspector<T>::getDimensions(val)) {
inspector<T>::serialize(val, this->begin());
explicit Writer(const T& val, const std::vector<size_t>& _dims, const DataType& /* file_datatype */)
: DeepCopyBuffer<T>(_dims) {
inspector<T>::serialize(val, _dims, this->begin());
}
};

template <typename T>
struct Writer<T, typename enable_string_copy<T>::type>: public StringBuffer<T, BufferMode::Write> {
explicit Writer(const T& val, const DataType& _file_datatype)
: StringBuffer<T, BufferMode::Write>(inspector<T>::getDimensions(val), _file_datatype) {
inspector<T>::serialize(val, this->begin());
explicit Writer(const T& val, const std::vector<size_t>& _dims, const DataType& _file_datatype)
: StringBuffer<T, BufferMode::Write>(_dims, _file_datatype) {
inspector<T>::serialize(val, _dims, this->begin());
}
};

Expand Down Expand Up @@ -402,8 +402,9 @@ struct Reader<T, typename enable_string_copy<T>::type>: public StringBuffer<T, B
struct data_converter {
template <typename T>
static Writer<T> serialize(const typename inspector<T>::type& val,
const std::vector<size_t>& dims,
const DataType& file_datatype) {
return Writer<T>(val, file_datatype);
return Writer<T>(val, dims, file_datatype);
}

template <typename T>
Expand Down
31 changes: 17 additions & 14 deletions include/highfive/bits/H5Inspector_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ inspector<T> {
// Return a point of the first value of val
static const hdf5_type* data(const type& val)
// Take a val and serialize it inside 'out'
static void serialize(const type& val, hdf5_type* out)
static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* out)
// Return an array of dimensions of the space needed for writing val
static std::vector<size_t> getDimensions(const type& val)
}
Expand Down Expand Up @@ -190,7 +190,7 @@ struct type_helper {
return &val;
}

static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
static_assert(is_trivially_copyable, "The type is not trivially copyable");
*m = val;
}
Expand Down Expand Up @@ -232,7 +232,7 @@ struct inspector<bool>: type_helper<bool> {
val = vec[0] != 0 ? true : false;
}

static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
*m = val ? 1 : 0;
}
};
Expand All @@ -250,7 +250,7 @@ struct inspector<std::string>: type_helper<std::string> {
}

template <class It>
static void serialize(const type& val, It m) {
static void serialize(const type& val, const std::vector<size_t>& /* dims*/, It m) {
(*m).assign(val.data(), val.size(), StringPadding::NullTerminated);
}

Expand All @@ -275,7 +275,7 @@ struct inspector<Reference>: type_helper<Reference> {
throw DataSpaceException("A Reference cannot be written directly.");
}

static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
hobj_ref_t ref;
val.create_ref(&ref);
*m = ref;
Expand Down Expand Up @@ -328,7 +328,7 @@ struct inspector<FixedLenStringArray<N>> {
return val.data();
}

static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
for (size_t i = 0; i < val.size(); ++i) {
std::memcpy(m + i * N, val[i], N);
}
Expand Down Expand Up @@ -393,11 +393,12 @@ struct inspector<std::vector<T>> {
}

template <class It>
static void serialize(const type& val, It m) {
static void serialize(const type& val, const std::vector<size_t>& dims, It m) {
if (!val.empty()) {
size_t subsize = inspector<value_type>::getSizeVal(val[0]);
auto subdims = std::vector<size_t>(dims.begin() + 1, dims.end());
for (auto&& e: val) {
inspector<value_type>::serialize(e, m);
inspector<value_type>::serialize(e, subdims, m);
m += subsize;
}
}
Expand Down Expand Up @@ -455,7 +456,7 @@ struct inspector<std::vector<bool>> {
throw DataSpaceException("A std::vector<bool> cannot be written directly.");
}

static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
for (size_t i = 0; i < val.size(); ++i) {
m[i] = val[i] ? 1 : 0;
}
Expand Down Expand Up @@ -522,10 +523,11 @@ struct inspector<std::array<T, N>> {
}

template <class It>
static void serialize(const type& val, It m) {
static void serialize(const type& val, const std::vector<size_t>& dims, It m) {
size_t subsize = inspector<value_type>::getSizeVal(val[0]);
auto subdims = std::vector<size_t>(dims.begin() + 1, dims.end());
for (auto& e: val) {
inspector<value_type>::serialize(e, m);
inspector<value_type>::serialize(e, subdims, m);
m += subsize;
}
}
Expand Down Expand Up @@ -573,7 +575,7 @@ struct inspector<T*> {

/* it works because there is only T[][][] currently
we will fix it one day */
static void serialize(const type& /* val */, hdf5_type* /* m */) {
static void serialize(const type& /* val */, const std::vector<size_t>& /* dims*/, hdf5_type* /* m */) {
throw DataSpaceException("Not possible to serialize a T*");
}
};
Expand Down Expand Up @@ -610,10 +612,11 @@ struct inspector<T[N]> {

/* it works because there is only T[][][] currently
we will fix it one day */
static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
size_t subsize = inspector<value_type>::getSizeVal(val[0]);
auto subdims = std::vector<size_t>(dims.begin() + 1, dims.end());
for (size_t i = 0; i < N; ++i) {
inspector<value_type>::serialize(val[i], m + i * subsize);
inspector<value_type>::serialize(val[i], subdims, m + i * subsize);
}
}
};
Expand Down
3 changes: 2 additions & 1 deletion include/highfive/bits/H5Slice_traits_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ template <typename T>
inline void SliceTraits<Derivate>::write(const T& buffer, const DataTransferProps& xfer_props) {
const auto& slice = static_cast<const Derivate&>(*this);
const DataSpace& mem_space = slice.getMemSpace();
auto dims = mem_space.getDimensions();

auto file_datatype = slice.getDataType();

Expand All @@ -256,7 +257,7 @@ inline void SliceTraits<Derivate>::write(const T& buffer, const DataTransferProp
<< " into dataset with n = " << buffer_info.n_dimensions << " dimensions.";
throw DataSpaceException(ss.str());
}
auto w = details::data_converter::serialize<T>(buffer, file_datatype);
auto w = details::data_converter::serialize<T>(buffer, dims, file_datatype);
write_raw(w.getPointer(), buffer_info.data_type, xfer_props);
}

Expand Down
10 changes: 6 additions & 4 deletions include/highfive/boost.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,12 @@ struct inspector<boost::multi_array<T, Dims>> {
}

template <class It>
static void serialize(const type& val, It m) {
static void serialize(const type& val, const std::vector<size_t>& dims, It m) {
size_t size = val.num_elements();
size_t subsize = inspector<value_type>::getSizeVal(*val.origin());
auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
for (size_t i = 0; i < size; ++i) {
inspector<value_type>::serialize(*(val.origin() + i), m + i * subsize);
inspector<value_type>::serialize(*(val.origin() + i), subdims, m + i * subsize);
}
}

Expand Down Expand Up @@ -136,11 +137,12 @@ struct inspector<boost::numeric::ublas::matrix<T>> {
return inspector<value_type>::data(val(0, 0));
}

static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
size_t size = val.size1() * val.size2();
size_t subsize = inspector<value_type>::getSizeVal(val(0, 0));
auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
for (size_t i = 0; i < size; ++i) {
inspector<value_type>::serialize(*(&val(0, 0) + i), m + i * subsize);
inspector<value_type>::serialize(*(&val(0, 0) + i), subdims, m + i * subsize);
}
}

Expand Down
2 changes: 1 addition & 1 deletion include/highfive/eigen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct inspector<Eigen::Matrix<T, M, N>> {
return inspector<value_type>::data(*val.data());
}

static void serialize(const type& val, hdf5_type* m) {
static void serialize(const type& val, const std::vector<size_t>& /* dims */, hdf5_type* m) {
assert_not_buggy(val.rows(), val.cols());
std::memcpy(m, val.data(), static_cast<size_t>(val.size()) * sizeof(hdf5_type));
}
Expand Down

0 comments on commit 4e43b51

Please sign in to comment.