Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-25 09:16:38

0001 /*
0002  *  Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
0003  *
0004  *  Distributed under the Boost Software License, Version 1.0.
0005  *    (See accompanying file LICENSE_1_0.txt or copy at
0006  *          http://www.boost.org/LICENSE_1_0.txt)
0007  *
0008  */
0009 #pragma once
0010 
0011 #include "../H5Easy.hpp"
0012 
0013 namespace H5Easy {
0014 
0015 namespace detail {
0016 
0017 // Generate error-stream and return "Exception" (not yet thrown).
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 // Generate specific dump error
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 // get a opened DataSet: nd-array
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 // get a opened DataSet: scalar
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 // get a opened Attribute: nd-array
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 // get a opened Attribute: scalar
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 }  // namespace detail
0179 }  // namespace H5Easy