Skip to content

Commit fa1eeca

Browse files
committed
added support for reference, see examples/reference
1 parent daecad7 commit fa1eeca

File tree

7 files changed

+327
-4
lines changed

7 files changed

+327
-4
lines changed

examples/reference/Makefile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# _________________________________________________________
2+
# Copyright (c) 2018-2021 Steven Varga, Toronto,ON Canada
3+
# Author: Varga, Steven <steven@vargaconsulting.ca>
4+
# _________________________________________________________
5+
6+
CXXFLAGS = -std=c++17
7+
LIBS = -lhdf5 -lz -ldl -lm
8+
INCLUDES = -I/usr/local/include -I/usr/include
9+
10+
test: reference
11+
./reference
12+
h5dump ref.h5
13+
14+
reference.o : reference.cpp
15+
$(CXX) $(INCLUDES) -o reference.o $(CXXFLAGS) -c reference.cpp
16+
17+
reference: reference.o
18+
$(CXX) $^ $(LIBS) -o $@
19+
20+
clean:
21+
@$(RM) *.o *.h5 $(apps) reference
22+
23+
dist-clean: clean
24+
.PHONY: test
25+
26+

examples/reference/reference.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
2+
#include <armadillo>
3+
#include <vector>
4+
#include <h5cpp/all>
5+
6+
int main(){
7+
h5::fd_t fd = h5::create("ref.h5", H5F_ACC_TRUNC);
8+
{
9+
h5::ds_t ds = h5::create<float>(fd,"01",
10+
h5::current_dims{10,20}, h5::chunk{2,2} | h5::fill_value<float>{1} );
11+
12+
h5::reference_t ref = h5::reference(fd, "01", h5::offset{2,2}, h5::count{4,4});
13+
h5::write(fd, "single reference", ref);
14+
/* you can factor out `count` this way : h5::count count{2,2}; */
15+
std::vector<h5::reference_t> idx {
16+
// The HDF5 CAPI reqires fd + dataset name, instead of hid_t to ds: wishy-washy
17+
h5::reference(fd, "01", h5::offset{2,2}, h5::count{4,4}),
18+
h5::reference(fd, "01", h5::offset{4,8}, h5::count{1,1}),
19+
h5::reference(fd, "01", h5::offset{6,12}, h5::count{3,3}),
20+
h5::reference(fd, "01", h5::offset{8,16}, h5::count{2,1})
21+
};
22+
// datset shape can be controlled with dimensions, in this case is 2x2
23+
// and is not related to the selected regions!!!
24+
// data type is H5R_DATASET_REGION when dataspace is provided, otherwise OBJECT
25+
h5::write(fd, "index", idx, h5::current_dims{2,2}, h5::max_dims{H5S_UNLIMITED, 2});
26+
}
27+
{ // we going to update the regions referenced by the set of region-references
28+
// stored in "index"
29+
h5::ds_t ds = h5::open(fd, "index");
30+
std::vector color(50, 9);
31+
// this is to read from selection
32+
for(auto& ref: h5::read<std::vector<h5::reference_t>>(ds))
33+
h5::exp::write(ds, ref, color.data());
34+
}
35+
36+
{ // we are reading back data from the regions, now they all must be 'color' value '9'
37+
h5::ds_t ds = h5::open(fd, "index");
38+
// this is to read from selection
39+
for(auto& ref: h5::read<std::vector<h5::reference_t>>(ds)){
40+
arma::fmat mat = h5::exp::read<arma::fmat>(ds, ref);
41+
std::cout << mat << "\n";
42+
}
43+
}
44+
{ // for verification
45+
std::cout << h5::read<arma::fmat>(fd, "01") << "\n\n";
46+
47+
}
48+
49+
}

h5cpp/H5Dwrite.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ namespace h5 {
117117
} else // SELECT_ALL this is the fastest approach, mem_space and file_space must match
118118
err = H5Sselect_all(file_space);
119119
// throw an exception if eny error
120-
H5CPP_CHECK_NZ(err, std::runtime_error, h5::error::msg::select_hyperslab);
120+
H5CPP_CHECK_NZ(err, h5::error::io::dataset::write, h5::error::msg::select_hyperslab);
121121
h5::write(ds, mem_space, file_space, dxpl, ptr);
122122
}
123123
return ds;

