27#include FT_CONFIG_STANDARD_LIBRARY_H
35#define FT_ERR_PREFIX Gzip_Err_
36#define FT_ERR_BASE FT_Mod_Err_Gzip
41#ifdef FT_CONFIG_OPTION_USE_ZLIB
43#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
56#ifndef USE_ZLIB_ZCALLOC
81#if defined( _MSC_VER )
86#pragma warning( push )
87#pragma warning( disable : 4244 )
90#if defined( __GNUC__ )
91#pragma GCC diagnostic push
93#pragma GCC diagnostic ignored "-Wstrict-prototypes"
95#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
96#pragma GCC diagnostic ignored "-Wredundant-decls"
106#if defined( __GNUC__ )
107#pragma GCC diagnostic pop
110#if defined( _MSC_VER )
111#pragma warning( pop )
129 ft_gzip_alloc( voidpf opaque,
133 FT_Memory memory = (FT_Memory)opaque;
134 FT_ULong sz = (FT_ULong)size * items;
140 FT_MEM_ALLOC( p, sz );
146 ft_gzip_free( voidpf opaque,
149 FT_Memory memory = (FT_Memory)opaque;
152 FT_MEM_FREE( address );
163#define FT_GZIP_BUFFER_SIZE 4096
165 typedef struct FT_GZipFileRec_
173 FT_Byte input[FT_GZIP_BUFFER_SIZE];
175 FT_Byte buffer[FT_GZIP_BUFFER_SIZE];
180 } FT_GZipFileRec, *FT_GZipFile;
184#define FT_GZIP_ASCII_FLAG 0x01
185#define FT_GZIP_HEAD_CRC 0x02
186#define FT_GZIP_EXTRA_FIELD 0x04
187#define FT_GZIP_ORIG_NAME 0x08
188#define FT_GZIP_COMMENT 0x10
189#define FT_GZIP_RESERVED 0xE0
194 ft_gzip_check_header( FT_Stream stream )
200 if ( FT_STREAM_SEEK( 0 ) ||
201 FT_STREAM_READ( head, 4 ) )
206 if ( head[0] != 0x1F ||
208 head[2] != Z_DEFLATED ||
209 (head[3] & FT_GZIP_RESERVED) )
211 error = FT_THROW( Invalid_File_Format );
216 (void)FT_STREAM_SKIP( 6 );
219 if ( head[3] & FT_GZIP_EXTRA_FIELD )
224 if ( FT_READ_USHORT_LE( len ) ||
225 FT_STREAM_SKIP( len ) )
230 if ( head[3] & FT_GZIP_ORIG_NAME )
236 if ( FT_READ_BYTE( c ) )
244 if ( head[3] & FT_GZIP_COMMENT )
250 if ( FT_READ_BYTE( c ) )
258 if ( head[3] & FT_GZIP_HEAD_CRC )
259 if ( FT_STREAM_SKIP( 2 ) )
268 ft_gzip_file_init( FT_GZipFile zip,
272 z_stream* zstream = &zip->zstream;
273 FT_Error error = FT_Err_Ok;
276 zip->stream = stream;
277 zip->source = source;
278 zip->memory = stream->memory;
280 zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
281 zip->cursor = zip->limit;
288 error = ft_gzip_check_header( stream );
292 zip->start = FT_STREAM_POS();
296 zstream->zalloc = ft_gzip_alloc;
297 zstream->zfree = ft_gzip_free;
298 zstream->opaque = stream->memory;
300 zstream->avail_in = 0;
301 zstream->next_in = zip->buffer;
303 if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
305 error = FT_THROW( Invalid_File_Format );
313 ft_gzip_file_done( FT_GZipFile zip )
315 z_stream* zstream = &zip->zstream;
318 inflateEnd( zstream );
321 zstream->zalloc = NULL;
322 zstream->zfree = NULL;
323 zstream->opaque = NULL;
324 zstream->next_in = NULL;
325 zstream->next_out = NULL;
326 zstream->avail_in = 0;
327 zstream->avail_out = 0;
336 ft_gzip_file_reset( FT_GZipFile zip )
338 FT_Stream stream = zip->source;
342 if ( !FT_STREAM_SEEK( zip->start ) )
344 z_stream* zstream = &zip->zstream;
347 inflateReset( zstream );
349 zstream->avail_in = 0;
350 zstream->next_in = zip->input;
351 zstream->avail_out = 0;
352 zstream->next_out = zip->buffer;
354 zip->limit = zip->buffer + FT_GZIP_BUFFER_SIZE;
355 zip->cursor = zip->limit;
364 ft_gzip_file_fill_input( FT_GZipFile zip )
366 z_stream* zstream = &zip->zstream;
367 FT_Stream stream = zip->source;
373 size = stream->read( stream, stream->pos, zip->input,
374 FT_GZIP_BUFFER_SIZE );
377 zip->limit = zip->cursor;
378 return FT_THROW( Invalid_Stream_Operation );
383 size = stream->size - stream->pos;
384 if ( size > FT_GZIP_BUFFER_SIZE )
385 size = FT_GZIP_BUFFER_SIZE;
389 zip->limit = zip->cursor;
390 return FT_THROW( Invalid_Stream_Operation );
393 FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
397 zstream->next_in = zip->input;
398 zstream->avail_in = size;
405 ft_gzip_file_fill_output( FT_GZipFile zip )
407 z_stream* zstream = &zip->zstream;
408 FT_Error error = FT_Err_Ok;
411 zip->cursor = zip->buffer;
412 zstream->next_out = zip->cursor;
413 zstream->avail_out = FT_GZIP_BUFFER_SIZE;
415 while ( zstream->avail_out > 0 )
420 if ( zstream->avail_in == 0 )
422 error = ft_gzip_file_fill_input( zip );
427 err = inflate( zstream, Z_NO_FLUSH );
429 if ( err == Z_STREAM_END )
431 zip->limit = zstream->next_out;
432 if ( zip->limit == zip->cursor )
433 error = FT_THROW( Invalid_Stream_Operation );
436 else if ( err != Z_OK )
438 zip->limit = zip->cursor;
439 error = FT_THROW( Invalid_Stream_Operation );
450 ft_gzip_file_skip_output( FT_GZipFile zip,
453 FT_Error error = FT_Err_Ok;
458 FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );
461 if ( delta >= count )
464 zip->cursor += delta;
471 error = ft_gzip_file_fill_output( zip );
481 ft_gzip_file_io( FT_GZipFile zip,
492 if ( pos < zip->pos )
494 error = ft_gzip_file_reset( zip );
500 if ( pos > zip->pos )
502 error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
516 delta = (FT_ULong)( zip->limit - zip->cursor );
517 if ( delta >= count )
520 FT_MEM_COPY( buffer, zip->cursor, delta );
523 zip->cursor += delta;
530 error = ft_gzip_file_fill_output( zip );
549 ft_gzip_stream_close( FT_Stream stream )
551 FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;
552 FT_Memory memory = stream->memory;
558 ft_gzip_file_done( zip );
562 stream->descriptor.pointer = NULL;
566 FT_FREE( stream->base );
571 ft_gzip_stream_io( FT_Stream stream,
572 unsigned long offset,
573 unsigned char* buffer,
574 unsigned long count )
576 FT_GZipFile zip = (FT_GZipFile)stream->descriptor.pointer;
579 return ft_gzip_file_io( zip, offset, buffer, count );
584 ft_gzip_get_uncompressed_size( FT_Stream stream )
591 old_pos = stream->pos;
592 if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
594 result = FT_Stream_ReadULongLE( stream, &error );
598 (void)FT_Stream_Seek( stream, old_pos );
607 FT_EXPORT_DEF( FT_Error )
608 FT_Stream_OpenGzip( FT_Stream stream,
613 FT_GZipFile zip = NULL;
616 if ( !stream || !source )
618 error = FT_THROW( Invalid_Stream_Handle );
622 memory = source->memory;
628 error = ft_gzip_check_header( source );
633 stream->memory = memory;
635 if ( !FT_QNEW( zip ) )
637 error = ft_gzip_file_init( zip, stream, source );
644 stream->descriptor.pointer = zip;
656 FT_ULong zip_size = ft_gzip_get_uncompressed_size( source );
659 if ( zip_size != 0 && zip_size < 40 * 1024 )
661 FT_Byte* zip_buff = NULL;
664 if ( !FT_QALLOC( zip_buff, zip_size ) )
669 count = ft_gzip_file_io( zip, 0, zip_buff, zip_size );
670 if ( count == zip_size )
672 ft_gzip_file_done( zip );
675 stream->descriptor.pointer = NULL;
677 stream->size = zip_size;
679 stream->base = zip_buff;
681 stream->close = ft_gzip_stream_close;
686 ft_gzip_file_io( zip, 0, NULL, 0 );
693 stream->size = zip_size;
695 stream->size = 0x7FFFFFFFL;
700 stream->read = ft_gzip_stream_io;
701 stream->close = ft_gzip_stream_close;
710 FT_EXPORT_DEF( FT_Error )
711 FT_Gzip_Uncompress( FT_Memory memory,
713 FT_ULong* output_len,
714 const FT_Byte* input,
723 if ( !memory || !output_len || !output )
724 return FT_THROW( Invalid_Argument );
728 stream.next_in = (Bytef*)input;
729 stream.avail_in = (uInt)input_len;
731 stream.next_out = output;
732 stream.avail_out = (uInt)*output_len;
734 stream.zalloc = ft_gzip_alloc;
735 stream.zfree = ft_gzip_free;
736 stream.opaque = memory;
738 err = inflateInit2( &stream, MAX_WBITS|32 );
741 return FT_THROW( Invalid_Argument );
743 err = inflate( &stream, Z_FINISH );
744 if ( err != Z_STREAM_END )
746 inflateEnd( &stream );
752 *output_len = stream.total_out;
754 err = inflateEnd( &stream );
757 if ( err == Z_MEM_ERROR )
758 return FT_THROW( Out_Of_Memory );
760 if ( err == Z_BUF_ERROR )
761 return FT_THROW( Array_Too_Large );
763 if ( err == Z_DATA_ERROR )
764 return FT_THROW( Invalid_Table );
766 if ( err == Z_NEED_DICT )
767 return FT_THROW( Invalid_Table );
775 FT_EXPORT_DEF( FT_Error )
776 FT_Stream_OpenGzip( FT_Stream stream,
782 return FT_THROW( Unimplemented_Feature );
786 FT_EXPORT_DEF( FT_Error )
787 FT_Gzip_Uncompress( FT_Memory memory,
789 FT_ULong* output_len,
790 const FT_Byte* input,
795 FT_UNUSED( output_len );
797 FT_UNUSED( input_len );
799 return FT_THROW( Unimplemented_Feature );