File indexing completed on 2026-09-25 09:16:38
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "../H5Easy.hpp"
0012
0013 namespace H5Easy {
0014
0015 namespace detail {
0016
0017
0018 inline Exception error(const File& file, const std::string& path, const std::string& message) {
0019 std::ostringstream ss;
0020 ss << message << std::endl
0021 << "Path: " << path << std::endl
0022 << "Filename: " << file.getName() << std::endl;
0023 return Exception(ss.str());
0024 }
0025
0026
0027 inline Exception dump_error(File& file, const std::string& path) {
0028 if (file.getObjectType(path) == ObjectType::Dataset) {
0029 return error(file,
0030 path,
0031 "H5Easy: Dataset already exists, dump with H5Easy::DumpMode::Overwrite "
0032 "to overwrite (with an array of the same shape).");
0033 } else {
0034 return error(
0035 file,
0036 path,
0037 "H5Easy: path exists, but does not correspond to a Dataset. Dump not possible.");
0038 }
0039 }
0040
0041
0042 template <class T>
0043 inline DataSet initDataset(File& file,
0044 const std::string& path,
0045 const std::vector<size_t>& shape,
0046 const DumpOptions& options) {
0047 if (!file.exist(path)) {
0048 if (!options.compress() && !options.isChunked()) {
0049 return file.createDataSet<T>(path, DataSpace(shape), {}, {}, true);
0050 } else {
0051 std::vector<hsize_t> chunks(shape.begin(), shape.end());
0052 if (options.isChunked()) {
0053 chunks = options.getChunkSize();
0054 if (chunks.size() != shape.size()) {
0055 throw error(file, path, "H5Easy::dump: Incorrect rank ChunkSize");
0056 }
0057 }
0058 DataSetCreateProps props;
0059 props.add(Chunking(chunks));
0060 if (options.compress()) {
0061 props.add(Shuffle());
0062 props.add(Deflate(options.getCompressionLevel()));
0063 }
0064 return file.createDataSet<T>(path, DataSpace(shape), props, {}, true);
0065 }
0066 } else if (options.overwrite() && file.getObjectType(path) == ObjectType::Dataset) {
0067 DataSet dataset = file.getDataSet(path);
0068 if (dataset.getDimensions() != shape) {
0069 throw error(file, path, "H5Easy::dump: Inconsistent dimensions");
0070 }
0071 return dataset;
0072 }
0073 throw dump_error(file, path);
0074 }
0075
0076
0077 template <class T>
0078 inline DataSet initScalarDataset(File& file,
0079 const std::string& path,
0080 const T& data,
0081 const DumpOptions& options) {
0082 if (!file.exist(path)) {
0083 return file.createDataSet<T>(path, DataSpace::From(data), {}, {}, true);
0084 } else if (options.overwrite() && file.getObjectType(path) == ObjectType::Dataset) {
0085 DataSet dataset = file.getDataSet(path);
0086 if (dataset.getElementCount() != 1) {
0087 throw error(file, path, "H5Easy::dump: Existing field not a scalar");
0088 }
0089 return dataset;
0090 }
0091 throw dump_error(file, path);
0092 }
0093
0094 template <class File, class F>
0095 auto apply_attr_func_impl(File& file, const std::string& path, F f) {
0096 auto type = file.getObjectType(path);
0097 if (type == ObjectType::Group) {
0098 auto group = file.getGroup(path);
0099 return f(group);
0100 } else if (type == ObjectType::Dataset) {
0101 auto dataset = file.getDataSet(path);
0102 return f(dataset);
0103 } else {
0104 throw error(file, path, "path is not the root, a group or a dataset.");
0105 }
0106 }
0107
0108 template <class F>
0109 auto apply_attr_func(const H5Easy::File& file, const std::string& path, F f) {
0110 return apply_attr_func_impl(file, path, f);
0111 }
0112
0113 template <class F>
0114 auto apply_attr_func(H5Easy::File& file, const std::string& path, F f) {
0115 return apply_attr_func_impl(file, path, f);
0116 }
0117
0118
0119 template <class T>
0120 inline Attribute initAttribute(File& file,
0121 const std::string& path,
0122 const std::string& key,
0123 const std::vector<size_t>& shape,
0124 const DumpOptions& options) {
0125 auto get_attribute = [&](auto& obj) {
0126 if (!obj.hasAttribute(key)) {
0127 return obj.template createAttribute<T>(key, DataSpace(shape));
0128 } else if (options.overwrite()) {
0129 Attribute attribute = obj.getAttribute(key);
0130 DataSpace dataspace = attribute.getSpace();
0131 if (dataspace.getDimensions() != shape) {
0132 throw error(file, path, "H5Easy::dumpAttribute: Inconsistent dimensions");
0133 }
0134 return attribute;
0135 }
0136 throw error(file,
0137 path,
0138 "H5Easy: Attribute exists, overwrite with H5Easy::DumpMode::Overwrite.");
0139 };
0140
0141 if (!file.exist(path)) {
0142 throw error(file, path, "H5Easy::dumpAttribute: path does not exist");
0143 }
0144
0145 return apply_attr_func(file, path, get_attribute);
0146 }
0147
0148
0149 template <class T>
0150 inline Attribute initScalarAttribute(File& file,
0151 const std::string& path,
0152 const std::string& key,
0153 const T& data,
0154 const DumpOptions& options) {
0155 auto get_attribute = [&](auto& obj) {
0156 if (!obj.hasAttribute(key)) {
0157 return obj.template createAttribute<T>(key, DataSpace::From(data));
0158 } else if (options.overwrite()) {
0159 Attribute attribute = obj.getAttribute(key);
0160 DataSpace dataspace = attribute.getSpace();
0161 if (dataspace.getElementCount() != 1) {
0162 throw error(file, path, "H5Easy::dumpAttribute: Existing field not a scalar");
0163 }
0164 return attribute;
0165 }
0166 throw error(file,
0167 path,
0168 "H5Easy: Attribute exists, overwrite with H5Easy::DumpMode::Overwrite.");
0169 };
0170
0171 if (!file.exist(path)) {
0172 throw error(file, path, "H5Easy::dumpAttribute: path does not exist");
0173 }
0174
0175 apply_attr_func(file, path, get_attribute);
0176 }
0177
0178 }
0179 }