h5cpp/H5Rall.hpp

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (c) 2018-2021 Steven Varga, Toronto,ON Canada
3+
* Author: Varga, Steven <steven@vargaconsulting.ca>
4+
*/
5+
#include <initializer_list>
6+
7+
8+
#ifndef H5CPP_RALL_HPP
9+
#define H5CPP_RALL_HPP
10+
11+
namespace h5 {
12+
template <class... args_t>
13+
reference_t reference(const h5::fd_t& fd, const std::string& dataset_path, args_t&&... args) {
14+
using tcount = typename arg::tpos<const h5::count_t&,const args_t&...>;
15+
using toffset = typename arg::tpos<const h5::offset_t&, const args_t&...>;
16+
using tstride = typename arg::tpos<const h5::stride_t&, const args_t&...>;
17+
using tblock = typename arg::tpos<const h5::block_t&, const args_t&...>;
18+
auto tuple = std::forward_as_tuple(args...);
19+
20+
if constexpr (toffset::present) { // region reference
21+
22+
h5::ds_t ds = h5::open(fd, dataset_path);
23+
h5::sp_t sp{H5Dget_space(ds)};
24+
int rank = h5::get_simple_extent_ndims(sp);
25+
herr_t err = 0;
26+
27+
h5::count_t count = std::get<tcount::value>( tuple ); //we make a copy of it
28+
const h5::block_t& block = arg::get( h5::default_block, args...);
29+
const h5::offset_t& offset = arg::get( h5::default_offset, args...);
30+
const h5::stride_t& stride = arg::get( h5::default_stride, args...);
31+
if constexpr( tblock::present ){ // we have to normalise `count` such that `size[i] = count[i] * block[i]` holds
32+
for(hsize_t i=0; i < rank; i++) count[i] /= block[i];
33+
err = H5Sselect_hyperslab(sp, H5S_SELECT_SET, *offset, *stride, *count, *block);
34+
} else { // we have to convert h5::count_t{..} to h5::block{..} and initiate a single block transfer
35+
h5::block_t block_ = static_cast<h5::block_t>(count);
36+
block_.rank = rank;
37+
err = H5Sselect_hyperslab(sp, H5S_SELECT_SET, *offset, *stride, *h5::default_count, *block_);
38+
}
39+
H5CPP_CHECK_NZ(err, h5::error::io::dataset::misc, h5::error::msg::select_hyperslab);
40+
reference_t ref;
41+
err = H5Rcreate(&ref.value, fd, dataset_path.data(), H5R_DATASET_REGION, sp);
42+
H5CPP_CHECK_NZ(err, h5::error::io::dataset::misc, "couldn't create reference to dataset...");
43+
return ref;
44+
} else { // TODO: object reference
45+
static_assert( !tcount::present && !tstride::present && !tblock::present
46+
,"count | stride | block are not allowed without h5::offset present.." );
47+
static_assert( !toffset::present, "object reference is not yet impleneted" );
48+
}
49+
}
50+
}
51+
/* TODO: needs be matched with function below
52+
template<class T, class... args_t>
53+
inline void read(const h5::ds_t& ds, h5::reference_t& reference, T& object, args_t&&... args){
54+
using element_t = typename impl::decay<T>::type;
55+
element_t* ptr = impl::data(object);
56+
h5::count_t size = impl::size(object);
57+
58+
h5::ds_t ds_ = H5Rdereference2(ds, H5P_DEFAULT, H5R_DATASET_REGION, &reference);
59+
h5::sp_t file_space = H5Rget_region(ds_, H5R_DATASET_REGION, &reference);
60+
61+
h5::sp_t mem_space = h5::create_simple( size );
62+
h5::dt_t<element_t> mem_type;
63+
h5::select_all( mem_space );
64+
h5::select_all( file_space );
65+
66+
H5CPP_CHECK_NZ(
67+
H5Dread(ds_, mem_type, mem_space, file_space, dxpl, ptr ),
68+
h5::error::io::dataset::read, h5::error::msg::read_dataset);
69+
}
70+
*/
71+
namespace h5::exp {
72+
template<class T, class... args_t>
73+
inline T read(const h5::ds_t& ds, h5::reference_t& reference, args_t&&... args){
74+
using element_t = typename impl::decay<T>::type;
75+
76+
h5::ds_t ds_ = H5Rdereference2(ds, H5P_DEFAULT, H5R_DATASET_REGION, &reference);
77+
h5::sp_t file_space = H5Rget_region(ds_, H5R_DATASET_REGION, &reference);
78+
79+
h5::dt_t<element_t> mem_type;
80+
h5::count_t start, stop, block;
81+
start.rank = stop.rank = block.rank = H5Sget_simple_extent_ndims(file_space);
82+
H5Sget_select_bounds(file_space, *start, *stop);
83+
for (auto i=0; i < block.rank; i++)
84+
block[i] = stop[i] - start[i]+1;
85+
T object = impl::get<T>::ctor(block);
86+
H5Sselect_hyperslab(file_space, H5S_SELECT_SET,
87+
*start, nullptr, *h5::default_count, *block);
88+
element_t *ptr = impl::data(object);
89+
h5::sp_t mem_space = h5::create_simple(block);
90+
h5::select_all(mem_space);
91+
92+
H5CPP_CHECK_NZ(
93+
H5Dread(ds_, mem_type, mem_space, file_space, dxpl, ptr ),
94+
h5::error::io::dataset::read, h5::error::msg::read_dataset);
95+
return object;
96+
97+
}
98+
99+
template <class T, class... args_t>
100+
inline h5::ds_t write( const h5::ds_t& ds, h5::reference_t& reference,
101+
const T* ptr, args_t&&... args ) try {
102+
h5::dt_t<T> mem_type;
103+
104+
const h5::dxpl_t& dxpl = arg::get(h5::default_dxpl, args...);
105+
h5::ds_t ds_ = H5Rdereference2(ds, H5P_DEFAULT, H5R_DATASET_REGION, &reference);
106+
h5::sp_t file_space = H5Rget_region(ds_, H5R_DATASET_REGION, &reference);
107+
h5::count_t start, stop, block;
108+
109+
start.rank = stop.rank = block.rank = H5Sget_simple_extent_ndims(file_space);
110+
H5Sget_select_bounds(file_space, *start, *stop);
111+
for (auto i=0; i < block.rank; i++)
112+
block[i] = stop[i] - start[i]+1;
113+
H5Sselect_hyperslab(file_space, H5S_SELECT_SET,
114+
*start, nullptr, *h5::default_count, *block);
115+
116+
h5::sp_t mem_space = h5::create_simple(block);
117+
h5::select_all(mem_space);
118+
119+
H5CPP_CHECK_NZ(
120+
H5Dwrite(ds_, mem_type, mem_space, file_space, dxpl, ptr),
121+
h5::error::io::dataset::write, h5::error::msg::write_dataset);
122+
return ds;
123+
} catch ( const std::exception& err ){
124+
throw h5::error::io::dataset::write( err.what() );
125+
}
126+
127+
128+
}
129+
#endif

