diff options
Diffstat (limited to '')
-rw-r--r-- | lzlib.c | 543 | ||||
-rw-r--r-- | lzlib.cc | 540 |
2 files changed, 543 insertions, 540 deletions
@@ -0,0 +1,543 @@ +/* Lzlib - A compression library for lzip files + Copyright (C) 2009, 2010, 2011, 2012 Antonio Diaz Diaz. + + This library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library. If not, see <http://www.gnu.org/licenses/>. + + As a special exception, you may use this file as part of a free + software library without restriction. Specifically, if other files + instantiate templates or use macros or inline functions from this + file, or you compile this file and link it with other files to + produce an executable, this file does not by itself cause the + resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. +*/ + +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "lzlib.h" +#include "clzip.h" +#include "tables.c" +#include "decoder.c" +#include "encoder.c" + + +struct LZ_Encoder + { + long long partial_in_size; + long long partial_out_size; + struct Matchfinder * matchfinder; + struct LZ_encoder * lz_encoder; + enum LZ_Errno lz_errno; + int flush_pending; + File_header member_header; + bool fatal; + }; + +static void LZ_Encoder_init( struct LZ_Encoder * const e, + const File_header header ) + { + int i; + e->partial_in_size = 0; + e->partial_out_size = 0; + e->matchfinder = 0; + e->lz_encoder = 0; + e->lz_errno = LZ_ok; + e->flush_pending = 0; + for( i = 0; i < Fh_size; ++i ) e->member_header[i] = header[i]; + e->fatal = false; + } + + +struct LZ_Decoder + { + long long partial_in_size; + long long partial_out_size; + struct Range_decoder * rdec; + struct LZ_decoder * lz_decoder; + enum LZ_Errno lz_errno; + File_header member_header; /* header of current member */ + bool fatal; + bool seeking; + }; + +static void LZ_Decoder_init( struct LZ_Decoder * const d ) + { + int i; + d->partial_in_size = 0; + d->partial_out_size = 0; + d->rdec = 0; + d->lz_decoder = 0; + d->lz_errno = LZ_ok; + for( i = 0; i < Fh_size; ++i ) d->member_header[i] = 0; + d->fatal = false; + d->seeking = false; + } + + +static bool verify_encoder( struct LZ_Encoder * const e ) + { + if( !e ) return false; + if( !e->matchfinder || !e->lz_encoder ) + { e->lz_errno = LZ_bad_argument; return false; } + return true; + } + + +static bool verify_decoder( struct LZ_Decoder * const d ) + { + if( !d ) return false; + if( !d->rdec ) + { d->lz_errno = LZ_bad_argument; return false; } + return true; + } + + +/*------------------------- Misc Functions -------------------------*/ + +const char * LZ_version( void ) { return LZ_version_string; } + + +const char * LZ_strerror( const enum LZ_Errno lz_errno ) + { + switch( lz_errno ) + { + case LZ_ok : return "ok"; + case LZ_bad_argument : return "bad argument"; + case LZ_mem_error : return "not enough memory"; + case LZ_sequence_error: return "sequence error"; + case LZ_header_error : return "header error"; + case LZ_unexpected_eof: return "unexpected eof"; + case LZ_data_error : return "data error"; + case LZ_library_error : return "library error"; + } + return "invalid error code"; + } + + +int LZ_min_dictionary_bits( void ) { return min_dictionary_bits; } +int LZ_min_dictionary_size( void ) { return min_dictionary_size; } +int LZ_max_dictionary_bits( void ) { return max_dictionary_bits; } +int LZ_max_dictionary_size( void ) { return max_dictionary_size; } +int LZ_min_match_len_limit( void ) { return min_match_len_limit; } +int LZ_max_match_len_limit( void ) { return max_match_len; } + + +/*---------------------- Compression Functions ----------------------*/ + +struct LZ_Encoder * LZ_compress_open( const int dictionary_size, + const int match_len_limit, + const long long member_size ) + { + File_header header; + Fh_set_magic( header ); + const bool error = ( !Fh_set_dictionary_size( header, dictionary_size ) || + match_len_limit < min_match_len_limit || + match_len_limit > max_match_len ); + + struct LZ_Encoder * const e = + (struct LZ_Encoder *)malloc( sizeof (struct LZ_Encoder) ); + if( !e ) return 0; + LZ_Encoder_init( e, header ); + if( error ) e->lz_errno = LZ_bad_argument; + else + { + e->matchfinder = (struct Matchfinder *)malloc( sizeof (struct Matchfinder) ); + e->lz_encoder = (struct LZ_encoder *)malloc( sizeof (struct LZ_encoder) ); + if( !e->matchfinder || !e->lz_encoder || + !Mf_init( e->matchfinder, + Fh_get_dictionary_size( header ), match_len_limit ) || + !LZe_init( e->lz_encoder, e->matchfinder, header, member_size ) ) + { + if( e->matchfinder ) + { Mf_free( e->matchfinder ); free( e->matchfinder ); e->matchfinder = 0; } + if( e->lz_encoder ) + { LZe_free( e->lz_encoder ); free( e->lz_encoder ); e->lz_encoder = 0; } + e->lz_errno = LZ_mem_error; + } + } + if( e->lz_errno != LZ_ok ) e->fatal = true; + return e; + } + + +int LZ_compress_close( struct LZ_Encoder * const e ) + { + if( !e ) return -1; + if( e->lz_encoder ) + { LZe_free( e->lz_encoder ); free( e->lz_encoder ); } + if( e->matchfinder ) + { Mf_free( e->matchfinder ); free( e->matchfinder ); } + free( e ); + return 0; + } + + +int LZ_compress_finish( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) || e->fatal ) return -1; + Mf_set_flushing( e->matchfinder, true ); + e->flush_pending = 0; + return 0; + } + + +int LZ_compress_restart_member( struct LZ_Encoder * const e, + const long long member_size ) + { + if( !verify_encoder( e ) || e->fatal ) return -1; + if( !LZe_member_finished( e->lz_encoder ) ) + { e->lz_errno = LZ_sequence_error; return -1; } + + e->partial_in_size += Mf_data_position( e->matchfinder ); + e->partial_out_size += Re_member_position( &e->lz_encoder->range_encoder ); + Mf_reset( e->matchfinder ); + + LZe_free( e->lz_encoder ); free( e->lz_encoder ); + e->lz_encoder = (struct LZ_encoder *)malloc( sizeof (struct LZ_encoder) ); + if( !e->lz_encoder || + !LZe_init( e->lz_encoder, e->matchfinder, e->member_header, member_size ) ) + { + if( e->lz_encoder ) + { LZe_free( e->lz_encoder ); free( e->lz_encoder ); e->lz_encoder = 0; } + e->lz_errno = LZ_mem_error; e->fatal = true; + return -1; + } + e->lz_errno = LZ_ok; + return 0; + } + + +int LZ_compress_sync_flush( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) || e->fatal ) return -1; + if( !e->flush_pending && !e->matchfinder->at_stream_end ) + { + e->flush_pending = 2; /* 2 consecutive markers guarantee decoding */ + Mf_set_flushing( e->matchfinder, true ); + if( !LZe_encode_member( e->lz_encoder, false ) ) + { e->lz_errno = LZ_library_error; e->fatal = true; return -1; } + while( e->flush_pending > 0 && LZe_sync_flush( e->lz_encoder ) ) + { if( --e->flush_pending <= 0 ) Mf_set_flushing( e->matchfinder, false ); } + } + return 0; + } + + +int LZ_compress_read( struct LZ_Encoder * const e, + uint8_t * const buffer, const int size ) + { + if( !verify_encoder( e ) || e->fatal ) return -1; + if( !LZe_encode_member( e->lz_encoder, !e->flush_pending ) ) + { e->lz_errno = LZ_library_error; e->fatal = true; return -1; } + while( e->flush_pending > 0 && LZe_sync_flush( e->lz_encoder ) ) + { if( --e->flush_pending <= 0 ) Mf_set_flushing( e->matchfinder, false ); } + return Re_read_data( &e->lz_encoder->range_encoder, buffer, size ); + } + + +int LZ_compress_write( struct LZ_Encoder * const e, + const uint8_t * const buffer, const int size ) + { + if( !verify_encoder( e ) || e->fatal ) return -1; + if( e->flush_pending ) return 0; + return Mf_write_data( e->matchfinder, buffer, size ); + } + + +int LZ_compress_write_size( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) || e->fatal ) return -1; + if( e->flush_pending ) return 0; + return Mf_free_bytes( e->matchfinder ); + } + + +enum LZ_Errno LZ_compress_errno( struct LZ_Encoder * const e ) + { + if( !e ) return LZ_bad_argument; + return e->lz_errno; + } + + +int LZ_compress_finished( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) ) return -1; + return ( !e->flush_pending && Mf_finished( e->matchfinder ) && + LZe_member_finished( e->lz_encoder ) ); + } + + +int LZ_compress_member_finished( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) ) return -1; + return LZe_member_finished( e->lz_encoder ); + } + + +long long LZ_compress_data_position( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) ) return -1; + return Mf_data_position( e->matchfinder ); + } + + +long long LZ_compress_member_position( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) ) return -1; + return Re_member_position( &e->lz_encoder->range_encoder ); + } + + +long long LZ_compress_total_in_size( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) ) return -1; + return e->partial_in_size + Mf_data_position( e->matchfinder ); + } + + +long long LZ_compress_total_out_size( struct LZ_Encoder * const e ) + { + if( !verify_encoder( e ) ) return -1; + return e->partial_out_size + + Re_member_position( &e->lz_encoder->range_encoder ); + } + + +/*--------------------- Decompression Functions ---------------------*/ + +struct LZ_Decoder * LZ_decompress_open( void ) + { + struct LZ_Decoder * const d = + (struct LZ_Decoder *)malloc( sizeof (struct LZ_Decoder) ); + if( !d ) return 0; + LZ_Decoder_init( d ); + + d->rdec = (struct Range_decoder *)malloc( sizeof (struct Range_decoder) ); + if( !d->rdec || !Rd_init( d->rdec ) ) + { + if( d->rdec ) { Rd_free( d->rdec ); free( d->rdec ); d->rdec = 0; } + d->lz_errno = LZ_mem_error; d->fatal = true; + } + return d; + } + + +int LZ_decompress_close( struct LZ_Decoder * const d ) + { + if( !d ) return -1; + if( d->lz_decoder ) + { LZd_free( d->lz_decoder ); free( d->lz_decoder ); } + if( d->rdec ) { Rd_free( d->rdec ); free( d->rdec ); } + free( d ); + return 0; + } + + +int LZ_decompress_finish( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) || d->fatal ) return -1; + if( d->seeking ) { d->seeking = false; Rd_purge( d->rdec ); } + else Rd_finish( d->rdec ); + return 0; + } + + +int LZ_decompress_reset( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + if( d->lz_decoder ) + { LZd_free( d->lz_decoder ); free( d->lz_decoder ); d->lz_decoder = 0; } + d->partial_in_size = 0; + d->partial_out_size = 0; + Rd_reset( d->rdec ); + d->lz_errno = LZ_ok; + d->fatal = false; + d->seeking = false; + return 0; + } + + +int LZ_decompress_sync_to_member( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + if( d->lz_decoder ) + { LZd_free( d->lz_decoder ); free( d->lz_decoder ); d->lz_decoder = 0; } + if( Rd_find_header( d->rdec ) ) d->seeking = false; + else + { + if( !d->rdec->at_stream_end ) d->seeking = true; + else { d->seeking = false; Rd_purge( d->rdec ); } + } + d->lz_errno = LZ_ok; + d->fatal = false; + return 0; + } + + +int LZ_decompress_read( struct LZ_Decoder * const d, + uint8_t * const buffer, const int size ) + { + if( !verify_decoder( d ) || d->fatal ) return -1; + if( d->seeking ) return 0; + if( d->lz_decoder && LZd_member_finished( d->lz_decoder ) ) + { + d->partial_in_size += d->rdec->member_position ; + d->partial_out_size += LZd_data_position( d->lz_decoder ); + LZd_free( d->lz_decoder ); free( d->lz_decoder ); d->lz_decoder = 0; + } + if( !d->lz_decoder ) + { + if( Rd_available_bytes( d->rdec ) < 5 + Fh_size ) + { + if( !d->rdec->at_stream_end || Rd_finished( d->rdec ) ) return 0; + Rd_purge( d->rdec ); /* remove trailing garbage */ + d->lz_errno = LZ_header_error; + d->fatal = true; + return -1; + } + if( !Rd_read_header( d->rdec, d->member_header ) ) + { + d->lz_errno = LZ_header_error; + d->fatal = true; + return -1; + } + d->lz_decoder = (struct LZ_decoder *)malloc( sizeof (struct LZ_decoder) ); + if( !d->lz_decoder || !LZd_init( d->lz_decoder, d->member_header, d->rdec ) ) + { /* not enough free memory */ + if( d->lz_decoder ) + { LZd_free( d->lz_decoder ); free( d->lz_decoder ); d->lz_decoder = 0; } + d->lz_errno = LZ_mem_error; + d->fatal = true; + return -1; + } + } + const int result = LZd_decode_member( d->lz_decoder ); + if( result != 0 ) + { + if( result == 2 ) d->lz_errno = LZ_unexpected_eof; + else d->lz_errno = LZ_data_error; + d->fatal = true; + return -1; + } + return Cb_read_data( &d->lz_decoder->cb, buffer, size ); + } + + +int LZ_decompress_write( struct LZ_Decoder * const d, + const uint8_t * const buffer, const int size ) + { + if( !verify_decoder( d ) || d->fatal ) return -1; + int result = Rd_write_data( d->rdec, buffer, size ); + while( d->seeking ) + { + if( Rd_find_header( d->rdec ) ) d->seeking = false; + if( result >= size ) break; + const int size2 = Rd_write_data( d->rdec, buffer + result, size - result ); + if( size2 > 0 ) result += size2; + else break; + } + return result; + } + + +int LZ_decompress_write_size( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) || d->fatal ) return -1; + return Rd_free_bytes( d->rdec ); + } + + +enum LZ_Errno LZ_decompress_errno( struct LZ_Decoder * const d ) + { + if( !d ) return LZ_bad_argument; + return d->lz_errno; + } + + +int LZ_decompress_finished( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + return ( Rd_finished( d->rdec ) && + ( !d->lz_decoder || LZd_member_finished( d->lz_decoder ) ) ); + } + + +int LZ_decompress_member_finished( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + return ( d->lz_decoder && LZd_member_finished( d->lz_decoder ) ); + } + + +int LZ_decompress_member_version( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + return Fh_version( d->member_header ); + } + + +int LZ_decompress_dictionary_size( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + return Fh_get_dictionary_size( d->member_header ); + } + + +unsigned int LZ_decompress_data_crc( struct LZ_Decoder * const d ) + { + if( verify_decoder( d ) && d->lz_decoder ) + return LZd_crc( d->lz_decoder ); + else return 0; + } + + +long long LZ_decompress_data_position( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + if( d->lz_decoder ) + return LZd_data_position( d->lz_decoder ); + else return 0; + } + + +long long LZ_decompress_member_position( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + if( d->lz_decoder ) + return d->rdec->member_position ; + else return 0; + } + + +long long LZ_decompress_total_in_size( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + if( d->lz_decoder ) + return d->partial_in_size + d->rdec->member_position ; + return d->partial_in_size; + } + + +long long LZ_decompress_total_out_size( struct LZ_Decoder * const d ) + { + if( !verify_decoder( d ) ) return -1; + if( d->lz_decoder ) + return d->partial_out_size + LZd_data_position( d->lz_decoder ); + return d->partial_out_size; + } diff --git a/lzlib.cc b/lzlib.cc deleted file mode 100644 index 4a4b77b..0000000 --- a/lzlib.cc +++ /dev/null @@ -1,540 +0,0 @@ -/* Lzlib - A compression library for lzip files - Copyright (C) 2009, 2010, 2011 Antonio Diaz Diaz. - - This library is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this library. If not, see <http://www.gnu.org/licenses/>. - - As a special exception, you may use this file as part of a free - software library without restriction. Specifically, if other files - instantiate templates or use macros or inline functions from this - file, or you compile this file and link it with other files to - produce an executable, this file does not by itself cause the - resulting executable to be covered by the GNU General Public - License. This exception does not however invalidate any other - reasons why the executable file might be covered by the GNU General - Public License. -*/ - -#include <algorithm> -#include <cstring> -#include <stdint.h> - -#include "lzlib.h" -#include "lzip.h" -#include "decoder.h" -#include "encoder.h" - - -using namespace Lzlib; - -struct LZ_Encoder - { - long long partial_in_size; - long long partial_out_size; - Matchfinder * matchfinder; - LZ_encoder * lz_encoder; - LZ_Errno lz_errno; - int flush_pending; - const File_header member_header; - bool fatal; - - LZ_Encoder( const File_header & header ) throw() - : - partial_in_size( 0 ), - partial_out_size( 0 ), - matchfinder( 0 ), - lz_encoder( 0 ), - lz_errno( LZ_ok ), - flush_pending( 0 ), - member_header( header ), - fatal( false ) - {} - }; - - -struct LZ_Decoder - { - long long partial_in_size; - long long partial_out_size; - Range_decoder * rdec; - LZ_decoder * lz_decoder; - LZ_Errno lz_errno; - File_header member_header; // header of current member - bool fatal; - bool seeking; - - LZ_Decoder() throw() - : - partial_in_size( 0 ), - partial_out_size( 0 ), - rdec( 0 ), - lz_decoder( 0 ), - lz_errno( LZ_ok ), - fatal( false ), - seeking( false ) - { - for( int i = 0; i < File_header::size; ++i ) member_header.data[i] = 0; - } - }; - - -namespace Lzlib { - -bool verify_encoder( LZ_Encoder * const encoder ) - { - if( !encoder ) return false; - if( !encoder->matchfinder || !encoder->lz_encoder ) - { encoder->lz_errno = LZ_bad_argument; return false; } - return true; - } - - -bool verify_decoder( struct LZ_Decoder * const decoder ) - { - if( !decoder ) return false; - if( !decoder->rdec ) - { decoder->lz_errno = LZ_bad_argument; return false; } - return true; - } - -} // end namespace Lzlib - - -const char * LZ_version() { return LZ_version_string; } - - -const char * LZ_strerror( const LZ_Errno lz_errno ) - { - switch( lz_errno ) - { - case LZ_ok : return "ok"; - case LZ_bad_argument : return "bad argument"; - case LZ_mem_error : return "not enough memory"; - case LZ_sequence_error: return "sequence error"; - case LZ_header_error : return "header error"; - case LZ_unexpected_eof: return "unexpected eof"; - case LZ_data_error : return "data error"; - case LZ_library_error : return "library error"; - } - return "invalid error code"; - } - - -int LZ_min_dictionary_bits() { return min_dictionary_bits; } -int LZ_min_dictionary_size() { return min_dictionary_size; } -int LZ_max_dictionary_bits() { return max_dictionary_bits; } -int LZ_max_dictionary_size() { return max_dictionary_size; } -int LZ_min_match_len_limit() { return min_match_len_limit; } -int LZ_max_match_len_limit() { return max_match_len; } - - -/*---------------------- Compression Functions ----------------------*/ - -LZ_Encoder * LZ_compress_open( const int dictionary_size, - const int match_len_limit, - const long long member_size ) - { - File_header header; - header.set_magic(); - const bool error = ( !header.dictionary_size( dictionary_size ) || - match_len_limit < min_match_len_limit || - match_len_limit > max_match_len ); - - LZ_Encoder * encoder = new( std::nothrow ) LZ_Encoder( header ); - if( !encoder ) return 0; - LZ_Encoder & e = *encoder; - if( error ) e.lz_errno = LZ_bad_argument; - else - { - try { - e.matchfinder = new Matchfinder( header.dictionary_size(), match_len_limit ); - } - catch( std::bad_alloc ) { e.matchfinder = 0; } - if( e.matchfinder ) - { - try { - e.lz_encoder = new LZ_encoder( *e.matchfinder, header, member_size ); - } - catch( std::bad_alloc ) - { - delete e.matchfinder; - e.matchfinder = 0; - e.lz_encoder = 0; - } - } - if( !e.lz_encoder ) e.lz_errno = LZ_mem_error; - } - if( e.lz_errno != LZ_ok ) e.fatal = true; - return encoder; - } - - -int LZ_compress_close( LZ_Encoder * const encoder ) - { - if( !encoder ) return -1; - if( encoder->lz_encoder ) delete encoder->lz_encoder; - if( encoder->matchfinder ) delete encoder->matchfinder; - delete encoder; - return 0; - } - - -int LZ_compress_finish( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) || encoder->fatal ) return -1; - encoder->matchfinder->flushing( true ); - encoder->flush_pending = 0; - return 0; - } - - -int LZ_compress_restart_member( LZ_Encoder * const encoder, - const long long member_size ) - { - if( !verify_encoder( encoder ) || encoder->fatal ) return -1; - LZ_Encoder & e = *encoder; - if( !e.lz_encoder->member_finished() ) - { e.lz_errno = LZ_sequence_error; return -1; } - - e.partial_in_size += e.matchfinder->data_position(); - e.partial_out_size += e.lz_encoder->member_position(); - e.matchfinder->reset(); - - delete e.lz_encoder; - try { - e.lz_encoder = new LZ_encoder( *e.matchfinder, e.member_header, member_size ); - } - catch( std::bad_alloc ) - { e.lz_encoder = 0; e.lz_errno = LZ_mem_error; e.fatal = true; return -1; } - e.lz_errno = LZ_ok; - return 0; - } - - -int LZ_compress_sync_flush( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) || encoder->fatal ) return -1; - LZ_Encoder & e = *encoder; - if( !e.flush_pending && !e.matchfinder->at_stream_end() ) - { - e.flush_pending = 2; // 2 consecutive markers guarantee decoding - e.matchfinder->flushing( true ); - if( !e.lz_encoder->encode_member( false ) ) - { e.lz_errno = LZ_library_error; e.fatal = true; return -1; } - while( e.flush_pending > 0 && e.lz_encoder->sync_flush() ) - { if( --e.flush_pending <= 0 ) e.matchfinder->flushing( false ); } - } - return 0; - } - - -int LZ_compress_read( LZ_Encoder * const encoder, - uint8_t * const buffer, const int size ) - { - if( !verify_encoder( encoder ) || encoder->fatal ) return -1; - LZ_Encoder & e = *encoder; - if( !e.lz_encoder->encode_member( !e.flush_pending ) ) - { e.lz_errno = LZ_library_error; e.fatal = true; return -1; } - while( e.flush_pending > 0 && e.lz_encoder->sync_flush() ) - { if( --e.flush_pending <= 0 ) e.matchfinder->flushing( false ); } - return e.lz_encoder->read_data( buffer, size ); - } - - -int LZ_compress_write( LZ_Encoder * const encoder, - const uint8_t * const buffer, const int size ) - { - if( !verify_encoder( encoder ) || encoder->fatal ) return -1; - if( encoder->flush_pending ) return 0; - return encoder->matchfinder->write_data( buffer, size ); - } - - -int LZ_compress_write_size( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) || encoder->fatal ) return -1; - if( encoder->flush_pending ) return 0; - return encoder->matchfinder->free_bytes(); - } - - -LZ_Errno LZ_compress_errno( LZ_Encoder * const encoder ) - { - if( !encoder ) return LZ_bad_argument; - return encoder->lz_errno; - } - - -int LZ_compress_finished( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) ) return -1; - return ( !encoder->flush_pending && encoder->matchfinder->finished() && - encoder->lz_encoder->member_finished() ); - } - - -int LZ_compress_member_finished( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) ) return -1; - return encoder->lz_encoder->member_finished(); - } - - -long long LZ_compress_data_position( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) ) return -1; - return encoder->matchfinder->data_position(); - } - - -long long LZ_compress_member_position( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) ) return -1; - return encoder->lz_encoder->member_position(); - } - - -long long LZ_compress_total_in_size( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) ) return -1; - return encoder->partial_in_size + encoder->matchfinder->data_position(); - } - - -long long LZ_compress_total_out_size( LZ_Encoder * const encoder ) - { - if( !verify_encoder( encoder ) ) return -1; - return encoder->partial_out_size + encoder->lz_encoder->member_position(); - } - - -/*--------------------- Decompression Functions ---------------------*/ - -struct LZ_Decoder * LZ_decompress_open() - { - LZ_Decoder * decoder = new( std::nothrow ) LZ_Decoder; - if( !decoder ) return 0; - - LZ_Decoder & d = *decoder; - try { d.rdec = new Range_decoder; } - catch( std::bad_alloc ) - { d.rdec = 0; d.lz_errno = LZ_mem_error; d.fatal = true; } - return decoder; - } - - -int LZ_decompress_close( struct LZ_Decoder * const decoder ) - { - if( !decoder ) return -1; - if( decoder->lz_decoder ) delete decoder->lz_decoder; - if( decoder->rdec ) delete decoder->rdec; - delete decoder; - return 0; - } - - -int LZ_decompress_finish( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) || decoder->fatal ) return -1; - LZ_Decoder & d = *decoder; - if( d.seeking ) { d.seeking = false; d.rdec->purge(); } - else d.rdec->finish(); - return 0; - } - - -int LZ_decompress_reset( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - LZ_Decoder & d = *decoder; - if( d.lz_decoder ) { delete d.lz_decoder; d.lz_decoder = 0; } - d.partial_in_size = 0; - d.partial_out_size = 0; - d.rdec->reset(); - d.lz_errno = LZ_ok; - d.fatal = false; - d.seeking = false; - return 0; - } - - -int LZ_decompress_sync_to_member( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - LZ_Decoder & d = *decoder; - if( d.lz_decoder ) { delete d.lz_decoder; d.lz_decoder = 0; } - if( d.rdec->find_header() ) d.seeking = false; - else - { - if( !d.rdec->at_stream_end() ) d.seeking = true; - else { d.seeking = false; d.rdec->purge(); } - } - d.lz_errno = LZ_ok; - d.fatal = false; - return 0; - } - - -int LZ_decompress_read( struct LZ_Decoder * const decoder, - uint8_t * const buffer, const int size ) - { - if( !verify_decoder( decoder ) || decoder->fatal ) return -1; - LZ_Decoder & d = *decoder; - if( d.seeking ) return 0; - if( d.lz_decoder && d.lz_decoder->member_finished() ) - { - d.partial_in_size += d.rdec->member_position(); - d.partial_out_size += d.lz_decoder->data_position(); - delete d.lz_decoder; - d.lz_decoder = 0; - } - if( !d.lz_decoder ) - { - if( d.rdec->used_bytes() < 5 + File_header::size ) - { - if( !d.rdec->at_stream_end() || d.rdec->finished() ) return 0; - d.rdec->purge(); // remove trailing garbage - d.lz_errno = LZ_header_error; - d.fatal = true; - return -1; - } - if( !d.rdec->read_header( d.member_header ) ) - { - d.lz_errno = LZ_header_error; - d.fatal = true; - return -1; - } - try { d.lz_decoder = new LZ_decoder( d.member_header, *d.rdec ); } - catch( std::bad_alloc ) // not enough free memory - { - d.lz_decoder = 0; - d.lz_errno = LZ_mem_error; - d.fatal = true; - return -1; - } - } - const int result = d.lz_decoder->decode_member(); - if( result != 0 ) - { - if( result == 2 ) d.lz_errno = LZ_unexpected_eof; - else d.lz_errno = LZ_data_error; - d.fatal = true; - return -1; - } - return d.lz_decoder->read_data( buffer, size ); - } - - -int LZ_decompress_write( struct LZ_Decoder * const decoder, - const uint8_t * const buffer, const int size ) - { - if( !verify_decoder( decoder ) || decoder->fatal ) return -1; - LZ_Decoder & d = *decoder; - int result = d.rdec->write_data( buffer, size ); - while( d.seeking ) - { - if( d.rdec->find_header() ) d.seeking = false; - if( result >= size ) break; - const int size2 = d.rdec->write_data( buffer + result, size - result ); - if( size2 > 0 ) result += size2; - else break; - } - return result; - } - - -int LZ_decompress_write_size( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) || decoder->fatal ) return -1; - return decoder->rdec->free_bytes(); - } - - -LZ_Errno LZ_decompress_errno( struct LZ_Decoder * const decoder ) - { - if( !decoder ) return LZ_bad_argument; - return decoder->lz_errno; - } - - -int LZ_decompress_finished( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - return ( decoder->rdec->finished() && - ( !decoder->lz_decoder || decoder->lz_decoder->member_finished() ) ); - } - - -int LZ_decompress_member_finished( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - return ( decoder->lz_decoder && decoder->lz_decoder->member_finished() ); - } - - -int LZ_decompress_member_version( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - return decoder->member_header.version(); - } - - -int LZ_decompress_dictionary_size( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - return decoder->member_header.dictionary_size(); - } - - -unsigned int LZ_decompress_data_crc( struct LZ_Decoder * const decoder ) - { - if( verify_decoder( decoder ) && decoder->lz_decoder ) - return decoder->lz_decoder->crc(); - else return 0; - } - - -long long LZ_decompress_data_position( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - if( decoder->lz_decoder ) - return decoder->lz_decoder->data_position(); - else return 0; - } - - -long long LZ_decompress_member_position( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - if( decoder->lz_decoder ) - return decoder->rdec->member_position(); - else return 0; - } - - -long long LZ_decompress_total_in_size( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - if( decoder->lz_decoder ) - return decoder->partial_in_size + decoder->rdec->member_position(); - return decoder->partial_in_size; - } - - -long long LZ_decompress_total_out_size( struct LZ_Decoder * const decoder ) - { - if( !verify_decoder( decoder ) ) return -1; - if( decoder->lz_decoder ) - return decoder->partial_out_size + decoder->lz_decoder->data_position(); - return decoder->partial_out_size; - } |