OpenShot Audio Library | OpenShotAudio: juce_GZIPCompressorOutputStream.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.4.0

Loading...
Searching...
No Matches
juce_GZIPCompressorOutputStream.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26class GZIPCompressorOutputStream::GZIPCompressorHelper
27{
28public:
29 GZIPCompressorHelper (int compressionLevel, int windowBits)
30 : compLevel ((compressionLevel < 0 || compressionLevel > 9) ? -1 : compressionLevel)
31 {
32 using namespace zlibNamespace;
33 zerostruct (stream);
34
35 streamIsValid = (deflateInit2 (&stream, compLevel, Z_DEFLATED,
36 windowBits != 0 ? windowBits : MAX_WBITS,
37 8, strategy) == Z_OK);
38 }
39
40 ~GZIPCompressorHelper()
41 {
42 if (streamIsValid)
43 zlibNamespace::deflateEnd (&stream);
44 }
45
46 bool write (const uint8* data, size_t dataSize, OutputStream& out)
47 {
48 // When you call flush() on a gzip stream, the stream is closed, and you can
49 // no longer continue to write data to it!
50 jassert (! finished);
51
52 while (dataSize > 0)
53 if (! doNextBlock (data, dataSize, out, Z_NO_FLUSH))
54 return false;
55
56 return true;
57 }
58
59 void finish (OutputStream& out)
60 {
61 const uint8* data = nullptr;
62 size_t dataSize = 0;
63
64 while (! finished)
65 doNextBlock (data, dataSize, out, Z_FINISH);
66 }
67
68private:
69 enum { strategy = 0 };
70
71 zlibNamespace::z_stream stream;
72 const int compLevel;
73 bool isFirstDeflate = true, streamIsValid = false, finished = false;
74 zlibNamespace::Bytef buffer[32768];
75
76 bool doNextBlock (const uint8*& data, size_t& dataSize, OutputStream& out, const int flushMode)
77 {
78 using namespace zlibNamespace;
79
80 if (streamIsValid)
81 {
82 stream.next_in = const_cast<uint8*> (data);
83 stream.next_out = buffer;
84 stream.avail_in = (z_uInt) dataSize;
85 stream.avail_out = (z_uInt) sizeof (buffer);
86
87 auto result = isFirstDeflate ? deflateParams (&stream, compLevel, strategy)
88 : deflate (&stream, flushMode);
89 isFirstDeflate = false;
90
91 switch (result)
92 {
93 case Z_STREAM_END:
94 finished = true;
95 JUCE_FALLTHROUGH
96 case Z_OK:
97 {
98 data += dataSize - stream.avail_in;
99 dataSize = stream.avail_in;
100 auto bytesDone = (ssize_t) sizeof (buffer) - (ssize_t) stream.avail_out;
101 return bytesDone <= 0 || out.write (buffer, (size_t) bytesDone);
102 }
103
104 default:
105 break;
106 }
107 }
108
109 return false;
110 }
111
112 JUCE_DECLARE_NON_COPYABLE (GZIPCompressorHelper)
113};
114
115//==============================================================================
116GZIPCompressorOutputStream::GZIPCompressorOutputStream (OutputStream& s, int compressionLevel, int windowBits)
117 : GZIPCompressorOutputStream (&s, compressionLevel, false, windowBits)
118{
119}
120
121 GZIPCompressorOutputStream::GZIPCompressorOutputStream (OutputStream* out, int compressionLevel, bool deleteDestStream, int windowBits)
122 : destStream (out, deleteDestStream),
123 helper (new GZIPCompressorHelper (compressionLevel, windowBits))
124{
125 jassert (out != nullptr);
126}
127
128GZIPCompressorOutputStream::~GZIPCompressorOutputStream()
129{
130 flush();
131}
132
133 void GZIPCompressorOutputStream::flush()
134{
135 helper->finish (*destStream);
136 destStream->flush();
137}
138
139 bool GZIPCompressorOutputStream::write (const void* destBuffer, size_t howMany)
140{
141 jassert (destBuffer != nullptr && (ssize_t) howMany >= 0);
142
143 return helper->write (static_cast<const uint8*> (destBuffer), howMany, *destStream);
144}
145
146int64 GZIPCompressorOutputStream::getPosition()
147{
148 return destStream->getPosition();
149}
150
151 bool GZIPCompressorOutputStream::setPosition (int64 /*newPosition*/)
152{
153 jassertfalse; // can't do it!
154 return false;
155}
156
157
158//==============================================================================
159//==============================================================================
160#if JUCE_UNIT_TESTS
161
162struct GZIPTests final : public UnitTest
163{
164 GZIPTests()
165 : UnitTest ("GZIP", UnitTestCategories::compression)
166 {}
167
168 void runTest() override
169 {
170 beginTest ("GZIP");
171 Random rng = getRandom();
172
173 for (int i = 100; --i >= 0;)
174 {
175 MemoryOutputStream original, compressed, uncompressed;
176
177 {
178 GZIPCompressorOutputStream zipper (compressed, rng.nextInt (10));
179
180 for (int j = rng.nextInt (100); --j >= 0;)
181 {
182 MemoryBlock data ((unsigned int) (rng.nextInt (2000) + 1));
183
184 for (int k = (int) data.getSize(); --k >= 0;)
185 data[k] = (char) rng.nextInt (255);
186
187 original << data;
188 zipper << data;
189 }
190 }
191
192 {
193 MemoryInputStream compressedInput (compressed.getData(), compressed.getDataSize(), false);
194 GZIPDecompressorInputStream unzipper (compressedInput);
195
196 uncompressed << unzipper;
197 }
198
199 expectEquals ((int) uncompressed.getDataSize(),
200 (int) original.getDataSize());
201
202 if (original.getDataSize() == uncompressed.getDataSize())
203 expect (memcmp (uncompressed.getData(),
204 original.getData(),
205 original.getDataSize()) == 0);
206 }
207 }
208};
209
210static GZIPTests gzipTests;
211
212#endif
213
214} // namespace juce
juce::GZIPCompressorOutputStream
Definition juce_GZIPCompressorOutputStream.h:39
juce::GZIPCompressorOutputStream::GZIPCompressorOutputStream
GZIPCompressorOutputStream(OutputStream &destStream, int compressionLevel=-1, int windowBits=0)
Definition juce_GZIPCompressorOutputStream.cpp:116
juce::GZIPCompressorOutputStream::setPosition
bool setPosition(int64) override
Definition juce_GZIPCompressorOutputStream.cpp:151
juce::GZIPCompressorOutputStream::write
bool write(const void *, size_t) override
Definition juce_GZIPCompressorOutputStream.cpp:139
juce::GZIPCompressorOutputStream::~GZIPCompressorOutputStream
~GZIPCompressorOutputStream() override
Definition juce_GZIPCompressorOutputStream.cpp:128
juce::GZIPCompressorOutputStream::flush
void flush() override
Definition juce_GZIPCompressorOutputStream.cpp:133
juce::GZIPCompressorOutputStream::getPosition
int64 getPosition() override
Definition juce_GZIPCompressorOutputStream.cpp:146
juce::OutputStream
Definition juce_OutputStream.h:38
juce::UnitTest
Definition juce_UnitTest.h:70