h5cpp/H5Tall.hpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@
77

88
namespace h5 {
99
template<class T> hid_t register_struct(){ return H5I_UNINIT; }
10+
struct reference_t {
11+
hdset_reg_ref_t value; //< region or object ref storage
12+
};
1013
}
1114

1215
/* template specialization from hid_t< .. > type which provides syntactic sugar in the form
1316
* h5::dt_t<int> dt;
1417
* */
15-
namespace h5 { namespace impl { namespace detail {
18+
namespace h5::impl::detail {
1619
template<class T> // parent type, data_type is inherited from, see H5Iall.hpp top section for details
1720
using dt_p = hid_t<T,H5Tclose,true,true,hdf5::any>;
1821
/*type id*/
@@ -24,7 +27,16 @@ namespace h5 { namespace impl { namespace detail {
2427
hid_t() : parent( H5I_UNINIT){}
2528
};
2629
template <class T> using dt_t = hid_t<T,H5Tclose,true,true,hdf5::type>;
27-
}}}
30+
//
31+
template <> struct hid_t<h5::reference_t, H5Tclose,true,true, hdf5::type> : public dt_p<h5::reference_t> {
32+
using parent = dt_p<h5::reference_t>;
33+
using dt_p<h5::reference_t>::hid_t;
34+
using hidtype = h5::reference_t;
35+
36+
hid_t() : parent( H5Tcopy(H5T_STD_REF_DSETREG) ) {
37+
}
38+
};
39+
}
2840

2941
/* template specialization is for the preceding class, and should be used only for HDF5 ELEMENT types
3042
* which are in C/C++ the integral types of: char,short,int,long, ... and C POD types.

h5cpp/H5Tconversion.hpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright (c) 2018 - 2021 vargaconsulting, Toronto,ON Canada
3+
* Author: Varga, Steven <steven@vargaconsulting.ca>
4+
*/
5+
#ifndef H5CPP_TCONVERSION_HPP
6+
#define H5CPP_TCONVERSION_HPP
7+
8+
#include <hdf5.h>
9+
#include <iostream>
10+
#include "H5Tall.hpp"
11+
#include <vector>
12+
#include <utility>
13+
14+
namespace h5::impl{
15+
template<class mem_t, class file_t = undefined_t, class element_t=typename meta::decay<mem_t>::type>
16+
struct convert_t {
17+
convert_t() = default;
18+
convert_t(const h5::dt_t<mem_t>& mem_type, const h5::dt_t<file_t>& file_type,
19+
const h5::count_t& count, const h5::dxpl_t& dxpl, const mem_t* ptr) {
20+
std::cout <<"????????T mem_t\n";
21+
this->ptr = +ptr;
22+
this->count = static_cast<hsize_t>(count) ;
23+
set_space();
24+
}
25+
26+
void set_space(){
27+
// we're transfering the same amount of data from memory as there is selected within file
28+
this->space = h5::create_simple(this->count);
29+
h5::select_all( space );
30+
}
31+
32+
h5::dt_t<mem_t> type;
33+
h5::sp_t space;
34+
hsize_t count;
35+
const void* ptr;
36+
};
37+
38+
template<class T, int N>
39+
struct convert_t <T[N], char*> {
40+
convert_t(const h5::dt_t<char[N]>& mem_type, const h5::dt_t<file_t>& file_type,
41+
const h5::count_t& count, const h5::dxpl_t& dxpl, const T* ptr ) {
42+
std::cout <<"!!!!!!1[ char: " << N <<"] !!!\n";
43+
44+
}
45+
};
46+
/*
47+
template<class T, int N>
48+
struct convert_t <const char*[N]> : public convert_t<const char**>{
49+
convert_t(const h5::dt_t<char[N]>& mem_type, const h5::dt_t<file_t>& file_type,
50+
const h5::count_t& count, const h5::dxpl_t& dxpl, const char* const(*ptr)[N] ) {
51+
std::cout <<"!!!!!!1[ char: " << N <<"] !!!\n";
52+
53+
}
54+
};
55+
*/
56+
// ARRAYS[N][M][..]
57+
template<class T, int N>
58+
struct convert_t <T[N]> : public convert_t<T*>{
59+
using convert_t<T*>::set_space;
60+
61+
convert_t(const h5::dt_t<T[N]>& mem_type, const h5::dt_t<file_t>& file_type,
62+
const h5::count_t& count, const h5::dxpl_t& dxpl, const T(*ptr)[N] ) {
63+
std::cout <<"-------" << N <<"] !!!\n";
64+
switch(H5Tget_class(file_type)){
65+
case H5T_INTEGER:
66+
[[fallthrough]];
67+
case H5T_FLOAT: // T[] -> S hypercube
68+
using element_t = typename std::remove_all_extents<T>::type;
69+
this->type = h5::create<element_t>();
70+
this->count = sizeof(T[N])/sizeof(element_t);
71+
break;
72+
case H5T_ARRAY: // T[] -> T[]
73+
this->type = h5::create<T[N]>();
74+
this->count = 1; // type contains the size, object count is `1`
75+
break;
76+
case H5T_COMPOUND:
77+
case H5T_OPAQUE:
78+
case H5T_ENUM:
79+
[[fallthrough]];
80+
case H5T_VLEN:
81+
throw(h5::error::conversion::any("not yet supported..."));
82+
default: break;
83+
}
84+
85+
set_space();
86+
this->ptr = +ptr;
87+
}
88+
};
89+
template<int N>
90+
struct convert_t <char16_t[N]> : public convert_t<char16_t, char16_t[N]>{
91+
using convert_t<char16_t, char16_t[N]>::set_space;
92+
convert_t(const h5::dt_t<char16_t[N]>& mem_type, const h5::dt_t<file_t>& file_type,
93+
const h5::count_t& count, const h5::dxpl_t& dxpl, const char16_t (*ptr)[N] ) {
94+
std::cout <<"!!!!!!!!!![ " << N <<"] !!!\n";
95+
this->type = h5::create<std::string>();
96+
hsize_t n_elements = static_cast<hsize_t>(count) + 2;
97+
this->ptr = +ptr;
98+
set_space();
99+
}
100+
};
101+
}
102+
103+
104+
namespace {
105+
106+
}
107+
#endif

h5cpp/io

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "H5Dcreate.hpp"
1313
#include "H5Dopen.hpp"
14+
#include "H5Rall.hpp"
1415
#include "H5Dwrite.hpp"
1516
#include "H5Dread.hpp"
1617
#include "H5Dappend.hpp"
@@ -19,6 +20,5 @@
1920
#include "H5Aopen.hpp"
2021
#include "H5Awrite.hpp"
2122
#include "H5Aread.hpp"
22-
2323
#endif
2424

0 commit comments

Comments
 (0)