mirror of
https://git.gfz-potsdam.de/naaice/poet.git
synced 2025-12-16 12:54:50 +01:00
296 lines
10 KiB
C++
296 lines
10 KiB
C++
/*
|
|
* Copyright (c), 2017, Ali Can Demiralp <ali.demiralp@rwth-aachen.de>
|
|
*
|
|
* Distributed under the Boost Software License, Version 1.0.
|
|
* (See accompanying file LICENSE_1_0.txt or copy at
|
|
* http://www.boost.org/LICENSE_1_0.txt)
|
|
*
|
|
*/
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
|
|
#include <H5Apublic.h>
|
|
|
|
#include "H5DataType.hpp"
|
|
#include "H5DataSpace.hpp"
|
|
#include "H5Object.hpp"
|
|
#include "bits/H5Friends.hpp"
|
|
#include "bits/H5Path_traits.hpp"
|
|
|
|
namespace HighFive {
|
|
class DataSpace;
|
|
|
|
namespace detail {
|
|
|
|
/// \brief Internal hack to create an `Attribute` from an ID.
|
|
///
|
|
/// WARNING: Creating an Attribute from an ID has implications w.r.t. the lifetime of the object
|
|
/// that got passed via its ID. Using this method careless opens up the suite of issues
|
|
/// related to C-style resource management, including the analog of double free, dangling
|
|
/// pointers, etc.
|
|
///
|
|
/// NOTE: This is not part of the API and only serves to work around a compiler issue in GCC which
|
|
/// prevents us from using `friend`s instead. This function should only be used for internal
|
|
/// purposes. The problematic construct is:
|
|
///
|
|
/// template<class Derived>
|
|
/// friend class SomeCRTP<Derived>;
|
|
///
|
|
/// \private
|
|
Attribute make_attribute(hid_t hid);
|
|
} // namespace detail
|
|
|
|
/// \brief Class representing an Attribute of a DataSet or Group
|
|
///
|
|
/// \sa AnnotateTraits::createAttribute, AnnotateTraits::getAttribute, AnnotateTraits::listAttributeNames, AnnotateTraits::hasAttribute, AnnotateTraits::deleteAttribute for create, get, list, check or delete Attribute
|
|
class Attribute: public Object, public PathTraits<Attribute> {
|
|
public:
|
|
const static ObjectType type = ObjectType::Attribute;
|
|
|
|
/// \brief Get the name of the current Attribute.
|
|
/// \code{.cpp}
|
|
/// auto attr = dset.createAttribute<std::string>("my_attribute", DataSpace::From(string_list));
|
|
/// std::cout << attr.getName() << std::endl; // Will print "my_attribute"
|
|
/// \endcode
|
|
/// \since 2.2.2
|
|
std::string getName() const;
|
|
|
|
/// \brief The number of bytes required to store the attribute in the HDF5 file.
|
|
/// \code{.cpp}
|
|
/// size_t size = dset.createAttribute<int>("foo", DataSpace(1, 2)).getStorageSize();
|
|
/// \endcode
|
|
/// \since 1.0
|
|
size_t getStorageSize() const;
|
|
|
|
/// \brief Get the DataType of the Attribute.
|
|
/// \code{.cpp}
|
|
/// Attribute attr = dset.createAttribute<int>("foo", DataSpace(1, 2));
|
|
/// auto dtype = attr.getDataType(); // Will be an hdf5 type deduced from int
|
|
/// \endcode
|
|
/// \since 1.0
|
|
DataType getDataType() const;
|
|
|
|
/// \brief Get a copy of the DataSpace of the current Attribute.
|
|
/// \code{.cpp}
|
|
/// Attribute attr = dset.createAttribute<int>("foo", DataSpace(1, 2));
|
|
/// auto dspace = attr.getSpace(); // This will be a DataSpace of dimension 1 * 2
|
|
/// \endcode
|
|
/// \since 1.0
|
|
DataSpace getSpace() const;
|
|
|
|
/// \brief Get the memory DataSpace of the current Attribute.
|
|
///
|
|
/// HDF5 attributes don't support selections. Therefore, there's no need
|
|
/// for a memory dataspace. However, HighFive supports allocating arrays
|
|
/// and checking dimensions, this requires the dimensions of the memspace.
|
|
///
|
|
/// \since 1.0
|
|
DataSpace getMemSpace() const;
|
|
|
|
/// \brief Get the value of the Attribute.
|
|
/// \code{.cpp}
|
|
/// Attribute attr = dset.getAttribute("foo");
|
|
/// // The value will contains what have been written in the attribute
|
|
/// std::vector<int> value = attr.read<std::vector<int>>();
|
|
/// \endcode
|
|
/// \since 2.5.0
|
|
template <typename T>
|
|
T read() const;
|
|
|
|
/// \brief Get the value of the Attribute in a buffer.
|
|
///
|
|
/// Read the attribute into an existing object. Only available for
|
|
/// supported types `T`. If `array` has preallocated the correct amount of
|
|
/// memory, then this routine should not trigger reallocation. Otherwise,
|
|
/// if supported, the object will be resized.
|
|
///
|
|
/// An exception is raised if the numbers of dimension of the buffer and of
|
|
/// the attribute are different.
|
|
///
|
|
/// \code{.cpp}
|
|
/// // Will read into `value` avoiding memory allocation if the dimensions
|
|
/// // match, i.e. if the attribute `"foo"` has three element.
|
|
/// std::vector<int> value(3);
|
|
/// file.getAttribute("foo").read(value);
|
|
/// \endcode
|
|
/// \since 1.0
|
|
template <typename T>
|
|
void read(T& array) const;
|
|
|
|
/// \brief Read the attribute into a pre-allocated buffer.
|
|
/// \param array A pointer to the first byte of sufficient pre-allocated memory.
|
|
/// \param mem_datatype The DataType of the array.
|
|
///
|
|
/// \note This is the shallowest wrapper around `H5Aread`. If possible
|
|
/// prefer either Attribute::read() const or Attribute::read(T&) const.
|
|
///
|
|
/// \code{.cpp}
|
|
/// auto attr = file.getAttribute("foo");
|
|
///
|
|
/// // Simulate custom allocation by the application.
|
|
/// size_t n_elements = attr.getSpace().getElementCount();
|
|
/// int * ptr = (int*) malloc(n_elements*sizeof(int));
|
|
///
|
|
/// // Read into the pre-allocated memory.
|
|
/// attr.read(ptr, mem_datatype);
|
|
/// \endcode
|
|
/// \since 2.2.2
|
|
template <typename T>
|
|
void read_raw(T* array, const DataType& mem_datatype) const;
|
|
|
|
/// \brief Read the attribute into a buffer.
|
|
/// Behaves like Attribute::read(T*, const DataType&) const but
|
|
/// additionally this overload deduces the memory datatype from `T`.
|
|
///
|
|
/// \param array Pointer to the first byte of pre-allocated memory.
|
|
///
|
|
/// \note If possible prefer either Attribute::read() const or Attribute::read(T&) const.
|
|
///
|
|
/// \code{.cpp}
|
|
/// auto attr = file.getAttribute("foo");
|
|
///
|
|
/// // Simulate custom allocation by the application.
|
|
/// size_t n_elements = attr.getSpace().getElementCount();
|
|
/// int * ptr = (int*) malloc(n_elements*sizeof(int));
|
|
///
|
|
/// // Read into the pre-allocated memory.
|
|
/// attr.read(ptr);
|
|
/// \endcode
|
|
/// \since 2.2.2
|
|
template <typename T>
|
|
void read_raw(T* array) const;
|
|
|
|
/// \brief Write the value into the Attribute.
|
|
///
|
|
/// Write the value to the attribute. For supported types `T`, this overload
|
|
/// will write the value to the attribute. The datatype and dataspace are
|
|
/// deduced automatically. However, since the attribute has already been
|
|
/// created, the dimensions of `value` must match those of the attribute.
|
|
///
|
|
/// \code{.cpp}
|
|
/// // Prefer the fused version if creating and writing the attribute
|
|
/// // at the same time.
|
|
/// dset.createAttribute("foo", std::vector<int>{1, 2, 3});
|
|
///
|
|
/// // To overwrite the value:
|
|
/// std::vector<int> value{4, 5, 6};
|
|
/// dset.getAttribute<int>("foo").write(value);
|
|
/// \endcode
|
|
/// \since 1.0
|
|
template <typename T>
|
|
void write(const T& value);
|
|
|
|
/// \brief Write from a raw pointer.
|
|
///
|
|
/// Values that have been correctly arranged memory, can be written directly
|
|
/// by passing a raw pointer.
|
|
///
|
|
/// \param buffer Pointer to the first byte of the value.
|
|
/// \param mem_datatype The DataType of the buffer.
|
|
///
|
|
/// \note This is the shallowest wrapper around `H5Awrite`. It's useful
|
|
/// if you need full control. If possible prefer Attribute::write.
|
|
///
|
|
/// \code{.cpp}
|
|
/// Attribute attr = dset.createAttribute<int>("foo", DataSpace(2, 3));
|
|
///
|
|
/// // Simulate the application creating `value` and only exposing access
|
|
/// // to the raw pointer `ptr`.
|
|
/// std::vector<std::array<int, 3>> value{{1, 2, 3}, {4, 5, 6}};
|
|
/// int * ptr = (int*) value.data();
|
|
///
|
|
/// // Simply write the bytes to disk.
|
|
/// attr.write(ptr, AtomicType<int>());
|
|
/// \endcode
|
|
/// \since 2.2.2
|
|
template <typename T>
|
|
void write_raw(const T* buffer, const DataType& mem_datatype);
|
|
|
|
/// \brief Write from a raw pointer.
|
|
///
|
|
/// Much like Attribute::write_raw(const T*, const DataType&).
|
|
/// Additionally, this overload attempts to automatically deduce the
|
|
/// datatype of the buffer. Note, that the file datatype is already set.
|
|
///
|
|
/// \param buffer Pointer to the first byte.
|
|
///
|
|
/// \note If possible prefer Attribute::write.
|
|
///
|
|
/// \code{.cpp}
|
|
/// // Simulate the application creating `value` and only exposing access
|
|
/// // to the raw pointer `ptr`.
|
|
/// std::vector<std::array<int, 3>> value{{1, 2, 3}, {4, 5, 6}};
|
|
/// int * ptr = (int*) value.data();
|
|
///
|
|
/// // Simply write the bytes to disk.
|
|
/// attr.write(ptr);
|
|
/// \endcode
|
|
/// \since 2.2.2
|
|
template <typename T>
|
|
void write_raw(const T* buffer);
|
|
|
|
/// \brief The create property list used for this attribute.
|
|
///
|
|
/// Some of HDF5 properties/setting of an attribute are defined by a
|
|
/// create property list. This method returns a copy of the create
|
|
/// property list used during creation of the attribute.
|
|
///
|
|
/// \code{.cpp}
|
|
/// auto acpl = attr.getCreatePropertyList();
|
|
///
|
|
/// // For example to create another attribute with the same properties.
|
|
/// file.createAttribute("foo", 42, acpl);
|
|
/// \endcode
|
|
/// \since 2.5.0
|
|
AttributeCreateProps getCreatePropertyList() const {
|
|
return details::get_plist<AttributeCreateProps>(*this, H5Aget_create_plist);
|
|
}
|
|
|
|
// No empty attributes
|
|
Attribute() = delete;
|
|
|
|
///
|
|
/// \brief Return an `Attribute` with `axes` squeezed from the memspace.
|
|
///
|
|
/// Returns an `Attribute` in which the memspace has been modified
|
|
/// to not include the axes listed in `axes`.
|
|
///
|
|
/// Throws if any axis to be squeezes has a dimension other than `1`.
|
|
///
|
|
/// \since 3.0
|
|
Attribute squeezeMemSpace(const std::vector<size_t>& axes) const;
|
|
|
|
///
|
|
/// \brief Return a `Attribute` with a simple memspace with `dims`.
|
|
///
|
|
/// Returns a `Attribute` in which the memspace has been modified
|
|
/// to be a simple dataspace with dimensions `dims`.
|
|
///
|
|
/// Throws if the number of elements changes.
|
|
///
|
|
/// \since 3.0
|
|
Attribute reshapeMemSpace(const std::vector<size_t>& dims) const;
|
|
|
|
protected:
|
|
using Object::Object;
|
|
|
|
private:
|
|
DataSpace _mem_space;
|
|
|
|
#if HIGHFIVE_HAS_FRIEND_DECLARATIONS
|
|
template <typename Derivate>
|
|
friend class ::HighFive::AnnotateTraits;
|
|
#endif
|
|
|
|
friend Attribute detail::make_attribute(hid_t);
|
|
};
|
|
|
|
namespace detail {
|
|
inline Attribute make_attribute(hid_t hid) {
|
|
return Attribute(hid);
|
|
}
|
|
} // namespace detail
|
|
|
|
} // namespace HighFive
|