BmnRoot
26.10.0-18-g4e3414f9
Software framework of the BM@N experiment
Toggle main menu visibility
Loading...
Searching...
No Matches
BmnFileReaderXzLzma.cxx
Go to the documentation of this file.
1
// headers from this target
2
#include "BmnFileReaderXzLzma.h"
3
4
#include "BmnDefinitions.h"
5
// std:: headers
6
#include <cassert>
7
#include <filesystem>
8
// the main XZ LZMA2 header
9
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
10
// This header holds various smaller headers and a few definitions - it's best to only add that header
11
#include <lzma.h>
12
#else
13
// If we build without the library, it would be find to use #pragma on the entire object, without push
14
// and pop, but it's nothing too important for us here - just for simplicity I'm going with this def
15
DISABLE_UNUSED_PARAM_WARNING
16
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
17
18
/*
19
* A wrapper around lzma_stream as it may not be forward declared due to the way devs wrote
20
* its definition. While we could use `void*` in `BmnFileReaderXzLzma.hpp`, this is more readable
21
*/
22
struct
LzmaContext
23
{
24
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
25
LzmaContext
()
26
:
fLzmaStream
(LZMA_STREAM_INIT)
27
{}
28
~LzmaContext
() { lzma_end(&
fLzmaStream
); }
29
30
public
:
31
lzma_stream
fLzmaStream
;
32
#else
33
LzmaContext
() =
default
;
34
~LzmaContext
() =
default
;
35
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
36
};
37
38
// 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
39
// ================== static function declaration ==================
40
// 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
41
42
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
43
44
/*
45
* A method that can be used for obtaining a string based on an error ID return by some LZMA function
46
* @param errorID An error ID return by a LZMA function
47
*/
48
[[nodiscard]]
static
std::string
GetLzmaReturnTypeDescription
(
const
int32_t errorID)
noexcept
;
49
/*
50
* A method that can be used for obtaining a string based on a lzma_ret value
51
* @param lzmaReturnEnum An enum-type returned by a LZMA function
52
*/
53
[[nodiscard]]
static
std::string
GetLzmaReturnTypeDescription
(
const
lzma_ret lzmaReturnEnum)
noexcept
;
54
55
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
56
57
// 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 o
58
// ================== BmnFileReaderXzLzma public methods ==================
59
// 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 o
60
61
size_t
BmnFileReaderXzLzma::sMaximalAllowedMemory
= 256ull * 1024ull * 1024ull;
62
63
BmnFileReaderXzLzma::BmnFileReaderXzLzma
(
const
std::string& fileName)
64
:
BmnIFileReader
(
BmnFileType
::
XZ_LZMA
, fileName)
65
,
fLzmaStream
(nullptr)
66
,
fArchiveReadManager
(*this)
67
,
fNumberOfReadBytes
(0ull)
68
,
fLastReturnStatus
(0)
69
{}
70
71
BmnFileReaderXzLzma::BmnFileReaderXzLzma
(std::string&& fileName)
72
:
BmnIFileReader
(
BmnFileType
::
XZ_LZMA
,
std
::move(fileName))
73
,
fLzmaStream
(nullptr)
74
,
fArchiveReadManager
(*this)
75
,
fNumberOfReadBytes
(0ull)
76
,
fLastReturnStatus
(0)
77
{}
78
79
BmnFileReaderXzLzma::BmnFileReaderXzLzma
(
const
std::filesystem::path& filePath)
80
:
BmnIFileReader
(
BmnFileType
::
XZ_LZMA
, filePath)
81
,
fLzmaStream
(nullptr)
82
,
fArchiveReadManager
(*this)
83
,
fNumberOfReadBytes
(0ull)
84
,
fLastReturnStatus
(0)
85
{}
86
87
BmnFileReaderXzLzma::BmnFileReaderXzLzma
(std::filesystem::path&& filePath)
88
:
BmnIFileReader
(
BmnFileType
::
XZ_LZMA
,
std
::move(filePath))
89
,
fLzmaStream
(nullptr)
90
,
fArchiveReadManager
(*this)
91
,
fNumberOfReadBytes
(0ull)
92
,
fLastReturnStatus
(0)
93
{}
94
95
BmnFileReaderXzLzma::~BmnFileReaderXzLzma
()
96
{
97
BmnFileReaderXzLzma::Close
();
98
}
99
100
void
BmnFileReaderXzLzma::Open
(
const
BmnBinaryFileProcessingOptions
processingFlags)
101
{
102
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
103
/*
104
While we actually don't need so many comments and checks here, we are still performing them just to ensure
105
one doesn't make an accidental mistake - it might be easier to catch it
106
*/
107
if
(
fLzmaStream
) {
108
LOG(error) <<
"LZMA stream is already valid!"
;
109
return
;
110
}
111
if
(!
PerformStandardChecksBeforeOpening
(processingFlags))
112
return
;
113
fArchiveReadManager
.Open(
fFilePath
, std::ios::in | std::ios::binary);
114
fLzmaStream
=
new
LzmaContext
{};
115
// we are looking for .xz files, not raw lzma so `lzma_stream_decoder` is find, no need to use `lzma_auto_decoder`
116
lzma_ret aReturnStatus = lzma_stream_decoder(&
fLzmaStream
->fLzmaStream,
sMaximalAllowedMemory
, LZMA_CONCATENATED);
117
if
(aReturnStatus != lzma_ret::LZMA_OK) {
118
fArchiveReadManager
.Close();
119
delete
fLzmaStream
;
120
fLzmaStream
=
nullptr
;
121
LOG(error) <<
"Failed to initialize lzma stream! Reason: "
<<
GetLzmaReturnTypeDescription
(aReturnStatus)
122
<<
'\n'
;
123
}
124
#else
125
throw
std::runtime_error{
"Trying to use LZMA while BMN is not compiled with it!"
};
126
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
127
}
128
129
void
BmnFileReaderXzLzma::Close
() noexcept
130
{
131
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
132
if
(!
fLzmaStream
)
133
return
;
134
// while lzma.h tells us we can reuse the stream, we could save some time that we will spend for allocating new
135
// buffers, but it's a safer and less error-prone approach - thus, I'm deleting buffers while closing
136
delete
fLzmaStream
;
137
fLzmaStream
=
nullptr
;
138
fArchiveReadManager
.Close();
139
fNumberOfReadBytes
= 0ull;
140
fLastReturnStatus
= 0;
141
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
142
}
143
144
int64_t
BmnFileReaderXzLzma::Read
(
void
* dataToFill,
const
int64_t sizeToFill)
145
{
146
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
147
if
(!
IsStreamInGoodState
())
148
return
0ll;
149
return
fArchiveReadManager
.Read(dataToFill, sizeToFill);
150
#else
151
throw
std::runtime_error{
"Trying to use LZMA while BMN is not compiled with it!"
};
152
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
153
}
154
155
int64_t
BmnFileReaderXzLzma::Tell
() const noexcept
156
{
157
return
fNumberOfReadBytes
+
fArchiveReadManager
.GetCurrentOutputBufferPosition()
158
-
fArchiveReadManager
.GetTotalOutputBufferFilledSize();
159
}
160
161
void
BmnFileReaderXzLzma::Seek
(int64_t value)
162
{
163
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
164
if
(value < 0ll || (
size_t
)value ==
fNumberOfReadBytes
)
165
return
;
166
if
(!
IsStreamInGoodState
()) {
167
LOG(error) <<
"Before calling `BmnFileReaderXzLzma::Seek` ensure to clear bad flags!\n"
;
168
return
;
169
}
170
if
(!
fLzmaStream
) {
171
LOG(error) <<
"Before calling `BmnFileReaderXzLzma::Seek` ensure to open the stream!\n"
;
172
return
;
173
}
174
if
(!
fArchiveReadManager
.IsOpen()) {
175
LOG(error) <<
"Reading file missing while calling `BmnFileReaderXzLzma::Seek`\n"
;
176
return
;
177
}
178
if
((
size_t
)value < (
fNumberOfReadBytes
-
fArchiveReadManager
.GetTotalOutputBufferFilledSize())) {
179
Close
();
180
Open
(
BmnBinaryFileProcessingOptions::ReadBinary
);
181
}
182
// in theory I could check IsOpen again for unexpected errors, but....
183
fArchiveReadManager
.MoveToDecompressingLocation(value);
184
#else
185
throw
std::runtime_error{
"Trying to use LZMA while BMN is not compiled with it!"
};
186
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
187
}
188
189
bool
BmnFileReaderXzLzma::IsGood
() const noexcept
190
{
191
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
192
return
fLzmaStream
&&
IsStreamInGoodState
() &&
fArchiveReadManager
.IsGood();
193
#else
194
return
false
;
195
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
196
}
197
198
bool
BmnFileReaderXzLzma::IsEOF
() const noexcept
199
{
200
return
fArchiveReadManager
.IsEOF();
201
}
202
203
void
BmnFileReaderXzLzma::ClearStateFlags
()
204
{
205
// I don't like this method much
206
fLastReturnStatus
= 0ull;
207
fArchiveReadManager
.Clear();
208
}
209
210
bool
BmnFileReaderXzLzma::IsOpen
() const noexcept
211
{
212
return
fArchiveReadManager
.IsOpen() &&
fLzmaStream
;
213
}
214
215
// ========== BmnIArchiveLib Interface ==========
216
217
BmnFileStreamResults
BmnFileReaderXzLzma::Uncompress
(
const
void
* source,
218
const
size_t
sourceTotalSize,
219
size_t
& numberOfReadBytes,
220
void
* output,
221
const
size_t
outputTotalSize,
222
size_t
& numberOfSetOutputBytes)
223
{
224
if
(!
fLzmaStream
)
225
return
BmnFileStreamResults::FileNotOpen
;
226
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
227
if
(!
IsStreamInGoodState
())
228
return
BmnFileStreamResults::TryingToReadBadStream
;
229
fLzmaStream
->fLzmaStream.next_out = (uint8_t*)output;
230
fLzmaStream
->fLzmaStream.avail_out = outputTotalSize;
231
fLzmaStream
->fLzmaStream.total_out = 0ull;
232
fLzmaStream
->fLzmaStream.next_in = (uint8_t*)source;
233
fLzmaStream
->fLzmaStream.avail_in = sourceTotalSize;
234
fLzmaStream
->fLzmaStream.total_in = 0ull;
235
if
(sourceTotalSize == 0ull)
236
fLastReturnStatus
= (int32_t)lzma_code(&
fLzmaStream
->fLzmaStream, lzma_action::LZMA_FINISH);
237
else
238
fLastReturnStatus
= (int32_t)lzma_code(&
fLzmaStream
->fLzmaStream, lzma_action::LZMA_RUN);
239
if
(!
IsStreamInGoodState
())
240
return
BmnFileStreamResults::UnexpectedFail
;
241
numberOfReadBytes = (size_t)
fLzmaStream
->fLzmaStream.total_in;
242
numberOfSetOutputBytes = (size_t)
fLzmaStream
->fLzmaStream.total_out;
243
fNumberOfReadBytes
+= numberOfSetOutputBytes;
244
if
(
fLastReturnStatus
== 1)
245
return
BmnFileStreamResults::ReachedEOF
;
246
return
BmnFileStreamResults::Success
;
247
#else
248
throw
std::runtime_error{
"Trying to use LZMA while BMN is not compiled with it!"
};
249
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
250
}
251
252
std::string
BmnFileReaderXzLzma::GetLastUncompressErrorDescription
() const noexcept
253
{
254
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
255
return
GetLzmaReturnTypeDescription
(
fLastReturnStatus
);
256
#else
257
return
std::string{
"BMN NOT BUILT WITH XZ LZMA"
};
258
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
259
}
260
261
bool
BmnFileReaderXzLzma::JumpsAllowed
() const noexcept
262
{
263
return
false
;
264
}
265
266
void
BmnFileReaderXzLzma::JumpTo
(
size_t
)
267
{
268
/*
269
In general with XZ LZMA we could allow jumping while carefully building LZMA blocks. Still,
270
that would be allowed only in files written by our own encoder, while XZ would not produce
271
the same results. Thus, we don't allow jumps no matter what and if jumps are needed, we can
272
think about it and adapt later
273
*/
274
LOG(warning) <<
"Calling `BmnFileReaderXzLzma::JumpTo` while the type doesn't allow jumping!\n"
;
275
}
276
277
size_t
BmnFileReaderXzLzma::GetNumberOfDecompressedBytes
() const noexcept
278
{
279
return
fNumberOfReadBytes
;
280
}
281
282
bool
BmnFileReaderXzLzma::HasReachedTheEndOfStream
() const noexcept
283
{
284
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
285
return
fLastReturnStatus
== 1;
286
#else
287
return
true
;
288
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
289
}
290
291
bool
BmnFileReaderXzLzma::IsStreamInGoodState
() const noexcept
292
{
293
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
294
assert(
fLastReturnStatus
>= 0);
295
return
fLastReturnStatus
< 4;
296
#else
297
return
false
;
298
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
299
}
300
301
// ========== BmnFileReaderXzLzma methods ==========
302
303
size_t
BmnFileReaderXzLzma::GetUsedMemoryByLZMA
() const noexcept
304
{
305
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
306
if
(!
fLzmaStream
)
307
return
0ull;
308
return
lzma_memusage(&
fLzmaStream
->fLzmaStream);
309
#else
310
return
0ull;
311
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
312
}
313
314
// 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
315
// ================== static function definition ==================
316
// 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
317
318
#ifdef BMNCOMPRESSION_WITH_XZ_LZMA
319
320
static
std::string
GetLzmaReturnTypeDescription
(
const
int32_t errorID)
noexcept
321
{
322
assert(errorID < 12);
323
return
GetLzmaReturnTypeDescription
(
static_cast<
lzma_ret
>
(errorID));
324
}
325
326
static
std::string
GetLzmaReturnTypeDescription
(
const
lzma_ret lzmaReturnEnum)
noexcept
327
{
328
switch
(lzmaReturnEnum) {
329
case
lzma_ret::LZMA_OK:
330
return
std::string{
"OK"
};
331
case
LZMA_STREAM_END:
332
return
std::string{
"STREAM END"
};
333
case
LZMA_NO_CHECK:
334
return
std::string{
"NO INFO"
};
335
case
LZMA_UNSUPPORTED_CHECK:
336
return
std::string{
"NO CHECK"
};
337
case
LZMA_GET_CHECK:
338
return
std::string{
"GET CHECK"
};
// don't understand this one
339
case
LZMA_MEM_ERROR:
340
return
std::string{
"MEMORY ALLOCATION FAILED"
};
341
case
LZMA_MEMLIMIT_ERROR:
342
return
std::string{
"MEMORY LIMIT REACHED"
};
343
case
LZMA_FORMAT_ERROR:
344
return
std::string{
"FILE IS NOT XZ LZMA"
};
345
case
LZMA_OPTIONS_ERROR:
346
return
std::string{
"BAD DECODING OPTIONS"
};
347
case
LZMA_DATA_ERROR:
348
return
std::string{
"LZMA DATA CORRUPTED"
};
349
case
LZMA_BUF_ERROR:
350
return
std::string{
"BAD BUFFERS"
};
351
case
LZMA_PROG_ERROR:
352
return
std::string{
"INVALID ARGUMENTS"
};
353
default
:
354
// HOW??
355
assert(
false
);
356
return
std::string{};
357
}
358
}
359
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
360
361
#ifndef BMNCOMPRESSION_WITH_XZ_LZMA
362
RESTORE_UNUSED_PARAM_WARNING
363
#endif
// BMNCOMPRESSION_WITH_XZ_LZMA
GetLzmaReturnTypeDescription
static std::string GetLzmaReturnTypeDescription(const int32_t errorID) noexcept
Definition
BmnFileReaderXzLzma.cxx:320
RESTORE_UNUSED_PARAM_WARNING
#define RESTORE_UNUSED_PARAM_WARNING
Definition
BmnDefinitions.h:23
DISABLE_UNUSED_PARAM_WARNING
#define DISABLE_UNUSED_PARAM_WARNING
Definition
BmnDefinitions.h:22
BmnFileReaderXzLzma::fNumberOfReadBytes
size_t fNumberOfReadBytes
Definition
BmnFileReaderXzLzma.h:217
BmnFileReaderXzLzma::BmnFileReaderXzLzma
BmnFileReaderXzLzma(const std::string &fileName="")
Definition
BmnFileReaderXzLzma.cxx:63
BmnFileReaderXzLzma::Open
virtual void Open(const BmnBinaryFileProcessingOptions processingFlags=BmnBinaryFileProcessingOptions::ReadBinary) override
Definition
BmnFileReaderXzLzma.cxx:100
BmnFileReaderXzLzma::Seek
virtual void Seek(int64_t value) override
Definition
BmnFileReaderXzLzma.cxx:161
BmnFileReaderXzLzma::Tell
virtual int64_t Tell() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:155
BmnFileReaderXzLzma::Read
virtual int64_t Read(void *dataToFill, const int64_t sizeToFill) override
Definition
BmnFileReaderXzLzma.cxx:144
BmnFileReaderXzLzma::fArchiveReadManager
BmnReaderCacheManager< 32ull *1024ull, 64ull *1024ull > fArchiveReadManager
Definition
BmnFileReaderXzLzma.h:216
BmnFileReaderXzLzma::fLastReturnStatus
int32_t fLastReturnStatus
Definition
BmnFileReaderXzLzma.h:218
BmnFileReaderXzLzma::HasReachedTheEndOfStream
virtual bool HasReachedTheEndOfStream() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:282
BmnFileReaderXzLzma::ClearStateFlags
virtual void ClearStateFlags() override
Definition
BmnFileReaderXzLzma.cxx:203
BmnFileReaderXzLzma::JumpTo
virtual void JumpTo(size_t) override
Definition
BmnFileReaderXzLzma.cxx:266
BmnFileReaderXzLzma::IsGood
virtual bool IsGood() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:189
BmnFileReaderXzLzma::Uncompress
virtual BmnFileStreamResults Uncompress(const void *source, const size_t sourceTotalSize, size_t &numberOfReadBytes, void *output, const size_t outputTotalSize, size_t &numberOfSetOutputBytes) override
Definition
BmnFileReaderXzLzma.cxx:217
BmnFileReaderXzLzma::GetUsedMemoryByLZMA
size_t GetUsedMemoryByLZMA() const noexcept
Definition
BmnFileReaderXzLzma.cxx:303
BmnFileReaderXzLzma::Close
virtual void Close() noexcept override
Definition
BmnFileReaderXzLzma.cxx:129
BmnFileReaderXzLzma::sMaximalAllowedMemory
static size_t sMaximalAllowedMemory
Definition
BmnFileReaderXzLzma.h:210
BmnFileReaderXzLzma::IsOpen
virtual bool IsOpen() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:210
BmnFileReaderXzLzma::GetLastUncompressErrorDescription
virtual std::string GetLastUncompressErrorDescription() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:252
BmnFileReaderXzLzma::fLzmaStream
LzmaContext * fLzmaStream
Definition
BmnFileReaderXzLzma.h:215
BmnFileReaderXzLzma::~BmnFileReaderXzLzma
virtual ~BmnFileReaderXzLzma() override
Definition
BmnFileReaderXzLzma.cxx:95
BmnFileReaderXzLzma::GetNumberOfDecompressedBytes
virtual size_t GetNumberOfDecompressedBytes() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:277
BmnFileReaderXzLzma::JumpsAllowed
virtual bool JumpsAllowed() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:261
BmnFileReaderXzLzma::IsEOF
virtual bool IsEOF() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:198
BmnFileReaderXzLzma::IsStreamInGoodState
virtual bool IsStreamInGoodState() const noexcept override
Definition
BmnFileReaderXzLzma.cxx:291
BmnIFileReader::BmnIFileReader
BmnIFileReader(const BmnFileType fileType, const std::string &fileName="")
Definition
BmnIFileReader.cxx:8
BmnIFileReader::fFilePath
std::filesystem::path fFilePath
Definition
BmnIFileReader.h:199
BmnIFileReader::PerformStandardChecksBeforeOpening
bool PerformStandardChecksBeforeOpening(const BmnBinaryFileProcessingOptions processingFlags)
Definition
BmnIFileReader.cxx:72
BmnFileStreamResults
BmnFileStreamResults
Definition
BmnFileProcessingFlags.h:70
BmnFileStreamResults::Success
@ Success
Definition
BmnFileProcessingFlags.h:72
BmnFileStreamResults::ReachedEOF
@ ReachedEOF
Definition
BmnFileProcessingFlags.h:74
BmnFileStreamResults::FileNotOpen
@ FileNotOpen
Definition
BmnFileProcessingFlags.h:80
BmnFileStreamResults::UnexpectedFail
@ UnexpectedFail
Definition
BmnFileProcessingFlags.h:82
BmnFileStreamResults::TryingToReadBadStream
@ TryingToReadBadStream
Definition
BmnFileProcessingFlags.h:78
BmnFileType
BmnFileType
Definition
BmnFileProcessingFlags.h:16
BmnFileType::XZ_LZMA
@ XZ_LZMA
Definition
BmnFileProcessingFlags.h:22
BmnBinaryFileProcessingOptions
BmnBinaryFileProcessingOptions
Definition
BmnFileProcessingFlags.h:95
BmnBinaryFileProcessingOptions::ReadBinary
@ ReadBinary
Definition
BmnFileProcessingFlags.h:103
std
Definition
json.hpp:4446
LzmaContext
Definition
BmnFileReaderXzLzma.cxx:23
LzmaContext::~LzmaContext
~LzmaContext()
Definition
BmnFileReaderXzLzma.cxx:28
LzmaContext::LzmaContext
LzmaContext()
Definition
BmnFileReaderXzLzma.cxx:25
LzmaContext::fLzmaStream
lzma_stream fLzmaStream
Definition
BmnFileReaderXzLzma.cxx:31
compression
sources
BmnFileReaderXzLzma.cxx
Generated on
for BmnRoot by
1.17.0