BmnRoot 26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Loading...
Searching...
No Matches
BmnFileReaderZLib.cxx
Go to the documentation of this file.
1// headers from this target
2#include "BmnFileReaderZLib.h"
3
4#include "BmnDefinitions.h"
5// std:: headers
6#include <cassert>
7#include <filesystem>
8// the main ZLib header
9#ifdef BMNCOMPRESSION_WITH_ZLIB
10#include <zlib.h>
11#else
12// If we build without the library, it would be find to use #pragma on the entire object, without push
13// and pop, but it's nothing too important for us here - just for simplicity I'm going with this def
15#endif // BMNCOMPRESSION_WITH_ZLIB
16
17// 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
18// ================== BmnFileReaderZLib public methods ==================
19// 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
20
21// ========== BmnIFileReaderInterface ==========
22
23BmnFileReaderZLib::BmnFileReaderZLib(const std::string& fileName)
24 : BmnIFileReader(BmnFileType::ZLib, fileName)
25 , fZlibStream(nullptr)
26 , fArchiveReadManager(*this)
27 , fNumberOfReadBytes(0ull)
29{}
30
32 : BmnIFileReader(BmnFileType::ZLib, std::move(fileName))
33 , fZlibStream(nullptr)
34 , fArchiveReadManager(*this)
35 , fNumberOfReadBytes(0ull)
37{}
38
39BmnFileReaderZLib::BmnFileReaderZLib(const std::filesystem::path& filePath)
40 : BmnIFileReader(BmnFileType::ZLib, filePath)
41 , fZlibStream(nullptr)
42 , fArchiveReadManager(*this)
43 , fNumberOfReadBytes(0ull)
45{}
46
47BmnFileReaderZLib::BmnFileReaderZLib(std::filesystem::path&& filePath)
48 : BmnIFileReader(BmnFileType::ZLib, std::move(filePath))
49 , fZlibStream(nullptr)
50 , fArchiveReadManager(*this)
51 , fNumberOfReadBytes(0ull)
53{}
54
56{
58 // another delete here as Close might go bad and still not break the code (in Release builds)
59#ifdef BMNCOMPRESSION_WITH_ZLIB
60 delete fZlibStream;
61#endif // BMNCOMPRESSION_WITH_ZLIB
62}
63
65{
66#ifdef BMNCOMPRESSION_WITH_ZLIB
67 /*
68 While we actually don't need so many comments and checks here, we are still performing them just to ensure
69 one doesn't make an accidental mistake - it might be easier to catch it
70 */
71 if (fZlibStream) {
72 LOG(error) << "ZLib stream is already valid!";
73 return;
74 }
75 if (!PerformStandardChecksBeforeOpening(processingFlags))
76 return;
77 fArchiveReadManager.Open(fFilePath, std::ios::in | std::ios::binary);
79 new z_stream_s{nullptr, 0u, 0u, nullptr, 0u, 0u, nullptr, nullptr, nullptr, nullptr, nullptr, 0, 0u, 0u};
80 // according to documentation, adding +32 enables auto-detection of headers, i.e., the stream will decide whether to
81 // use gzip or zlib formats
82 if (inflateInit2(fZlibStream, 15 + 32) != Z_OK) {
83 LOG(error) << "Failed to initialize ZLib stream! Reason: " << fZlibStream->msg << '\n';
84 inflateEnd(fZlibStream);
85 delete fZlibStream;
86 fZlibStream = nullptr;
87 fArchiveReadManager.Close();
88 }
89
90#else
91 throw std::runtime_error{"Trying to use ZLIB while BMN is not compiled with it!"};
92#endif // BMNCOMPRESSION_WITH_ZLIB
93}
94
96{
97#ifdef BMNCOMPRESSION_WITH_ZLIB
98 if (!fZlibStream)
99 return;
100 if (inflateEnd(fZlibStream) != Z_OK) {
101 LOG(fatal) << "Failed to free ZLib stream - possible huge memory leak! Failure reason: " << fZlibStream->msg
102 << '\n';
103 std::terminate();
104 }
105 delete fZlibStream;
106 fZlibStream = nullptr;
107 fArchiveReadManager.Close();
108 fNumberOfReadBytes = 0ull;
110#endif // BMNCOMPRESSION_WITH_ZLIB
111}
112
113int64_t BmnFileReaderZLib::Read(void* dataToFill, const int64_t sizeToFill)
114{
115#ifdef BMNCOMPRESSION_WITH_ZLIB
116 if (!IsStreamInGoodState())
117 return 0ll;
118 return fArchiveReadManager.Read(dataToFill, sizeToFill);
119#else
120 throw std::runtime_error{"Trying to use ZLIB while BMN is not compiled with it!"};
121#endif // BMNCOMPRESSION_WITH_ZLIB
122}
123
124int64_t BmnFileReaderZLib::Tell() const noexcept
125{
126 return fNumberOfReadBytes + fArchiveReadManager.GetCurrentOutputBufferPosition()
127 - fArchiveReadManager.GetTotalOutputBufferFilledSize();
128}
129
130void BmnFileReaderZLib::Seek(int64_t value)
131{
132#ifdef BMNCOMPRESSION_WITH_ZLIB
133 if (value < 0ll || (size_t)value == fNumberOfReadBytes)
134 return;
135 if (!IsStreamInGoodState()) {
136 LOG(error) << "Before calling `BmnFileReaderZLib::Seek` ensure to clear bad flags!\n";
137 return;
138 }
139 if (!fZlibStream) {
140 LOG(error) << "Before calling `BmnFileReaderZLib::Seek` ensure to open the stream!\n";
141 return;
142 }
143 if (!fArchiveReadManager.IsOpen()) {
144 LOG(error) << "Reading file missing while calling `BmnFileReaderZLib::Seek`\n";
145 return;
146 }
147 if ((size_t)value < (fNumberOfReadBytes - fArchiveReadManager.GetTotalOutputBufferFilledSize())) {
148 Close();
150 }
151 // in theory I could check IsOpen again for unexpected errors, but....
152 fArchiveReadManager.MoveToDecompressingLocation(value);
153#else
154 throw std::runtime_error{"Trying to use ZLIB while BMN is not compiled with it!"};
155#endif // BMNCOMPRESSION_WITH_ZLIB
156}
157
158bool BmnFileReaderZLib::IsGood() const noexcept
159{
160#ifdef BMNCOMPRESSION_WITH_ZLIB
162#else
163 return false;
164#endif // BMNCOMPRESSION_WITH_ZLIB
165}
166
167bool BmnFileReaderZLib::IsEOF() const noexcept
168{
169 return fArchiveReadManager.IsEOF();
170}
171
173{
174 // I don't like this method much
176 fArchiveReadManager.Clear();
177}
178
179bool BmnFileReaderZLib::IsOpen() const noexcept
180{
181 return fArchiveReadManager.IsOpen() && fZlibStream;
182}
183
184// ========== BmnIArchiveLib Interface ==========
185
187 const size_t sourceTotalSize,
188 size_t& numberOfReadBytes,
189 void* output,
190 const size_t outputTotalSize,
191 size_t& numberOfSetOutputBytes)
192{
193 if (!fZlibStream)
195#ifdef BMNCOMPRESSION_WITH_ZLIB
196 if (!IsStreamInGoodState())
198 fZlibStream->next_out = (Bytef*)output;
199 fZlibStream->avail_out = (uInt)outputTotalSize;
200 fZlibStream->total_out = 0u;
201 fZlibStream->next_in = (Bytef*)source;
202 fZlibStream->avail_in = (uInt)sourceTotalSize;
203 fZlibStream->total_in = 0u;
204 fLastReturnStatus = inflate(fZlibStream, Z_NO_FLUSH);
205 if (!IsStreamInGoodState())
207 numberOfReadBytes = (size_t)fZlibStream->total_in;
208 numberOfSetOutputBytes = (size_t)fZlibStream->total_out;
209 fNumberOfReadBytes += numberOfSetOutputBytes;
210 if (fLastReturnStatus == Z_STREAM_END)
213#else
214 throw std::runtime_error{"Trying to use ZLIB while BMN is not compiled with it!"};
215#endif // BMNCOMPRESSION_WITH_ZLIB
216}
217
219{
220#ifdef BMNCOMPRESSION_WITH_ZLIB
221 std::string strToReturn{};
222 if (fZlibStream && fZlibStream->msg)
223 strToReturn = std::string{fZlibStream->msg};
224 return strToReturn;
225#else
226 return std::string{"BMN NOT BUILT WITH ZLIB"};
227#endif // BMNCOMPRESSION_WITH_ZLIB
228}
229
231{
232 return false;
233}
234
236{
237 /*
238 In general with ZLib we could allow jumping while carefully building ZLib blocks. Still,
239 that would be allowed only in files written by our own encoder, while GZip would not produce
240 the same results. Thus, we don't allow jumps no matter what and if jumps are needed, we can
241 think about it and adapt later
242 */
243 LOG(warning) << "Calling `BmnFileReaderZLib::JumpTo` while the type doesn't allow jumping!\n";
244}
245
247{
248 return fNumberOfReadBytes;
249}
250
252{
253#ifdef BMNCOMPRESSION_WITH_ZLIB
254 if (!IsStreamInGoodState())
255 return true;
256 return fLastReturnStatus == Z_STREAM_END;
257#else
258 return true;
259#endif // BMNCOMPRESSION_WITH_ZLIB
260}
261
263{
264#ifdef BMNCOMPRESSION_WITH_ZLIB
265 return fLastReturnStatus >= 0;
266#else
267 return false;
268#endif // BMNCOMPRESSION_WITH_ZLIB
269}
270
271#ifndef BMNCOMPRESSION_WITH_ZLIB
273#endif // BMNCOMPRESSION_WITH_ZLIB
#define RESTORE_UNUSED_PARAM_WARNING
#define DISABLE_UNUSED_PARAM_WARNING
virtual bool JumpsAllowed() const noexcept override
virtual std::string GetLastUncompressErrorDescription() const noexcept override
virtual ~BmnFileReaderZLib() override
virtual void JumpTo(size_t) override
virtual size_t GetNumberOfDecompressedBytes() const noexcept override
virtual int64_t Read(void *dataToFill, const int64_t sizeToFill) override
virtual bool IsStreamInGoodState() const noexcept override
virtual int64_t Tell() const noexcept override
BmnFileReaderZLib(const std::string &fileName="")
virtual bool IsGood() const noexcept override
virtual bool IsEOF() const noexcept override
virtual void Open(const BmnBinaryFileProcessingOptions processingFlags=BmnBinaryFileProcessingOptions::ReadBinary) override
virtual bool IsOpen() const noexcept override
virtual void Close() noexcept override
virtual BmnFileStreamResults Uncompress(const void *source, const size_t sourceTotalSize, size_t &numberOfReadBytes, void *output, const size_t outputTotalSize, size_t &numberOfSetOutputBytes) override
BmnReaderCacheManager< 32ull *1024ull, 64ull *1024ull > fArchiveReadManager
virtual bool HasReachedTheEndOfStream() const noexcept override
virtual void Seek(int64_t value) override
virtual void ClearStateFlags() override
BmnIFileReader(const BmnFileType fileType, const std::string &fileName="")
std::filesystem::path fFilePath
bool PerformStandardChecksBeforeOpening(const BmnBinaryFileProcessingOptions processingFlags)
BmnBinaryFileProcessingOptions
Definition json.hpp:4446