Program Listing for File h5ppFile.h¶
↰ Return to documentation for file (/home/david/GitProjects/h5pp/h5pp/include/h5pp/details/h5ppFile.h
)
#pragma once
#include "h5ppConstants.h"
#include "h5ppDimensionType.h"
#include "h5ppEigen.h"
#include "h5ppEnums.h"
#include "h5ppFilesystem.h"
#include "h5ppHdf5.h"
#include "h5ppHid.h"
#include "h5ppLogger.h"
#include "h5ppOptional.h"
#include "h5ppPropertyLists.h"
#include "h5ppScan.h"
#include "h5ppTypeCompoundCreate.h"
#include "h5ppUtils.h"
#include <hdf5.h>
#include <hdf5_hl.h>
#include <string>
#include <utility>
namespace h5pp {
class File {
private:
fs::path filePath;
h5pp::FilePermission permission = h5pp::FilePermission::RENAME;
size_t logLevel = 2;
bool logTimestamp = false;
hid::h5e error_stack;
unsigned int currentCompressionLevel = 0;
void init() {
h5pp::logger::setLogger("h5pp|init", logLevel, logTimestamp);
h5pp::logger::log->debug("Initializing HDF5 file: [{}]", filePath.string());
/* Set default error print output */
error_stack = H5Eget_current_stack();
herr_t turnOffAutomaticErrorPrinting = H5Eset_auto2(error_stack, nullptr, nullptr);
if(turnOffAutomaticErrorPrinting < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error("Failed to turn off H5E error printing");
}
// The following function can modify the resulting filePath depending on permission.
filePath = h5pp::hdf5::createFile(filePath, permission, plists);
h5pp::type::compound::initTypes();
h5pp::logger::setLogger("h5pp|" + filePath.filename().string(), logLevel, logTimestamp);
h5pp::logger::log->debug("Successfully initialized file [{}]", filePath.string());
}
public:
// The following struct contains modifiable property lists.
// This allows us to use h5pp with MPI, for instance.
// Unmodified, these default to serial (non-MPI) use.
// We expose these property lists here so the user may set them as needed.
// To enable MPI, the user can call H5Pset_fapl_mpio(hid_t file_access_plist, MPI_Comm comm, MPI_Info info)
// The user is responsible for linking to MPI and learning how to set properties for MPI usage
PropertyLists plists;
File() {
h5pp::logger::setLogger("h5pp", logLevel, logTimestamp);
h5pp::logger::log->debug("Default-constructing h5pp file object");
}
File(const File &other) {
h5pp::logger::log->debug("Copy-constructing this file [{}] from given file: [{}]", filePath.string(), other.getFilePath());
*this = other;
}
explicit File(const std::string &filePath_, h5pp::FilePermission permission_ = h5pp::FilePermission::RENAME, size_t logLevel_ = 2, bool logTimestamp_ = false)
: filePath(filePath_), permission(permission_), logLevel(logLevel_), logTimestamp(logTimestamp_) {
init();
}
explicit File(const std::string &filePath_, unsigned int H5F_ACC_FLAGS, size_t logLevel_ = 2, bool logTimestamp_ = false)
: filePath(filePath_), logLevel(logLevel_), logTimestamp(logTimestamp_) {
permission = h5pp::hdf5::convertFileAccessFlags(H5F_ACC_FLAGS);
init();
}
~File() {
h5pp::logger::log->debug("Closing file [{}]", filePath.string());
H5garbage_collect();
H5Eprint(H5E_DEFAULT, stderr);
}
File &operator=(const File &other) {
h5pp::logger::log->debug("Assignment to this file [{}] from given file: [{}]", filePath.string(), other.getFilePath());
if(&other != this) {
logLevel = other.logLevel;
logTimestamp = other.logTimestamp;
permission = other.permission;
filePath = other.filePath;
plists = other.plists;
h5pp::logger::setLogger("h5pp|" + filePath.filename().string(), logLevel, logTimestamp);
}
return *this;
}
void flush() {
h5pp::logger::log->trace("Flushing caches");
H5Fflush(openFileHandle(), H5F_scope_t::H5F_SCOPE_GLOBAL);
H5garbage_collect();
H5Eprint(H5E_DEFAULT, stderr);
}
[[nodiscard]] hid::h5f openFileHandle() const {
h5pp::logger::setLogger("h5pp|" + filePath.filename().string(), logLevel, logTimestamp);
if(permission == h5pp::FilePermission::READONLY) {
h5pp::logger::log->trace("Opening file in READONLY mode");
hid_t fileHandle = H5Fopen(filePath.string().c_str(), H5F_ACC_RDONLY, plists.fileAccess);
if(fileHandle < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Failed to open file in read-only mode [{}]", filePath.string()));
} else
return fileHandle;
} else {
h5pp::logger::log->trace("Opening file in READWRITE mode");
hid_t fileHandle = H5Fopen(filePath.string().c_str(), H5F_ACC_RDWR, plists.fileAccess);
if(fileHandle < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Failed to open file in read-write mode [{}]", filePath.string()));
} else
return fileHandle;
}
}
/*
*
* Functions for file properties
*
*/
[[nodiscard]] h5pp::FilePermission getFilePermission() const { return permission; }
[[nodiscard]] std::string getFileName() const { return filePath.filename().string(); }
[[nodiscard]] std::string getFilePath() const { return filePath.string(); }
void setFilePermission(h5pp::FilePermission permission_) { permission = permission_; }
void setDriver_sec2() {
plists.fileAccess = H5Fget_access_plist(openFileHandle());
H5Pset_fapl_sec2(plists.fileAccess);
}
void setDriver_stdio() {
plists.fileAccess = H5Fget_access_plist(openFileHandle());
H5Pset_fapl_stdio(plists.fileAccess);
}
void setDriver_core(bool writeOnClose = true, size_t bytesPerMalloc = 10240000) {
plists.fileAccess = H5Fget_access_plist(openFileHandle());
H5Pset_fapl_core(plists.fileAccess, bytesPerMalloc, static_cast<hbool_t>(writeOnClose));
}
#ifdef H5_HAVE_PARALLEL
void setDriver_mpio(MPI_Comm comm, MPI_Info info) {
plists.fileAccess = H5Fget_access_plist(openFileHandle());
H5Pset_fapl_mpio(plists.fileAccess, comm, info);
}
#endif
/*
*
* Functions for managing file location
*
*/
[[maybe_unused]] fs::path copyFileTo(const std::string &targetFilePath, const FilePermission &perm = FilePermission::COLLISION_FAIL) const {
return h5pp::hdf5::copyFile(getFilePath(), targetFilePath, perm, plists);
}
[[maybe_unused]] fs::path moveFileTo(const std::string &targetFilePath, const FilePermission &perm = FilePermission::COLLISION_FAIL) {
auto newPath = h5pp::hdf5::moveFile(getFilePath(), targetFilePath, perm, plists);
if(fs::exists(newPath)) { filePath = newPath; }
return newPath;
}
/*
*
* Functions for transfering contents between locations or files
*
*/
void copyLinkToFile(const std::string & localLinkPath,
const std::string & targetFilePath,
const std::string & targetLinkPath,
const FilePermission &targetFileCreatePermission = FilePermission::READWRITE) const {
return h5pp::hdf5::copyLink(getFilePath(), localLinkPath, targetFilePath, targetLinkPath, targetFileCreatePermission, plists);
}
void copyLinkFromFile(const std::string &localLinkPath, const std::string &sourceFilePath, const std::string &sourceLinkPath) {
return h5pp::hdf5::copyLink(sourceFilePath, sourceLinkPath, getFilePath(), localLinkPath, h5pp::FilePermission::READWRITE, plists);
}
template<typename h5x_tgt, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_tgt>>
void copyLinkToLocation(const std::string &localLinkPath, const h5x_tgt &targetLocationId, const std::string &targetLinkPath) const {
return h5pp::hdf5::copyLink(openFileHandle(), localLinkPath, targetLocationId, targetLinkPath, plists);
}
template<typename h5x_src, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_src>>
void copyLinkFromLocation(const std::string &localLinkPath, const h5x_src &sourceLocationId, const std::string &sourceLinkPath) {
return h5pp::hdf5::copyLink(sourceLocationId, sourceLinkPath, openFileHandle(), localLinkPath, h5pp::FilePermission::READWRITE, plists);
}
/*
*
* Functions for logging
*
*/
[[nodiscard]] size_t getLogLevel() const { return logLevel; }
void setLogLevel(size_t logLevelZeroToFive) {
logLevel = logLevelZeroToFive;
h5pp::logger::setLogLevel(logLevelZeroToFive);
}
/*
*
* Functions related to datasets
*
*/
void setCompressionLevel(unsigned int compressionLevelZeroToNine) { currentCompressionLevel = h5pp::hdf5::getValidCompressionLevel(compressionLevelZeroToNine); }
[[nodiscard]] unsigned int getCompressionLevel() const { return currentCompressionLevel; }
[[nodiscard]] unsigned int getCompressionLevel(std::optional<unsigned int> desiredCompressionLevel) const {
if(desiredCompressionLevel)
return h5pp::hdf5::getValidCompressionLevel(desiredCompressionLevel.value());
else
return currentCompressionLevel;
}
void createGroup(std::string_view group_relative_name) { h5pp::hdf5::createGroup(openFileHandle(), group_relative_name, std::nullopt, plists); }
void resizeDataset(DsetInfo &info, const DimsType &newDimensions, std::optional<h5pp::ResizeMode> mode_override = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to resize dataset on read-only file [{}]", filePath.string()));
h5pp::hdf5::resizeDataset(info, newDimensions, mode_override);
}
template<typename DsetDimsType = std::initializer_list<hsize_t>, typename = h5pp::type::sfinae::enable_if_is_integral_iterable_or_num<DsetDimsType>>
DsetInfo resizeDataset(std::string_view dsetPath, const DsetDimsType &newDimensions, std::optional<h5pp::ResizeMode> mode = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to resize dataset on read-only file [{}]", filePath.string()));
Options options;
options.linkPath = dsetPath;
options.resizeMode = mode;
auto info = h5pp::scan::getDsetInfo(openFileHandle(), dsetPath, options, plists);
if(not info.dsetExists.value()) throw std::runtime_error(h5pp::format("Failed to resize dataset [{}]: dataset does not exist", dsetPath));
h5pp::hdf5::resizeDataset(info, h5pp::util::getDimVector(newDimensions), mode);
return info;
}
void createDataset(DsetInfo &info) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to create dataset on read-only file [{}]", filePath.string()));
h5pp::hdf5::createDataset(info, plists);
}
DsetInfo createDataset(const Options &options) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to create dataset on read-only file [{}]", filePath.string()));
options.assertWellDefined();
if(not options.linkPath) throw std::runtime_error(h5pp::format("Error creating dataset: No dataset path specified"));
if(not options.dataDims) throw std::runtime_error(h5pp::format("Error creating dataset [{}]: Dimensions or size not specified", options.linkPath.value()));
if(not options.h5Type) throw std::runtime_error(h5pp::format("Error creating dataset [{}]: HDF5 type not specified", options.linkPath.value()));
auto dsetInfo = h5pp::scan::getDsetInfo(openFileHandle(), options, plists);
h5pp::File::createDataset(dsetInfo);
return dsetInfo;
}
DsetInfo createDataset(std::optional<hid::h5t> h5Type,
std::string_view dsetPath,
const DimsType & dsetDims,
std::optional<H5D_layout_t> h5Layout = std::nullopt,
const OptDimsType & dsetDimsChunk = std::nullopt,
const OptDimsType & dsetDimsMax = std::nullopt,
std::optional<unsigned int> compression = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to create dataset on read-only file [{}]", filePath.string()));
Options options;
options.linkPath = dsetPath;
options.dataDims = dsetDims;
options.dsetDimsChunk = dsetDimsChunk;
options.dsetDimsMax = dsetDimsMax;
options.h5Type = std::move(h5Type);
options.h5Layout = h5Layout;
options.compression = getCompressionLevel(compression);
return createDataset(options);
}
template<typename DataType>
DsetInfo createDataset(const DataType &data, const Options &options) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to create dataset on read-only file [{}]", filePath.string()));
auto dsetInfo = h5pp::scan::getDsetInfo(openFileHandle(), data, options, plists);
h5pp::File::createDataset(dsetInfo);
return dsetInfo;
}
template<typename DataType>
DsetInfo createDataset(const DataType & data,
std::string_view dsetPath,
const OptDimsType & dataDims = std::nullopt,
std::optional<H5D_layout_t> h5Layout = std::nullopt,
const OptDimsType & dsetDimsChunk = std::nullopt,
const OptDimsType & dsetDimsMax = std::nullopt,
std::optional<unsigned int> compression = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to create dataset on read-only file [{}]", filePath.string()));
Options options;
options.linkPath = dsetPath;
options.dataDims = dataDims;
options.dsetDimsChunk = dsetDimsChunk;
options.dsetDimsMax = dsetDimsMax;
options.h5Type = h5pp::util::getH5Type<DataType>();
options.h5Layout = h5Layout;
options.compression = getCompressionLevel(compression);
// If dsetdims is a nullopt we can infer its dimensions from the given dataset
return createDataset(data, options);
}
template<typename DataType>
void writeDataset(const DataType &data, DsetInfo &dsetInfo, const Options &options = Options()) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
if(not dsetInfo.dsetExists or not dsetInfo.dsetExists.value()) createDataset(dsetInfo);
auto dataInfo = h5pp::scan::getDataInfo(data,options);
resizeDataset(dsetInfo, dataInfo.dataDims.value());
h5pp::hdf5::writeDataset(data, dataInfo, dsetInfo, plists);
}
template<typename DataType>
void writeDataset(const DataType &data, const DataInfo &dataInfo, DsetInfo &dsetInfo) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
// The infos passed should be parsed and ready to write with
if(not dsetInfo.dsetExists or not dsetInfo.dsetExists.value()) createDataset(dsetInfo);
resizeDataset(dsetInfo, dataInfo.dataDims.value());
h5pp::hdf5::writeDataset(data, dataInfo, dsetInfo, plists);
}
template<typename DataType>
DsetInfo writeDataset(const DataType &data, const Options &options) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
options.assertWellDefined();
auto dataInfo = h5pp::scan::getDataInfo(data, options);
auto dsetInfo = h5pp::scan::getDsetInfo(openFileHandle(), data, options, plists); // Creates if it doesn't exist, otherwise it just fills the meta data
writeDataset(data, dataInfo, dsetInfo);
return dsetInfo;
}
template<typename DataType>
DsetInfo writeDataset(const DataType & data,
std::string_view dsetPath,
const OptDimsType & dataDims = std::nullopt,
std::optional<H5D_layout_t> h5Layout = std::nullopt,
const OptDimsType & dsetDimsChunk = std::nullopt,
const OptDimsType & dsetDimsMax = std::nullopt,
std::optional<hid::h5t> h5Type = std::nullopt,
std::optional<ResizeMode> resizeMode = std::nullopt,
std::optional<unsigned int> compression = std::nullopt)
{
Options options;
options.linkPath = dsetPath;
options.dataDims = dataDims;
options.dsetDimsChunk = dsetDimsChunk;
options.dsetDimsMax = dsetDimsMax;
options.h5Layout = h5Layout;
options.h5Type = std::move(h5Type);
options.resizeMode = resizeMode;
options.compression = getCompressionLevel(compression);
return writeDataset(data, options);
}
template<typename DataType>
DsetInfo writeDataset(const DataType & data,
std::string_view dsetPath,
hid::h5t & h5Type,
const OptDimsType & dataDims = std::nullopt,
std::optional<H5D_layout_t> h5Layout = std::nullopt,
const OptDimsType & dsetDimsChunk = std::nullopt,
const OptDimsType & dsetDimsMax = std::nullopt,
std::optional<ResizeMode> resizeMode = std::nullopt,
std::optional<unsigned int> compression = std::nullopt)
{
Options options;
options.linkPath = dsetPath;
options.dataDims = dataDims;
options.dsetDimsChunk = dsetDimsChunk;
options.dsetDimsMax = dsetDimsMax;
options.h5Layout = h5Layout;
options.h5Type = h5Type;
options.resizeMode = resizeMode;
options.compression = getCompressionLevel(compression);
return writeDataset(data, options);
}
template<typename DataType>
DsetInfo writeDataset(const DataType & data,
std::string_view dsetPath,
H5D_layout_t h5Layout,
const OptDimsType & dataDims = std::nullopt,
const OptDimsType & dsetDimsChunk = std::nullopt,
const OptDimsType & dsetDimsMax = std::nullopt,
std::optional<hid::h5t> h5Type = std::nullopt,
std::optional<ResizeMode> resizeMode = std::nullopt,
std::optional<unsigned int> compression = std::nullopt)
{
Options options;
options.linkPath = dsetPath;
options.dataDims = dataDims;
options.dsetDimsChunk = dsetDimsChunk;
options.dsetDimsMax = dsetDimsMax;
options.h5Layout = h5Layout;
options.h5Type = std::move(h5Type);
options.resizeMode = resizeMode;
options.compression = getCompressionLevel(compression);
return writeDataset(data, options);
}
template<typename DataType>
DsetInfo writeDataset_compact(const DataType &data, std::string_view dsetPath, const OptDimsType &dataDims = std::nullopt, std::optional<hid::h5t> h5Type = std::nullopt) {
Options options;
options.linkPath = dsetPath;
options.dataDims = dataDims;
options.h5Layout = H5D_COMPACT;
options.h5Type = std::move(h5Type);
options.compression = 0;
return writeDataset(data, options);
}
template<typename DataType>
DsetInfo
writeDataset_contiguous(const DataType &data, std::string_view dsetPath, const OptDimsType &dataDims = std::nullopt, std::optional<hid::h5t> h5Type = std::nullopt) {
Options options; // Get optional iterable should have three different return states, nullopt, empty or nonempty, ´,
options.linkPath = dsetPath;
options.dataDims = dataDims;
options.h5Layout = H5D_CONTIGUOUS;
options.h5Type = std::move(h5Type);
options.compression = 0;
return writeDataset(data, options);
}
template<typename DataType>
DsetInfo writeDataset_chunked(const DataType & data,
std::string_view dsetPath,
const OptDimsType & dataDims = std::nullopt,
const OptDimsType & dsetDimsChunk = std::nullopt,
const OptDimsType & dsetDimsMax = std::nullopt,
std::optional<hid::h5t> h5Type = std::nullopt,
std::optional<unsigned int> compression = std::nullopt) {
Options options; // Get optional iterable should have three different return states, nullopt, empty or nonempty, ´,
options.linkPath = dsetPath;
options.dataDims = dataDims;
options.dsetDimsChunk = dsetDimsChunk;
options.dsetDimsMax = dsetDimsMax;
options.h5Layout = H5D_CHUNKED;
options.h5Type = std::move(h5Type);
options.compression = getCompressionLevel(compression);
return writeDataset(data, options);
}
void writeSymbolicLink(std::string_view src_path, std::string_view tgt_path) {
hid::h5f file = openFileHandle();
h5pp::hdf5::writeSymbolicLink(file, src_path, tgt_path, plists);
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
void readDataset(DataType &data, const DataInfo &dataInfo, const DsetInfo &dsetInfo) const {
h5pp::hdf5::readDataset(data, dataInfo, dsetInfo, plists);
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
DataType readDataset(const DataInfo &dataInfo, const DsetInfo &dsetInfo) const {
DataType data;
readDataset(data, dataInfo, dsetInfo);
return data;
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
void readDataset(DataType &data, const DsetInfo &dsetInfo, const Options &options = Options()) const {
h5pp::hdf5::resizeData(data, dsetInfo);
auto dataInfo = h5pp::scan::getDataInfo(data, options);
readDataset(data, dataInfo, dsetInfo);
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
DataType readDataset(DsetInfo &dsetInfo, const Options &options = Options()) const {
DataType data;
readDataset(data, dsetInfo, options);
return data;
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
DataType readDataset(DsetInfo &dsetInfo, const DimsType &dataDims) const {
DataType data;
Options options;
options.dataDims = dataDims;
readDataset(data, dsetInfo, options);
return data;
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
void readDataset(DataType &data, const Options &options) const {
options.assertWellDefined();
auto dsetInfo = h5pp::scan::readDsetInfo(openFileHandle(), options, plists);
if(dsetInfo.dsetExists and not dsetInfo.dsetExists.value())
throw std::runtime_error(h5pp::format("Cannot read dataset [{}]: It does not exist", options.linkPath.value()));
h5pp::hdf5::resizeData(data, dsetInfo);
auto dataInfo = h5pp::scan::getDataInfo(data, options);
h5pp::hdf5::readDataset(data, dataInfo, dsetInfo, plists);
}
template<typename DataType>
void readDataset(DataType &data, std::string_view dsetPath, const OptDimsType &dataDims = std::nullopt) const {
Options options;
options.linkPath = dsetPath;
options.dataDims = dataDims;
readDataset(data, options);
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
DataType readDataset(std::string_view datasetPath, const OptDimsType &dataDims = std::nullopt) const {
DataType data;
readDataset(data, datasetPath, dataDims);
return data;
}
template<typename DataType>
void appendToDataset(DataType &data, const DataInfo &dataInfo, DsetInfo &dsetInfo, size_t axis) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
h5pp::hdf5::extendDataset(dsetInfo, dataInfo, axis);
h5pp::hdf5::writeDataset(data, dataInfo, dsetInfo, plists);
}
template<typename DataType>
void appendToDataset(DataType &data, DsetInfo &dsetInfo, size_t axis, const OptDimsType &dataDims = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
Options options;
options.dataDims = dataDims;
auto dataInfo = h5pp::scan::getDataInfo(data, options);
appendToDataset(data, dataInfo, dsetInfo, axis);
}
template<typename DataType>
DsetInfo appendToDataset(DataType &data, size_t axis, const Options &options = Options()) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
options.assertWellDefined();
auto dataInfo = h5pp::scan::getDataInfo(data, options);
auto dsetInfo = h5pp::scan::readDsetInfo(openFileHandle(), options, plists);
appendToDataset(data, dataInfo, dsetInfo, axis);
return dsetInfo;
}
template<typename DataType>
DsetInfo appendToDataset(DataType &data, std::string_view dsetPath, size_t axis, const OptDimsType &dataDims = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
Options options;
options.linkPath = dsetPath;
options.dataDims = dataDims;
return appendToDataset(data, axis, options);
}
/*
*
* Functions related to attributes
*
*/
void createAttribute(AttrInfo &attrInfo) { h5pp::hdf5::createAttribute(attrInfo); }
template<typename DataType>
AttrInfo createAttribute(const DataType &data, const Options &options) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to create attribute on read-only file [{}]", filePath.string()));
auto attrInfo = h5pp::scan::getAttrInfo(openFileHandle(), data, options, plists);
createAttribute(attrInfo);
return attrInfo;
}
template<typename DataType>
void createAttribute(const DataType &data, const DimsType &dataDims, std::string_view attrName, std::string_view linkPath) {
Options options;
options.linkPath = linkPath;
options.attrName = attrName;
options.dataDims = dataDims;
createAttribute(data, options);
}
template<typename DataType>
void writeAttribute(const DataType &data, const Options &options) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
options.assertWellDefined();
auto dataInfo = h5pp::scan::getDataInfo(data, options);
auto attrInfo = createAttribute(data, options);
h5pp::hdf5::writeAttribute(data, dataInfo, attrInfo);
}
template<typename DataType>
void writeAttribute(const DataType & data,
std::string_view attrName,
std::string_view linkPath,
const OptDimsType & dataDims = std::nullopt,
std::optional<hid::h5t> h5Type = std::nullopt) {
Options options;
options.linkPath = linkPath;
options.attrName = attrName;
options.dataDims = dataDims;
options.h5Type = std::move(h5Type);
writeAttribute(data, options);
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
void readAttribute(DataType &data, const Options &options) const {
options.assertWellDefined();
auto attrInfo = h5pp::scan::readAttrInfo(openFileHandle(), options, plists);
if(attrInfo.linkExists and not attrInfo.linkExists.value())
throw std::runtime_error(h5pp::format("Could not read attribute [{}] in link [{}]: "
"Link does not exist",
attrInfo.attrName.value(),
attrInfo.linkPath.value()));
if(attrInfo.attrExists and not attrInfo.attrExists.value())
throw std::runtime_error(h5pp::format("Could not read attribute [{}] in link [{}]: "
"Attribute does not exist",
attrInfo.attrName.value(),
attrInfo.linkPath.value()));
h5pp::hdf5::resizeData(data, attrInfo);
auto dataInfo = h5pp::scan::getDataInfo(data, options);
h5pp::hdf5::readAttribute(data, dataInfo, attrInfo);
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
void readAttribute(DataType &data, std::string_view attrName, std::string_view linkPath, const OptDimsType &dataDims = std::nullopt) const {
Options options;
options.linkPath = linkPath;
options.attrName = attrName;
options.dataDims = dataDims;
readAttribute(data, options);
}
template<typename DataType, typename = std::enable_if_t<not std::is_const_v<DataType>>>
[[nodiscard]] DataType readAttribute(std::string_view attrName, std::string_view linkPath, const OptDimsType &dataDims = std::nullopt) const {
DataType data;
readAttribute(data, attrName, linkPath, dataDims);
return data;
}
[[nodiscard]] inline std::vector<std::string> getAttributeNames(std::string_view linkPath) const {
return h5pp::hdf5::getAttributeNames(openFileHandle(), linkPath, std::nullopt, plists.linkAccess);
}
/*
*
*
* Functions related to tables
*
*
*/
TableInfo createTable(const hid::h5t & h5EntryType,
std::string_view tableName,
std::string_view tableTitle,
const std::optional<hsize_t> desiredChunkSize = std::nullopt,
const std::optional<unsigned int> desiredCompressionLevel = std::nullopt
) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
auto tableInfo = h5pp::scan::newTableInfo(h5EntryType, tableName, tableTitle, desiredChunkSize, desiredCompressionLevel);
h5pp::hdf5::createTable(openFileHandle(), tableInfo, plists);
return tableInfo;
}
template<typename DataType>
TableInfo appendTableEntries(const DataType &data, std::string_view tableName) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
auto info = h5pp::scan::getTableInfo(openFileHandle(), tableName, std::nullopt, plists);
if(not info.tableExists.value()) throw std::runtime_error(h5pp::format("Cannot append to table [{}]: it does not exist", tableName));
h5pp::hdf5::appendTableEntries(data, info);
return info;
}
void addTableEntriesFrom(const h5pp::TableInfo & srcInfo,
h5pp::TableInfo & tgtInfo,
TableSelection tableSelection,
const std::optional<hsize_t> desiredChunkSize = std::nullopt,
const std::optional<unsigned int> desiredCompressionLevel = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
if(not srcInfo.tableExists) throw std::runtime_error("Source table info has not been initialized");
if(not srcInfo.tableExists.value()) throw std::runtime_error("Source table does not exist");
if(not tgtInfo.tableExists or not tgtInfo.tableExists.value())
tgtInfo = createTable(srcInfo.tableType.value(), tgtInfo.tablePath.value(), srcInfo.tableTitle.value(), desiredChunkSize, desiredCompressionLevel);
hsize_t srcStartEntry = 0;
hsize_t tgtStartEntry = 0;
hsize_t numEntries = 0;
switch(tableSelection) {
case h5pp::TableSelection::ALL: numEntries = srcInfo.numRecords.value(); break;
case h5pp::TableSelection::FIRST:
numEntries = 1;
if(tgtInfo.numRecords.value() > 0) tgtStartEntry = tgtInfo.numRecords.value() - 1;
break;
case h5pp::TableSelection::LAST:
numEntries = 1;
if(tgtInfo.numRecords.value() > 0) tgtStartEntry = tgtInfo.numRecords.value() - 1;
if(srcInfo.numRecords.value() > 0) srcStartEntry = srcInfo.numRecords.value() - 1;
break;
}
h5pp::hdf5::addTableEntriesFrom(srcInfo, tgtInfo, srcStartEntry, tgtStartEntry, numEntries);
}
TableInfo addTableEntriesFrom(const h5pp::TableInfo & srcInfo,
std::string_view tgtTableName,
TableSelection tableSelection,
const std::optional<hsize_t> desiredChunkSize = std::nullopt,
const std::optional<unsigned int> desiredCompressionLevel = std::nullopt) {
auto tgtInfo = h5pp::scan::getTableInfo(openFileHandle(), tgtTableName, std::nullopt, plists);
addTableEntriesFrom(srcInfo, tgtInfo, tableSelection, desiredChunkSize, desiredCompressionLevel);
return tgtInfo;
}
template<typename h5x_src, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_src>>
TableInfo addTableEntriesFrom(const h5x_src & srcLocation,
std::string_view srcTableName,
std::string_view tgtTableName,
TableSelection tableSelection,
const std::optional<hsize_t> desiredChunkSize = std::nullopt,
const std::optional<unsigned int> desiredCompressionLevel = std::nullopt) {
auto srcInfo = h5pp::scan::getTableInfo(srcLocation, srcTableName, std::nullopt, plists);
return addTableEntriesFrom(srcInfo, tgtTableName, tableSelection, desiredChunkSize, desiredCompressionLevel);
}
void addTableEntriesFrom(const h5pp::TableInfo & srcInfo,
h5pp::TableInfo & tgtInfo,
hsize_t srcStartEntry,
hsize_t tgtStartEntry,
hsize_t numEntries,
const std::optional<hsize_t> desiredChunkSize = std::nullopt,
const std::optional<unsigned int> desiredCompressionLevel = std::nullopt) {
if(permission == h5pp::FilePermission::READONLY) throw std::runtime_error(h5pp::format("Attempted to write on read-only file [{}]", filePath.string()));
if(not srcInfo.tableExists) throw std::runtime_error("Source table info has not been initialized");
if(not srcInfo.tableExists.value()) throw std::runtime_error("Source table does not exist");
if(not tgtInfo.tableExists.value())
tgtInfo = createTable(srcInfo.tableType.value(), tgtInfo.tablePath.value(), srcInfo.tableTitle.value(), desiredChunkSize, desiredCompressionLevel);
h5pp::hdf5::addTableEntriesFrom(srcInfo, tgtInfo, srcStartEntry, tgtStartEntry, numEntries);
}
template<typename h5x_src, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_src>>
TableInfo addTableEntriesFrom(const h5pp::TableInfo & srcInfo,
std::string_view tgtTableName,
hsize_t srcStartEntry,
hsize_t tgtStartEntry,
hsize_t numEntries,
const std::optional<hsize_t> desiredChunkSize = std::nullopt,
const std::optional<unsigned int> desiredCompressionLevel = std::nullopt) {
auto tgtInfo = h5pp::scan::getTableInfo(openFileHandle(), tgtTableName, std::nullopt, plists);
addTableEntriesFrom(srcInfo, tgtInfo, srcStartEntry, tgtStartEntry, numEntries, desiredChunkSize, desiredCompressionLevel);
return tgtInfo;
}
template<typename h5x_src, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_src>>
TableInfo addTableEntriesFrom(const h5x_src & srcLocation,
std::string_view srcTableName,
std::string_view tgtTableName,
hsize_t srcStartIdx,
hsize_t tgtStartIdx,
hsize_t numRecords,
const std::optional<hsize_t> desiredChunkSize = std::nullopt,
const std::optional<unsigned int> desiredCompressionLevel = std::nullopt) {
auto srcInfo = h5pp::scan::getTableInfo(srcLocation, srcTableName, std::nullopt, plists);
return addTableEntriesFrom(srcInfo, tgtTableName, srcStartIdx, tgtStartIdx, numRecords, desiredChunkSize, desiredCompressionLevel);
}
template<typename DataType>
void readTableEntries(DataType &data, std::string_view tableName, std::optional<size_t> startEntry = std::nullopt, std::optional<size_t> numEntries = std::nullopt) const {
auto info = h5pp::scan::getTableInfo(openFileHandle(), tableName, std::nullopt, plists);
h5pp::hdf5::readTableEntries(data, info, startEntry, numEntries);
}
template<typename DataType>
DataType readTableEntries(std::string_view tablePath, std::optional<size_t> startEntry = std::nullopt, std::optional<size_t> numEntries = std::nullopt) const {
DataType data;
readTableEntries(data, tablePath, startEntry, numEntries);
return data;
}
template<typename DataType>
void readTableField(DataType & data,
std::string_view tablePath,
std::string_view fieldNames,
std::optional<size_t> startEntry = std::nullopt,
std::optional<size_t> numEntries = std::nullopt) const {
auto info = h5pp::scan::getTableInfo(openFileHandle(), tablePath, std::nullopt, plists);
h5pp::hdf5::readTableField(data, info, fieldNames, startEntry, numEntries);
}
template<typename DataType>
DataType readTableField(std::string_view tablePath,
std::string_view fieldName,
std::optional<size_t> startEntry = std::nullopt,
std::optional<size_t> numEntries = std::nullopt) const {
DataType data;
readTableField(data, tablePath, fieldName, startEntry, numEntries);
return data;
}
template<typename DataType>
void readTableField(DataType &data, std::string_view tablePath, std::string_view fieldNames, TableSelection tableSelection) const {
auto info = h5pp::scan::getTableInfo(openFileHandle(), tablePath, std::nullopt, plists);
hsize_t startEntry = 0;
hsize_t numEntries = 0;
switch(tableSelection) {
case h5pp::TableSelection::ALL:
startEntry = 0;
numEntries = info.numRecords.value();
break;
case h5pp::TableSelection::FIRST:
startEntry = 0;
numEntries = 1;
break;
case h5pp::TableSelection::LAST:
startEntry = info.numRecords.value() - 1;
numEntries = 1;
break;
}
h5pp::hdf5::readTableField(data, info, fieldNames, startEntry, numEntries);
}
template<typename DataType>
DataType readTableField(std::string_view tablePath, std::string_view fieldName, TableSelection tableSelection) const {
DataType data;
readTableField(data, tablePath, fieldName, tableSelection);
return data;
}
/*
*
*
* Functions for querying
*
*
*/
[[nodiscard]] int getDatasetRank(std::string_view datasetPath) const {
auto dataset = h5pp::hdf5::openLink<hid::h5d>(openFileHandle(), datasetPath);
return h5pp::hdf5::getRank(dataset);
}
[[nodiscard]] std::vector<hsize_t> getDatasetDimensions(std::string_view datasetPath) const {
auto dataset = h5pp::hdf5::openLink<hid::h5d>(openFileHandle(), datasetPath);
return h5pp::hdf5::getDimensions(dataset);
}
[[nodiscard]] std::optional<std::vector<hsize_t>> getDatasetMaxDimensions(std::string_view datasetPath) const {
auto dataset = h5pp::hdf5::openLink<hid::h5d>(openFileHandle(), datasetPath);
return h5pp::hdf5::getMaxDimensions(dataset);
}
[[nodiscard]] std::optional<std::vector<hsize_t>> getDatasetChunkDimensions(std::string_view datasetPath) const {
auto dataset = h5pp::hdf5::openLink<hid::h5d>(openFileHandle(), datasetPath);
return h5pp::hdf5::getChunkDimensions(dataset);
}
[[nodiscard]] bool linkExists(std::string_view link) const { return h5pp::hdf5::checkIfLinkExists(openFileHandle(), link, std::nullopt, plists.linkAccess); }
// [[nodiscard]] std::vector<std::string> getLinks(std::string_view root = "/", long maxDepth = 0) const {
// return h5pp::hdf5::getContentsOfLink<H5O_type_t::H5O_TYPE_UNKNOWN>(openFileHandle(), root, maxDepth, plists.linkAccess);
// }
//
// [[nodiscard]] std::vector<std::string> getDatasets(std::string_view root = "/", long maxDepth = 0) const {
// return h5pp::hdf5::getContentsOfLink<H5O_type_t::H5O_TYPE_DATASET>(openFileHandle(), root, maxDepth, plists.linkAccess);
// }
//
// [[nodiscard]] std::vector<std::string> getGroups(std::string_view root = "/", long maxDepth = 0) const {
// return h5pp::hdf5::getContentsOfLink<H5O_type_t::H5O_TYPE_GROUP>(openFileHandle(), root, maxDepth, plists.linkAccess);
// }
[[nodiscard]] std::vector<std::string> findLinks(std::string_view searchKey = "", std::string_view searchRoot = "/", long maxHits = -1, long maxDepth = -1) const {
return h5pp::hdf5::findLinks<H5O_TYPE_UNKNOWN>(openFileHandle(), searchKey, searchRoot, maxHits, maxDepth, plists.linkAccess);
}
[[nodiscard]] std::vector<std::string> findDatasets(std::string_view searchKey = "", std::string_view searchRoot = "/", long maxHits = -1, long maxDepth = -1) const {
return h5pp::hdf5::findLinks<H5O_TYPE_DATASET>(openFileHandle(), searchKey, searchRoot, maxHits, maxDepth, plists.linkAccess);
}
[[nodiscard]] std::vector<std::string> findGroups(std::string_view searchKey = "", std::string_view searchRoot = "/", long maxHits = -1, long maxDepth = -1) const {
return h5pp::hdf5::findLinks<H5O_TYPE_GROUP>(openFileHandle(), searchKey, searchRoot, maxHits, maxDepth, plists.linkAccess);
}
[[nodiscard]] DsetInfo getDatasetInfo(std::string_view dsetPath) const {
Options options;
options.linkPath = h5pp::util::safe_str(dsetPath);
return h5pp::scan::readDsetInfo(openFileHandle(), options, plists);
}
[[nodiscard]] AttrInfo getAttributeInfo(std::string_view linkPath, std::string_view attrName) const {
Options options;
options.linkPath = h5pp::util::safe_str(linkPath);
options.attrName = h5pp::util::safe_str(attrName);
return h5pp::scan::readAttrInfo(openFileHandle(), options, plists);
}
[[nodiscard]] TableInfo getTableInfo(std::string_view tablePath) const { return h5pp::scan::getTableInfo(openFileHandle(), tablePath, std::nullopt, plists); }
[[nodiscard]] TypeInfo getTypeInfoDataset(std::string_view dsetPath) const { return h5pp::hdf5::getTypeInfo(openFileHandle(), dsetPath, std::nullopt, plists.linkAccess); }
[[nodiscard]] TypeInfo getTypeInfoAttribute(std::string_view linkPath, std::string_view attrName) const {
return h5pp::hdf5::getTypeInfo(openFileHandle(), linkPath, attrName, std::nullopt, std::nullopt, plists.linkAccess);
}
[[nodiscard]] std::vector<TypeInfo> getTypeInfoAttributes(std::string_view linkPath) const {
return h5pp::hdf5::getTypeInfo_allAttributes(openFileHandle(), linkPath, std::nullopt, plists.linkAccess);
}
[[nodiscard]] bool fileIsValid() const { return h5pp::hdf5::fileIsValid(filePath); }
};
}