Zlib unable to decompress a gzip .gz file....?

BlitzMax Forums/BlitzMax Programming/Zlib unable to decompress a gzip .gz file....?

Hi,

I've just found out that the uncompress method, once I had worked out how to use it, does not work with gzip (.gz) files!

The Zlib Manual indicates it's possible to read a gzip file with the gzopen() and gzread() commands.

So has anyone managed to get these commands to work with the blitzmax Zlib module?

And more importantly have a simple code example to help me get started!

Regards

Merx

Found this Module Tweak now I'm off to see if I can get it to work... but if you have a working example please let me know!

Well one step forward!

Using the module tweak above I have unzipped a gzip file!

Rem 
	gzip decompression using zlib
End Rem

Framework brl.standardIO
Import pub.zlib ' Tweaked version
Import brl.bank
Import brl.bankstream

Local fileName:String = "test.gz"
'Local filePtr:Byte Ptr = fileName.ToCString()

' Load the file
Local bank:TBank = LoadBank(fileName)

'Display it's uncompressed file
Print bank.PeekInt(bank.size()-4)

'Create bank for unzipped file
Local bank2:TBank = CreateBank(bank.PeekInt(bank.size()-4)) ' last four bytes of .gz are uncompressed size

Local length:Int = bank2.size()

Print length

'Open the file for reading
Local gzfile = gzopen(filePtr, "rb")

'unzip it to the new bank
gzread(gzfile, bank2.Buf(), bank2.size())


'Create a stream and output file

Local bankStream:TBankStream = CreateBankStream(bank2)

Local line:String = bankStream.ReadLine()
	
While Eof(bankStream) = False And line.length > 0
   Print line
   line = bankStream.ReadLine()
Wend



But as I am downloading files using FTP via BaH.libcurlssl the next level is to work out how to unzip a bank or stream of data...!

All working examples welcome! ;o)

Got it wow forgot how gnarly c code can be and how hard technical documents can be to read through...

OK Zlib does support gzip format you either need to use it's nice file gzip functions as per previous post or start getting a little bit more indepth with the inflateInit2() parameters!

But I have managed to write a little wrapper c code that does all the work for you!

*** Warning this is a work in progress ***!

This is the way I have done it...

1. drop gzWrap.c file in with the zlib.mod folder
#include "zlib.h"



/* ---------------------------------------------------------------------------------------
	A wrapper for inflating and deflating to buffers derived from the Zlib example.c file

	Converted by Allan Rowntree 2008
   ---------------------------------------------------------------------------------------
*/



/* ===========================================================================
 * gzinflate() with correct size buffers
 */
int gzinflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    d_stream.zalloc = (alloc_func)0;
    d_stream.zfree = (free_func)0;
    d_stream.opaque = (voidpf)0;

    d_stream.next_in  = compr;
    d_stream.next_out = uncompr;
    d_stream.avail_in = (uInt)comprLen;
    d_stream.avail_out = (uInt)uncomprLen;

    err = inflateInit2(&d_stream, 32+MAX_WBITS);

    if (err == Z_OK)
    {

	    //for (;;) {
	        //d_stream.next_out = uncompr;            /* discard the output */
	        //d_stream.avail_out = (uInt)uncomprLen;
	        err = inflate(&d_stream, Z_FINISH);
	        //if (err == Z_STREAM_END) break;
	    //}
		if ((err == Z_OK)  || (err == Z_STREAM_END)) {
    		err = inflateEnd(&d_stream);
		}
	}

	return err;
}




/* ===========================================================================
 *  gzdeflate() with large buffers
 */
void gzdeflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    z_stream c_stream; /* compression stream */
    int err;

    c_stream.zalloc = (alloc_func)0;
    c_stream.zfree = (free_func)0;
    c_stream.opaque = (voidpf)0;

    err = deflateInit(&c_stream, Z_BEST_SPEED);

    if (err == Z_OK)
    {

    	c_stream.next_out = compr;
    	c_stream.avail_out = (uInt)comprLen;

    /* At this point, uncompr is still mostly zeroes, so it should compress
     * very well:
     */
    	c_stream.next_in = uncompr;
    	c_stream.avail_in = (uInt)uncomprLen;

    	err = deflate(&c_stream, Z_NO_FLUSH);

    	if (err == Z_OK) {
			err = deflateEnd(&c_stream);
		}
	}
    return err;
}

