BmnRoot 26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
BmnFileReaderZStd.h
Go to the documentation of this file.
1#pragma once
2#ifndef BmnFileReaderZStd_h
3#define BmnFileReaderZStd_h
4
5// headers from this target
7#include "BmnIFileReader.h"
9
10// keeping it only as a declaration so one would be able to include the header even if <zstd.h> is not in the include
11// list
12struct ZSTD_DCtx_s;
13
14/*
15 * A class responsible for reading compressed ZSTD files. The primary goal of this class is to read
16 * large compressed files (possibly a few GB) such as those for raw data. If smaller files are used,
17 * there might be better ways to compress/uncompress data (e.g., with dictionaries), but such cases
18 * were not considered while preparing this class - if needed, add a new one that handles such cases
19 * or upgrade this.
20 * It's advisable to allocate this class on the heap as internally it uses big std::array
21 * @warning Using this class directly can result in throws if the zstd library is not found during compilation.
22 * Therefore, it's always advisable to obtain appropriate read objects through
23 * `BmnCompressionCreateNewSuitableReaderForAFile`
24 */
26 : public BmnIFileReader
27 , public BmnIArchiveLibRead
28{
29 public:
30 /*
31 * A standard constructor that sets a path to the input binary (ZSTD) file
32 * @note The constructor will not check whether the file actually exists
33 * @param fileName A path (most likely relative) to the input binary (ZSTD) file
34 * @warning If using relative paths, be very careful about currently-working directory as it might
35 * be something unexpected based on the directory that initalized an application
36 */
37 explicit BmnFileReaderZStd(const std::string& fileName = "");
38
39 /*
40 * A standard constructor that sets a path to the input binary (ZSTD) file
41 * @note The constructor will not check whether the file actually exists
42 * @param fileName A path (most likely relative) to the input binary (ZSTD) file
43 * @warning If using relative paths, be very careful about currently-working directory as it might
44 * be something unexpected based on the directory that initalized an application
45 */
46 explicit BmnFileReaderZStd(std::string&& fileName);
47
48 /*
49 * A standard constructor that sets a path to the input binary (ZSTD) file
50 * @note The constructor will not check whether the file actually exists
51 * @param filePath A path to the input binary (ZSTD) file
52 * @warning If using relative paths, be very careful about currently-working directory as it might
53 * be something unexpected based on the directory that initalized an application
54 */
55 explicit BmnFileReaderZStd(const std::filesystem::path& filePath);
56
57 /*
58 * A standard constructor that sets a path to the input binary (ZSTD) file
59 * @note The constructor will not check whether the file actually exists
60 * @param filePath A path to the input binary (ZSTD) file
61 * @warning If using relative paths, be very careful about currently-working directory as it might
62 * be something unexpected based on the directory that initalized an application
63 */
64 explicit BmnFileReaderZStd(std::filesystem::path&& filePath);
65
66 // Closes the stream while destroying the instance
67 virtual ~BmnFileReaderZStd() override;
71 BmnFileReaderZStd& operator=(BmnFileReaderZStd&&) noexcept = delete;
72
73 // ========== BmnIFileReaderInterface ==========
74
75 /*
76 * Opens a file for reading. The path of the file should be provided before calling this method
77 * @param processingFlags A flag that tells us how to open the file for reading. This class only supports
78 * `ReadBinary` flag
79 */
80 virtual void Open(
82
83 /*
84 * Closes the stream and resets all internal data. After calling `Close`, it's safe to reopen using the same
85 * instance of this class
86 */
87 virtual void Close() noexcept override;
88
89 /*
90 * Reads and decompresses the data while still managing caching for efficiency.
91 * @param dataToFill A buffer that will be filled with uncompressed data
92 * @param sizeToFill A number of bytes that will be filled in `dataToFill`
93 * @return A number of bytes that were filled in `dataToFill`. This value should almost always be the same as
94 * `sizeToFill` except when the end of the stream is reached (only if the user asked for more data than possible)
95 */
96 virtual int64_t Read(void* dataToFill, const int64_t sizeToFill) override;
97
98 /*
99 * A method that tells us what's next to read
100 * @return A position of the next byte that should be read
101 */
102 [[nodiscard]] virtual int64_t Tell() const noexcept override;
103
104 /*
105 * A method that allows us to go to another place in the file (uncompressed data) and read from that place.
106 * This method is NOT EFFICIENT as it still needs to uncompress data to reach the needed place!
107 * @param value A position in uncompressed data to which one wants to move before the next read
108 */
109 virtual void Seek(int64_t value) override;
110
111 /*
112 * Checks whether the reading stream is good
113 * @return 'true' if no decompression error has occurred and the input-file stream is good, or 'false' otherwise
114 */
115 [[nodiscard]] virtual bool IsGood() const noexcept override;
116
117 /*
118 * Check if we have reached the file. This will tell us if we have reached EOF in the uncompressed data, not
119 * in the file itself. That is, the file might be at EOF, while this method returns will return true as cache
120 * still has some data
121 * @return 'true' if both file and internal cache are completely read, 'false' otherwise
122 */
123 [[nodiscard]] virtual bool IsEOF() const noexcept override;
124
125 /*
126 * A method that clears bad flags after an error has occurred. Just calling this error will most likely
127 * not solve the problem, and you will get an error again in the next read. That is, before calling `Read`,
128 * remove the previous error source
129 */
130 virtual void ClearStateFlags() override;
131
132 /*
133 * @return 'true' if the input stream is open, or 'false' if not
134 */
135 [[nodiscard]] virtual bool IsOpen() const noexcept override;
136
137 // ========== BmnIArchiveLib Interface ==========
138
139 /*
140 * A method that is called to uncompress ZSTD data
141 * @param source A pointer to a buffer with the subsequent compressed data that should be uncompressed
142 * @param sourceTotalSize A number of bytes available in the source buffer
143 * @param numberOfReadBytes A number of bytes that were consumed by ZSTD while compressing. This value will be set.
144 * @param output A pointer to a buffer that will be filled with uncompressed data
145 * @param outputTotalSize A number of bytes that may be filled in the output buffer
146 * @param numberOfSetOutputBytes A number of bytes that were set while decompressing. This value will be set.
147 * @return There are a few options:
148 * 1. `BmnFileStreamResults::FileNotOpen` if the stream is not open
149 * 2. `BmnFileStreamResults::TryingToReadBadStream` if the stream previously hit an error while it wasn't
150 * cleared later
151 * 3. `BmnFileStreamResults::UnexpectedFail` ZSTD failed while decompressing
152 * 4. `BmnFileStreamResults::ReachedEOF` ZSTD reached the end of frame (in our case file)
153 * 5. `BmnFileStreamResults::Success` ZSTD successfully uncompressed the package
154 */
155 virtual BmnFileStreamResults Uncompress(const void* source,
156 const size_t sourceTotalSize,
157 size_t& numberOfReadBytes,
158 void* output,
159 const size_t outputTotalSize,
160 size_t& numberOfSetOutputBytes) override;
161
162 /*
163 * If an error occurred while decompressing, this method can be called to obtain a description of the error
164 * @return A description of an error that occurred while decompressing, or an empty string if no such error happened
165 */
166 [[nodiscard]] virtual std::string GetLastUncompressErrorDescription() const noexcept override;
167
168 /*
169 * @return 'false' - this class doesn't allow jumping
170 */
171 [[nodiscard]] virtual bool JumpsAllowed() const noexcept override;
172
173 /*
174 * This method will do nothing but print an error. ZSTD doesn't allow us to efficiently jump over the compressed
175 * file
176 */
177 virtual void JumpTo(size_t) override;
178
179 /*
180 * A method that tells us how many uncompressed bytes were read from an input file
181 * @return A number of uncompressed bytes that passed through the ZSTD
182 */
183 [[nodiscard]] virtual size_t GetNumberOfDecompressedBytes() const noexcept override;
184
185 /*
186 * A method that checks whether there's something left in ZSTD cache, i.e., if we should
187 * continue reading even though we have reached the end of the stream. If stream is in a
188 * bad state, it will also return as EOF
189 * @return 'true' if the underlying stream has a bad state or empty internal cache, or 'false' otherwise
190 */
191 [[nodiscard]] virtual bool HasReachedTheEndOfStream() const noexcept override;
192
193 /*
194 * A method that tells us whether an underlying ZSTD stream reported an error or not
195 * @return 'true' if previous read calls didn't report an error, otherwise 'false'
196 */
197 [[nodiscard]] virtual bool IsStreamInGoodState() const noexcept override;
198
199 // ========== BmnFileReaderZStd inlines ==========
200
201 [[nodiscard]] inline ZSTD_DCtx_s* GetUnderlyingLibraryHandler() const noexcept;
202 [[nodiscard]] inline size_t GetLastReadReturnValue() const noexcept;
203 // Get number of read bytes via `GetNumberOfDecompressedBytes`
204 // No need to expose `fArchiveReadManager`
205
206 private:
207 ZSTD_DCtx_s* fZstdStream;
208 BmnReaderCacheManager<32ull * 1024ull, 64ull * 1024ull> fArchiveReadManager;
209 size_t fNumberOfReadBytes;
210 size_t fLastReadReturnValue; // possibly carries information about an error that occurred
211};
212
213// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
214// ================== BmnFileReaderZStd inline methods ==================
215// o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
216
217ZSTD_DCtx_s* BmnFileReaderZStd::GetUnderlyingLibraryHandler() const noexcept
218{
219 return fZstdStream;
220}
221
222size_t BmnFileReaderZStd::GetLastReadReturnValue() const noexcept
223{
225}
226
227#endif // BmnFileReaderZStd_h
virtual void Seek(int64_t value) override
virtual BmnFileStreamResults Uncompress(const void *source, const size_t sourceTotalSize, size_t &numberOfReadBytes, void *output, const size_t outputTotalSize, size_t &numberOfSetOutputBytes) override
BmnFileReaderZStd(const std::filesystem::path &filePath)
virtual bool IsGood() const noexcept override
size_t GetLastReadReturnValue() const noexcept
ZSTD_DCtx_s * GetUnderlyingLibraryHandler() const noexcept
virtual void Close() noexcept override
BmnReaderCacheManager< 32ull *1024ull, 64ull *1024ull > fArchiveReadManager
virtual void ClearStateFlags() override
virtual size_t GetNumberOfDecompressedBytes() const noexcept override
BmnFileReaderZStd(std::filesystem::path &&filePath)
virtual bool IsStreamInGoodState() const noexcept override
BmnFileReaderZStd(std::string &&fileName)
virtual int64_t Tell() const noexcept override
virtual std::string GetLastUncompressErrorDescription() const noexcept override
virtual void JumpTo(size_t) override
virtual bool HasReachedTheEndOfStream() const noexcept override
BmnFileReaderZStd & operator=(const BmnFileReaderZStd &)=delete
virtual int64_t Read(void *dataToFill, const int64_t sizeToFill) override
BmnFileReaderZStd(const std::string &fileName="")
virtual bool IsOpen() const noexcept override
ZSTD_DCtx_s * fZstdStream
virtual ~BmnFileReaderZStd() override
BmnFileReaderZStd(BmnFileReaderZStd &&) noexcept=delete
virtual bool IsEOF() const noexcept override
BmnFileReaderZStd(const BmnFileReaderZStd &)=delete
virtual void Open(const BmnBinaryFileProcessingOptions processingFlags=BmnBinaryFileProcessingOptions::ReadBinary) override
virtual bool JumpsAllowed() const noexcept override
BmnBinaryFileProcessingOptions
Definition json.hpp:4446