openMSX
ZlibInflate.cc
Go to the documentation of this file.
1#include "ZlibInflate.hh"
2#include "FileException.hh"
3#include "MemBuffer.hh"
4#include "narrow.hh"
5#include "xrange.hh"
6#include <limits>
7
8namespace openmsx {
9
10ZlibInflate::ZlibInflate(std::span<const uint8_t> input)
11{
12 if (input.size() > std::numeric_limits<decltype(s.avail_in)>::max()) {
13 throw FileException(
14 "Error while decompressing: input file too big");
15 }
16 auto inputLen = static_cast<decltype(s.avail_in)>(input.size());
17
18 s.zalloc = nullptr;
19 s.zfree = nullptr;
20 s.opaque = nullptr;
21 s.next_in = const_cast<uint8_t*>(input.data());
22 s.avail_in = inputLen;
23 wasInit = false;
24}
25
27{
28 if (wasInit) {
29 inflateEnd(&s);
30 }
31}
32
33void ZlibInflate::skip(size_t num)
34{
35 repeat(num, [&] { (void)getByte(); });
36}
37
39{
40 if (s.avail_in <= 0) {
41 throw FileException(
42 "Error while decompressing: unexpected end of file.");
43 }
44 --s.avail_in;
45 return *(s.next_in++);
46}
47
49{
50 unsigned result = getByte();
51 result += getByte() << 8;
52 return result;
53}
54
56{
57 unsigned result = getByte();
58 result += getByte() << 8;
59 result += getByte() << 16;
60 result += getByte() << 24;
61 return result;
62}
63
64std::string ZlibInflate::getString(size_t len)
65{
66 std::string result;
67 result.reserve(len);
68 repeat(len, [&] { result.push_back(narrow_cast<char>(getByte())); });
69 return result;
70}
71
73{
74 std::string result;
75 while (auto c = narrow_cast<char>(getByte())) {
76 result.push_back(c);
77 }
78 return result;
79}
80
81size_t ZlibInflate::inflate(MemBuffer<uint8_t>& output, size_t sizeHint)
82{
83 if (int err = inflateInit2(&s, -MAX_WBITS);
84 err != Z_OK) {
85 throw FileException(
86 "Error initializing inflate struct: ", zError(err));
87 }
88 wasInit = true;
89
90 size_t outSize = sizeHint;
91 output.resize(outSize);
92 s.avail_out = uInt(outSize); // TODO overflow?
93 while (true) {
94 s.next_out = output.data() + s.total_out;
95 int err = ::inflate(&s, Z_NO_FLUSH);
96 if (err == Z_STREAM_END) {
97 break;
98 }
99 if (err != Z_OK) {
100 throw FileException("Error decompressing gzip: ", zError(err));
101 }
102 auto oldSize = outSize;
103 outSize = oldSize * 2; // double buffer size
104 output.resize(outSize);
105 s.avail_out = uInt(outSize - oldSize); // TODO overflow?
106 }
107
108 // set actual size
109 output.resize(s.total_out);
110 return s.total_out;
111}
112
113} // namespace openmsx
This class manages the lifetime of a block of memory.
Definition MemBuffer.hh:29
void resize(size_t size)
Grow or shrink the memory block.
Definition MemBuffer.hh:111
const T * data() const
Returns pointer to the start of the memory buffer.
Definition MemBuffer.hh:81
std::string getString(size_t len)
ZlibInflate(std::span< const uint8_t > input)
std::string getCString()
void skip(size_t num)
size_t inflate(MemBuffer< uint8_t > &output, size_t sizeHint=65536)
This file implemented 3 utility functions:
Definition Autofire.cc:11
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition xrange.hh:147