Page 2 of 2
Re: HttpRequest with gzip
Posted: Mon Feb 24, 2025 11:41 pm
by idle
matalog wrote: Mon Feb 24, 2025 11:07 pm
idle wrote: Sat Jan 11, 2025 5:14 am
gzip is just deflate with a header and checksum, why not use deflate?
CompressMemory(*input,len,*output,outputlen,#PB_PackerPlugin_Zip)
Idle, can I use what you are describing to ungzip a file using PB's own capabilities, without requiring zlib?
see sergey's code
https://www.purebasic.fr/english/viewto ... 21#p633621
it still needs zlib
Re: HttpRequest with gzip
Posted: Tue Feb 25, 2025 12:21 am
by matalog
idle wrote: Mon Feb 24, 2025 11:41 pm
matalog wrote: Mon Feb 24, 2025 11:07 pm
idle wrote: Sat Jan 11, 2025 5:14 am
gzip is just deflate with a header and checksum, why not use deflate?
CompressMemory(*input,len,*output,outputlen,#PB_PackerPlugin_Zip)
Idle, can I use what you are describing to ungzip a file using PB's own capabilities, without requiring zlib?
see sergey's code
https://www.purebasic.fr/english/viewto ... 21#p633621
it still needs zlib
Yes, I have got that to work by putting my file in memory, but I would like to not rely on zlib, as I have worked with programs that relied on zlib, and they have had problems with accessing or finding the library.
I thought that your suggestion would allow a single file to be ungzipped without zlib. Is that not correct?
Re: HttpRequest with gzip
Posted: Tue Feb 25, 2025 1:32 am
by idle
matalog wrote: Tue Feb 25, 2025 12:21 am
idle wrote: Mon Feb 24, 2025 11:41 pm
matalog wrote: Mon Feb 24, 2025 11:07 pm
idle wrote: Sat Jan 11, 2025 5:14 am
gzip is just deflate with a header and checksum, why not use deflate?
CompressMemory(*input,len,*output,outputlen,#PB_PackerPlugin_Zip)
Idle, can I use what you are describing to ungzip a file using PB's own capabilities, without requiring zlib?
see sergey's code
https://www.purebasic.fr/english/viewto ... 21#p633621
it still needs zlib
Yes, I have got that to work by putting my file in memory, but I would like to not rely on zlib, as I have worked with programs that relied on zlib, and they have had problems with accessing or finding the library.
I thought that your suggestion would allow a single file to be ungzipped without zlib. Is that not correct?
zlib is linked statically to your executable so there's no problem in finding it.
if the import is causing issues, say your on linux or osx then you could do the import as
Code: Select all
UseZipPacker()
ImportC "";zlib.lib"
inflateInit2_.l(*stream.z_stream, windowBits.l, *version, streamsize.l)
inflate.l(*stream.z_stream, flush.l)
inflateEnd.l(*stream.z_stream)
EndImport
No I didn't mean you could ungzip a file without zlib, gzip is a zlib format.
Re: HttpRequest with gzip
Posted: Tue Feb 25, 2025 1:59 am
by matalog
zlib is linked statically to your executable so there's no problem in finding it.
if the import is causing issues, say your on linux or osx then you could do the import as
Code: Select all
UseZipPacker()
ImportC "";zlib.lib"
inflateInit2_.l(*stream.z_stream, windowBits.l, *version, streamsize.l)
inflate.l(*stream.z_stream, flush.l)
inflateEnd.l(*stream.z_stream)
EndImport
No I didn't mean you could ungzip a file without zlib, gzip is a zlib format.
Brilliant, so I can compile, and use on another Windows 10 PC without problem? That would be great

.
I'll give it a try.
Re: HttpRequest with gzip
Posted: Wed Feb 26, 2025 8:16 pm
by matalog
Sergey wrote: Mon Jan 13, 2025 10:37 pm
Hi, Rinzwind
I adapted Windows code from this forum to your needs,
just test it and correct lines how you want
Please wait for ending, on my PC it took about 18 sec. buffer 1024
Buffer 1024 * 1024 (1 MB) took 0.1 sec.
No need any PB packer's code like ZIP or LZMA
Code: Select all
EnableExplicit
#Z_BUFFER_SIZE = 1024 * 1024 ;- buffer size
#ZLIB_VERSION = "1.2.8"
#Z_OK = 0
#Z_STREAM_END = 1
#Z_FULL_FLUSH = 3
#Z_FINISH = 4
#ENABLE_GZIP = 16
Structure z_stream Align #PB_Structure_AlignC
*next_in.BYTE
avail_in.l
total_in.l ;uLong
*next_out.BYTE
avail_out.l
total_out.l ;uLong
*msg.BYTE
*state
zalloc.i
zfree.i
opaque.i
data_type.l
adler.l ;uLong
reserved.l ;uLong
;without this, the inflateInit2() fails with a version error
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
alignment.l
CompilerEndIf
EndStructure
ImportC "zlib.lib"
inflateInit2_.l(*stream.z_stream, windowBits.l, *version, streamsize.l)
inflate.l(*stream.z_stream, flush.l)
inflateEnd.l(*stream.z_stream)
EndImport
Procedure ungzip(*buf)
Protected gzip_strm.z_stream, gzip_opaque.l, *gzip_buffer, *gzip_out, gzip_result.l, gzip_unpacked_size.l
Protected buf_memory_size = MemorySize(*buf)
Protected *buf2
If buf_memory_size > 0
Debug "gzip_packed_size = " + Str(buf_memory_size)
gzip_strm.z_stream
gzip_strm\next_in = *buf
gzip_strm\avail_in = buf_memory_size
gzip_strm\opaque = @gzip_opaque
inflateInit2_(gzip_strm, 15 | #ENABLE_GZIP, #ZLIB_VERSION, SizeOf(z_stream))
*gzip_buffer = AllocateMemory(#Z_BUFFER_SIZE)
*gzip_out = AllocateMemory(#Z_BUFFER_SIZE)
If *gzip_buffer And *gzip_out
Repeat
gzip_strm\next_out = *gzip_buffer
gzip_strm\avail_out = #Z_BUFFER_SIZE
gzip_result = inflate(gzip_strm, #Z_FULL_FLUSH)
If gzip_result = #Z_OK Or gzip_result = #Z_STREAM_END Or gzip_strm\avail_in = 0
CopyMemory(*gzip_buffer, *gzip_out + MemorySize(*gzip_out) - #Z_BUFFER_SIZE, #Z_BUFFER_SIZE)
If gzip_result = #Z_STREAM_END Or gzip_strm\avail_in = 0
Break
Else
*gzip_out = ReAllocateMemory(*gzip_out, MemorySize(*gzip_out) + #Z_BUFFER_SIZE)
EndIf
Else
If gzip_strm\msg
Debug PeekS(gzip_strm\msg, #PB_UTF8)
Else
Debug "gzip_result = " + Str(gzip_result)
EndIf
Break
EndIf
ForEver
gzip_unpacked_size = gzip_strm\total_out
If gzip_unpacked_size > 0
Debug "gzip_unpacked_size = " + Str(gzip_unpacked_size)
Debug "compression ratio: " + StrF(buf_memory_size * 100 / gzip_unpacked_size, 1) + "%"
*buf2 = AllocateMemory(gzip_unpacked_size)
CopyMemory(*gzip_out, *buf2, gzip_unpacked_size)
EndIf
buf_memory_size = gzip_unpacked_size
FreeMemory(*gzip_out)
FreeMemory(*gzip_buffer)
inflateEnd(gzip_strm)
EndIf
Else
Debug "buf_memory_size = 0"
EndIf
ProcedureReturn *buf2
EndProcedure
Define t1 = ElapsedMilliseconds()
Define url.s = "https://raw.githubusercontent.com/json-iterator/test-data/refs/heads/master/large-file.json"
Define NewMap headers.s()
headers("Accept-Encoding") = "gzip"
Debug url
Define req = HTTPRequestMemory(#PB_HTTP_Get, url, 0, 0, 0, headers())
Debug "HTTPRequest Timer: " + Str(ElapsedMilliseconds() - t1)
If req
Define stat.s = HTTPInfo(req, #PB_HTTP_StatusCode)
Define res.s = HTTPInfo(req, #PB_HTTP_Response)
Debug Left(res, 100) + "..."
Define *buf = HTTPMemory(req)
FinishHTTP(req)
If *buf
Define res2.s = PeekS(*buf, MemorySize(*buf), #PB_UTF8 | #PB_ByteLength)
Debug Left(res2, 100) + "..."
Define t2 = ElapsedMilliseconds()
Define *buf2 = ungzip(*buf)
Debug "UnGZIP Timer: " + Str(ElapsedMilliseconds() - t2)
If *buf2
res2.s = PeekS(*buf2, MemorySize(*buf2), #PB_UTF8 | #PB_ByteLength)
Debug Left(res2, 100) + "..."
FreeMemory(*buf2)
EndIf
FreeMemory(*buf)
EndIf
EndIf
Would this be easy to amend so that instead of ungzip, it will gzip instead?
Re: HttpRequest with gzip
Posted: Wed Feb 26, 2025 9:55 pm
by PeDe
Hello matalog,
here is a procedure that I have tested. A .NET program can read the GZIP-compressed data. The program saves its data in compressed form (.NET GZipStream).
Peter
Code: Select all
UseZipPacker()
UseCRC32Fingerprint()
;- GZip-Header.
Structure uGzipHeader
iId1.b ; ID1, ID2 - magic header (immer 0x1F, 0x8B)
iId2.b
iCm.b ; CM - Compression method DEFLATE.
iFlg.b ; FLG -Bitfield.
iMTime.l; MTIME - Modification timestamp as Unix time.
iXfl.b ; XFL - Additional information specific to the compression method.
iOs.b ; OS - Type of file system or operating system.
EndStructure
Procedure.i GzipMemory(*Data, iDataSize.i, *GzipData.Integer)
; Compresses the passed memory in GZIP format.
; -> *Data: Pointer to the data to be compressed.
; -> iDataSize: The length of the data.
; <- *GzipData: A pointer to the compressed data.
; Return: The length of the compressed data, or zero in the event of an error.
; The memory with the compressed data must be released again.
Protected iReturn.i, fResult.i, iGzipSize.i, iCrc.l, iOffset.i
Protected *uGzipHeader.uGzipHeader
; Check passed parameters.
fResult = Bool(*Data And iDataSize)
If (Not fResult)
Debug("The pointer or the length of the memory is zero. *Data = " + *Data +
", iDataSize = " + iDataSize)
EndIf
If fResult
fResult = Bool(*GzipData)
If (Not fResult)
Debug("The pointer for the return of the compressed data is zero. *GzipData = Null")
EndIf
EndIf
If fResult
*GzipData\i = AllocateMemory(iDataSize + 10000) ; More space if the data cannot be compressed.
If *GzipData\i
iOffset = SizeOf(uGzipHeader) - 2 ; The zlib header is later overwritten with the GZIP header.
iGzipSize = CompressMemory(*Data, iDataSize, *GzipData\i + iOffset, iDataSize + 10000 - iOffset,
#PB_PackerPlugin_Zip, 6)
If iGzipSize
; Write the GZIP header.
*uGzipHeader = *GzipData\i
With *uGzipHeader
\iId1 = $1F
\iId2 = $8B
\iCm = $08
\iFlg = $00
\iMTime = $00 ; Date()
; The zlib magic header (2 bytes) is overwritten here; this is not used.
\iXfl = $04
\iOs = $00
EndWith
; Calculate and write the CRC32 of the uncompressed data.
iCrc = Val("$" + Fingerprint(*Data, iDataSize, #PB_Cipher_CRC32))
; Overwrite the CRC32 (Adler32?) at the end of the compressed data, this is not used.
iOffset = iGzipSize + SizeOf(uGzipHeader) - 2 ; plus Gzip header minus overwritten zlib header.
iOffset - 4 ; Overwrite CRC32 (Adler32?) at the end of the zlib data.
PokeL(*GzipData\i + iOffset, iCrc)
; Write the length of the uncompressed data.
iOffset + 4
PokeL(*GzipData\i + iOffset, iDataSize)
; Return the length of the GZip data.
iReturn = iOffset + 4
EndIf
EndIf
EndIf
ProcedureReturn iReturn
EndProcedure
Re: HttpRequest with gzip
Posted: Fri Feb 28, 2025 12:47 am
by kenmo
I had to take a swing at a single-procedure solution.
Takes a *gzip buffer and returns an unpacked buffer. Uses PB's UseZipPacker() but nothing else.
Does this work for you?
Code: Select all
Procedure.i UngzipToBuffer(*gzip, gzipBytes.i = #PB_Default) ; #PB_Default --> get gzipBytes from MemorySize(*gzip)
Protected *Buffer = #Null
If (*gzip)
UseZipPacker()
If (gzipBytes = #PB_Default)
gzipBytes = MemorySize(*gzip)
EndIf
If (gzipBytes > 0)
Protected CompressedBytes.i, UncompressedBytes.i, BufferSize.i, UnpackedBytes.i, TempWord.w
If ((PeekA(*gzip + 0) = $1F) And (PeekA(*gzip + 1) = $8B)) ; magic number
If (PeekA(*gzip + 2) = $08) ; DEFLATE compression method
If (PeekA(*gzip + 3) = $00) ; no header flags supported (yet)
UncompressedBytes = PeekL(*gzip + gzipBytes - 4)
If (UncompressedBytes > 0)
CompressedBytes = gzipBytes - (10 + 8)
If (CompressedBytes > 0)
BufferSize = UncompressedBytes + 16
*Buffer = AllocateMemory(BufferSize, #PB_Memory_NoClear)
If (*Buffer)
PokeU(*Buffer + UncompressedBytes - 1, $7F7F)
TempWord = PeekW(*gzip + 8)
PokeA(*gzip + 8, $78) ; zlib magic number
PokeA(*gzip + 9, $9C) ; assume "Default Compression"
UnpackedBytes = UncompressMemory(*gzip + (10 - 2), 2 + CompressedBytes + 4, *Buffer, BufferSize)
PokeW(*gzip + 8, TempWord)
If (UnpackedBytes = -1)
If ((PeekA(*Buffer + UncompressedBytes - 1) <> $7F) And (PeekA(*Buffer + UncompressedBytes) = $7F))
UnpackedBytes = UncompressedBytes
EndIf
EndIf
If (UnpackedBytes = UncompressedBytes)
*Buffer = ReAllocateMemory(*Buffer, UnpackedBytes)
Else
FreeMemory(*Buffer)
*Buffer = #Null
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
ProcedureReturn (*Buffer)
EndProcedure
And a second helper procedure to un-gzip to file:
Code: Select all
Procedure.i UngzipToFile(*gzip, File.s, gzipBytes.i = #PB_Default) ; #PB_Default --> get gzipBytes from MemorySize(*gzip)
Protected Result.i = #False
If (File)
Protected *Buffer = UngzipToBuffer(*gzip, gzipBytes)
If (*Buffer)
Protected FN.i = CreateFile(#PB_Any, File)
If (FN)
Protected BufferSize.i = MemorySize(*Buffer)
If (WriteData(FN, *Buffer, BufferSize) = BufferSize)
Result = #True
EndIf
CloseFile(FN)
EndIf
FreeMemory(*Buffer)
EndIf
EndIf
ProcedureReturn (Result)
EndProcedure
Note, it does everything in-memory rather than iterating chunks of data, so I would not recommend using this for huge/gigabytes of data!
Re: HttpRequest with gzip
Posted: Mon Mar 03, 2025 2:20 pm
by matalog
Thanks, I will try those.
Re: HttpRequest with gzip
Posted: Fri May 09, 2025 8:38 am
by Rinzwind
Any way to get this into v6.21? PM if needed.
ps forum is extremely slow. (edit: reboot? everything speedy again for now)
Re: HttpRequest with gzip
Posted: Fri May 09, 2025 9:32 am
by Fred
We won't add anything to 6.21 but it should be in 6.30.