openMSX
ZlibInflate.cc
Go to the documentation of this file.
1 #include "ZlibInflate.hh"
2 #include "FileException.hh"
3 #include "MemBuffer.hh"
4 #include <limits>
5 
6 namespace openmsx {
7 
9 {
10  if (input.size() > std::numeric_limits<decltype(s.avail_in)>::max()) {
11  throw FileException(
12  "Error while decompressing: input file too big");
13  }
14  auto inputLen = static_cast<decltype(s.avail_in)>(input.size());
15 
16  s.zalloc = nullptr;
17  s.zfree = nullptr;
18  s.opaque = nullptr;
19  s.next_in = const_cast<uint8_t*>(input.data());
20  s.avail_in = inputLen;
21  wasInit = false;
22 }
23 
25 {
26  if (wasInit) {
27  inflateEnd(&s);
28  }
29 }
30 
31 void ZlibInflate::skip(size_t num)
32 {
33  for (size_t i = 0; i < num; ++i) {
34  getByte();
35  }
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 
64 std::string ZlibInflate::getString(size_t len)
65 {
66  std::string result;
67  for (size_t i = 0; i < len; ++i) {
68  result.push_back(getByte());
69  }
70  return result;
71 }
72 
74 {
75  std::string result;
76  while (char c = getByte()) {
77  result.push_back(c);
78  }
79  return result;
80 }
81 
82 size_t ZlibInflate::inflate(MemBuffer<uint8_t>& output, size_t sizeHint)
83 {
84  int initErr = inflateInit2(&s, -MAX_WBITS);
85  if (initErr != Z_OK) {
86  throw FileException(
87  "Error initializing inflate struct: ", zError(initErr));
88  }
89  wasInit = true;
90 
91  size_t outSize = sizeHint;
92  output.resize(outSize);
93  s.avail_out = uInt(outSize); // TODO overflow?
94  while (true) {
95  s.next_out = output.data() + s.total_out;
96  int err = ::inflate(&s, Z_NO_FLUSH);
97  if (err == Z_STREAM_END) {
98  break;
99  }
100  if (err != Z_OK) {
101  throw FileException("Error decompressing gzip: ", zError(err));
102  }
103  auto oldSize = outSize;
104  outSize = oldSize * 2; // double buffer size
105  output.resize(outSize);
106  s.avail_out = uInt(outSize - oldSize); // TODO overflow?
107  }
108 
109  // set actual size
110  output.resize(s.total_out);
111  return s.total_out;
112 }
113 
114 } // namespace openmsx
ZlibInflate(span< uint8_t > input)
Definition: ZlibInflate.cc:8
Definition: span.hh:34
std::string getCString()
Definition: ZlibInflate.cc:73
vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:287
std::string getString(size_t len)
Definition: ZlibInflate.cc:64
void skip(size_t num)
Definition: ZlibInflate.cc:31
void resize(size_t size)
Grow or shrink the memory block.
Definition: MemBuffer.hh:120
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:90
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
size_t inflate(MemBuffer< uint8_t > &output, size_t sizeHint=65536)
Definition: ZlibInflate.cc:82