29#include FT_CONFIG_STANDARD_LIBRARY_H
37#define FT_ERR_PREFIX Bzip2_Err_
38#define FT_ERR_BASE FT_Mod_Err_Bzip2
43#ifdef FT_CONFIG_OPTION_USE_BZIP2
60 typedef void* (*alloc_func)(
void*, int, int );
61 typedef void (*free_func) (
void*,
void* );
65 ft_bzip2_alloc(
void* memory_,
69 FT_Memory memory = (FT_Memory)memory_;
71 FT_ULong sz = (FT_ULong)size * (FT_ULong)items;
76 FT_MEM_QALLOC( p, sz );
82 ft_bzip2_free(
void* memory_,
85 FT_Memory memory = (FT_Memory)memory_;
88 FT_MEM_FREE( address );
100#define FT_BZIP2_BUFFER_SIZE 4096
102 typedef struct FT_BZip2FileRec_
109 FT_Byte input[FT_BZIP2_BUFFER_SIZE];
111 FT_Byte buffer[FT_BZIP2_BUFFER_SIZE];
117 } FT_BZip2FileRec, *FT_BZip2File;
122 ft_bzip2_check_header( FT_Stream stream )
124 FT_Error error = FT_Err_Ok;
128 if ( FT_STREAM_SEEK( 0 ) ||
129 FT_STREAM_READ( head, 4 ) )
134 if ( head[0] != 0x42 ||
138 error = FT_THROW( Invalid_File_Format );
148 ft_bzip2_file_init( FT_BZip2File zip,
152 bz_stream* bzstream = &zip->bzstream;
153 FT_Error error = FT_Err_Ok;
156 zip->stream = stream;
157 zip->source = source;
158 zip->memory = stream->memory;
160 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
161 zip->cursor = zip->limit;
169 error = ft_bzip2_check_header( stream );
173 if ( FT_STREAM_SEEK( 0 ) )
178 bzstream->bzalloc = ft_bzip2_alloc;
179 bzstream->bzfree = ft_bzip2_free;
180 bzstream->opaque = zip->memory;
182 bzstream->avail_in = 0;
183 bzstream->next_in = (
char*)zip->buffer;
185 if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
187 error = FT_THROW( Invalid_File_Format );
195 ft_bzip2_file_done( FT_BZip2File zip )
197 bz_stream* bzstream = &zip->bzstream;
200 BZ2_bzDecompressEnd( bzstream );
203 bzstream->bzalloc = NULL;
204 bzstream->bzfree = NULL;
205 bzstream->opaque = NULL;
206 bzstream->next_in = NULL;
207 bzstream->next_out = NULL;
208 bzstream->avail_in = 0;
209 bzstream->avail_out = 0;
218 ft_bzip2_file_reset( FT_BZip2File zip )
220 FT_Stream stream = zip->source;
224 if ( !FT_STREAM_SEEK( 0 ) )
226 bz_stream* bzstream = &zip->bzstream;
229 BZ2_bzDecompressEnd( bzstream );
231 bzstream->avail_in = 0;
232 bzstream->next_in = (
char*)zip->input;
233 bzstream->avail_out = 0;
234 bzstream->next_out = (
char*)zip->buffer;
236 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
237 zip->cursor = zip->limit;
241 BZ2_bzDecompressInit( bzstream, 0, 0 );
249 ft_bzip2_file_fill_input( FT_BZip2File zip )
251 bz_stream* bzstream = &zip->bzstream;
252 FT_Stream stream = zip->source;
258 size = stream->read( stream, stream->pos, zip->input,
259 FT_BZIP2_BUFFER_SIZE );
262 zip->limit = zip->cursor;
263 return FT_THROW( Invalid_Stream_Operation );
268 size = stream->size - stream->pos;
269 if ( size > FT_BZIP2_BUFFER_SIZE )
270 size = FT_BZIP2_BUFFER_SIZE;
274 zip->limit = zip->cursor;
275 return FT_THROW( Invalid_Stream_Operation );
278 FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
282 bzstream->next_in = (
char*)zip->input;
283 bzstream->avail_in = size;
290 ft_bzip2_file_fill_output( FT_BZip2File zip )
292 bz_stream* bzstream = &zip->bzstream;
293 FT_Error error = FT_Err_Ok;
296 zip->cursor = zip->buffer;
297 bzstream->next_out = (
char*)zip->cursor;
298 bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
300 while ( bzstream->avail_out > 0 )
305 if ( bzstream->avail_in == 0 )
307 error = ft_bzip2_file_fill_input( zip );
312 err = BZ2_bzDecompress( bzstream );
318 if ( err == BZ_STREAM_END )
320 zip->limit = (FT_Byte*)bzstream->next_out;
321 if ( zip->limit == zip->cursor )
322 error = FT_THROW( Invalid_Stream_Operation );
327 zip->limit = zip->cursor;
328 error = FT_THROW( Invalid_Stream_Operation );
340 ft_bzip2_file_skip_output( FT_BZip2File zip,
343 FT_Error error = FT_Err_Ok;
348 FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );
351 if ( delta >= count )
354 zip->cursor += delta;
361 error = ft_bzip2_file_fill_output( zip );
371 ft_bzip2_file_io( FT_BZip2File zip,
382 if ( pos < zip->pos || zip->reset )
384 error = ft_bzip2_file_reset( zip );
390 if ( pos > zip->pos )
392 error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
406 delta = (FT_ULong)( zip->limit - zip->cursor );
407 if ( delta >= count )
410 FT_MEM_COPY( buffer, zip->cursor, delta );
413 zip->cursor += delta;
420 error = ft_bzip2_file_fill_output( zip );
439 ft_bzip2_stream_close( FT_Stream stream )
441 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
442 FT_Memory memory = stream->memory;
448 ft_bzip2_file_done( zip );
452 stream->descriptor.pointer = NULL;
458 ft_bzip2_stream_io( FT_Stream stream,
459 unsigned long offset,
460 unsigned char* buffer,
461 unsigned long count )
463 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
466 return ft_bzip2_file_io( zip, offset, buffer, count );
470 FT_EXPORT_DEF( FT_Error )
471 FT_Stream_OpenBzip2( FT_Stream stream,
476 FT_BZip2File zip = NULL;
479 if ( !stream || !source )
481 error = FT_THROW( Invalid_Stream_Handle );
485 memory = source->memory;
491 error = ft_bzip2_check_header( source );
496 stream->memory = memory;
498 if ( !FT_QNEW( zip ) )
500 error = ft_bzip2_file_init( zip, stream, source );
507 stream->descriptor.pointer = zip;
510 stream->size = 0x7FFFFFFFL;
513 stream->read = ft_bzip2_stream_io;
514 stream->close = ft_bzip2_stream_close;
522 FT_EXPORT_DEF( FT_Error )
523 FT_Stream_OpenBzip2( FT_Stream stream,
529 return FT_THROW( Unimplemented_Feature );