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.

206 lines
5.6KB

  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. namespace zlibNamespace
  20. {
  21. #if JUCE_INCLUDE_ZLIB_CODE
  22. #undef OS_CODE
  23. #undef fdopen
  24. #include "zlib/zlib.h"
  25. #undef OS_CODE
  26. #else
  27. #include <zlib.h>
  28. #endif
  29. }
  30. BEGIN_JUCE_NAMESPACE
  31. #include "juce_GZIPCompressorOutputStream.h"
  32. //==============================================================================
  33. // internal helper object that holds the zlib structures so they don't have to be
  34. // included publicly.
  35. class GZIPCompressorHelper
  36. {
  37. public:
  38. GZIPCompressorHelper (const int compressionLevel, const bool nowrap)
  39. : data (0),
  40. dataSize (0),
  41. compLevel (compressionLevel),
  42. strategy (0),
  43. setParams (true),
  44. streamIsValid (false),
  45. finished (false),
  46. shouldFinish (false)
  47. {
  48. using namespace zlibNamespace;
  49. zerostruct (stream);
  50. streamIsValid = (deflateInit2 (&stream, compLevel, Z_DEFLATED,
  51. nowrap ? -MAX_WBITS : MAX_WBITS,
  52. 8, strategy) == Z_OK);
  53. }
  54. ~GZIPCompressorHelper()
  55. {
  56. using namespace zlibNamespace;
  57. if (streamIsValid)
  58. deflateEnd (&stream);
  59. }
  60. bool needsInput() const throw()
  61. {
  62. return dataSize <= 0;
  63. }
  64. void setInput (uint8* const newData, const int size) throw()
  65. {
  66. data = newData;
  67. dataSize = size;
  68. }
  69. int doNextBlock (uint8* const dest, const int destSize) throw()
  70. {
  71. using namespace zlibNamespace;
  72. if (streamIsValid)
  73. {
  74. stream.next_in = data;
  75. stream.next_out = dest;
  76. stream.avail_in = dataSize;
  77. stream.avail_out = destSize;
  78. const int result = setParams ? deflateParams (&stream, compLevel, strategy)
  79. : deflate (&stream, shouldFinish ? Z_FINISH : Z_NO_FLUSH);
  80. setParams = false;
  81. switch (result)
  82. {
  83. case Z_STREAM_END:
  84. finished = true;
  85. // Deliberate fall-through..
  86. case Z_OK:
  87. data += dataSize - stream.avail_in;
  88. dataSize = stream.avail_in;
  89. return destSize - stream.avail_out;
  90. default:
  91. break;
  92. }
  93. }
  94. return 0;
  95. }
  96. private:
  97. zlibNamespace::z_stream stream;
  98. uint8* data;
  99. int dataSize, compLevel, strategy;
  100. bool setParams, streamIsValid;
  101. public:
  102. bool finished, shouldFinish;
  103. };
  104. //==============================================================================
  105. const int gzipCompBufferSize = 32768;
  106. GZIPCompressorOutputStream::GZIPCompressorOutputStream (OutputStream* const destStream_,
  107. int compressionLevel,
  108. const bool deleteDestStream,
  109. const bool noWrap)
  110. : destStream (destStream_),
  111. streamToDelete (deleteDestStream ? destStream_ : 0),
  112. buffer (gzipCompBufferSize)
  113. {
  114. if (compressionLevel < 1 || compressionLevel > 9)
  115. compressionLevel = -1;
  116. helper = new GZIPCompressorHelper (compressionLevel, noWrap);
  117. }
  118. GZIPCompressorOutputStream::~GZIPCompressorOutputStream()
  119. {
  120. flush();
  121. }
  122. //==============================================================================
  123. void GZIPCompressorOutputStream::flush()
  124. {
  125. if (! helper->finished)
  126. {
  127. helper->shouldFinish = true;
  128. while (! helper->finished)
  129. doNextBlock();
  130. }
  131. destStream->flush();
  132. }
  133. bool GZIPCompressorOutputStream::write (const void* destBuffer, int howMany)
  134. {
  135. if (! helper->finished)
  136. {
  137. helper->setInput ((uint8*) destBuffer, howMany);
  138. while (! helper->needsInput())
  139. {
  140. if (! doNextBlock())
  141. return false;
  142. }
  143. }
  144. return true;
  145. }
  146. bool GZIPCompressorOutputStream::doNextBlock()
  147. {
  148. const int len = helper->doNextBlock (buffer, gzipCompBufferSize);
  149. if (len > 0)
  150. return destStream->write (buffer, len);
  151. else
  152. return true;
  153. }
  154. int64 GZIPCompressorOutputStream::getPosition()
  155. {
  156. return destStream->getPosition();
  157. }
  158. bool GZIPCompressorOutputStream::setPosition (int64 /*newPosition*/)
  159. {
  160. jassertfalse // can't do it!
  161. return false;
  162. }
  163. END_JUCE_NAMESPACE