2014-05-22 09:38:59 +02:00
|
|
|
/*+
|
|
|
|
This is CosmoTool (./src/hdf5_array.hpp) -- Copyright (C) Guilhem Lavaux (2007-2014)
|
|
|
|
|
|
|
|
guilhem.lavaux@gmail.com
|
|
|
|
|
|
|
|
This software is a computer program whose purpose is to provide a toolbox for cosmological
|
|
|
|
data analysis (e.g. filters, generalized Fourier transforms, power spectra, ...)
|
|
|
|
|
|
|
|
This software is governed by the CeCILL license under French law and
|
|
|
|
abiding by the rules of distribution of free software. You can use,
|
|
|
|
modify and/ or redistribute the software under the terms of the CeCILL
|
|
|
|
license as circulated by CEA, CNRS and INRIA at the following URL
|
|
|
|
"http://www.cecill.info".
|
|
|
|
|
|
|
|
As a counterpart to the access to the source code and rights to copy,
|
|
|
|
modify and redistribute granted by the license, users are provided only
|
|
|
|
with a limited warranty and the software's author, the holder of the
|
|
|
|
economic rights, and the successive licensors have only limited
|
|
|
|
liability.
|
|
|
|
|
|
|
|
In this respect, the user's attention is drawn to the risks associated
|
|
|
|
with loading, using, modifying and/or developing or reproducing the
|
|
|
|
software by the user in light of its specific status of free software,
|
2015-03-09 15:31:11 +01:00
|
|
|
sthat may mean that it is complicated to manipulate, and that also
|
2014-05-22 09:38:59 +02:00
|
|
|
therefore means that it is reserved for developers and experienced
|
|
|
|
professionals having in-depth computer knowledge. Users are therefore
|
|
|
|
encouraged to load and test the software's suitability as regards their
|
|
|
|
requirements in conditions enabling the security of their systems and/or
|
|
|
|
data to be ensured and, more generally, to use and operate it in the
|
|
|
|
same conditions as regards security.
|
|
|
|
|
|
|
|
The fact that you are presently reading this means that you have had
|
|
|
|
knowledge of the CeCILL license and that you accept its terms.
|
|
|
|
+*/
|
2014-05-20 16:16:46 +02:00
|
|
|
#ifndef __COSMO_HDF5_ARRAY_HPP
|
|
|
|
#define __COSMO_HDF5_ARRAY_HPP
|
|
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <boost/static_assert.hpp>
|
|
|
|
#include <boost/utility.hpp>
|
|
|
|
#include <boost/mpl/assert.hpp>
|
|
|
|
#include <boost/multi_array.hpp>
|
|
|
|
#include <boost/type_traits/is_same.hpp>
|
|
|
|
#include <boost/type_traits/is_floating_point.hpp>
|
2015-01-31 15:11:44 +01:00
|
|
|
#include <boost/preprocessor/cat.hpp>
|
|
|
|
#include <boost/preprocessor/stringize.hpp>
|
|
|
|
#include <boost/preprocessor/seq/for_each.hpp>
|
2014-05-20 16:16:46 +02:00
|
|
|
#include <vector>
|
|
|
|
#include <H5Cpp.h>
|
|
|
|
|
|
|
|
namespace CosmoTool {
|
2018-11-02 08:02:26 +01:00
|
|
|
#if H5_VERSION_GE(1,8,20)
|
2019-04-18 11:22:54 +02:00
|
|
|
#if H5_VERSION_GE(1,10,1)
|
|
|
|
typedef H5::H5Location H5_CommonFileGroup;
|
|
|
|
#else
|
2017-12-16 17:33:21 +01:00
|
|
|
typedef H5::CommonFG H5_CommonFileGroup;
|
2019-04-18 11:22:54 +02:00
|
|
|
#endif
|
2017-12-16 17:33:21 +01:00
|
|
|
#else
|
|
|
|
typedef H5::Group H5_CommonFileGroup;
|
|
|
|
#endif
|
2014-05-20 16:16:46 +02:00
|
|
|
|
|
|
|
//!_______________________________________________________________________________________
|
|
|
|
//!
|
|
|
|
//! map types to HDF5 types
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! Leo Goodstadt (04 March 2013), improved with enable_if by Guilhem Lavaux (May 2014)
|
|
|
|
//!_______________________________________________________________________________________
|
|
|
|
|
|
|
|
template<typename T, class Enable = void> struct get_hdf5_data_type
|
|
|
|
{
|
2015-01-31 15:11:44 +01:00
|
|
|
static H5::DataType type()
|
2014-05-20 16:16:46 +02:00
|
|
|
{
|
|
|
|
BOOST_MPL_ASSERT_MSG(0, Unknown_HDF5_data_type, ());
|
|
|
|
return H5::PredType::NATIVE_DOUBLE;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-11-03 08:10:15 +01:00
|
|
|
//, typename boost::enable_if<boost::is_same<T, tl> >::type> \
|
|
|
|
//
|
2014-05-20 16:16:46 +02:00
|
|
|
#define HDF5_TYPE(tl, thdf5) \
|
2016-11-03 08:10:15 +01:00
|
|
|
template<typename T> struct get_hdf5_data_type<T, typename boost::enable_if<boost::is_same<T,tl> >::type > \
|
|
|
|
{ static H5::DataType type() { return H5::PredType::thdf5; }; }
|
|
|
|
|
|
|
|
#define HDF5_SAFE_TYPE(tl, othertl, thdf5) \
|
|
|
|
template<typename T> struct get_hdf5_data_type<T, \
|
|
|
|
typename boost::enable_if< \
|
|
|
|
boost::integral_constant<bool, \
|
|
|
|
boost::is_same<T, tl>::value \
|
|
|
|
&& !boost::is_same<T,othertl>::value > \
|
|
|
|
>::type \
|
|
|
|
> \
|
2015-01-31 15:11:44 +01:00
|
|
|
{ static H5::DataType type() { return H5::PredType::thdf5; }; }
|
2014-05-20 16:16:46 +02:00
|
|
|
|
2016-11-03 08:10:15 +01:00
|
|
|
|
|
|
|
HDF5_SAFE_TYPE(long, int , NATIVE_LONG);
|
|
|
|
HDF5_SAFE_TYPE(unsigned long, unsigned int , NATIVE_ULONG);
|
|
|
|
HDF5_SAFE_TYPE(long long, long , NATIVE_LLONG);
|
|
|
|
HDF5_SAFE_TYPE(unsigned long long, unsigned long, NATIVE_ULLONG);
|
2014-05-20 16:16:46 +02:00
|
|
|
HDF5_TYPE(char , NATIVE_CHAR);
|
2016-11-03 08:10:15 +01:00
|
|
|
HDF5_TYPE(unsigned char , NATIVE_UCHAR);
|
|
|
|
HDF5_TYPE(int , NATIVE_INT);
|
|
|
|
HDF5_TYPE(unsigned int , NATIVE_UINT);
|
2014-05-20 16:16:46 +02:00
|
|
|
HDF5_TYPE(float , NATIVE_FLOAT);
|
|
|
|
HDF5_TYPE(double , NATIVE_DOUBLE);
|
|
|
|
|
|
|
|
#undef HDF5_TYPE
|
2016-11-03 08:10:15 +01:00
|
|
|
#undef HDF5_SAFE_TYPE
|
2014-05-20 16:16:46 +02:00
|
|
|
|
2015-03-21 18:27:09 +01:00
|
|
|
// Extent generator
|
|
|
|
template<std::size_t r>
|
|
|
|
struct hdf5_extent_gen {
|
|
|
|
typedef typename boost::detail::multi_array::extent_gen<r> type;
|
|
|
|
|
|
|
|
static inline type build(hsize_t *d)
|
|
|
|
{
|
|
|
|
return (hdf5_extent_gen<r-1>::build(d))[d[r-1]];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct hdf5_extent_gen<0> {
|
|
|
|
static inline boost::multi_array_types::extent_gen build(hsize_t *d)
|
|
|
|
{
|
|
|
|
return boost::extents;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-05-20 16:16:46 +02:00
|
|
|
//!_______________________________________________________________________________________
|
|
|
|
//!
|
|
|
|
//! write_hdf5 multi_array
|
|
|
|
//!
|
2015-03-21 18:27:09 +01:00
|
|
|
//! \author Guilhem Lavaux (2014-2015)
|
2014-05-20 16:16:46 +02:00
|
|
|
//! \author leo Goodstadt (04 March 2013)
|
|
|
|
//!
|
|
|
|
//!_______________________________________________________________________________________
|
2015-02-11 21:23:44 +01:00
|
|
|
template<typename ArrayType, typename hdf5_data_type>
|
2017-12-16 17:33:21 +01:00
|
|
|
void hdf5_write_array(H5_CommonFileGroup& fg, const std::string& data_set_name,
|
2015-02-11 21:23:44 +01:00
|
|
|
const ArrayType& data,
|
2015-03-09 15:31:11 +01:00
|
|
|
const hdf5_data_type& datatype,
|
|
|
|
const std::vector<hsize_t>& dimensions,
|
|
|
|
bool doCreate = true,
|
|
|
|
bool useBases = false)
|
2014-05-20 16:16:46 +02:00
|
|
|
{
|
2015-04-08 21:01:27 +02:00
|
|
|
std::vector<hsize_t> memdims(data.shape(), data.shape() + data.num_dimensions());
|
|
|
|
H5::DataSpace dataspace(dimensions.size(), dimensions.data());
|
|
|
|
H5::DataSpace memspace(memdims.size(), memdims.data());
|
2014-05-20 16:16:46 +02:00
|
|
|
|
2015-03-09 15:31:11 +01:00
|
|
|
if (useBases) {
|
2015-04-08 21:01:27 +02:00
|
|
|
std::vector<hsize_t> offsets(data.index_bases(), data.index_bases() + data.num_dimensions());
|
|
|
|
dataspace.selectHyperslab(H5S_SELECT_SET, memdims.data(), offsets.data());
|
2015-03-09 15:31:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
H5::DataSet dataset;
|
|
|
|
if (doCreate)
|
|
|
|
dataset = fg.createDataSet(data_set_name, datatype, dataspace);
|
|
|
|
else
|
|
|
|
dataset = fg.openDataSet(data_set_name);
|
2014-05-20 16:16:46 +02:00
|
|
|
|
2015-04-08 21:01:27 +02:00
|
|
|
dataset.write(data.data(), datatype, memspace, dataspace);
|
2014-05-20 16:16:46 +02:00
|
|
|
}
|
2015-03-09 15:31:11 +01:00
|
|
|
|
|
|
|
|
|
|
|
template<typename ArrayType, typename hdf5_data_type>
|
2017-12-16 17:33:21 +01:00
|
|
|
void hdf5_write_array(H5_CommonFileGroup& fg, const std::string& data_set_name,
|
2015-03-09 15:31:11 +01:00
|
|
|
const ArrayType& data,
|
|
|
|
const hdf5_data_type& datatype,
|
|
|
|
bool doCreate = true,
|
|
|
|
bool useBases = false)
|
|
|
|
{
|
|
|
|
std::vector<hsize_t> dimensions(data.shape(), data.shape() + data.num_dimensions());
|
|
|
|
hdf5_write_array(fg, data_set_name, data, datatype, dimensions, doCreate, useBases);
|
|
|
|
}
|
2017-12-16 17:33:21 +01:00
|
|
|
|
2014-05-20 16:16:46 +02:00
|
|
|
/* HDF5 complex type */
|
|
|
|
template<typename T>
|
|
|
|
class hdf5_ComplexType
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
H5::CompType type;
|
|
|
|
|
|
|
|
hdf5_ComplexType()
|
|
|
|
: type(sizeof(std::complex<T>))
|
|
|
|
{
|
|
|
|
get_hdf5_data_type<T> hdf_data_type;
|
|
|
|
type.insertMember("r", 0, hdf_data_type.type());
|
|
|
|
type.insertMember("i", sizeof(T), hdf_data_type.type());
|
|
|
|
type.pack();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const hdf5_ComplexType<T> *ctype()
|
|
|
|
{
|
|
|
|
static hdf5_ComplexType<T> singleton;
|
|
|
|
|
|
|
|
return &singleton;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-11 21:23:44 +01:00
|
|
|
template<> struct get_hdf5_data_type<std::complex<float> > {
|
|
|
|
static H5::DataType type() {
|
|
|
|
return hdf5_ComplexType<float>::ctype()->type;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct get_hdf5_data_type<std::complex<double> > {
|
|
|
|
static H5::DataType type() {
|
|
|
|
return hdf5_ComplexType<double>::ctype()->type;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-12-11 16:26:17 +01:00
|
|
|
class hdf5_StringType
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
H5::StrType type;
|
|
|
|
|
|
|
|
hdf5_StringType()
|
|
|
|
: type(0, H5T_VARIABLE)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static const hdf5_StringType *ctype()
|
|
|
|
{
|
|
|
|
static hdf5_StringType singleton;
|
|
|
|
return &singleton;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct get_hdf5_data_type<std::string> {
|
|
|
|
static H5::DataType type() {
|
|
|
|
return hdf5_StringType::ctype()->type;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-16 10:59:33 +01:00
|
|
|
class hdf5_BoolType
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
H5::EnumType type;
|
|
|
|
|
|
|
|
hdf5_BoolType()
|
|
|
|
: type(sizeof(bool))
|
|
|
|
{
|
|
|
|
bool v;
|
|
|
|
|
|
|
|
v = true;
|
|
|
|
type.insert("TRUE", &v);
|
|
|
|
v = false;
|
|
|
|
type.insert("FALSE", &v);
|
|
|
|
}
|
|
|
|
static const hdf5_BoolType *ctype()
|
|
|
|
{
|
|
|
|
static hdf5_BoolType singleton;
|
|
|
|
|
|
|
|
return &singleton;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct get_hdf5_data_type<bool> {
|
|
|
|
static H5::DataType type() {
|
|
|
|
return hdf5_BoolType::ctype()->type;
|
|
|
|
}
|
|
|
|
};
|
2015-02-11 21:23:44 +01:00
|
|
|
|
|
|
|
template<typename ArrayType>
|
2017-12-16 17:33:21 +01:00
|
|
|
void hdf5_write_array(H5_CommonFileGroup& fg, const std::string& data_set_name, const ArrayType& data )
|
2014-05-20 16:16:46 +02:00
|
|
|
{
|
2015-02-11 21:27:27 +01:00
|
|
|
typedef typename ArrayType::element T;
|
2014-05-20 16:16:46 +02:00
|
|
|
get_hdf5_data_type<T> hdf_data_type;
|
2015-02-11 21:23:44 +01:00
|
|
|
|
2014-05-20 16:16:46 +02:00
|
|
|
hdf5_write_array(fg, data_set_name, data, hdf_data_type.type());
|
|
|
|
}
|
2017-12-16 17:33:21 +01:00
|
|
|
|
2014-05-20 16:16:46 +02:00
|
|
|
// HDF5 array reader
|
|
|
|
//
|
|
|
|
// Author Guilhem Lavaux (May 2014)
|
|
|
|
|
|
|
|
class InvalidDimensions: virtual std::exception {
|
|
|
|
};
|
|
|
|
|
2015-02-12 08:50:07 +01:00
|
|
|
|
2015-03-21 18:27:09 +01:00
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
// Conditional resize support
|
|
|
|
// If the Array type support resize then it is called. Otherwise
|
|
|
|
// the dimensions are checked and lead to a failure if they are different
|
2015-02-12 08:50:07 +01:00
|
|
|
|
|
|
|
template<typename Array> class array_has_resize {
|
|
|
|
struct Fallback { int resize; };
|
|
|
|
struct Derived: Array, Fallback {};
|
|
|
|
|
|
|
|
typedef char yes[1];
|
|
|
|
typedef char no[2];
|
|
|
|
|
|
|
|
template<typename U, U> struct Check;
|
2014-05-20 16:16:46 +02:00
|
|
|
|
2015-02-12 08:50:07 +01:00
|
|
|
template<typename U>
|
|
|
|
static yes& func(Check<int Fallback::*, &U::resize> *);
|
2014-05-20 16:16:46 +02:00
|
|
|
|
2015-02-12 08:50:07 +01:00
|
|
|
template<typename U>
|
|
|
|
static no& func(...);
|
|
|
|
public:
|
|
|
|
typedef array_has_resize type;
|
|
|
|
enum { value = sizeof(func<Derived>(0)) == sizeof(no) };
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename ArrayType>
|
|
|
|
typename boost::enable_if<
|
|
|
|
array_has_resize<ArrayType>
|
|
|
|
>::type
|
|
|
|
hdf5_resize_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
|
|
|
data.resize(
|
|
|
|
hdf5_extent_gen<ArrayType::dimensionality>::build(dims.data())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-02-15 19:40:14 +01:00
|
|
|
template<typename ArrayType>
|
|
|
|
void hdf5_check_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
2016-12-11 14:47:44 +01:00
|
|
|
for (size_t i = 0; i < data.num_dimensions(); i++) {
|
2015-02-15 19:40:14 +01:00
|
|
|
if (data.shape()[i] != dims[i]) {
|
|
|
|
throw InvalidDimensions();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-23 17:34:53 +01:00
|
|
|
template<typename ArrayType>
|
|
|
|
void hdf5_weak_check_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
2016-12-11 14:47:44 +01:00
|
|
|
for (size_t i = 0; i < data.num_dimensions(); i++) {
|
2016-02-23 17:34:53 +01:00
|
|
|
if (data.index_bases()[i] < 0) {
|
|
|
|
// Negative indexes are not supported right now.
|
|
|
|
throw InvalidDimensions();
|
|
|
|
}
|
|
|
|
if (data.index_bases()[i]+data.shape()[i] > dims[i]) {
|
|
|
|
throw InvalidDimensions();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-02-12 08:50:07 +01:00
|
|
|
template<typename ArrayType>
|
|
|
|
typename boost::disable_if<
|
|
|
|
array_has_resize<ArrayType>
|
|
|
|
>::type
|
|
|
|
hdf5_resize_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
2015-02-15 19:40:14 +01:00
|
|
|
hdf5_check_array(data, dims);
|
2015-02-12 08:50:07 +01:00
|
|
|
}
|
2015-03-21 18:27:09 +01:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
2015-02-12 08:50:07 +01:00
|
|
|
|
2015-02-11 21:38:43 +01:00
|
|
|
template<typename ArrayType, typename hdf5_data_type>
|
2017-12-16 17:33:21 +01:00
|
|
|
void hdf5_read_array_typed(H5_CommonFileGroup& fg, const std::string& data_set_name,
|
2015-03-21 18:27:09 +01:00
|
|
|
ArrayType& data,
|
2016-02-23 17:34:53 +01:00
|
|
|
const hdf5_data_type& datatype, bool auto_resize = true, bool useBases = false)
|
2014-05-20 16:16:46 +02:00
|
|
|
{
|
|
|
|
H5::DataSet dataset = fg.openDataSet(data_set_name);
|
|
|
|
H5::DataSpace dataspace = dataset.getSpace();
|
2015-02-11 21:38:43 +01:00
|
|
|
std::vector<hsize_t> dimensions(data.num_dimensions());
|
2014-05-20 16:16:46 +02:00
|
|
|
|
2016-12-11 16:26:17 +01:00
|
|
|
if ((size_t)dataspace.getSimpleExtentNdims() != (size_t)data.num_dimensions())
|
2014-05-20 16:16:46 +02:00
|
|
|
{
|
|
|
|
throw InvalidDimensions();
|
|
|
|
}
|
|
|
|
|
|
|
|
dataspace.getSimpleExtentDims(dimensions.data());
|
2015-02-15 19:40:14 +01:00
|
|
|
if (auto_resize)
|
|
|
|
hdf5_resize_array(data, dimensions);
|
2016-02-23 17:34:53 +01:00
|
|
|
else {
|
|
|
|
if (useBases) {
|
|
|
|
hdf5_weak_check_array(data, dimensions);
|
|
|
|
|
|
|
|
std::vector<hsize_t> memdims(data.shape(), data.shape() + data.num_dimensions());
|
|
|
|
H5::DataSpace memspace(memdims.size(), memdims.data());
|
|
|
|
|
|
|
|
std::vector<hsize_t> offsets(data.index_bases(), data.index_bases() + data.num_dimensions());
|
|
|
|
dataspace.selectHyperslab(H5S_SELECT_SET, memdims.data(), offsets.data());
|
|
|
|
|
|
|
|
dataset.read(data.data(), datatype, memspace, dataspace);
|
2016-02-25 10:41:28 +01:00
|
|
|
return;
|
2016-02-23 17:34:53 +01:00
|
|
|
} else {
|
|
|
|
hdf5_check_array(data, dimensions);
|
|
|
|
}
|
|
|
|
}
|
2014-05-20 16:16:46 +02:00
|
|
|
dataset.read(data.data(), datatype);
|
|
|
|
}
|
|
|
|
|
2015-02-11 21:38:43 +01:00
|
|
|
template<typename ArrayType>
|
2017-12-16 17:33:21 +01:00
|
|
|
void hdf5_read_array(H5_CommonFileGroup& fg, const std::string& data_set_name, ArrayType& data, bool auto_resize = true,
|
2016-02-23 17:34:53 +01:00
|
|
|
bool useBases = false )
|
2014-05-20 16:16:46 +02:00
|
|
|
{
|
2015-02-11 21:38:43 +01:00
|
|
|
typedef typename ArrayType::element T;
|
|
|
|
|
2016-02-23 17:34:53 +01:00
|
|
|
hdf5_read_array_typed(fg, data_set_name, data, get_hdf5_data_type<T>::type(), auto_resize, useBases);
|
2014-05-20 16:16:46 +02:00
|
|
|
}
|
|
|
|
|
2015-01-31 15:11:44 +01:00
|
|
|
|
|
|
|
#define CTOOL_HDF5_NAME(STRUCT) BOOST_PP_CAT(hdf5_,STRUCT)
|
|
|
|
#define CTOOL_HDF5_INSERT_ELEMENT(r, STRUCT, element) \
|
|
|
|
{ \
|
2015-01-31 18:11:35 +01:00
|
|
|
::CosmoTool::get_hdf5_data_type<BOOST_PP_TUPLE_ELEM(2, 0, element)> t; \
|
2015-01-31 15:47:44 +01:00
|
|
|
position = HOFFSET(STRUCT, BOOST_PP_TUPLE_ELEM(2, 1, element)); \
|
|
|
|
const char *field_name = BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, element)); \
|
|
|
|
type.insertMember(field_name, position, t.type()); \
|
2015-01-31 15:11:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#define CTOOL_STRUCT_TYPE(STRUCT, TNAME, ATTRIBUTES) \
|
|
|
|
namespace CosmoTool { \
|
2015-01-31 15:47:44 +01:00
|
|
|
class TNAME { \
|
2015-01-31 15:11:44 +01:00
|
|
|
public: \
|
|
|
|
H5::CompType type; \
|
|
|
|
\
|
2015-01-31 15:47:44 +01:00
|
|
|
TNAME() : type(sizeof(STRUCT)) \
|
2015-01-31 15:11:44 +01:00
|
|
|
{ \
|
|
|
|
long position; \
|
|
|
|
BOOST_PP_SEQ_FOR_EACH(CTOOL_HDF5_INSERT_ELEMENT, STRUCT, ATTRIBUTES) \
|
|
|
|
} \
|
|
|
|
\
|
2015-01-31 15:47:44 +01:00
|
|
|
static const TNAME *ctype() \
|
2015-01-31 15:11:44 +01:00
|
|
|
{ \
|
2015-01-31 15:47:44 +01:00
|
|
|
static TNAME singleton; \
|
2015-01-31 15:11:44 +01:00
|
|
|
return &singleton; \
|
|
|
|
} \
|
|
|
|
}; \
|
|
|
|
template<> struct get_hdf5_data_type<STRUCT> { \
|
2015-01-31 15:47:44 +01:00
|
|
|
static H5::DataType type() { return TNAME::ctype()->type; }; \
|
2015-01-31 15:11:44 +01:00
|
|
|
}; \
|
|
|
|
};
|
|
|
|
|
2015-02-16 10:59:33 +01:00
|
|
|
|
|
|
|
#define CTOOL_HDF5_INSERT_ENUM_ELEMENT(r, STRUCT, element) \
|
|
|
|
{ \
|
|
|
|
const char *field_name = BOOST_PP_STRINGIZE(element); \
|
|
|
|
STRUCT a = element; \
|
|
|
|
type.insert(field_name, &a); \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define CTOOL_ENUM_TYPE(STRUCT, TNAME, ATTRIBUTES) \
|
|
|
|
namespace CosmoTool { \
|
|
|
|
class TNAME { \
|
|
|
|
public: \
|
|
|
|
H5::EnumType type; \
|
|
|
|
\
|
|
|
|
TNAME() : type(sizeof(STRUCT)) \
|
|
|
|
{ \
|
|
|
|
long position; \
|
|
|
|
BOOST_PP_SEQ_FOR_EACH(CTOOL_HDF5_INSERT_ENUM_ELEMENT, STRUCT, ATTRIBUTES) \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
static const TNAME *ctype() \
|
|
|
|
{ \
|
|
|
|
static TNAME singleton; \
|
|
|
|
return &singleton; \
|
|
|
|
} \
|
|
|
|
}; \
|
|
|
|
template<> struct get_hdf5_data_type<STRUCT> { \
|
|
|
|
static H5::DataType type() { return TNAME::ctype()->type; }; \
|
|
|
|
}; \
|
|
|
|
};
|
|
|
|
|
2015-02-13 15:45:17 +01:00
|
|
|
#define CTOOL_ARRAY_TYPE(ARRAY_TYPE, DIM, TNAME) \
|
|
|
|
namespace CosmoTool { \
|
|
|
|
class TNAME { \
|
|
|
|
public: \
|
|
|
|
H5::ArrayType *type; \
|
|
|
|
\
|
|
|
|
TNAME() \
|
|
|
|
{ \
|
|
|
|
hsize_t dims[1] = { DIM }; \
|
|
|
|
type = new H5::ArrayType(get_hdf5_data_type<ARRAY_TYPE>::type(), 1, dims); \
|
|
|
|
} \
|
|
|
|
~TNAME() { delete type; } \
|
|
|
|
\
|
|
|
|
static const TNAME *ctype() \
|
|
|
|
{ \
|
|
|
|
static TNAME singleton; \
|
|
|
|
return &singleton; \
|
|
|
|
} \
|
|
|
|
}; \
|
|
|
|
\
|
|
|
|
template<> struct get_hdf5_data_type< ARRAY_TYPE[DIM] > { \
|
|
|
|
static H5::DataType type() { return *(TNAME::ctype()->type); }; \
|
|
|
|
}; \
|
|
|
|
};
|
|
|
|
|
2014-05-20 16:16:46 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|