The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
7.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../core/juce_StandardHeader.h"
  19. #if JUCE_MSVC
  20. #pragma warning (push)
  21. #pragma warning (disable: 4309 4305)
  22. #endif
  23. namespace zlibNamespace
  24. {
  25. #if JUCE_INCLUDE_ZLIB_CODE
  26. extern "C"
  27. {
  28. #undef OS_CODE
  29. #undef fdopen
  30. #define ZLIB_INTERNAL
  31. #define NO_DUMMY_DECL
  32. #include "zlib/zlib.h"
  33. #include "zlib/adler32.c"
  34. #include "zlib/compress.c"
  35. #undef DO1
  36. #undef DO8
  37. #include "zlib/crc32.c"
  38. #include "zlib/deflate.c"
  39. #include "zlib/inffast.c"
  40. #undef PULLBYTE
  41. #undef LOAD
  42. #undef RESTORE
  43. #undef INITBITS
  44. #undef NEEDBITS
  45. #undef DROPBITS
  46. #undef BYTEBITS
  47. #include "zlib/inflate.c"
  48. #include "zlib/inftrees.c"
  49. #include "zlib/trees.c"
  50. #include "zlib/zutil.c"
  51. #undef Byte
  52. }
  53. #else
  54. #include <zlib.h>
  55. #endif
  56. }
  57. #if JUCE_MSVC
  58. #pragma warning (pop)
  59. #endif
  60. BEGIN_JUCE_NAMESPACE
  61. #include "juce_GZIPDecompressorInputStream.h"
  62. using namespace zlibNamespace;
  63. //==============================================================================
  64. // internal helper object that holds the zlib structures so they don't have to be
  65. // included publicly.
  66. class GZIPDecompressHelper
  67. {
  68. public:
  69. GZIPDecompressHelper (const bool noWrap) throw()
  70. : data (0),
  71. dataSize (0),
  72. finished (true),
  73. needsDictionary (false),
  74. error (true),
  75. streamIsValid (false)
  76. {
  77. zerostruct (stream);
  78. streamIsValid = (inflateInit2 (&stream, noWrap ? -MAX_WBITS : MAX_WBITS) == Z_OK);
  79. finished = error = ! streamIsValid;
  80. }
  81. ~GZIPDecompressHelper() throw()
  82. {
  83. if (streamIsValid)
  84. inflateEnd (&stream);
  85. }
  86. bool needsInput() const throw() { return dataSize <= 0; }
  87. void setInput (uint8* const data_, const int size) throw()
  88. {
  89. data = data_;
  90. dataSize = size;
  91. }
  92. int doNextBlock (uint8* const dest, const int destSize) throw()
  93. {
  94. if (streamIsValid && data != 0 && ! finished)
  95. {
  96. stream.next_in = data;
  97. stream.next_out = dest;
  98. stream.avail_in = dataSize;
  99. stream.avail_out = destSize;
  100. switch (inflate (&stream, Z_PARTIAL_FLUSH))
  101. {
  102. case Z_STREAM_END:
  103. finished = true;
  104. // deliberate fall-through
  105. case Z_OK:
  106. data += dataSize - stream.avail_in;
  107. dataSize = stream.avail_in;
  108. return destSize - stream.avail_out;
  109. case Z_NEED_DICT:
  110. needsDictionary = true;
  111. data += dataSize - stream.avail_in;
  112. dataSize = stream.avail_in;
  113. break;
  114. case Z_DATA_ERROR:
  115. case Z_MEM_ERROR:
  116. error = true;
  117. default:
  118. break;
  119. }
  120. }
  121. return 0;
  122. }
  123. private:
  124. z_stream stream;
  125. uint8* data;
  126. int dataSize;
  127. public:
  128. bool finished, needsDictionary, error, streamIsValid;
  129. };
  130. //==============================================================================
  131. const int gzipDecompBufferSize = 32768;
  132. GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream* const sourceStream_,
  133. const bool deleteSourceWhenDestroyed,
  134. const bool noWrap_,
  135. const int64 uncompressedStreamLength_)
  136. : sourceStream (sourceStream_),
  137. streamToDelete (deleteSourceWhenDestroyed ? sourceStream_ : 0),
  138. uncompressedStreamLength (uncompressedStreamLength_),
  139. noWrap (noWrap_),
  140. isEof (false),
  141. activeBufferSize (0),
  142. originalSourcePos (sourceStream_->getPosition()),
  143. currentPos (0),
  144. buffer (gzipDecompBufferSize),
  145. helper (new GZIPDecompressHelper (noWrap_))
  146. {
  147. }
  148. GZIPDecompressorInputStream::~GZIPDecompressorInputStream()
  149. {
  150. }
  151. int64 GZIPDecompressorInputStream::getTotalLength()
  152. {
  153. return uncompressedStreamLength;
  154. }
  155. int GZIPDecompressorInputStream::read (void* destBuffer, int howMany)
  156. {
  157. if ((howMany > 0) && ! isEof)
  158. {
  159. jassert (destBuffer != 0);
  160. if (destBuffer != 0)
  161. {
  162. int numRead = 0;
  163. uint8* d = (uint8*) destBuffer;
  164. while (! helper->error)
  165. {
  166. const int n = helper->doNextBlock (d, howMany);
  167. currentPos += n;
  168. if (n == 0)
  169. {
  170. if (helper->finished || helper->needsDictionary)
  171. {
  172. isEof = true;
  173. return numRead;
  174. }
  175. if (helper->needsInput())
  176. {
  177. activeBufferSize = sourceStream->read (buffer, gzipDecompBufferSize);
  178. if (activeBufferSize > 0)
  179. {
  180. helper->setInput ((uint8*) buffer, activeBufferSize);
  181. }
  182. else
  183. {
  184. isEof = true;
  185. return numRead;
  186. }
  187. }
  188. }
  189. else
  190. {
  191. numRead += n;
  192. howMany -= n;
  193. d += n;
  194. if (howMany <= 0)
  195. return numRead;
  196. }
  197. }
  198. }
  199. }
  200. return 0;
  201. }
  202. bool GZIPDecompressorInputStream::isExhausted()
  203. {
  204. return helper->error || isEof;
  205. }
  206. int64 GZIPDecompressorInputStream::getPosition()
  207. {
  208. return currentPos;
  209. }
  210. bool GZIPDecompressorInputStream::setPosition (int64 newPos)
  211. {
  212. if (newPos < currentPos)
  213. {
  214. // to go backwards, reset the stream and start again..
  215. isEof = false;
  216. activeBufferSize = 0;
  217. currentPos = 0;
  218. helper = new GZIPDecompressHelper (noWrap);
  219. sourceStream->setPosition (originalSourcePos);
  220. }
  221. skipNextBytes (newPos - currentPos);
  222. return true;
  223. }
  224. END_JUCE_NAMESPACE