1d86ed7fbStbbdev /*
2*b15aabb3Stbbdev Copyright (c) 2005-2021 Intel Corporation
3d86ed7fbStbbdev
4d86ed7fbStbbdev Licensed under the Apache License, Version 2.0 (the "License");
5d86ed7fbStbbdev you may not use this file except in compliance with the License.
6d86ed7fbStbbdev You may obtain a copy of the License at
7d86ed7fbStbbdev
8d86ed7fbStbbdev http://www.apache.org/licenses/LICENSE-2.0
9d86ed7fbStbbdev
10d86ed7fbStbbdev Unless required by applicable law or agreed to in writing, software
11d86ed7fbStbbdev distributed under the License is distributed on an "AS IS" BASIS,
12d86ed7fbStbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d86ed7fbStbbdev See the License for the specific language governing permissions and
14d86ed7fbStbbdev limitations under the License.
15d86ed7fbStbbdev */
16d86ed7fbStbbdev
17d86ed7fbStbbdev /*-------------------------------------------------------------*/
18d86ed7fbStbbdev /*--- Library top-level functions. ---*/
19d86ed7fbStbbdev /*--- bzlib.cpp ---*/
20d86ed7fbStbbdev /*-------------------------------------------------------------*/
21d86ed7fbStbbdev
22d86ed7fbStbbdev /* ------------------------------------------------------------------
23d86ed7fbStbbdev The original source for this example:
24d86ed7fbStbbdev This file is part of bzip2/libbzip2, a program and library for
25d86ed7fbStbbdev lossless, block-sorting data compression.
26d86ed7fbStbbdev
27d86ed7fbStbbdev bzip2/libbzip2 version 1.0.6 of 6 September 2010
28d86ed7fbStbbdev Copyright (C) 1996-2010 Julian Seward <[email protected]>
29d86ed7fbStbbdev
30d86ed7fbStbbdev This program, "bzip2", the associated library "libbzip2", and all
31d86ed7fbStbbdev documentation, are copyright (C) 1996-2010 Julian R Seward. All
32d86ed7fbStbbdev rights reserved.
33d86ed7fbStbbdev
34d86ed7fbStbbdev Redistribution and use in source and binary forms, with or without
35d86ed7fbStbbdev modification, are permitted provided that the following conditions
36d86ed7fbStbbdev are met:
37d86ed7fbStbbdev
38d86ed7fbStbbdev 1. Redistributions of source code must retain the above copyright
39d86ed7fbStbbdev notice, this list of conditions and the following disclaimer.
40d86ed7fbStbbdev
41d86ed7fbStbbdev 2. The origin of this software must not be misrepresented; you must
42d86ed7fbStbbdev not claim that you wrote the original software. If you use this
43d86ed7fbStbbdev software in a product, an acknowledgment in the product
44d86ed7fbStbbdev documentation would be appreciated but is not required.
45d86ed7fbStbbdev
46d86ed7fbStbbdev 3. Altered source versions must be plainly marked as such, and must
47d86ed7fbStbbdev not be misrepresented as being the original software.
48d86ed7fbStbbdev
49d86ed7fbStbbdev 4. The name of the author may not be used to endorse or promote
50d86ed7fbStbbdev products derived from this software without specific prior written
51d86ed7fbStbbdev permission.
52d86ed7fbStbbdev
53d86ed7fbStbbdev THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
54d86ed7fbStbbdev OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
55d86ed7fbStbbdev WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56d86ed7fbStbbdev ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
57d86ed7fbStbbdev DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58d86ed7fbStbbdev DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
59d86ed7fbStbbdev GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60d86ed7fbStbbdev INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
61d86ed7fbStbbdev WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62d86ed7fbStbbdev NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63d86ed7fbStbbdev SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64d86ed7fbStbbdev
65d86ed7fbStbbdev Julian Seward, [email protected]
66d86ed7fbStbbdev bzip2/libbzip2 version 1.0.6 of 6 September 2010
67d86ed7fbStbbdev ------------------------------------------------------------------ */
68d86ed7fbStbbdev
69d86ed7fbStbbdev /* CHANGES
70d86ed7fbStbbdev 0.9.0 -- original version.
71d86ed7fbStbbdev 0.9.0a/b -- no changes in this file.
72d86ed7fbStbbdev 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress().
73d86ed7fbStbbdev fixed bzWrite/bzRead to ignore zero-length requests.
74d86ed7fbStbbdev fixed bzread to correctly handle read requests after EOF.
75d86ed7fbStbbdev wrong parameter order in call to bzDecompressInit in
76d86ed7fbStbbdev bzBuffToBuffDecompress. Fixed.
77d86ed7fbStbbdev */
78d86ed7fbStbbdev
79d86ed7fbStbbdev #include "bzlib_private.hpp"
80d86ed7fbStbbdev
81d86ed7fbStbbdev /*---------------------------------------------------*/
82d86ed7fbStbbdev /*--- Compression stuff ---*/
83d86ed7fbStbbdev /*---------------------------------------------------*/
84d86ed7fbStbbdev
85d86ed7fbStbbdev /*---------------------------------------------------*/
86d86ed7fbStbbdev #ifndef BZ_NO_STDIO
BZ2_bz__AssertH__fail(int errcode)87d86ed7fbStbbdev void BZ2_bz__AssertH__fail(int errcode) {
88d86ed7fbStbbdev fprintf(stderr,
89d86ed7fbStbbdev "\n\nbzip2/libbzip2: internal error number %d.\n"
90d86ed7fbStbbdev "This is a bug in bzip2/libbzip2, %s.\n"
91d86ed7fbStbbdev "Please report it to me at: [email protected]. If this happened\n"
92d86ed7fbStbbdev "when you were using some program which uses libbzip2 as a\n"
93d86ed7fbStbbdev "component, you should also report this bug to the author(s)\n"
94d86ed7fbStbbdev "of that program. Please make an effort to report this bug;\n"
95d86ed7fbStbbdev "timely and accurate bug reports eventually lead to higher\n"
96d86ed7fbStbbdev "quality software. Thanks. Julian Seward, 10 December 2007.\n\n",
97d86ed7fbStbbdev errcode,
98d86ed7fbStbbdev BZ2_bzlibVersion());
99d86ed7fbStbbdev
100d86ed7fbStbbdev if (errcode == 1007) {
101d86ed7fbStbbdev fprintf(stderr,
102d86ed7fbStbbdev "\n*** A special note about internal error number 1007 ***\n"
103d86ed7fbStbbdev "\n"
104d86ed7fbStbbdev "Experience suggests that a common cause of i.e. 1007\n"
105d86ed7fbStbbdev "is unreliable memory or other hardware. The 1007 assertion\n"
106d86ed7fbStbbdev "just happens to cross-check the results of huge numbers of\n"
107d86ed7fbStbbdev "memory reads/writes, and so acts (unintendedly) as a stress\n"
108d86ed7fbStbbdev "test of your memory system.\n"
109d86ed7fbStbbdev "\n"
110d86ed7fbStbbdev "I suggest the following: try compressing the file again,\n"
111d86ed7fbStbbdev "possibly monitoring progress in detail with the -vv flag.\n"
112d86ed7fbStbbdev "\n"
113d86ed7fbStbbdev "* If the error cannot be reproduced, and/or happens at different\n"
114d86ed7fbStbbdev " points in compression, you may have a flaky memory system.\n"
115d86ed7fbStbbdev " Try a memory-test program. I have used Memtest86\n"
116d86ed7fbStbbdev " (www.memtest86.com). At the time of writing it is free (GPLd).\n"
117d86ed7fbStbbdev " Memtest86 tests memory much more thorougly than your BIOSs\n"
118d86ed7fbStbbdev " power-on test, and may find failures that the BIOS doesn't.\n"
119d86ed7fbStbbdev "\n"
120d86ed7fbStbbdev "* If the error can be repeatably reproduced, this is a bug in\n"
121d86ed7fbStbbdev " bzip2, and I would very much like to hear about it. Please\n"
122d86ed7fbStbbdev " let me know, and, ideally, save a copy of the file causing the\n"
123d86ed7fbStbbdev " problem -- without which I will be unable to investigate it.\n"
124d86ed7fbStbbdev "\n");
125d86ed7fbStbbdev }
126d86ed7fbStbbdev
127d86ed7fbStbbdev std::exit(-1);
128d86ed7fbStbbdev }
129d86ed7fbStbbdev #endif
130d86ed7fbStbbdev
131d86ed7fbStbbdev /*---------------------------------------------------*/
bz_config_ok(void)132d86ed7fbStbbdev static int bz_config_ok(void) {
133d86ed7fbStbbdev if (sizeof(int) != 4)
134d86ed7fbStbbdev return 0;
135d86ed7fbStbbdev if (sizeof(short) != 2)
136d86ed7fbStbbdev return 0;
137d86ed7fbStbbdev if (sizeof(char) != 1)
138d86ed7fbStbbdev return 0;
139d86ed7fbStbbdev return 1;
140d86ed7fbStbbdev }
141d86ed7fbStbbdev
142d86ed7fbStbbdev /*---------------------------------------------------*/
default_bzalloc(void * opaque,Int32 items,Int32 size)143d86ed7fbStbbdev static void* default_bzalloc(void* opaque, Int32 items, Int32 size) {
144d86ed7fbStbbdev void* v = malloc(items * size);
145d86ed7fbStbbdev return v;
146d86ed7fbStbbdev }
147d86ed7fbStbbdev
default_bzfree(void * opaque,void * addr)148d86ed7fbStbbdev static void default_bzfree(void* opaque, void* addr) {
149d86ed7fbStbbdev if (addr != nullptr)
150d86ed7fbStbbdev free(addr);
151d86ed7fbStbbdev }
152d86ed7fbStbbdev
153d86ed7fbStbbdev /*---------------------------------------------------*/
prepare_new_block(EState * s)154d86ed7fbStbbdev static void prepare_new_block(EState* s) {
155d86ed7fbStbbdev Int32 i;
156d86ed7fbStbbdev s->nblock = 0;
157d86ed7fbStbbdev s->numZ = 0;
158d86ed7fbStbbdev s->state_out_pos = 0;
159d86ed7fbStbbdev BZ_INITIALISE_CRC(s->blockCRC);
160d86ed7fbStbbdev for (i = 0; i < 256; i++)
161d86ed7fbStbbdev s->inUse[i] = False;
162d86ed7fbStbbdev s->blockNo++;
163d86ed7fbStbbdev }
164d86ed7fbStbbdev
165d86ed7fbStbbdev /*---------------------------------------------------*/
init_RL(EState * s)166d86ed7fbStbbdev static void init_RL(EState* s) {
167d86ed7fbStbbdev s->state_in_ch = 256;
168d86ed7fbStbbdev s->state_in_len = 0;
169d86ed7fbStbbdev }
170d86ed7fbStbbdev
isempty_RL(EState * s)171d86ed7fbStbbdev static Bool isempty_RL(EState* s) {
172d86ed7fbStbbdev if (s->state_in_ch < 256 && s->state_in_len > 0)
173d86ed7fbStbbdev return False;
174d86ed7fbStbbdev else
175d86ed7fbStbbdev return True;
176d86ed7fbStbbdev }
177d86ed7fbStbbdev
178d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressInit)179d86ed7fbStbbdev int BZ_API(BZ2_bzCompressInit)(bz_stream* strm, int blockSize100k, int verbosity, int workFactor) {
180d86ed7fbStbbdev Int32 n;
181d86ed7fbStbbdev EState* s;
182d86ed7fbStbbdev
183d86ed7fbStbbdev if (!bz_config_ok())
184d86ed7fbStbbdev return BZ_CONFIG_ERROR;
185d86ed7fbStbbdev
186d86ed7fbStbbdev if (strm == nullptr || blockSize100k < 1 || blockSize100k > 9 || workFactor < 0 ||
187d86ed7fbStbbdev workFactor > 250)
188d86ed7fbStbbdev return BZ_PARAM_ERROR;
189d86ed7fbStbbdev
190d86ed7fbStbbdev if (workFactor == 0)
191d86ed7fbStbbdev workFactor = 30;
192d86ed7fbStbbdev if (strm->bzalloc == nullptr)
193d86ed7fbStbbdev strm->bzalloc = default_bzalloc;
194d86ed7fbStbbdev if (strm->bzfree == nullptr)
195d86ed7fbStbbdev strm->bzfree = default_bzfree;
196d86ed7fbStbbdev
197d86ed7fbStbbdev s = (EState*)BZALLOC(sizeof(EState));
198d86ed7fbStbbdev if (s == nullptr)
199d86ed7fbStbbdev return BZ_MEM_ERROR;
200d86ed7fbStbbdev s->strm = strm;
201d86ed7fbStbbdev
202d86ed7fbStbbdev s->arr1 = nullptr;
203d86ed7fbStbbdev s->arr2 = nullptr;
204d86ed7fbStbbdev s->ftab = nullptr;
205d86ed7fbStbbdev
206d86ed7fbStbbdev n = 100000 * blockSize100k;
207d86ed7fbStbbdev s->arr1 = (UInt32*)BZALLOC(n * sizeof(UInt32));
208d86ed7fbStbbdev s->arr2 = (UInt32*)BZALLOC((n + BZ_N_OVERSHOOT) * sizeof(UInt32));
209d86ed7fbStbbdev s->ftab = (UInt32*)BZALLOC(65537 * sizeof(UInt32));
210d86ed7fbStbbdev
211d86ed7fbStbbdev if (s->arr1 == nullptr || s->arr2 == nullptr || s->ftab == nullptr) {
212d86ed7fbStbbdev if (s->arr1 != nullptr)
213d86ed7fbStbbdev BZFREE(s->arr1);
214d86ed7fbStbbdev if (s->arr2 != nullptr)
215d86ed7fbStbbdev BZFREE(s->arr2);
216d86ed7fbStbbdev if (s->ftab != nullptr)
217d86ed7fbStbbdev BZFREE(s->ftab);
218d86ed7fbStbbdev if (s != nullptr)
219d86ed7fbStbbdev BZFREE(s);
220d86ed7fbStbbdev return BZ_MEM_ERROR;
221d86ed7fbStbbdev }
222d86ed7fbStbbdev
223d86ed7fbStbbdev s->blockNo = 0;
224d86ed7fbStbbdev s->state = BZ_S_INPUT;
225d86ed7fbStbbdev s->mode = BZ_M_RUNNING;
226d86ed7fbStbbdev s->combinedCRC = 0;
227d86ed7fbStbbdev s->blockSize100k = blockSize100k;
228d86ed7fbStbbdev s->nblockMAX = 100000 * blockSize100k - 19;
229d86ed7fbStbbdev s->verbosity = verbosity;
230d86ed7fbStbbdev s->workFactor = workFactor;
231d86ed7fbStbbdev
232d86ed7fbStbbdev s->block = (UChar*)s->arr2;
233d86ed7fbStbbdev s->mtfv = (UInt16*)s->arr1;
234d86ed7fbStbbdev s->zbits = nullptr;
235d86ed7fbStbbdev s->ptr = (UInt32*)s->arr1;
236d86ed7fbStbbdev
237d86ed7fbStbbdev strm->state = s;
238d86ed7fbStbbdev strm->total_in_lo32 = 0;
239d86ed7fbStbbdev strm->total_in_hi32 = 0;
240d86ed7fbStbbdev strm->total_out_lo32 = 0;
241d86ed7fbStbbdev strm->total_out_hi32 = 0;
242d86ed7fbStbbdev init_RL(s);
243d86ed7fbStbbdev prepare_new_block(s);
244d86ed7fbStbbdev return BZ_OK;
245d86ed7fbStbbdev }
246d86ed7fbStbbdev
247d86ed7fbStbbdev /*---------------------------------------------------*/
add_pair_to_block(EState * s)248d86ed7fbStbbdev static void add_pair_to_block(EState* s) {
249d86ed7fbStbbdev Int32 i;
250d86ed7fbStbbdev UChar ch = (UChar)(s->state_in_ch);
251d86ed7fbStbbdev for (i = 0; i < s->state_in_len; i++) {
252d86ed7fbStbbdev BZ_UPDATE_CRC(s->blockCRC, ch);
253d86ed7fbStbbdev }
254d86ed7fbStbbdev s->inUse[s->state_in_ch] = True;
255d86ed7fbStbbdev switch (s->state_in_len) {
256d86ed7fbStbbdev case 1:
257d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
258d86ed7fbStbbdev s->nblock++;
259d86ed7fbStbbdev break;
260d86ed7fbStbbdev case 2:
261d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
262d86ed7fbStbbdev s->nblock++;
263d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
264d86ed7fbStbbdev s->nblock++;
265d86ed7fbStbbdev break;
266d86ed7fbStbbdev case 3:
267d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
268d86ed7fbStbbdev s->nblock++;
269d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
270d86ed7fbStbbdev s->nblock++;
271d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
272d86ed7fbStbbdev s->nblock++;
273d86ed7fbStbbdev break;
274d86ed7fbStbbdev default:
275d86ed7fbStbbdev s->inUse[s->state_in_len - 4] = True;
276d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
277d86ed7fbStbbdev s->nblock++;
278d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
279d86ed7fbStbbdev s->nblock++;
280d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
281d86ed7fbStbbdev s->nblock++;
282d86ed7fbStbbdev s->block[s->nblock] = (UChar)ch;
283d86ed7fbStbbdev s->nblock++;
284d86ed7fbStbbdev s->block[s->nblock] = ((UChar)(s->state_in_len - 4));
285d86ed7fbStbbdev s->nblock++;
286d86ed7fbStbbdev break;
287d86ed7fbStbbdev }
288d86ed7fbStbbdev }
289d86ed7fbStbbdev
290d86ed7fbStbbdev /*---------------------------------------------------*/
flush_RL(EState * s)291d86ed7fbStbbdev static void flush_RL(EState* s) {
292d86ed7fbStbbdev if (s->state_in_ch < 256)
293d86ed7fbStbbdev add_pair_to_block(s);
294d86ed7fbStbbdev init_RL(s);
295d86ed7fbStbbdev }
296d86ed7fbStbbdev
297d86ed7fbStbbdev /*---------------------------------------------------*/
298d86ed7fbStbbdev #define ADD_CHAR_TO_BLOCK(zs, zchh0) \
299d86ed7fbStbbdev { \
300d86ed7fbStbbdev UInt32 zchh = (UInt32)(zchh0); \
301d86ed7fbStbbdev /*-- fast track the common case --*/ \
302d86ed7fbStbbdev if (zchh != zs->state_in_ch && zs->state_in_len == 1) { \
303d86ed7fbStbbdev UChar ch = (UChar)(zs->state_in_ch); \
304d86ed7fbStbbdev BZ_UPDATE_CRC(zs->blockCRC, ch); \
305d86ed7fbStbbdev zs->inUse[zs->state_in_ch] = True; \
306d86ed7fbStbbdev zs->block[zs->nblock] = (UChar)ch; \
307d86ed7fbStbbdev zs->nblock++; \
308d86ed7fbStbbdev zs->state_in_ch = zchh; \
309d86ed7fbStbbdev } \
310d86ed7fbStbbdev else /*-- general, uncommon cases --*/ \
311d86ed7fbStbbdev if (zchh != zs->state_in_ch || zs->state_in_len == 255) { \
312d86ed7fbStbbdev if (zs->state_in_ch < 256) \
313d86ed7fbStbbdev add_pair_to_block(zs); \
314d86ed7fbStbbdev zs->state_in_ch = zchh; \
315d86ed7fbStbbdev zs->state_in_len = 1; \
316d86ed7fbStbbdev } \
317d86ed7fbStbbdev else { \
318d86ed7fbStbbdev zs->state_in_len++; \
319d86ed7fbStbbdev } \
320d86ed7fbStbbdev }
321d86ed7fbStbbdev
322d86ed7fbStbbdev /*---------------------------------------------------*/
copy_input_until_stop(EState * s)323d86ed7fbStbbdev static Bool copy_input_until_stop(EState* s) {
324d86ed7fbStbbdev Bool progress_in = False;
325d86ed7fbStbbdev
326d86ed7fbStbbdev if (s->mode == BZ_M_RUNNING) {
327d86ed7fbStbbdev /*-- fast track the common case --*/
328d86ed7fbStbbdev while (True) {
329d86ed7fbStbbdev /*-- block full? --*/
330d86ed7fbStbbdev if (s->nblock >= s->nblockMAX)
331d86ed7fbStbbdev break;
332d86ed7fbStbbdev /*-- no input? --*/
333d86ed7fbStbbdev if (s->strm->avail_in == 0)
334d86ed7fbStbbdev break;
335d86ed7fbStbbdev progress_in = True;
336d86ed7fbStbbdev ADD_CHAR_TO_BLOCK(s, (UInt32)(*((UChar*)(s->strm->next_in))));
337d86ed7fbStbbdev s->strm->next_in++;
338d86ed7fbStbbdev s->strm->avail_in--;
339d86ed7fbStbbdev s->strm->total_in_lo32++;
340d86ed7fbStbbdev if (s->strm->total_in_lo32 == 0)
341d86ed7fbStbbdev s->strm->total_in_hi32++;
342d86ed7fbStbbdev }
343d86ed7fbStbbdev }
344d86ed7fbStbbdev else {
345d86ed7fbStbbdev /*-- general, uncommon case --*/
346d86ed7fbStbbdev while (True) {
347d86ed7fbStbbdev /*-- block full? --*/
348d86ed7fbStbbdev if (s->nblock >= s->nblockMAX)
349d86ed7fbStbbdev break;
350d86ed7fbStbbdev /*-- no input? --*/
351d86ed7fbStbbdev if (s->strm->avail_in == 0)
352d86ed7fbStbbdev break;
353d86ed7fbStbbdev /*-- flush/finish end? --*/
354d86ed7fbStbbdev if (s->avail_in_expect == 0)
355d86ed7fbStbbdev break;
356d86ed7fbStbbdev progress_in = True;
357d86ed7fbStbbdev ADD_CHAR_TO_BLOCK(s, (UInt32)(*((UChar*)(s->strm->next_in))));
358d86ed7fbStbbdev s->strm->next_in++;
359d86ed7fbStbbdev s->strm->avail_in--;
360d86ed7fbStbbdev s->strm->total_in_lo32++;
361d86ed7fbStbbdev if (s->strm->total_in_lo32 == 0)
362d86ed7fbStbbdev s->strm->total_in_hi32++;
363d86ed7fbStbbdev s->avail_in_expect--;
364d86ed7fbStbbdev }
365d86ed7fbStbbdev }
366d86ed7fbStbbdev return progress_in;
367d86ed7fbStbbdev }
368d86ed7fbStbbdev
369d86ed7fbStbbdev /*---------------------------------------------------*/
copy_output_until_stop(EState * s)370d86ed7fbStbbdev static Bool copy_output_until_stop(EState* s) {
371d86ed7fbStbbdev Bool progress_out = False;
372d86ed7fbStbbdev
373d86ed7fbStbbdev while (True) {
374d86ed7fbStbbdev /*-- no output space? --*/
375d86ed7fbStbbdev if (s->strm->avail_out == 0)
376d86ed7fbStbbdev break;
377d86ed7fbStbbdev
378d86ed7fbStbbdev /*-- block done? --*/
379d86ed7fbStbbdev if (s->state_out_pos >= s->numZ)
380d86ed7fbStbbdev break;
381d86ed7fbStbbdev
382d86ed7fbStbbdev progress_out = True;
383d86ed7fbStbbdev *(s->strm->next_out) = s->zbits[s->state_out_pos];
384d86ed7fbStbbdev s->state_out_pos++;
385d86ed7fbStbbdev s->strm->avail_out--;
386d86ed7fbStbbdev s->strm->next_out++;
387d86ed7fbStbbdev s->strm->total_out_lo32++;
388d86ed7fbStbbdev if (s->strm->total_out_lo32 == 0)
389d86ed7fbStbbdev s->strm->total_out_hi32++;
390d86ed7fbStbbdev }
391d86ed7fbStbbdev
392d86ed7fbStbbdev return progress_out;
393d86ed7fbStbbdev }
394d86ed7fbStbbdev
395d86ed7fbStbbdev /*---------------------------------------------------*/
handle_compress(bz_stream * strm)396d86ed7fbStbbdev static Bool handle_compress(bz_stream* strm) {
397d86ed7fbStbbdev Bool progress_in = False;
398d86ed7fbStbbdev Bool progress_out = False;
399d86ed7fbStbbdev EState* s = (EState*)strm->state;
400d86ed7fbStbbdev
401d86ed7fbStbbdev while (True) {
402d86ed7fbStbbdev if (s->state == BZ_S_OUTPUT) {
403d86ed7fbStbbdev progress_out |= copy_output_until_stop(s);
404d86ed7fbStbbdev if (s->state_out_pos < s->numZ)
405d86ed7fbStbbdev break;
406d86ed7fbStbbdev if (s->mode == BZ_M_FINISHING && s->avail_in_expect == 0 && isempty_RL(s))
407d86ed7fbStbbdev break;
408d86ed7fbStbbdev prepare_new_block(s);
409d86ed7fbStbbdev s->state = BZ_S_INPUT;
410d86ed7fbStbbdev if (s->mode == BZ_M_FLUSHING && s->avail_in_expect == 0 && isempty_RL(s))
411d86ed7fbStbbdev break;
412d86ed7fbStbbdev }
413d86ed7fbStbbdev
414d86ed7fbStbbdev if (s->state == BZ_S_INPUT) {
415d86ed7fbStbbdev progress_in |= copy_input_until_stop(s);
416d86ed7fbStbbdev if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
417d86ed7fbStbbdev flush_RL(s);
418d86ed7fbStbbdev BZ2_compressBlock(s, (Bool)(s->mode == BZ_M_FINISHING));
419d86ed7fbStbbdev s->state = BZ_S_OUTPUT;
420d86ed7fbStbbdev }
421d86ed7fbStbbdev else if (s->nblock >= s->nblockMAX) {
422d86ed7fbStbbdev BZ2_compressBlock(s, False);
423d86ed7fbStbbdev s->state = BZ_S_OUTPUT;
424d86ed7fbStbbdev }
425d86ed7fbStbbdev else if (s->strm->avail_in == 0) {
426d86ed7fbStbbdev break;
427d86ed7fbStbbdev }
428d86ed7fbStbbdev }
429d86ed7fbStbbdev }
430d86ed7fbStbbdev
431d86ed7fbStbbdev return progress_in || progress_out;
432d86ed7fbStbbdev }
433d86ed7fbStbbdev
434d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzCompress)435d86ed7fbStbbdev int BZ_API(BZ2_bzCompress)(bz_stream* strm, int action) {
436d86ed7fbStbbdev Bool progress;
437d86ed7fbStbbdev EState* s;
438d86ed7fbStbbdev if (strm == nullptr)
439d86ed7fbStbbdev return BZ_PARAM_ERROR;
440d86ed7fbStbbdev s = (EState*)strm->state;
441d86ed7fbStbbdev if (s == nullptr)
442d86ed7fbStbbdev return BZ_PARAM_ERROR;
443d86ed7fbStbbdev if (s->strm != strm)
444d86ed7fbStbbdev return BZ_PARAM_ERROR;
445d86ed7fbStbbdev
446d86ed7fbStbbdev preswitch:
447d86ed7fbStbbdev switch (s->mode) {
448d86ed7fbStbbdev case BZ_M_IDLE: return BZ_SEQUENCE_ERROR;
449d86ed7fbStbbdev
450d86ed7fbStbbdev case BZ_M_RUNNING:
451d86ed7fbStbbdev if (action == BZ_RUN) {
452d86ed7fbStbbdev progress = handle_compress(strm);
453d86ed7fbStbbdev return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;
454d86ed7fbStbbdev }
455d86ed7fbStbbdev else if (action == BZ_FLUSH) {
456d86ed7fbStbbdev s->avail_in_expect = strm->avail_in;
457d86ed7fbStbbdev s->mode = BZ_M_FLUSHING;
458d86ed7fbStbbdev goto preswitch;
459d86ed7fbStbbdev }
460d86ed7fbStbbdev else if (action == BZ_FINISH) {
461d86ed7fbStbbdev s->avail_in_expect = strm->avail_in;
462d86ed7fbStbbdev s->mode = BZ_M_FINISHING;
463d86ed7fbStbbdev goto preswitch;
464d86ed7fbStbbdev }
465d86ed7fbStbbdev else
466d86ed7fbStbbdev return BZ_PARAM_ERROR;
467d86ed7fbStbbdev
468d86ed7fbStbbdev case BZ_M_FLUSHING:
469d86ed7fbStbbdev if (action != BZ_FLUSH)
470d86ed7fbStbbdev return BZ_SEQUENCE_ERROR;
471d86ed7fbStbbdev if (s->avail_in_expect != s->strm->avail_in)
472d86ed7fbStbbdev return BZ_SEQUENCE_ERROR;
473d86ed7fbStbbdev progress = handle_compress(strm);
474d86ed7fbStbbdev if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ)
475d86ed7fbStbbdev return BZ_FLUSH_OK;
476d86ed7fbStbbdev s->mode = BZ_M_RUNNING;
477d86ed7fbStbbdev return BZ_RUN_OK;
478d86ed7fbStbbdev
479d86ed7fbStbbdev case BZ_M_FINISHING:
480d86ed7fbStbbdev if (action != BZ_FINISH)
481d86ed7fbStbbdev return BZ_SEQUENCE_ERROR;
482d86ed7fbStbbdev if (s->avail_in_expect != s->strm->avail_in)
483d86ed7fbStbbdev return BZ_SEQUENCE_ERROR;
484d86ed7fbStbbdev progress = handle_compress(strm);
485d86ed7fbStbbdev if (!progress)
486d86ed7fbStbbdev return BZ_SEQUENCE_ERROR;
487d86ed7fbStbbdev if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ)
488d86ed7fbStbbdev return BZ_FINISH_OK;
489d86ed7fbStbbdev s->mode = BZ_M_IDLE;
490d86ed7fbStbbdev return BZ_STREAM_END;
491d86ed7fbStbbdev }
492d86ed7fbStbbdev return BZ_OK; /*--not reached--*/
493d86ed7fbStbbdev }
494d86ed7fbStbbdev
495d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzCompressEnd)496d86ed7fbStbbdev int BZ_API(BZ2_bzCompressEnd)(bz_stream* strm) {
497d86ed7fbStbbdev EState* s;
498d86ed7fbStbbdev if (strm == nullptr)
499d86ed7fbStbbdev return BZ_PARAM_ERROR;
500d86ed7fbStbbdev s = (EState*)strm->state;
501d86ed7fbStbbdev if (s == nullptr)
502d86ed7fbStbbdev return BZ_PARAM_ERROR;
503d86ed7fbStbbdev if (s->strm != strm)
504d86ed7fbStbbdev return BZ_PARAM_ERROR;
505d86ed7fbStbbdev
506d86ed7fbStbbdev if (s->arr1 != nullptr)
507d86ed7fbStbbdev BZFREE(s->arr1);
508d86ed7fbStbbdev if (s->arr2 != nullptr)
509d86ed7fbStbbdev BZFREE(s->arr2);
510d86ed7fbStbbdev if (s->ftab != nullptr)
511d86ed7fbStbbdev BZFREE(s->ftab);
512d86ed7fbStbbdev BZFREE(strm->state);
513d86ed7fbStbbdev
514d86ed7fbStbbdev strm->state = nullptr;
515d86ed7fbStbbdev
516d86ed7fbStbbdev return BZ_OK;
517d86ed7fbStbbdev }
518d86ed7fbStbbdev
519d86ed7fbStbbdev /*---------------------------------------------------*/
520d86ed7fbStbbdev /*--- Decompression stuff ---*/
521d86ed7fbStbbdev /*---------------------------------------------------*/
522d86ed7fbStbbdev
523d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressInit)524d86ed7fbStbbdev int BZ_API(BZ2_bzDecompressInit)(bz_stream* strm, int verbosity, int small) {
525d86ed7fbStbbdev DState* s;
526d86ed7fbStbbdev
527d86ed7fbStbbdev if (!bz_config_ok())
528d86ed7fbStbbdev return BZ_CONFIG_ERROR;
529d86ed7fbStbbdev
530d86ed7fbStbbdev if (strm == nullptr)
531d86ed7fbStbbdev return BZ_PARAM_ERROR;
532d86ed7fbStbbdev if (small != 0 && small != 1)
533d86ed7fbStbbdev return BZ_PARAM_ERROR;
534d86ed7fbStbbdev if (verbosity < 0 || verbosity > 4)
535d86ed7fbStbbdev return BZ_PARAM_ERROR;
536d86ed7fbStbbdev
537d86ed7fbStbbdev if (strm->bzalloc == nullptr)
538d86ed7fbStbbdev strm->bzalloc = default_bzalloc;
539d86ed7fbStbbdev if (strm->bzfree == nullptr)
540d86ed7fbStbbdev strm->bzfree = default_bzfree;
541d86ed7fbStbbdev
542d86ed7fbStbbdev s = (DState*)BZALLOC(sizeof(DState));
543d86ed7fbStbbdev if (s == nullptr)
544d86ed7fbStbbdev return BZ_MEM_ERROR;
545d86ed7fbStbbdev s->strm = strm;
546d86ed7fbStbbdev strm->state = s;
547d86ed7fbStbbdev s->state = BZ_X_MAGIC_1;
548d86ed7fbStbbdev s->bsLive = 0;
549d86ed7fbStbbdev s->bsBuff = 0;
550d86ed7fbStbbdev s->calculatedCombinedCRC = 0;
551d86ed7fbStbbdev strm->total_in_lo32 = 0;
552d86ed7fbStbbdev strm->total_in_hi32 = 0;
553d86ed7fbStbbdev strm->total_out_lo32 = 0;
554d86ed7fbStbbdev strm->total_out_hi32 = 0;
555d86ed7fbStbbdev s->smallDecompress = (Bool)small;
556d86ed7fbStbbdev s->ll4 = nullptr;
557d86ed7fbStbbdev s->ll16 = nullptr;
558d86ed7fbStbbdev s->tt = nullptr;
559d86ed7fbStbbdev s->currBlockNo = 0;
560d86ed7fbStbbdev s->verbosity = verbosity;
561d86ed7fbStbbdev
562d86ed7fbStbbdev return BZ_OK;
563d86ed7fbStbbdev }
564d86ed7fbStbbdev
565d86ed7fbStbbdev /*---------------------------------------------------*/
566d86ed7fbStbbdev /* Return True iff data corruption is discovered.
567d86ed7fbStbbdev Returns False if there is no problem.
568d86ed7fbStbbdev */
unRLE_obuf_to_output_FAST(DState * s)569d86ed7fbStbbdev static Bool unRLE_obuf_to_output_FAST(DState* s) {
570d86ed7fbStbbdev UChar k1;
571d86ed7fbStbbdev
572d86ed7fbStbbdev if (s->blockRandomised) {
573d86ed7fbStbbdev while (True) {
574d86ed7fbStbbdev /* try to finish existing run */
575d86ed7fbStbbdev while (True) {
576d86ed7fbStbbdev if (s->strm->avail_out == 0)
577d86ed7fbStbbdev return False;
578d86ed7fbStbbdev if (s->state_out_len == 0)
579d86ed7fbStbbdev break;
580d86ed7fbStbbdev *((UChar*)(s->strm->next_out)) = s->state_out_ch;
581d86ed7fbStbbdev BZ_UPDATE_CRC(s->calculatedBlockCRC, s->state_out_ch);
582d86ed7fbStbbdev s->state_out_len--;
583d86ed7fbStbbdev s->strm->next_out++;
584d86ed7fbStbbdev s->strm->avail_out--;
585d86ed7fbStbbdev s->strm->total_out_lo32++;
586d86ed7fbStbbdev if (s->strm->total_out_lo32 == 0)
587d86ed7fbStbbdev s->strm->total_out_hi32++;
588d86ed7fbStbbdev }
589d86ed7fbStbbdev
590d86ed7fbStbbdev /* can a new run be started? */
591d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
592d86ed7fbStbbdev return False;
593d86ed7fbStbbdev
594d86ed7fbStbbdev /* Only caused by corrupt data stream? */
595d86ed7fbStbbdev if (s->nblock_used > s->save_nblock + 1)
596d86ed7fbStbbdev return True;
597d86ed7fbStbbdev
598d86ed7fbStbbdev s->state_out_len = 1;
599d86ed7fbStbbdev s->state_out_ch = s->k0;
600d86ed7fbStbbdev BZ_GET_FAST(k1);
601d86ed7fbStbbdev BZ_RAND_UPD_MASK;
602d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
603d86ed7fbStbbdev s->nblock_used++;
604d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
605d86ed7fbStbbdev continue;
606d86ed7fbStbbdev if (k1 != s->k0) {
607d86ed7fbStbbdev s->k0 = k1;
608d86ed7fbStbbdev continue;
609d86ed7fbStbbdev };
610d86ed7fbStbbdev
611d86ed7fbStbbdev s->state_out_len = 2;
612d86ed7fbStbbdev BZ_GET_FAST(k1);
613d86ed7fbStbbdev BZ_RAND_UPD_MASK;
614d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
615d86ed7fbStbbdev s->nblock_used++;
616d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
617d86ed7fbStbbdev continue;
618d86ed7fbStbbdev if (k1 != s->k0) {
619d86ed7fbStbbdev s->k0 = k1;
620d86ed7fbStbbdev continue;
621d86ed7fbStbbdev };
622d86ed7fbStbbdev
623d86ed7fbStbbdev s->state_out_len = 3;
624d86ed7fbStbbdev BZ_GET_FAST(k1);
625d86ed7fbStbbdev BZ_RAND_UPD_MASK;
626d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
627d86ed7fbStbbdev s->nblock_used++;
628d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
629d86ed7fbStbbdev continue;
630d86ed7fbStbbdev if (k1 != s->k0) {
631d86ed7fbStbbdev s->k0 = k1;
632d86ed7fbStbbdev continue;
633d86ed7fbStbbdev };
634d86ed7fbStbbdev
635d86ed7fbStbbdev BZ_GET_FAST(k1);
636d86ed7fbStbbdev BZ_RAND_UPD_MASK;
637d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
638d86ed7fbStbbdev s->nblock_used++;
639d86ed7fbStbbdev s->state_out_len = ((Int32)k1) + 4;
640d86ed7fbStbbdev BZ_GET_FAST(s->k0);
641d86ed7fbStbbdev BZ_RAND_UPD_MASK;
642d86ed7fbStbbdev s->k0 ^= BZ_RAND_MASK;
643d86ed7fbStbbdev s->nblock_used++;
644d86ed7fbStbbdev }
645d86ed7fbStbbdev }
646d86ed7fbStbbdev else {
647d86ed7fbStbbdev /* restore */
648d86ed7fbStbbdev UInt32 c_calculatedBlockCRC = s->calculatedBlockCRC;
649d86ed7fbStbbdev UChar c_state_out_ch = s->state_out_ch;
650d86ed7fbStbbdev Int32 c_state_out_len = s->state_out_len;
651d86ed7fbStbbdev Int32 c_nblock_used = s->nblock_used;
652d86ed7fbStbbdev Int32 c_k0 = s->k0;
653d86ed7fbStbbdev UInt32* c_tt = s->tt;
654d86ed7fbStbbdev UInt32 c_tPos = s->tPos;
655d86ed7fbStbbdev char* cs_next_out = s->strm->next_out;
656d86ed7fbStbbdev unsigned int cs_avail_out = s->strm->avail_out;
657d86ed7fbStbbdev Int32 ro_blockSize100k = s->blockSize100k;
658d86ed7fbStbbdev /* end restore */
659d86ed7fbStbbdev
660d86ed7fbStbbdev UInt32 avail_out_INIT = cs_avail_out;
661d86ed7fbStbbdev Int32 s_save_nblockPP = s->save_nblock + 1;
662d86ed7fbStbbdev unsigned int total_out_lo32_old;
663d86ed7fbStbbdev
664d86ed7fbStbbdev while (True) {
665d86ed7fbStbbdev /* try to finish existing run */
666d86ed7fbStbbdev if (c_state_out_len > 0) {
667d86ed7fbStbbdev while (True) {
668d86ed7fbStbbdev if (cs_avail_out == 0)
669d86ed7fbStbbdev goto return_notr;
670d86ed7fbStbbdev if (c_state_out_len == 1)
671d86ed7fbStbbdev break;
672d86ed7fbStbbdev *((UChar*)(cs_next_out)) = c_state_out_ch;
673d86ed7fbStbbdev BZ_UPDATE_CRC(c_calculatedBlockCRC, c_state_out_ch);
674d86ed7fbStbbdev c_state_out_len--;
675d86ed7fbStbbdev cs_next_out++;
676d86ed7fbStbbdev cs_avail_out--;
677d86ed7fbStbbdev }
678d86ed7fbStbbdev s_state_out_len_eq_one : {
679d86ed7fbStbbdev if (cs_avail_out == 0) {
680d86ed7fbStbbdev c_state_out_len = 1;
681d86ed7fbStbbdev goto return_notr;
682d86ed7fbStbbdev };
683d86ed7fbStbbdev *((UChar*)(cs_next_out)) = c_state_out_ch;
684d86ed7fbStbbdev BZ_UPDATE_CRC(c_calculatedBlockCRC, c_state_out_ch);
685d86ed7fbStbbdev cs_next_out++;
686d86ed7fbStbbdev cs_avail_out--;
687d86ed7fbStbbdev }
688d86ed7fbStbbdev }
689d86ed7fbStbbdev /* Only caused by corrupt data stream? */
690d86ed7fbStbbdev if (c_nblock_used > s_save_nblockPP)
691d86ed7fbStbbdev return True;
692d86ed7fbStbbdev
693d86ed7fbStbbdev /* can a new run be started? */
694d86ed7fbStbbdev if (c_nblock_used == s_save_nblockPP) {
695d86ed7fbStbbdev c_state_out_len = 0;
696d86ed7fbStbbdev goto return_notr;
697d86ed7fbStbbdev };
698d86ed7fbStbbdev c_state_out_ch = c_k0;
699d86ed7fbStbbdev BZ_GET_FAST_C(k1);
700d86ed7fbStbbdev c_nblock_used++;
701d86ed7fbStbbdev if (k1 != c_k0) {
702d86ed7fbStbbdev c_k0 = k1;
703d86ed7fbStbbdev goto s_state_out_len_eq_one;
704d86ed7fbStbbdev };
705d86ed7fbStbbdev if (c_nblock_used == s_save_nblockPP)
706d86ed7fbStbbdev goto s_state_out_len_eq_one;
707d86ed7fbStbbdev
708d86ed7fbStbbdev c_state_out_len = 2;
709d86ed7fbStbbdev BZ_GET_FAST_C(k1);
710d86ed7fbStbbdev c_nblock_used++;
711d86ed7fbStbbdev if (c_nblock_used == s_save_nblockPP)
712d86ed7fbStbbdev continue;
713d86ed7fbStbbdev if (k1 != c_k0) {
714d86ed7fbStbbdev c_k0 = k1;
715d86ed7fbStbbdev continue;
716d86ed7fbStbbdev };
717d86ed7fbStbbdev
718d86ed7fbStbbdev c_state_out_len = 3;
719d86ed7fbStbbdev BZ_GET_FAST_C(k1);
720d86ed7fbStbbdev c_nblock_used++;
721d86ed7fbStbbdev if (c_nblock_used == s_save_nblockPP)
722d86ed7fbStbbdev continue;
723d86ed7fbStbbdev if (k1 != c_k0) {
724d86ed7fbStbbdev c_k0 = k1;
725d86ed7fbStbbdev continue;
726d86ed7fbStbbdev };
727d86ed7fbStbbdev
728d86ed7fbStbbdev BZ_GET_FAST_C(k1);
729d86ed7fbStbbdev c_nblock_used++;
730d86ed7fbStbbdev c_state_out_len = ((Int32)k1) + 4;
731d86ed7fbStbbdev BZ_GET_FAST_C(c_k0);
732d86ed7fbStbbdev c_nblock_used++;
733d86ed7fbStbbdev }
734d86ed7fbStbbdev
735d86ed7fbStbbdev return_notr:
736d86ed7fbStbbdev total_out_lo32_old = s->strm->total_out_lo32;
737d86ed7fbStbbdev s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
738d86ed7fbStbbdev if (s->strm->total_out_lo32 < total_out_lo32_old)
739d86ed7fbStbbdev s->strm->total_out_hi32++;
740d86ed7fbStbbdev
741d86ed7fbStbbdev /* save */
742d86ed7fbStbbdev s->calculatedBlockCRC = c_calculatedBlockCRC;
743d86ed7fbStbbdev s->state_out_ch = c_state_out_ch;
744d86ed7fbStbbdev s->state_out_len = c_state_out_len;
745d86ed7fbStbbdev s->nblock_used = c_nblock_used;
746d86ed7fbStbbdev s->k0 = c_k0;
747d86ed7fbStbbdev s->tt = c_tt;
748d86ed7fbStbbdev s->tPos = c_tPos;
749d86ed7fbStbbdev s->strm->next_out = cs_next_out;
750d86ed7fbStbbdev s->strm->avail_out = cs_avail_out;
751d86ed7fbStbbdev /* end save */
752d86ed7fbStbbdev }
753d86ed7fbStbbdev return False;
754d86ed7fbStbbdev }
755d86ed7fbStbbdev
756d86ed7fbStbbdev /*---------------------------------------------------*/
BZ2_indexIntoF(Int32 indx,Int32 * cftab)757d86ed7fbStbbdev Int32 BZ2_indexIntoF(Int32 indx, Int32* cftab) {
758d86ed7fbStbbdev Int32 nb, na, mid;
759d86ed7fbStbbdev nb = 0;
760d86ed7fbStbbdev na = 256;
761d86ed7fbStbbdev do {
762d86ed7fbStbbdev mid = (nb + na) >> 1;
763d86ed7fbStbbdev if (indx >= cftab[mid])
764d86ed7fbStbbdev nb = mid;
765d86ed7fbStbbdev else
766d86ed7fbStbbdev na = mid;
767d86ed7fbStbbdev } while (na - nb != 1);
768d86ed7fbStbbdev return nb;
769d86ed7fbStbbdev }
770d86ed7fbStbbdev
771d86ed7fbStbbdev /*---------------------------------------------------*/
772d86ed7fbStbbdev /* Return True iff data corruption is discovered.
773d86ed7fbStbbdev Returns False if there is no problem.
774d86ed7fbStbbdev */
unRLE_obuf_to_output_SMALL(DState * s)775d86ed7fbStbbdev static Bool unRLE_obuf_to_output_SMALL(DState* s) {
776d86ed7fbStbbdev UChar k1;
777d86ed7fbStbbdev
778d86ed7fbStbbdev if (s->blockRandomised) {
779d86ed7fbStbbdev while (True) {
780d86ed7fbStbbdev /* try to finish existing run */
781d86ed7fbStbbdev while (True) {
782d86ed7fbStbbdev if (s->strm->avail_out == 0)
783d86ed7fbStbbdev return False;
784d86ed7fbStbbdev if (s->state_out_len == 0)
785d86ed7fbStbbdev break;
786d86ed7fbStbbdev *((UChar*)(s->strm->next_out)) = s->state_out_ch;
787d86ed7fbStbbdev BZ_UPDATE_CRC(s->calculatedBlockCRC, s->state_out_ch);
788d86ed7fbStbbdev s->state_out_len--;
789d86ed7fbStbbdev s->strm->next_out++;
790d86ed7fbStbbdev s->strm->avail_out--;
791d86ed7fbStbbdev s->strm->total_out_lo32++;
792d86ed7fbStbbdev if (s->strm->total_out_lo32 == 0)
793d86ed7fbStbbdev s->strm->total_out_hi32++;
794d86ed7fbStbbdev }
795d86ed7fbStbbdev
796d86ed7fbStbbdev /* can a new run be started? */
797d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
798d86ed7fbStbbdev return False;
799d86ed7fbStbbdev
800d86ed7fbStbbdev /* Only caused by corrupt data stream? */
801d86ed7fbStbbdev if (s->nblock_used > s->save_nblock + 1)
802d86ed7fbStbbdev return True;
803d86ed7fbStbbdev
804d86ed7fbStbbdev s->state_out_len = 1;
805d86ed7fbStbbdev s->state_out_ch = s->k0;
806d86ed7fbStbbdev BZ_GET_SMALL(k1);
807d86ed7fbStbbdev BZ_RAND_UPD_MASK;
808d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
809d86ed7fbStbbdev s->nblock_used++;
810d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
811d86ed7fbStbbdev continue;
812d86ed7fbStbbdev if (k1 != s->k0) {
813d86ed7fbStbbdev s->k0 = k1;
814d86ed7fbStbbdev continue;
815d86ed7fbStbbdev };
816d86ed7fbStbbdev
817d86ed7fbStbbdev s->state_out_len = 2;
818d86ed7fbStbbdev BZ_GET_SMALL(k1);
819d86ed7fbStbbdev BZ_RAND_UPD_MASK;
820d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
821d86ed7fbStbbdev s->nblock_used++;
822d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
823d86ed7fbStbbdev continue;
824d86ed7fbStbbdev if (k1 != s->k0) {
825d86ed7fbStbbdev s->k0 = k1;
826d86ed7fbStbbdev continue;
827d86ed7fbStbbdev };
828d86ed7fbStbbdev
829d86ed7fbStbbdev s->state_out_len = 3;
830d86ed7fbStbbdev BZ_GET_SMALL(k1);
831d86ed7fbStbbdev BZ_RAND_UPD_MASK;
832d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
833d86ed7fbStbbdev s->nblock_used++;
834d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
835d86ed7fbStbbdev continue;
836d86ed7fbStbbdev if (k1 != s->k0) {
837d86ed7fbStbbdev s->k0 = k1;
838d86ed7fbStbbdev continue;
839d86ed7fbStbbdev };
840d86ed7fbStbbdev
841d86ed7fbStbbdev BZ_GET_SMALL(k1);
842d86ed7fbStbbdev BZ_RAND_UPD_MASK;
843d86ed7fbStbbdev k1 ^= BZ_RAND_MASK;
844d86ed7fbStbbdev s->nblock_used++;
845d86ed7fbStbbdev s->state_out_len = ((Int32)k1) + 4;
846d86ed7fbStbbdev BZ_GET_SMALL(s->k0);
847d86ed7fbStbbdev BZ_RAND_UPD_MASK;
848d86ed7fbStbbdev s->k0 ^= BZ_RAND_MASK;
849d86ed7fbStbbdev s->nblock_used++;
850d86ed7fbStbbdev }
851d86ed7fbStbbdev }
852d86ed7fbStbbdev else {
853d86ed7fbStbbdev while (True) {
854d86ed7fbStbbdev /* try to finish existing run */
855d86ed7fbStbbdev while (True) {
856d86ed7fbStbbdev if (s->strm->avail_out == 0)
857d86ed7fbStbbdev return False;
858d86ed7fbStbbdev if (s->state_out_len == 0)
859d86ed7fbStbbdev break;
860d86ed7fbStbbdev *((UChar*)(s->strm->next_out)) = s->state_out_ch;
861d86ed7fbStbbdev BZ_UPDATE_CRC(s->calculatedBlockCRC, s->state_out_ch);
862d86ed7fbStbbdev s->state_out_len--;
863d86ed7fbStbbdev s->strm->next_out++;
864d86ed7fbStbbdev s->strm->avail_out--;
865d86ed7fbStbbdev s->strm->total_out_lo32++;
866d86ed7fbStbbdev if (s->strm->total_out_lo32 == 0)
867d86ed7fbStbbdev s->strm->total_out_hi32++;
868d86ed7fbStbbdev }
869d86ed7fbStbbdev
870d86ed7fbStbbdev /* can a new run be started? */
871d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
872d86ed7fbStbbdev return False;
873d86ed7fbStbbdev
874d86ed7fbStbbdev /* Only caused by corrupt data stream? */
875d86ed7fbStbbdev if (s->nblock_used > s->save_nblock + 1)
876d86ed7fbStbbdev return True;
877d86ed7fbStbbdev
878d86ed7fbStbbdev s->state_out_len = 1;
879d86ed7fbStbbdev s->state_out_ch = s->k0;
880d86ed7fbStbbdev BZ_GET_SMALL(k1);
881d86ed7fbStbbdev s->nblock_used++;
882d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
883d86ed7fbStbbdev continue;
884d86ed7fbStbbdev if (k1 != s->k0) {
885d86ed7fbStbbdev s->k0 = k1;
886d86ed7fbStbbdev continue;
887d86ed7fbStbbdev };
888d86ed7fbStbbdev
889d86ed7fbStbbdev s->state_out_len = 2;
890d86ed7fbStbbdev BZ_GET_SMALL(k1);
891d86ed7fbStbbdev s->nblock_used++;
892d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
893d86ed7fbStbbdev continue;
894d86ed7fbStbbdev if (k1 != s->k0) {
895d86ed7fbStbbdev s->k0 = k1;
896d86ed7fbStbbdev continue;
897d86ed7fbStbbdev };
898d86ed7fbStbbdev
899d86ed7fbStbbdev s->state_out_len = 3;
900d86ed7fbStbbdev BZ_GET_SMALL(k1);
901d86ed7fbStbbdev s->nblock_used++;
902d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1)
903d86ed7fbStbbdev continue;
904d86ed7fbStbbdev if (k1 != s->k0) {
905d86ed7fbStbbdev s->k0 = k1;
906d86ed7fbStbbdev continue;
907d86ed7fbStbbdev };
908d86ed7fbStbbdev
909d86ed7fbStbbdev BZ_GET_SMALL(k1);
910d86ed7fbStbbdev s->nblock_used++;
911d86ed7fbStbbdev s->state_out_len = ((Int32)k1) + 4;
912d86ed7fbStbbdev BZ_GET_SMALL(s->k0);
913d86ed7fbStbbdev s->nblock_used++;
914d86ed7fbStbbdev }
915d86ed7fbStbbdev }
916d86ed7fbStbbdev }
917d86ed7fbStbbdev
918d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompress)919d86ed7fbStbbdev int BZ_API(BZ2_bzDecompress)(bz_stream* strm) {
920d86ed7fbStbbdev Bool corrupt;
921d86ed7fbStbbdev DState* s;
922d86ed7fbStbbdev if (strm == nullptr)
923d86ed7fbStbbdev return BZ_PARAM_ERROR;
924d86ed7fbStbbdev s = (DState*)strm->state;
925d86ed7fbStbbdev if (s == nullptr)
926d86ed7fbStbbdev return BZ_PARAM_ERROR;
927d86ed7fbStbbdev if (s->strm != strm)
928d86ed7fbStbbdev return BZ_PARAM_ERROR;
929d86ed7fbStbbdev
930d86ed7fbStbbdev while (True) {
931d86ed7fbStbbdev if (s->state == BZ_X_IDLE)
932d86ed7fbStbbdev return BZ_SEQUENCE_ERROR;
933d86ed7fbStbbdev if (s->state == BZ_X_OUTPUT) {
934d86ed7fbStbbdev if (s->smallDecompress)
935d86ed7fbStbbdev corrupt = unRLE_obuf_to_output_SMALL(s);
936d86ed7fbStbbdev else
937d86ed7fbStbbdev corrupt = unRLE_obuf_to_output_FAST(s);
938d86ed7fbStbbdev if (corrupt)
939d86ed7fbStbbdev return BZ_DATA_ERROR;
940d86ed7fbStbbdev if (s->nblock_used == s->save_nblock + 1 && s->state_out_len == 0) {
941d86ed7fbStbbdev BZ_FINALISE_CRC(s->calculatedBlockCRC);
942d86ed7fbStbbdev if (s->verbosity >= 3)
943d86ed7fbStbbdev VPrintf2(" {0x%08x, 0x%08x}", s->storedBlockCRC, s->calculatedBlockCRC);
944d86ed7fbStbbdev if (s->verbosity >= 2)
945d86ed7fbStbbdev VPrintf0("]");
946d86ed7fbStbbdev if (s->calculatedBlockCRC != s->storedBlockCRC)
947d86ed7fbStbbdev return BZ_DATA_ERROR;
948d86ed7fbStbbdev s->calculatedCombinedCRC =
949d86ed7fbStbbdev (s->calculatedCombinedCRC << 1) | (s->calculatedCombinedCRC >> 31);
950d86ed7fbStbbdev s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
951d86ed7fbStbbdev s->state = BZ_X_BLKHDR_1;
952d86ed7fbStbbdev }
953d86ed7fbStbbdev else {
954d86ed7fbStbbdev return BZ_OK;
955d86ed7fbStbbdev }
956d86ed7fbStbbdev }
957d86ed7fbStbbdev if (s->state >= BZ_X_MAGIC_1) {
958d86ed7fbStbbdev Int32 r = BZ2_decompress(s);
959d86ed7fbStbbdev if (r == BZ_STREAM_END) {
960d86ed7fbStbbdev if (s->verbosity >= 3)
961d86ed7fbStbbdev VPrintf2("\n combined CRCs: stored = 0x%08x, computed = 0x%08x",
962d86ed7fbStbbdev s->storedCombinedCRC,
963d86ed7fbStbbdev s->calculatedCombinedCRC);
964d86ed7fbStbbdev if (s->calculatedCombinedCRC != s->storedCombinedCRC)
965d86ed7fbStbbdev return BZ_DATA_ERROR;
966d86ed7fbStbbdev return r;
967d86ed7fbStbbdev }
968d86ed7fbStbbdev if (s->state != BZ_X_OUTPUT)
969d86ed7fbStbbdev return r;
970d86ed7fbStbbdev }
971d86ed7fbStbbdev }
972d86ed7fbStbbdev
973d86ed7fbStbbdev AssertH(0, 6001);
974d86ed7fbStbbdev
975d86ed7fbStbbdev return 0; /*NOTREACHED*/
976d86ed7fbStbbdev }
977d86ed7fbStbbdev
978d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzDecompressEnd)979d86ed7fbStbbdev int BZ_API(BZ2_bzDecompressEnd)(bz_stream* strm) {
980d86ed7fbStbbdev DState* s;
981d86ed7fbStbbdev if (strm == nullptr)
982d86ed7fbStbbdev return BZ_PARAM_ERROR;
983d86ed7fbStbbdev s = (DState*)strm->state;
984d86ed7fbStbbdev if (s == nullptr)
985d86ed7fbStbbdev return BZ_PARAM_ERROR;
986d86ed7fbStbbdev if (s->strm != strm)
987d86ed7fbStbbdev return BZ_PARAM_ERROR;
988d86ed7fbStbbdev
989d86ed7fbStbbdev if (s->tt != nullptr)
990d86ed7fbStbbdev BZFREE(s->tt);
991d86ed7fbStbbdev if (s->ll16 != nullptr)
992d86ed7fbStbbdev BZFREE(s->ll16);
993d86ed7fbStbbdev if (s->ll4 != nullptr)
994d86ed7fbStbbdev BZFREE(s->ll4);
995d86ed7fbStbbdev
996d86ed7fbStbbdev BZFREE(strm->state);
997d86ed7fbStbbdev strm->state = nullptr;
998d86ed7fbStbbdev
999d86ed7fbStbbdev return BZ_OK;
1000d86ed7fbStbbdev }
1001d86ed7fbStbbdev
1002d86ed7fbStbbdev #ifndef BZ_NO_STDIO
1003d86ed7fbStbbdev /*---------------------------------------------------*/
1004d86ed7fbStbbdev /*--- File I/O stuff ---*/
1005d86ed7fbStbbdev /*---------------------------------------------------*/
1006d86ed7fbStbbdev
1007d86ed7fbStbbdev #define BZ_SETERR(eee) \
1008d86ed7fbStbbdev { \
1009d86ed7fbStbbdev if (bzerror != nullptr) \
1010d86ed7fbStbbdev *bzerror = eee; \
1011d86ed7fbStbbdev if (bzf != nullptr) \
1012d86ed7fbStbbdev bzf->lastErr = eee; \
1013d86ed7fbStbbdev }
1014d86ed7fbStbbdev
1015d86ed7fbStbbdev typedef struct {
1016d86ed7fbStbbdev FILE* handle;
1017d86ed7fbStbbdev Char buf[BZ_MAX_UNUSED];
1018d86ed7fbStbbdev Int32 bufN;
1019d86ed7fbStbbdev Bool writing;
1020d86ed7fbStbbdev bz_stream strm;
1021d86ed7fbStbbdev Int32 lastErr;
1022d86ed7fbStbbdev Bool initialisedOk;
1023d86ed7fbStbbdev } bzFile;
1024d86ed7fbStbbdev
1025d86ed7fbStbbdev /*---------------------------------------------*/
myfeof(FILE * f)1026d86ed7fbStbbdev static Bool myfeof(FILE* f) {
1027d86ed7fbStbbdev Int32 c = fgetc(f);
1028d86ed7fbStbbdev if (c == EOF)
1029d86ed7fbStbbdev return True;
1030d86ed7fbStbbdev ungetc(c, f);
1031d86ed7fbStbbdev return False;
1032d86ed7fbStbbdev }
1033d86ed7fbStbbdev
1034d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteOpen)1035d86ed7fbStbbdev BZFILE* BZ_API(
1036d86ed7fbStbbdev BZ2_bzWriteOpen)(int* bzerror, FILE* f, int blockSize100k, int verbosity, int workFactor) {
1037d86ed7fbStbbdev Int32 ret;
1038d86ed7fbStbbdev bzFile* bzf = nullptr;
1039d86ed7fbStbbdev
1040d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1041d86ed7fbStbbdev
1042d86ed7fbStbbdev if (f == nullptr || (blockSize100k < 1 || blockSize100k > 9) ||
1043d86ed7fbStbbdev (workFactor < 0 || workFactor > 250) || (verbosity < 0 || verbosity > 4)) {
1044d86ed7fbStbbdev BZ_SETERR(BZ_PARAM_ERROR);
1045d86ed7fbStbbdev return nullptr;
1046d86ed7fbStbbdev };
1047d86ed7fbStbbdev
1048d86ed7fbStbbdev if (ferror(f)) {
1049d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1050d86ed7fbStbbdev return nullptr;
1051d86ed7fbStbbdev };
1052d86ed7fbStbbdev
1053d86ed7fbStbbdev bzf = (bzFile*)malloc(sizeof(bzFile));
1054d86ed7fbStbbdev if (bzf == nullptr) {
1055d86ed7fbStbbdev BZ_SETERR(BZ_MEM_ERROR);
1056d86ed7fbStbbdev return nullptr;
1057d86ed7fbStbbdev };
1058d86ed7fbStbbdev
1059d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1060d86ed7fbStbbdev bzf->initialisedOk = False;
1061d86ed7fbStbbdev bzf->bufN = 0;
1062d86ed7fbStbbdev bzf->handle = f;
1063d86ed7fbStbbdev bzf->writing = True;
1064d86ed7fbStbbdev bzf->strm.bzalloc = nullptr;
1065d86ed7fbStbbdev bzf->strm.bzfree = nullptr;
1066d86ed7fbStbbdev bzf->strm.opaque = nullptr;
1067d86ed7fbStbbdev
1068d86ed7fbStbbdev if (workFactor == 0)
1069d86ed7fbStbbdev workFactor = 30;
1070d86ed7fbStbbdev ret = BZ2_bzCompressInit(&(bzf->strm), blockSize100k, verbosity, workFactor);
1071d86ed7fbStbbdev if (ret != BZ_OK) {
1072d86ed7fbStbbdev BZ_SETERR(ret);
1073d86ed7fbStbbdev free(bzf);
1074d86ed7fbStbbdev return nullptr;
1075d86ed7fbStbbdev };
1076d86ed7fbStbbdev
1077d86ed7fbStbbdev bzf->strm.avail_in = 0;
1078d86ed7fbStbbdev bzf->initialisedOk = True;
1079d86ed7fbStbbdev return bzf;
1080d86ed7fbStbbdev }
1081d86ed7fbStbbdev
1082d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzWrite)1083d86ed7fbStbbdev void BZ_API(BZ2_bzWrite)(int* bzerror, BZFILE* b, void* buf, int len) {
1084d86ed7fbStbbdev Int32 n, n2, ret;
1085d86ed7fbStbbdev bzFile* bzf = (bzFile*)b;
1086d86ed7fbStbbdev
1087d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1088d86ed7fbStbbdev if (bzf == nullptr || buf == nullptr || len < 0) {
1089d86ed7fbStbbdev BZ_SETERR(BZ_PARAM_ERROR);
1090d86ed7fbStbbdev return;
1091d86ed7fbStbbdev };
1092d86ed7fbStbbdev if (!(bzf->writing)) {
1093d86ed7fbStbbdev BZ_SETERR(BZ_SEQUENCE_ERROR);
1094d86ed7fbStbbdev return;
1095d86ed7fbStbbdev };
1096d86ed7fbStbbdev if (ferror(bzf->handle)) {
1097d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1098d86ed7fbStbbdev return;
1099d86ed7fbStbbdev };
1100d86ed7fbStbbdev
1101d86ed7fbStbbdev if (len == 0) {
1102d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1103d86ed7fbStbbdev return;
1104d86ed7fbStbbdev };
1105d86ed7fbStbbdev
1106d86ed7fbStbbdev bzf->strm.avail_in = len;
1107d86ed7fbStbbdev bzf->strm.next_in = (char*)buf;
1108d86ed7fbStbbdev
1109d86ed7fbStbbdev while (True) {
1110d86ed7fbStbbdev bzf->strm.avail_out = BZ_MAX_UNUSED;
1111d86ed7fbStbbdev bzf->strm.next_out = bzf->buf;
1112d86ed7fbStbbdev ret = BZ2_bzCompress(&(bzf->strm), BZ_RUN);
1113d86ed7fbStbbdev if (ret != BZ_RUN_OK) {
1114d86ed7fbStbbdev BZ_SETERR(ret);
1115d86ed7fbStbbdev return;
1116d86ed7fbStbbdev };
1117d86ed7fbStbbdev
1118d86ed7fbStbbdev if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1119d86ed7fbStbbdev n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1120d86ed7fbStbbdev n2 = fwrite((void*)(bzf->buf), sizeof(UChar), n, bzf->handle);
1121d86ed7fbStbbdev if (n != n2 || ferror(bzf->handle)) {
1122d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1123d86ed7fbStbbdev return;
1124d86ed7fbStbbdev };
1125d86ed7fbStbbdev }
1126d86ed7fbStbbdev
1127d86ed7fbStbbdev if (bzf->strm.avail_in == 0) {
1128d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1129d86ed7fbStbbdev return;
1130d86ed7fbStbbdev };
1131d86ed7fbStbbdev }
1132d86ed7fbStbbdev }
1133d86ed7fbStbbdev
1134d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzWriteClose)1135d86ed7fbStbbdev void BZ_API(BZ2_bzWriteClose)(int* bzerror,
1136d86ed7fbStbbdev BZFILE* b,
1137d86ed7fbStbbdev int abandon,
1138d86ed7fbStbbdev unsigned int* nbytes_in,
1139d86ed7fbStbbdev unsigned int* nbytes_out) {
1140d86ed7fbStbbdev BZ2_bzWriteClose64(bzerror, b, abandon, nbytes_in, nullptr, nbytes_out, nullptr);
1141d86ed7fbStbbdev }
1142d86ed7fbStbbdev
BZ_API(BZ2_bzWriteClose64)1143d86ed7fbStbbdev void BZ_API(BZ2_bzWriteClose64)(int* bzerror,
1144d86ed7fbStbbdev BZFILE* b,
1145d86ed7fbStbbdev int abandon,
1146d86ed7fbStbbdev unsigned int* nbytes_in_lo32,
1147d86ed7fbStbbdev unsigned int* nbytes_in_hi32,
1148d86ed7fbStbbdev unsigned int* nbytes_out_lo32,
1149d86ed7fbStbbdev unsigned int* nbytes_out_hi32) {
1150d86ed7fbStbbdev Int32 n, n2, ret;
1151d86ed7fbStbbdev bzFile* bzf = (bzFile*)b;
1152d86ed7fbStbbdev
1153d86ed7fbStbbdev if (bzf == nullptr) {
1154d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1155d86ed7fbStbbdev return;
1156d86ed7fbStbbdev };
1157d86ed7fbStbbdev if (!(bzf->writing)) {
1158d86ed7fbStbbdev BZ_SETERR(BZ_SEQUENCE_ERROR);
1159d86ed7fbStbbdev return;
1160d86ed7fbStbbdev };
1161d86ed7fbStbbdev if (ferror(bzf->handle)) {
1162d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1163d86ed7fbStbbdev return;
1164d86ed7fbStbbdev };
1165d86ed7fbStbbdev
1166d86ed7fbStbbdev if (nbytes_in_lo32 != nullptr)
1167d86ed7fbStbbdev *nbytes_in_lo32 = 0;
1168d86ed7fbStbbdev if (nbytes_in_hi32 != nullptr)
1169d86ed7fbStbbdev *nbytes_in_hi32 = 0;
1170d86ed7fbStbbdev if (nbytes_out_lo32 != nullptr)
1171d86ed7fbStbbdev *nbytes_out_lo32 = 0;
1172d86ed7fbStbbdev if (nbytes_out_hi32 != nullptr)
1173d86ed7fbStbbdev *nbytes_out_hi32 = 0;
1174d86ed7fbStbbdev
1175d86ed7fbStbbdev if ((!abandon) && bzf->lastErr == BZ_OK) {
1176d86ed7fbStbbdev while (True) {
1177d86ed7fbStbbdev bzf->strm.avail_out = BZ_MAX_UNUSED;
1178d86ed7fbStbbdev bzf->strm.next_out = bzf->buf;
1179d86ed7fbStbbdev ret = BZ2_bzCompress(&(bzf->strm), BZ_FINISH);
1180d86ed7fbStbbdev if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) {
1181d86ed7fbStbbdev BZ_SETERR(ret);
1182d86ed7fbStbbdev return;
1183d86ed7fbStbbdev };
1184d86ed7fbStbbdev
1185d86ed7fbStbbdev if (bzf->strm.avail_out < BZ_MAX_UNUSED) {
1186d86ed7fbStbbdev n = BZ_MAX_UNUSED - bzf->strm.avail_out;
1187d86ed7fbStbbdev n2 = fwrite((void*)(bzf->buf), sizeof(UChar), n, bzf->handle);
1188d86ed7fbStbbdev if (n != n2 || ferror(bzf->handle)) {
1189d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1190d86ed7fbStbbdev return;
1191d86ed7fbStbbdev };
1192d86ed7fbStbbdev }
1193d86ed7fbStbbdev
1194d86ed7fbStbbdev if (ret == BZ_STREAM_END)
1195d86ed7fbStbbdev break;
1196d86ed7fbStbbdev }
1197d86ed7fbStbbdev }
1198d86ed7fbStbbdev
1199d86ed7fbStbbdev if (!abandon && !ferror(bzf->handle)) {
1200d86ed7fbStbbdev fflush(bzf->handle);
1201d86ed7fbStbbdev if (ferror(bzf->handle)) {
1202d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1203d86ed7fbStbbdev return;
1204d86ed7fbStbbdev };
1205d86ed7fbStbbdev }
1206d86ed7fbStbbdev
1207d86ed7fbStbbdev if (nbytes_in_lo32 != nullptr)
1208d86ed7fbStbbdev *nbytes_in_lo32 = bzf->strm.total_in_lo32;
1209d86ed7fbStbbdev if (nbytes_in_hi32 != nullptr)
1210d86ed7fbStbbdev *nbytes_in_hi32 = bzf->strm.total_in_hi32;
1211d86ed7fbStbbdev if (nbytes_out_lo32 != nullptr)
1212d86ed7fbStbbdev *nbytes_out_lo32 = bzf->strm.total_out_lo32;
1213d86ed7fbStbbdev if (nbytes_out_hi32 != nullptr)
1214d86ed7fbStbbdev *nbytes_out_hi32 = bzf->strm.total_out_hi32;
1215d86ed7fbStbbdev
1216d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1217d86ed7fbStbbdev BZ2_bzCompressEnd(&(bzf->strm));
1218d86ed7fbStbbdev free(bzf);
1219d86ed7fbStbbdev }
1220d86ed7fbStbbdev
1221d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzReadOpen)1222d86ed7fbStbbdev BZFILE* BZ_API(
1223d86ed7fbStbbdev BZ2_bzReadOpen)(int* bzerror, FILE* f, int verbosity, int small, void* unused, int nUnused) {
1224d86ed7fbStbbdev bzFile* bzf = nullptr;
1225d86ed7fbStbbdev int ret;
1226d86ed7fbStbbdev
1227d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1228d86ed7fbStbbdev
1229d86ed7fbStbbdev if (f == nullptr || (small != 0 && small != 1) || (verbosity < 0 || verbosity > 4) ||
1230d86ed7fbStbbdev (unused == nullptr && nUnused != 0) ||
1231d86ed7fbStbbdev (unused != nullptr && (nUnused < 0 || nUnused > BZ_MAX_UNUSED))) {
1232d86ed7fbStbbdev BZ_SETERR(BZ_PARAM_ERROR);
1233d86ed7fbStbbdev return nullptr;
1234d86ed7fbStbbdev };
1235d86ed7fbStbbdev
1236d86ed7fbStbbdev if (ferror(f)) {
1237d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1238d86ed7fbStbbdev return nullptr;
1239d86ed7fbStbbdev };
1240d86ed7fbStbbdev
1241d86ed7fbStbbdev bzf = (bzFile*)malloc(sizeof(bzFile));
1242d86ed7fbStbbdev if (bzf == nullptr) {
1243d86ed7fbStbbdev BZ_SETERR(BZ_MEM_ERROR);
1244d86ed7fbStbbdev return nullptr;
1245d86ed7fbStbbdev };
1246d86ed7fbStbbdev
1247d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1248d86ed7fbStbbdev
1249d86ed7fbStbbdev bzf->initialisedOk = False;
1250d86ed7fbStbbdev bzf->handle = f;
1251d86ed7fbStbbdev bzf->bufN = 0;
1252d86ed7fbStbbdev bzf->writing = False;
1253d86ed7fbStbbdev bzf->strm.bzalloc = nullptr;
1254d86ed7fbStbbdev bzf->strm.bzfree = nullptr;
1255d86ed7fbStbbdev bzf->strm.opaque = nullptr;
1256d86ed7fbStbbdev
1257d86ed7fbStbbdev while (nUnused > 0) {
1258d86ed7fbStbbdev bzf->buf[bzf->bufN] = *((UChar*)(unused));
1259d86ed7fbStbbdev bzf->bufN++;
1260d86ed7fbStbbdev unused = ((void*)(1 + ((UChar*)(unused))));
1261d86ed7fbStbbdev nUnused--;
1262d86ed7fbStbbdev }
1263d86ed7fbStbbdev
1264d86ed7fbStbbdev ret = BZ2_bzDecompressInit(&(bzf->strm), verbosity, small);
1265d86ed7fbStbbdev if (ret != BZ_OK) {
1266d86ed7fbStbbdev BZ_SETERR(ret);
1267d86ed7fbStbbdev free(bzf);
1268d86ed7fbStbbdev return nullptr;
1269d86ed7fbStbbdev };
1270d86ed7fbStbbdev
1271d86ed7fbStbbdev bzf->strm.avail_in = bzf->bufN;
1272d86ed7fbStbbdev bzf->strm.next_in = bzf->buf;
1273d86ed7fbStbbdev
1274d86ed7fbStbbdev bzf->initialisedOk = True;
1275d86ed7fbStbbdev return bzf;
1276d86ed7fbStbbdev }
1277d86ed7fbStbbdev
1278d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzReadClose)1279d86ed7fbStbbdev void BZ_API(BZ2_bzReadClose)(int* bzerror, BZFILE* b) {
1280d86ed7fbStbbdev bzFile* bzf = (bzFile*)b;
1281d86ed7fbStbbdev
1282d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1283d86ed7fbStbbdev if (bzf == nullptr) {
1284d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1285d86ed7fbStbbdev return;
1286d86ed7fbStbbdev };
1287d86ed7fbStbbdev
1288d86ed7fbStbbdev if (bzf->writing) {
1289d86ed7fbStbbdev BZ_SETERR(BZ_SEQUENCE_ERROR);
1290d86ed7fbStbbdev return;
1291d86ed7fbStbbdev };
1292d86ed7fbStbbdev
1293d86ed7fbStbbdev if (bzf->initialisedOk)
1294d86ed7fbStbbdev (void)BZ2_bzDecompressEnd(&(bzf->strm));
1295d86ed7fbStbbdev free(bzf);
1296d86ed7fbStbbdev }
1297d86ed7fbStbbdev
1298d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzRead)1299d86ed7fbStbbdev int BZ_API(BZ2_bzRead)(int* bzerror, BZFILE* b, void* buf, int len) {
1300d86ed7fbStbbdev Int32 n, ret;
1301d86ed7fbStbbdev bzFile* bzf = (bzFile*)b;
1302d86ed7fbStbbdev
1303d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1304d86ed7fbStbbdev
1305d86ed7fbStbbdev if (bzf == nullptr || buf == nullptr || len < 0) {
1306d86ed7fbStbbdev BZ_SETERR(BZ_PARAM_ERROR);
1307d86ed7fbStbbdev return 0;
1308d86ed7fbStbbdev };
1309d86ed7fbStbbdev
1310d86ed7fbStbbdev if (bzf->writing) {
1311d86ed7fbStbbdev BZ_SETERR(BZ_SEQUENCE_ERROR);
1312d86ed7fbStbbdev return 0;
1313d86ed7fbStbbdev };
1314d86ed7fbStbbdev
1315d86ed7fbStbbdev if (len == 0) {
1316d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1317d86ed7fbStbbdev return 0;
1318d86ed7fbStbbdev };
1319d86ed7fbStbbdev
1320d86ed7fbStbbdev bzf->strm.avail_out = len;
1321d86ed7fbStbbdev bzf->strm.next_out = (char*)buf;
1322d86ed7fbStbbdev
1323d86ed7fbStbbdev while (True) {
1324d86ed7fbStbbdev if (ferror(bzf->handle)) {
1325d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1326d86ed7fbStbbdev return 0;
1327d86ed7fbStbbdev };
1328d86ed7fbStbbdev
1329d86ed7fbStbbdev if (bzf->strm.avail_in == 0 && !myfeof(bzf->handle)) {
1330d86ed7fbStbbdev n = fread(bzf->buf, sizeof(UChar), BZ_MAX_UNUSED, bzf->handle);
1331d86ed7fbStbbdev if (ferror(bzf->handle)) {
1332d86ed7fbStbbdev BZ_SETERR(BZ_IO_ERROR);
1333d86ed7fbStbbdev return 0;
1334d86ed7fbStbbdev };
1335d86ed7fbStbbdev bzf->bufN = n;
1336d86ed7fbStbbdev bzf->strm.avail_in = bzf->bufN;
1337d86ed7fbStbbdev bzf->strm.next_in = bzf->buf;
1338d86ed7fbStbbdev }
1339d86ed7fbStbbdev
1340d86ed7fbStbbdev ret = BZ2_bzDecompress(&(bzf->strm));
1341d86ed7fbStbbdev
1342d86ed7fbStbbdev if (ret != BZ_OK && ret != BZ_STREAM_END) {
1343d86ed7fbStbbdev BZ_SETERR(ret);
1344d86ed7fbStbbdev return 0;
1345d86ed7fbStbbdev };
1346d86ed7fbStbbdev
1347d86ed7fbStbbdev if (ret == BZ_OK && myfeof(bzf->handle) && bzf->strm.avail_in == 0 &&
1348d86ed7fbStbbdev bzf->strm.avail_out > 0) {
1349d86ed7fbStbbdev BZ_SETERR(BZ_UNEXPECTED_EOF);
1350d86ed7fbStbbdev return 0;
1351d86ed7fbStbbdev };
1352d86ed7fbStbbdev
1353d86ed7fbStbbdev if (ret == BZ_STREAM_END) {
1354d86ed7fbStbbdev BZ_SETERR(BZ_STREAM_END);
1355d86ed7fbStbbdev return len - bzf->strm.avail_out;
1356d86ed7fbStbbdev };
1357d86ed7fbStbbdev if (bzf->strm.avail_out == 0) {
1358d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1359d86ed7fbStbbdev return len;
1360d86ed7fbStbbdev };
1361d86ed7fbStbbdev }
1362d86ed7fbStbbdev
1363d86ed7fbStbbdev return 0; /*not reached*/
1364d86ed7fbStbbdev }
1365d86ed7fbStbbdev
1366d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzReadGetUnused)1367d86ed7fbStbbdev void BZ_API(BZ2_bzReadGetUnused)(int* bzerror, BZFILE* b, void** unused, int* nUnused) {
1368d86ed7fbStbbdev bzFile* bzf = (bzFile*)b;
1369d86ed7fbStbbdev if (bzf == nullptr) {
1370d86ed7fbStbbdev BZ_SETERR(BZ_PARAM_ERROR);
1371d86ed7fbStbbdev return;
1372d86ed7fbStbbdev };
1373d86ed7fbStbbdev if (bzf->lastErr != BZ_STREAM_END) {
1374d86ed7fbStbbdev BZ_SETERR(BZ_SEQUENCE_ERROR);
1375d86ed7fbStbbdev return;
1376d86ed7fbStbbdev };
1377d86ed7fbStbbdev if (unused == nullptr || nUnused == nullptr) {
1378d86ed7fbStbbdev BZ_SETERR(BZ_PARAM_ERROR);
1379d86ed7fbStbbdev return;
1380d86ed7fbStbbdev };
1381d86ed7fbStbbdev
1382d86ed7fbStbbdev BZ_SETERR(BZ_OK);
1383d86ed7fbStbbdev *nUnused = bzf->strm.avail_in;
1384d86ed7fbStbbdev *unused = bzf->strm.next_in;
1385d86ed7fbStbbdev }
1386d86ed7fbStbbdev #endif
1387d86ed7fbStbbdev
1388d86ed7fbStbbdev /*---------------------------------------------------*/
1389d86ed7fbStbbdev /*--- Misc convenience stuff ---*/
1390d86ed7fbStbbdev /*---------------------------------------------------*/
1391d86ed7fbStbbdev
1392d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffCompress)1393d86ed7fbStbbdev int BZ_API(BZ2_bzBuffToBuffCompress)(char* dest,
1394d86ed7fbStbbdev unsigned int* destLen,
1395d86ed7fbStbbdev char* source,
1396d86ed7fbStbbdev unsigned int sourceLen,
1397d86ed7fbStbbdev int blockSize100k,
1398d86ed7fbStbbdev int verbosity,
1399d86ed7fbStbbdev int workFactor) {
1400d86ed7fbStbbdev bz_stream strm;
1401d86ed7fbStbbdev int ret;
1402d86ed7fbStbbdev
1403d86ed7fbStbbdev if (dest == nullptr || destLen == nullptr || source == nullptr || blockSize100k < 1 ||
1404d86ed7fbStbbdev blockSize100k > 9 || verbosity < 0 || verbosity > 4 || workFactor < 0 || workFactor > 250)
1405d86ed7fbStbbdev return BZ_PARAM_ERROR;
1406d86ed7fbStbbdev
1407d86ed7fbStbbdev if (workFactor == 0)
1408d86ed7fbStbbdev workFactor = 30;
1409d86ed7fbStbbdev strm.bzalloc = nullptr;
1410d86ed7fbStbbdev strm.bzfree = nullptr;
1411d86ed7fbStbbdev strm.opaque = nullptr;
1412d86ed7fbStbbdev ret = BZ2_bzCompressInit(&strm, blockSize100k, verbosity, workFactor);
1413d86ed7fbStbbdev if (ret != BZ_OK)
1414d86ed7fbStbbdev return ret;
1415d86ed7fbStbbdev
1416d86ed7fbStbbdev strm.next_in = source;
1417d86ed7fbStbbdev strm.next_out = dest;
1418d86ed7fbStbbdev strm.avail_in = sourceLen;
1419d86ed7fbStbbdev strm.avail_out = *destLen;
1420d86ed7fbStbbdev
1421d86ed7fbStbbdev ret = BZ2_bzCompress(&strm, BZ_FINISH);
1422d86ed7fbStbbdev if (ret == BZ_FINISH_OK)
1423d86ed7fbStbbdev goto output_overflow;
1424d86ed7fbStbbdev if (ret != BZ_STREAM_END)
1425d86ed7fbStbbdev goto errhandler;
1426d86ed7fbStbbdev
1427d86ed7fbStbbdev /* normal termination */
1428d86ed7fbStbbdev *destLen -= strm.avail_out;
1429d86ed7fbStbbdev BZ2_bzCompressEnd(&strm);
1430d86ed7fbStbbdev return BZ_OK;
1431d86ed7fbStbbdev
1432d86ed7fbStbbdev output_overflow:
1433d86ed7fbStbbdev BZ2_bzCompressEnd(&strm);
1434d86ed7fbStbbdev return BZ_OUTBUFF_FULL;
1435d86ed7fbStbbdev
1436d86ed7fbStbbdev errhandler:
1437d86ed7fbStbbdev BZ2_bzCompressEnd(&strm);
1438d86ed7fbStbbdev return ret;
1439d86ed7fbStbbdev }
1440d86ed7fbStbbdev
1441d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzBuffToBuffDecompress)1442d86ed7fbStbbdev int BZ_API(BZ2_bzBuffToBuffDecompress)(char* dest,
1443d86ed7fbStbbdev unsigned int* destLen,
1444d86ed7fbStbbdev char* source,
1445d86ed7fbStbbdev unsigned int sourceLen,
1446d86ed7fbStbbdev int small,
1447d86ed7fbStbbdev int verbosity) {
1448d86ed7fbStbbdev bz_stream strm;
1449d86ed7fbStbbdev int ret;
1450d86ed7fbStbbdev
1451d86ed7fbStbbdev if (dest == nullptr || destLen == nullptr || source == nullptr || (small != 0 && small != 1) ||
1452d86ed7fbStbbdev verbosity < 0 || verbosity > 4)
1453d86ed7fbStbbdev return BZ_PARAM_ERROR;
1454d86ed7fbStbbdev
1455d86ed7fbStbbdev strm.bzalloc = nullptr;
1456d86ed7fbStbbdev strm.bzfree = nullptr;
1457d86ed7fbStbbdev strm.opaque = nullptr;
1458d86ed7fbStbbdev ret = BZ2_bzDecompressInit(&strm, verbosity, small);
1459d86ed7fbStbbdev if (ret != BZ_OK)
1460d86ed7fbStbbdev return ret;
1461d86ed7fbStbbdev
1462d86ed7fbStbbdev strm.next_in = source;
1463d86ed7fbStbbdev strm.next_out = dest;
1464d86ed7fbStbbdev strm.avail_in = sourceLen;
1465d86ed7fbStbbdev strm.avail_out = *destLen;
1466d86ed7fbStbbdev
1467d86ed7fbStbbdev ret = BZ2_bzDecompress(&strm);
1468d86ed7fbStbbdev if (ret == BZ_OK)
1469d86ed7fbStbbdev goto output_overflow_or_eof;
1470d86ed7fbStbbdev if (ret != BZ_STREAM_END)
1471d86ed7fbStbbdev goto errhandler;
1472d86ed7fbStbbdev
1473d86ed7fbStbbdev /* normal termination */
1474d86ed7fbStbbdev *destLen -= strm.avail_out;
1475d86ed7fbStbbdev BZ2_bzDecompressEnd(&strm);
1476d86ed7fbStbbdev return BZ_OK;
1477d86ed7fbStbbdev
1478d86ed7fbStbbdev output_overflow_or_eof:
1479d86ed7fbStbbdev if (strm.avail_out > 0) {
1480d86ed7fbStbbdev BZ2_bzDecompressEnd(&strm);
1481d86ed7fbStbbdev return BZ_UNEXPECTED_EOF;
1482d86ed7fbStbbdev }
1483d86ed7fbStbbdev else {
1484d86ed7fbStbbdev BZ2_bzDecompressEnd(&strm);
1485d86ed7fbStbbdev return BZ_OUTBUFF_FULL;
1486d86ed7fbStbbdev };
1487d86ed7fbStbbdev
1488d86ed7fbStbbdev errhandler:
1489d86ed7fbStbbdev BZ2_bzDecompressEnd(&strm);
1490d86ed7fbStbbdev return ret;
1491d86ed7fbStbbdev }
1492d86ed7fbStbbdev
1493d86ed7fbStbbdev /*---------------------------------------------------*/
1494d86ed7fbStbbdev /*--
1495d86ed7fbStbbdev Code contributed by Yoshioka Tsuneo ([email protected])
1496d86ed7fbStbbdev to support better zlib compatibility.
1497d86ed7fbStbbdev This code is not _officially_ part of libbzip2 (yet);
1498d86ed7fbStbbdev I haven't tested it, documented it, or considered the
1499d86ed7fbStbbdev threading-safeness of it.
1500d86ed7fbStbbdev If this code breaks, please contact both Yoshioka and me.
1501d86ed7fbStbbdev --*/
1502d86ed7fbStbbdev /*---------------------------------------------------*/
1503d86ed7fbStbbdev
1504d86ed7fbStbbdev /*---------------------------------------------------*/
1505d86ed7fbStbbdev /*--
1506d86ed7fbStbbdev return version like "0.9.5d, 4-Sept-1999".
1507d86ed7fbStbbdev --*/
BZ_API(BZ2_bzlibVersion)1508d86ed7fbStbbdev const char* BZ_API(BZ2_bzlibVersion)(void) {
1509d86ed7fbStbbdev return BZ_VERSION;
1510d86ed7fbStbbdev }
1511d86ed7fbStbbdev
1512d86ed7fbStbbdev #ifndef BZ_NO_STDIO
1513d86ed7fbStbbdev /*---------------------------------------------------*/
1514d86ed7fbStbbdev
1515d86ed7fbStbbdev #if defined(_WIN32) || defined(OS2) || defined(MSDOS)
1516d86ed7fbStbbdev #include <fcntl.h>
1517d86ed7fbStbbdev #include <io.h>
1518d86ed7fbStbbdev #define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
1519d86ed7fbStbbdev #else
1520d86ed7fbStbbdev #define SET_BINARY_MODE(file)
1521d86ed7fbStbbdev #endif
bzopen_or_bzdopen(const char * path,int fd,const char * mode,int open_mode)1522d86ed7fbStbbdev static BZFILE* bzopen_or_bzdopen(const char* path, /* no use when bzdopen */
1523d86ed7fbStbbdev int fd, /* no use when bzdopen */
1524d86ed7fbStbbdev const char* mode,
1525d86ed7fbStbbdev int open_mode) /* bzopen: 0, bzdopen:1 */
1526d86ed7fbStbbdev {
1527d86ed7fbStbbdev int bzerr;
1528d86ed7fbStbbdev char unused[BZ_MAX_UNUSED];
1529d86ed7fbStbbdev int blockSize100k = 9;
1530d86ed7fbStbbdev int writing = 0;
1531d86ed7fbStbbdev char mode2[10] = "";
1532d86ed7fbStbbdev FILE* fp = nullptr;
1533d86ed7fbStbbdev BZFILE* bzfp = nullptr;
1534d86ed7fbStbbdev int verbosity = 0;
1535d86ed7fbStbbdev int workFactor = 30;
1536d86ed7fbStbbdev int smallMode = 0;
1537d86ed7fbStbbdev int nUnused = 0;
1538d86ed7fbStbbdev
1539d86ed7fbStbbdev if (mode == nullptr)
1540d86ed7fbStbbdev return nullptr;
1541d86ed7fbStbbdev while (*mode) {
1542d86ed7fbStbbdev switch (*mode) {
1543d86ed7fbStbbdev case 'r': writing = 0; break;
1544d86ed7fbStbbdev case 'w': writing = 1; break;
1545d86ed7fbStbbdev case 's': smallMode = 1; break;
1546d86ed7fbStbbdev default:
1547d86ed7fbStbbdev if (isdigit((int)(*mode))) {
1548d86ed7fbStbbdev blockSize100k = *mode - BZ_HDR_0;
1549d86ed7fbStbbdev }
1550d86ed7fbStbbdev }
1551d86ed7fbStbbdev mode++;
1552d86ed7fbStbbdev }
1553d86ed7fbStbbdev strcat(mode2, writing ? "w" : "r");
1554d86ed7fbStbbdev strcat(mode2, "b"); /* binary mode */
1555d86ed7fbStbbdev
1556d86ed7fbStbbdev if (open_mode == 0) {
1557d86ed7fbStbbdev if (path == nullptr || strcmp(path, "") == 0) {
1558d86ed7fbStbbdev fp = (writing ? stdout : stdin);
1559d86ed7fbStbbdev SET_BINARY_MODE(fp);
1560d86ed7fbStbbdev }
1561d86ed7fbStbbdev else {
1562d86ed7fbStbbdev fp = fopen(path, mode2);
1563d86ed7fbStbbdev }
1564d86ed7fbStbbdev }
1565d86ed7fbStbbdev else {
1566d86ed7fbStbbdev #ifdef BZ_STRICT_ANSI
1567d86ed7fbStbbdev fp = nullptr;
1568d86ed7fbStbbdev #else
1569d86ed7fbStbbdev fp = fdopen(fd, mode2);
1570d86ed7fbStbbdev #endif
1571d86ed7fbStbbdev }
1572d86ed7fbStbbdev if (fp == nullptr)
1573d86ed7fbStbbdev return nullptr;
1574d86ed7fbStbbdev
1575d86ed7fbStbbdev if (writing) {
1576d86ed7fbStbbdev /* Guard against total chaos and anarchy -- JRS */
1577d86ed7fbStbbdev if (blockSize100k < 1)
1578d86ed7fbStbbdev blockSize100k = 1;
1579d86ed7fbStbbdev if (blockSize100k > 9)
1580d86ed7fbStbbdev blockSize100k = 9;
1581d86ed7fbStbbdev bzfp = BZ2_bzWriteOpen(&bzerr, fp, blockSize100k, verbosity, workFactor);
1582d86ed7fbStbbdev }
1583d86ed7fbStbbdev else {
1584d86ed7fbStbbdev bzfp = BZ2_bzReadOpen(&bzerr, fp, verbosity, smallMode, unused, nUnused);
1585d86ed7fbStbbdev }
1586d86ed7fbStbbdev if (bzfp == nullptr) {
1587d86ed7fbStbbdev if (fp != stdin && fp != stdout)
1588d86ed7fbStbbdev fclose(fp);
1589d86ed7fbStbbdev return nullptr;
1590d86ed7fbStbbdev }
1591d86ed7fbStbbdev return bzfp;
1592d86ed7fbStbbdev }
1593d86ed7fbStbbdev
1594d86ed7fbStbbdev /*---------------------------------------------------*/
1595d86ed7fbStbbdev /*--
1596d86ed7fbStbbdev open file for read or write.
1597d86ed7fbStbbdev ex) bzopen("file","w9")
1598d86ed7fbStbbdev case path="" or nullptr => use stdin or stdout.
1599d86ed7fbStbbdev --*/
BZ_API(BZ2_bzopen)1600d86ed7fbStbbdev BZFILE* BZ_API(BZ2_bzopen)(const char* path, const char* mode) {
1601d86ed7fbStbbdev return bzopen_or_bzdopen(path, -1, mode, /*bzopen*/ 0);
1602d86ed7fbStbbdev }
1603d86ed7fbStbbdev
1604d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzdopen)1605d86ed7fbStbbdev BZFILE* BZ_API(BZ2_bzdopen)(int fd, const char* mode) {
1606d86ed7fbStbbdev return bzopen_or_bzdopen(nullptr, fd, mode, /*bzdopen*/ 1);
1607d86ed7fbStbbdev }
1608d86ed7fbStbbdev
1609d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzread)1610d86ed7fbStbbdev int BZ_API(BZ2_bzread)(BZFILE* b, void* buf, int len) {
1611d86ed7fbStbbdev int bzerr, nread;
1612d86ed7fbStbbdev if (((bzFile*)b)->lastErr == BZ_STREAM_END)
1613d86ed7fbStbbdev return 0;
1614d86ed7fbStbbdev nread = BZ2_bzRead(&bzerr, b, buf, len);
1615d86ed7fbStbbdev if (bzerr == BZ_OK || bzerr == BZ_STREAM_END) {
1616d86ed7fbStbbdev return nread;
1617d86ed7fbStbbdev }
1618d86ed7fbStbbdev else {
1619d86ed7fbStbbdev return -1;
1620d86ed7fbStbbdev }
1621d86ed7fbStbbdev }
1622d86ed7fbStbbdev
1623d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzwrite)1624d86ed7fbStbbdev int BZ_API(BZ2_bzwrite)(BZFILE* b, void* buf, int len) {
1625d86ed7fbStbbdev int bzerr;
1626d86ed7fbStbbdev
1627d86ed7fbStbbdev BZ2_bzWrite(&bzerr, b, buf, len);
1628d86ed7fbStbbdev if (bzerr == BZ_OK) {
1629d86ed7fbStbbdev return len;
1630d86ed7fbStbbdev }
1631d86ed7fbStbbdev else {
1632d86ed7fbStbbdev return -1;
1633d86ed7fbStbbdev }
1634d86ed7fbStbbdev }
1635d86ed7fbStbbdev
1636d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzflush)1637d86ed7fbStbbdev int BZ_API(BZ2_bzflush)(BZFILE* b) {
1638d86ed7fbStbbdev /* do nothing now... */
1639d86ed7fbStbbdev return 0;
1640d86ed7fbStbbdev }
1641d86ed7fbStbbdev
1642d86ed7fbStbbdev /*---------------------------------------------------*/
BZ_API(BZ2_bzclose)1643d86ed7fbStbbdev void BZ_API(BZ2_bzclose)(BZFILE* b) {
1644d86ed7fbStbbdev int bzerr;
1645d86ed7fbStbbdev FILE* fp;
1646d86ed7fbStbbdev
1647d86ed7fbStbbdev if (b == nullptr) {
1648d86ed7fbStbbdev return;
1649d86ed7fbStbbdev }
1650d86ed7fbStbbdev fp = ((bzFile*)b)->handle;
1651d86ed7fbStbbdev if (((bzFile*)b)->writing) {
1652d86ed7fbStbbdev BZ2_bzWriteClose(&bzerr, b, 0, nullptr, nullptr);
1653d86ed7fbStbbdev if (bzerr != BZ_OK) {
1654d86ed7fbStbbdev BZ2_bzWriteClose(nullptr, b, 1, nullptr, nullptr);
1655d86ed7fbStbbdev }
1656d86ed7fbStbbdev }
1657d86ed7fbStbbdev else {
1658d86ed7fbStbbdev BZ2_bzReadClose(&bzerr, b);
1659d86ed7fbStbbdev }
1660d86ed7fbStbbdev if (fp != stdin && fp != stdout) {
1661d86ed7fbStbbdev fclose(fp);
1662d86ed7fbStbbdev }
1663d86ed7fbStbbdev }
1664d86ed7fbStbbdev
1665d86ed7fbStbbdev /*---------------------------------------------------*/
1666d86ed7fbStbbdev /*--
1667d86ed7fbStbbdev return last error code
1668d86ed7fbStbbdev --*/
1669d86ed7fbStbbdev static const char* bzerrorstrings[] = {
1670d86ed7fbStbbdev "OK",
1671d86ed7fbStbbdev "SEQUENCE_ERROR",
1672d86ed7fbStbbdev "PARAM_ERROR",
1673d86ed7fbStbbdev "MEM_ERROR",
1674d86ed7fbStbbdev "DATA_ERROR",
1675d86ed7fbStbbdev "DATA_ERROR_MAGIC",
1676d86ed7fbStbbdev "IO_ERROR",
1677d86ed7fbStbbdev "UNEXPECTED_EOF",
1678d86ed7fbStbbdev "OUTBUFF_FULL",
1679d86ed7fbStbbdev "CONFIG_ERROR",
1680d86ed7fbStbbdev "???" /* for future */
1681d86ed7fbStbbdev ,
1682d86ed7fbStbbdev "???" /* for future */
1683d86ed7fbStbbdev ,
1684d86ed7fbStbbdev "???" /* for future */
1685d86ed7fbStbbdev ,
1686d86ed7fbStbbdev "???" /* for future */
1687d86ed7fbStbbdev ,
1688d86ed7fbStbbdev "???" /* for future */
1689d86ed7fbStbbdev ,
1690d86ed7fbStbbdev "???" /* for future */
1691d86ed7fbStbbdev };
1692d86ed7fbStbbdev
BZ_API(BZ2_bzerror)1693d86ed7fbStbbdev const char* BZ_API(BZ2_bzerror)(BZFILE* b, int* errnum) {
1694d86ed7fbStbbdev int err = ((bzFile*)b)->lastErr;
1695d86ed7fbStbbdev
1696d86ed7fbStbbdev if (err > 0)
1697d86ed7fbStbbdev err = 0;
1698d86ed7fbStbbdev *errnum = err;
1699d86ed7fbStbbdev return bzerrorstrings[err * -1];
1700d86ed7fbStbbdev }
1701d86ed7fbStbbdev #endif
1702d86ed7fbStbbdev
1703d86ed7fbStbbdev /*-------------------------------------------------------------*/
1704d86ed7fbStbbdev /*--- end bzlib.c ---*/
1705d86ed7fbStbbdev /*-------------------------------------------------------------*/
1706