Subversion Repositories nw_plus

Rev

Details | Last modification | View Log | RSS feed

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