2. update the zlib.bmx file to include it and add the functionality

Rem
bbdoc: Miscellaneous/ZLib compression
End Rem
Module Pub.zlib

ModuleInfo "Version: 1.02"
ModuleInfo "Author: Jean-loup Gailly, Mark Adler"
ModuleInfo "License: ZLib/PNG License"
ModuleInfo "Modserver: BRL"
ModuleInfo "Credit: Adapted for BlitzMax by Mark Sibly"

ModuleInfo "History: 1.02"
ModuleInfo "History: Updated zlib to 1.2.3"

Import "adler32.c"
Import "compress.c"
Import "crc32.c"
Import "deflate.c"
Import "gzio.c"
Import "infback.c"
'Import "infcodes.c"
Import "inffast.c"
Import "inflate.c"
Import "inftrees.c"
'Import "infutil.c"
Import "trees.c"
Import "uncompr.c"
Import "zutil.c"

Import "gzWrap.c"

Extern

Rem
bbdoc: Compress a block of data at default compression level
end rem
Function compress( dest:Byte Ptr,dest_len Var,source:Byte Ptr,source_len )

Rem
bbdoc: Compress a block of data at specified compression level
end rem
Function compress2( dest:Byte Ptr,dest_len Var,source:Byte Ptr,source_len,level )

Rem
bbdoc: Uncompress a block of data
end rem
Function uncompress( dest:Byte Ptr,dest_len Var,source:Byte Ptr,source_len )


'*** Merx adding gzip functions

Rem
bbdoc: Opens a gzip-compressed file
End Rem
Function gzopen( source:Byte Ptr, mode:Byte Ptr)

Rem
bbdoc: Closes a gzip-compressed file
End Rem
Function gzclose( fileid )

Rem
bbdoc: Returns the last gzError into error Variable
End Rem
Function gzerror( fileid, error Var)

Rem
bbdoc: Reads from a gzip-compressed file
End Rem
Function gzread( fileid, dest:Byte Ptr, dest_len)


Rem
bbdoc: Compress a block of data at default compression level
end rem
Function gzdeflate( dest:Byte Ptr,dest_len Var,source:Byte Ptr,source_len )

Rem
bbdoc: Uncompress a block of data
end rem
Function gzinflate( dest:Byte Ptr,dest_len Var,source:Byte Ptr,source_len )



End Extern

3. Rebuild modules

4. Run the following test code with a valid test.gz file
Rem  
	inflationGzip - inflate gzip file from buffer to buffer
End Rem

Framework brl.standardIO
Import pub.zlib
Import brl.bank
Import brl.bankstream

' Ideal code version
Local fileName:String = "test.gz"

Local zipped:TBank = LoadBank(fileName)

Print "ID1:"+zipped.PeekByte(0) '31 gzip
Print "ID2:"+zipped.PeekByte(1) '139 gzip


Local unzippedLength:Int = zipped.PeekInt(zipped.size()-4) ' last four bytes of .gz are uncompressed size

Print "unzipped length:"+unzippedLength

Local unzipped:TBank = CreateBank(unzippedLength) 

unzippedLength = unzipped.size()

Local zippedLength:Int = zipped.size()

Print "zipped length:"+zippedLength

Print "Inflating..."

Local result = gzInflate(zipped.Buf(), zippedLength, unzipped.Buf(), unzippedLength)

Print "inflating result = "+result

If result = 0 Then
	
	Local bankStream:TBankStream = CreateBankStream(unzipped)
	
	Local line:String = bankStream.ReadLine()
		
	While Eof(bankStream) = False And line.length > 0	
		Print line
		line = bankStream.ReadLine()
	Wend
	
EndIf


I still need to get it working in a nice buffered manner!

Any and all suggestions welcome!

Regards

Merx