OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_GZIPCompressorOutputStream.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
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 // Deliberate fall-through..
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//==============================================================================
120
122 : destStream (out, deleteDestStream),
123 helper (new GZIPCompressorHelper (compressionLevel, windowBits))
124{
125 jassert (out != nullptr);
126}
127
132
134{
135 helper->finish (*destStream);
136 destStream->flush();
137}
138
140{
141 jassert (destBuffer != nullptr && (ssize_t) howMany >= 0);
142
143 return helper->write (static_cast<const uint8*> (destBuffer), howMany, *destStream);
144}
145
147{
148 return destStream->getPosition();
149}
150
151bool 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 : 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
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
Array()=default
ElementType * data() noexcept
Definition juce_Array.h:360
GZIPCompressorOutputStream(OutputStream &destStream, int compressionLevel=-1, int windowBits=0)
bool write(const void *, size_t) override