Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix support of bool #654

Merged
merged 22 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions include/highfive/H5DataType.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,10 @@ class FixedLenStringArray {
/// }
/// HIGHFIVE_REGISTER_TYPE(FooBar, create_enum_foobar)
/// \endcode
#define HIGHFIVE_REGISTER_TYPE(type, function) \
template <> \
HighFive::DataType HighFive::create_datatype<type>() { \
return function(); \
#define HIGHFIVE_REGISTER_TYPE(type, function) \
template <> \
inline HighFive::DataType HighFive::create_datatype<type>() { \
return function(); \
}

#include "bits/H5DataType_misc.hpp"
38 changes: 33 additions & 5 deletions include/highfive/bits/H5Converter_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ struct type_helper {
static constexpr size_t recursive_ndim = ndim;
static constexpr bool is_trivially_copyable = std::is_trivially_copyable<type>::value;

static_assert(!std::is_same<type, bool>::value, "Booleans are not supported yet.");

static std::vector<size_t> getDimensions(const type& /* val */) {
return {};
}
Expand Down Expand Up @@ -123,6 +121,36 @@ struct type_helper {
template <typename T>
struct inspector: type_helper<T> {};

enum Boolean : int8_t {
FALSE = 0,
TRUE = 1,
};
template <>
struct inspector<bool>: type_helper<bool> {
using base_type = Boolean;
using hdf5_type = int8_t;

static constexpr bool is_trivially_copyable = false;

static hdf5_type* data(type& /* val */) {
throw DataSpaceException("A boolean cannot be read directly.");
}

static const hdf5_type* data(const type& /* val */) {
throw DataSpaceException("A boolean cannot be write directly.");
alkino marked this conversation as resolved.
Show resolved Hide resolved
}

static void unserialize(const hdf5_type* vec,
const std::vector<size_t>& /* dims */,
type& val) {
val = vec[0] == 1 ? true : false;
}

static void serialize(const type& val, hdf5_type* m) {
*m = val ? 1 : 0;
}
};

template <>
struct inspector<std::string>: type_helper<std::string> {
using hdf5_type = const char*;
Expand Down Expand Up @@ -259,7 +287,7 @@ struct inspector<std::vector<T>> {
static void prepare(type& val, const std::vector<size_t>& dims) {
val.resize(dims[0]);
std::vector<size_t> next_dims(dims.begin() + 1, dims.end());
for (auto& e: val) {
for (auto&& e: val) {
inspector<value_type>::prepare(e, next_dims);
}
}
Expand All @@ -274,7 +302,7 @@ struct inspector<std::vector<T>> {

static void serialize(const type& val, hdf5_type* m) {
size_t subsize = inspector<value_type>::getSizeVal(val[0]);
for (auto& e: val) {
for (auto&& e: val) {
inspector<value_type>::serialize(e, m);
m += subsize;
}
Expand All @@ -295,7 +323,7 @@ struct inspector<std::vector<T>> {
template <typename T, size_t N>
struct inspector<std::array<T, N>> {
using type = std::array<T, N>;
using value_type = T;
using value_type = unqualified_t<T>;
using base_type = typename inspector<value_type>::base_type;
using hdf5_type = typename inspector<value_type>::hdf5_type;

Expand Down
12 changes: 6 additions & 6 deletions include/highfive/bits/H5DataType_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,6 @@ inline AtomicType<long double>::AtomicType() {
_hid = H5Tcopy(H5T_NATIVE_LDOUBLE);
}

// boolean mapping
template <>
inline AtomicType<bool>::AtomicType() {
_hid = H5Tcopy(H5T_NATIVE_HBOOL);
}

// std string
template <>
inline AtomicType<std::string>::AtomicType() {
Expand Down Expand Up @@ -200,6 +194,11 @@ class AtomicType<std::complex<T>>: public DataType {
}
};

// For boolean we act as h5py
inline EnumType<details::Boolean> create_enum_boolean() {
return {{"FALSE", details::Boolean::FALSE}, {"TRUE", details::Boolean::TRUE}};
}

// Other cases not supported. Fail early with a user message
template <typename T>
AtomicType<T>::AtomicType() {
Expand Down Expand Up @@ -493,3 +492,4 @@ inline DataType create_and_check_datatype() {
}

} // namespace HighFive
HIGHFIVE_REGISTER_TYPE(HighFive::details::Boolean, HighFive::create_enum_boolean)
16 changes: 15 additions & 1 deletion include/highfive/bits/H5Node_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "../H5PropertyList.hpp"
#include "H5_definitions.hpp"
#include "H5Converter_misc.hpp"

namespace HighFive {

Expand Down Expand Up @@ -47,7 +48,20 @@ class NodeTraits {
/// \param accessProps A property list with data set access properties
/// \param parents Create intermediate groups if needed. Default: true.
/// \return DataSet Object
template <typename Type>
template <typename T,
typename std::enable_if<
std::is_same<typename details::inspector<T>::base_type, details::Boolean>::value,
int>::type* = nullptr>
DataSet createDataSet(const std::string& dataset_name,
const DataSpace& space,
const DataSetCreateProps& createProps = DataSetCreateProps::Default(),
const DataSetAccessProps& accessProps = DataSetAccessProps::Default(),
bool parents = true);

template <typename T,
typename std::enable_if<
!std::is_same<typename details::inspector<T>::base_type, details::Boolean>::value,
int>::type* = nullptr>
DataSet createDataSet(const std::string& dataset_name,
const DataSpace& space,
const DataSetCreateProps& createProps = DataSetCreateProps::Default(),
Expand Down
25 changes: 23 additions & 2 deletions include/highfive/bits/H5Node_traits_misc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,35 @@ inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_na
}

template <typename Derivate>
template <typename Type>
template <typename T,
typename std::enable_if<
std::is_same<typename details::inspector<T>::base_type, details::Boolean>::value,
int>::type*>
inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
const DataSpace& space,
const DataSetCreateProps& createProps,
const DataSetAccessProps& accessProps,
bool parents) {
return createDataSet(dataset_name,
space,
create_and_check_datatype<typename details::inspector<T>::base_type>(),
createProps,
accessProps,
parents);
}

template <typename Derivate>
template <typename T,
typename std::enable_if<
!std::is_same<typename details::inspector<T>::base_type, details::Boolean>::value,
int>::type*>
inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
const DataSpace& space,
const DataSetCreateProps& createProps,
const DataSetAccessProps& accessProps,
bool parents) {
return createDataSet(
dataset_name, space, create_and_check_datatype<Type>(), createProps, accessProps, parents);
dataset_name, space, create_and_check_datatype<T>(), createProps, accessProps, parents);
}

template <typename Derivate>
Expand Down
4 changes: 2 additions & 2 deletions tests/test_project_integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test_install() {
mkdir -p "${builddir}"
pushd "${builddir}"
cmake "${TESTDIR}/${project}" "$@"
make VERBOSE=1
cmake --build . --verbose
ctest
popd
rm "${TESTDIR}/${project}/deps/HighFive"
Expand All @@ -29,7 +29,7 @@ cmake "${ROOT}" \
-DHIGHFIVE_EXAMPLES=OFF \
-DHIGHFIVE_UNIT_TESTS=OFF \
-DCMAKE_INSTALL_PREFIX="${PWD}/install"
make install
cmake --build . --target install
popd

for project in test_project test_dependent_library; do
Expand Down