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