TRIQS/h5 1.3.0
C++ interface to HDF5
Loading...
Searching...
No Matches
file.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-2024 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Thomas Hahn, Olivier Parcollet, Nils Wentzell
16
22#include "./file.hpp"
23
24#include <hdf5.h>
25#include <hdf5_hl.h>
26
27#include <stdexcept>
28
29using namespace std::string_literals;
30
31// throw an exception with a given message if a condition is not met
32#define CHECK_OR_THROW(Cond, Mess) \
33 if (!(Cond)) throw std::runtime_error("Error in h5::file: "s + (Mess));
34
35namespace h5 {
36
37 file::file(const char *name, char mode) {
38 switch (mode) {
39 // open existing file in read only mode
40 case 'r': id = H5Fopen(name, H5F_ACC_RDONLY, H5P_DEFAULT); break;
41 // create new or overwrite existing file in read-write mode
42 case 'w': id = H5Fcreate(name, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); break;
43 // create new or append to exisiting file in read-write mode
44 case 'a': {
45 // turn off error handling
46 herr_t (*old_func)(void *) = nullptr;
47 void *old_client_data = nullptr;
48 H5Eget_auto1(&old_func, &old_client_data);
49 H5Eset_auto1(nullptr, nullptr);
50
51 // this may fail
52 id = H5Fcreate(name, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
53
54 // turn on error handling
55 H5Eset_auto1(old_func, old_client_data);
56
57 // open in read-write mode if creation failed
58 if (id < 0) id = H5Fopen(name, H5F_ACC_RDWR, H5P_DEFAULT);
59 break;
60 }
61 // create new file in read-write mode if the file does not exist yet
62 case 'e': id = H5Fcreate(name, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT); break;
63 default: throw std::runtime_error("File mode is not one of r, w, a, e");
64 }
65
66 // throw an exception if opening/creating the file failed
67 if (id < 0) throw std::runtime_error("Opening/Creating the file "s + name + " failed");
68 }
69
70 // same function is used in h5::group
71 std::string file::name() const {
72 // get length of the name
73 ssize_t size = H5Fget_name(id, nullptr, 1);
74
75 // reserve a buffer and get name
76 std::vector<char> buf(size + 1, 0x00);
77 H5Fget_name(id, buf.data(), size + 1);
78
79 // return string
80 std::string res = "";
81 res.append(&(buf.front()));
82 return res;
83 }
84
85 void file::flush() {
86 if (not is_valid()) return;
87 auto err = H5Fflush(id, H5F_SCOPE_GLOBAL);
88 CHECK_OR_THROW((err >= 0), "Flushing the file failed");
89 }
90
92 // create a file access property list
93 proplist fapl = H5Pcreate(H5P_FILE_ACCESS);
94 CHECK_OR_THROW((fapl >= 0), "Creating the fapl failed");
95
96 // set the file driver to use the `H5FD_CORE` driver
97 auto err = H5Pset_fapl_core(fapl, (size_t)(64 * 1024), false);
98 CHECK_OR_THROW((err >= 0), "Setting the core file driver in fapl failed");
99
100 // create a buffered memory file
101 this->id = H5Fcreate("MemoryBuffer", 0, H5P_DEFAULT, fapl);
102 CHECK_OR_THROW((this->is_valid()), "Creating a buffered memory file failed");
103 }
104
105 file::file(const std::byte *buf, size_t size) {
106 // create a file access property list
107 proplist fapl = H5Pcreate(H5P_FILE_ACCESS);
108 CHECK_OR_THROW((fapl >= 0), "Creating the fapl failed");
109
110 // set the file driver to use the `H5FD_CORE` driver
111 auto err = H5Pset_fapl_core(fapl, (size_t)(64 * 1024), false);
112 CHECK_OR_THROW((err >= 0), "Setting the core file driver in fapl failed");
113
114 // set the initial file image to the given memory buffer
115 err = H5Pset_file_image(fapl, (void *)buf, size);
116 CHECK_OR_THROW((err >= 0), "Setting the file image to a given memory buffer failed");
117
118 // create a buffered memory file
119 this->id = H5Fopen("MemoryBuffer", H5F_ACC_RDWR, fapl);
120 CHECK_OR_THROW((this->is_valid()), "Creating a buffered memory file failed");
121 }
122
123 std::vector<std::byte> file::as_buffer() const {
124 // flush the file
125 auto f = hid_t(*this);
126 auto err = H5Fflush(f, H5F_SCOPE_GLOBAL);
127 CHECK_OR_THROW((err >= 0), "Flushing the buffered memory file failed");
128
129 // retrieve size of the file image
130 ssize_t image_len = H5Fget_file_image(f, nullptr, (size_t)0);
131 CHECK_OR_THROW((image_len > 0), "Getting the file image size failed");
132
133 // create buffer and copy file image to it
134 std::vector<std::byte> buf(image_len, std::byte{0});
135 ssize_t bytes_read = H5Fget_file_image(f, (void *)buf.data(), (size_t)image_len);
136 CHECK_OR_THROW(bytes_read == image_len, "Writing file image to buffer failed");
137
138 return buf;
139 }
140
141} // namespace h5
std::string name() const
Get the name of the file.
Definition file.cpp:71
std::vector< std::byte > as_buffer() const
Get a copy of the associated byte buffer.
Definition file.cpp:123
void flush()
Flush the file by calling H5Fflush.
Definition file.cpp:85
file()
Default constructor creates a buffered memory file.
Definition file.cpp:91
A generic handle for HDF5 objects.
Definition object.hpp:49
bool is_valid() const
Ensure that the wrapped HDF5 ID is valid (by calling H5Iis_valid).
Definition object.cpp:116
Provides a handle to an HDF5 file.
int64_t hid_t
ID type used in HDF5.
Definition utils.hpp:45