SourcePP
Several modern C++20 libraries for sanely parsing Valve's formats.
Toggle main menu visibility
Loading...
Searching...
No Matches
LZMA.cpp
Go to the documentation of this file.
1
#include <
sourcepp/compression/LZMA.h
>
2
3
#include <BufferStream.h>
4
#include <lzma.h>
5
6
using namespace
sourcepp
;
7
8
std::optional<std::vector<std::byte>>
compression::compressValveLZMA
(std::span<const std::byte> data, uint8_t compressLevel) {
9
// Shift over 4 bytes for Valve LZMA header signature
10
std::vector<std::byte> compressedData(
sizeof
(uint32_t) + data.size() * 2);
11
12
lzma_options_lzma options{};
13
if
(lzma_lzma_preset(&options, std::clamp<uint8_t>(compressLevel, 0, 9))) {
14
return
std::nullopt;
15
}
16
17
lzma_stream stream = LZMA_STREAM_INIT;
18
19
if
(lzma_alone_encoder(&stream, &options) != LZMA_OK) {
20
lzma_end(&stream);
21
return
std::nullopt;
22
}
23
24
stream.next_in =
reinterpret_cast<
const
uint8_t*
>
(data.data());
25
stream.avail_in = data.size();
26
stream.next_out =
reinterpret_cast<
uint8_t*
>
(compressedData.data() +
sizeof
(uint32_t));
27
stream.avail_out = compressedData.size() -
sizeof
(uint32_t);
28
29
lzma_ret ret = lzma_code(&stream, LZMA_FINISH);
30
lzma_end(&stream);
31
if
(ret != LZMA_STREAM_END) {
32
return
std::nullopt;
33
}
34
35
// Switch out normal header with Valve one
36
BufferStream compressedStream{compressedData};
37
compressedStream.seek(0).write(
VALVE_LZMA_SIGNATURE
);
38
const
auto
properties = compressedStream.read<uint8_t>();
39
const
auto
dictionarySize = compressedStream.read<uint32_t>();
40
compressedStream
41
.seek_u(
sizeof
(uint32_t))
42
.write<uint32_t>(data.size())
43
.write(compressedData.size() - (
sizeof
(uint32_t) * 3) + (
sizeof
(uint8_t) * 5))
44
.write(properties)
45
.write(dictionarySize);
46
47
compressedData.resize(stream.total_out +
sizeof
(uint32_t));
48
return
compressedData;
49
}
50
51
std::optional<std::vector<std::byte>>
compression::decompressValveLZMA
(std::span<const std::byte> data) {
52
if
(data.size() < 18) {
53
// Valve LZMA header length + 1 null byte
54
return
std::nullopt;
55
}
56
57
std::vector<std::byte> compressedData{data.begin() +
sizeof
(uint32_t), data.end()};
58
std::vector<std::byte> uncompressedData;
59
{
60
// Switch out Valve header with normal one
61
BufferStreamReadOnly in{data};
62
if
(in.read<uint32_t>() !=
VALVE_LZMA_SIGNATURE
) {
63
return
std::nullopt;
64
}
65
const
uint64_t uncompressedLength = in.read<uint32_t>();
66
in.skip<uint32_t>();
// compressed length is easily inferred
67
const
auto
properties = in.read<uint8_t>();
68
const
auto
dictionarySize = in.read<uint32_t>();
69
BufferStream out{compressedData.data(), compressedData.size()};
70
out
71
.write(properties)
72
.write(dictionarySize)
73
.write(uncompressedLength);
74
75
uncompressedData.resize(uncompressedLength);
76
}
77
78
lzma_stream stream = LZMA_STREAM_INIT;
79
stream.next_in =
reinterpret_cast<
const
uint8_t*
>
(compressedData.data());
80
stream.avail_in = compressedData.size();
81
stream.next_out =
reinterpret_cast<
uint8_t*
>
(uncompressedData.data());
82
stream.avail_out = uncompressedData.size();
83
84
if
(lzma_alone_decoder(&stream, UINT64_MAX) != LZMA_OK) {
85
lzma_end(&stream);
86
return
std::nullopt;
87
}
88
while
(
true
) {
89
const
auto
ret = lzma_code(&stream, LZMA_RUN);
90
if
(ret == LZMA_STREAM_END || stream.avail_out == 0) {
91
break
;
92
}
93
if
(ret != LZMA_OK) {
94
lzma_end(&stream);
95
return
std::nullopt;
96
}
97
}
98
if
(
const
auto
ret = lzma_code(&stream, LZMA_FINISH); ret != LZMA_OK && ret != LZMA_STREAM_END) {
99
lzma_end(&stream);
100
return
std::nullopt;
101
}
102
lzma_end(&stream);
103
104
return
uncompressedData;
105
}
LZMA.h
sourcepp::compression::compressValveLZMA
std::optional< std::vector< std::byte > > compressValveLZMA(std::span< const std::byte > data, uint8_t compressLevel=6)
Definition
LZMA.cpp:8
sourcepp::compression::VALVE_LZMA_SIGNATURE
constexpr auto VALVE_LZMA_SIGNATURE
Definition
LZMA.h:13
sourcepp::compression::decompressValveLZMA
std::optional< std::vector< std::byte > > decompressValveLZMA(std::span< const std::byte > data)
Definition
LZMA.cpp:51
sourcepp
Definition
LZMA.h:11
src
sourcepp
compression
LZMA.cpp
Generated on
for SourcePP by
1.17.0