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