Merge from vendor branch LESS:
[dragonfly.git] / contrib / bzip2-1.0 / bzlib.c
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 /*-------------------------------------------------------------*/