WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Samples from Users
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

ZLIB Compression UDFs


;zlibUDF returns one of the following:
;  buf:  handle to a valid compressed buffer, if calling function with "compress" parameter
;        which you must "binaryFree" this in your main program 
; data:  handle to the uncompressed buffer, if calling function with "decompress" or "uncompress" parameter
;        This NO LONGER closes out the buffer that was passed to it.  It must be closed by the user using "binaryFree"
;Errors returns:
;  0:  invalid parameter passed to zlibUDF(), or ZLIB1.DLL doesn't exist
; -1:  zero-byte string or file...cannot compress/decompress
; -2:  if there was another problem with the actual DLLCall of the ZLIB1.DLL


#DefineFunction zlibUDF(data,compOrDecomp)  ;this could be a valid filename or just a string.  If it's a filename, then it will get converted to a string.

   ; VALIDATE ZLIB COMPRESSION LIBRARY
   dll = "zlib1.dll"  ;needs to be in the system path, or in the directory of the main EXE calling this UDF
                      ;  zlib1.dll can be located here:  http://www.gzip.org/zlib/
   If !FileExist(StrCat(DirWindows(1),dll))                       ;if dll does not exist in system directory
      If FileExist(StrCat(FilePath(IntControl(1004,0,0,0,0)),dll)) ;if dll exists in current wbt path
         FileCopy(StrCat(FilePath(IntControl(1004,0,0,0,0)),dll),DirWindows(1),@FALSE)   ;copy it to system directory
      Else
         Return 0   ;otherwise throw an error.
      EndIf
   EndIf

   ; VALIDATE COMPRESSION/DECOMPRESSION PARAMETER
   If StriCmp(compOrDecomp,"compress") != 0 && StriCmp(compOrDecomp,"uncompress") != 0 && StriCmp(compOrDecomp,"decompress") != 0
      Message("zlib Error!",StrCat('"',compOrDecomp,'" is not a valid parameter for zlibUDF()!'))
      Return 0
   EndIf

   ; CHECK IF INPUT IS A FILE, STRING OR A BUFFER AND GET THE SIZE
   If FileExist(data)
      size = FileSize(data) ;if so, get it's size
      dataType = "FILE"
   Else
      If BinaryBufInfo(data,-1) == @TRUE ;if it's a valid buffer
         size = binaryEodGet(data)  ;gets the size of the INITIALIZED data in the buffer
         dataType = "BUF"
      Else
         size = StrLen(data)   ;otherwise get the size of the string itself.
         dataType = "STRING"
      EndIf
   EndIf


   ; COMPRESS
   If StriCmp(compOrDecomp,"compress") == 0

      ; RETURN ERROR IF THE DATA IS 0 BYTES
      If size == 0 Then Return (-1)

      ; PREP THE SOURCE LENGTH BUFFER
      size = StrFixLeft(size,"0",15)  ;this is the original size, which will get appended onto the last 15 bytes of the buffer
      sourceLen = DllCallCDecl(dll,long:"compressBound",long:size)  ;gets a minimum amount of space to allocate for the Dest buffer, but this
                                                                    ;  value is slightly larger because zLib1.dll needs extra space for swapping
      ; READ THE FILE OR STRING INTO THE SOURCE BUFFER
      If dataType == "FILE" || dataType == "STRING"
         bufSource = BinaryAlloc(sourceLen) ;create a buffer the size of the source file or string
         If dataType == "FILE"
            BinaryRead(bufSource,data)        ;file
         Else  ;dataType == "STRING"
            BinaryPokeStr(bufSource,0,data)   ;string
         EndIf
      Else
         bufSource = data  ;data is already a buffer, so just set bufSource equal to it for uniformity.
      EndIf

      ; PREP THE DEST LENGTH BUFFER
      destLen = sourceLen
      bufDestLen = BinaryAlloc(destLen) ;create a buffer that will tell how long the destination buffer should be
      BinaryPoke4(bufDestLen,0,destLen) ;  and poke that value into the buffer

      ; PREP THE DEST BUFFER
      bufDest = BinaryAlloc(destLen+15)  ;create a buffer that will contain the final compressed data, plus 15 extra bytes

      ; COMPRESS THE SOURCE BUFFER INTO THE DEST BUFFER
      ret = DllCallCDecl(dll,long:"compress",LPBINARY:bufDest,LPBINARY:bufDestLen,LPBINARY:bufSource,LONG:sourceLen)
      If ret != 0
         BinaryFree(bufDestLen)  ;
         dataType <> "BUF" then BinaryFree(bufSource)   ;free up the memory from the now-unused buffers
         BinaryFree(bufDest)     ;
         Return(-2)
      EndIf

      ; ADD ORIGINAL SOURCE LENGTH TO THE END OF THE COMPRESSED DATA FOR UNCOMPRESSING LATER
      BinaryEodSet(bufDest,BinaryPeek4(bufDestLen,0)+15)    ;add 15 bytes onto the end of the compressed buffer, after the last initialized byte
      BinaryPokeStr(bufDest,BinaryPeek4(bufDestLen,0),size) ;and then poke the original uncompressed size onto the end of the buffer (for "uncompress" to use later)
      BinaryFree(bufDestLen)  ;free up the memory from the now-unused buffers
      If dataType <> "BUF" Then BinaryFree(bufSource)  ;don't free the passed in buffer. That's up to the caller to do I should think.

      Return(bufDest)  ;returns a buffer handle to the compressed data
   EndIf


   ; DECOMPRESS
   If StriCmp(compOrDecomp,"uncompress") == 0 || StriCmp(compOrDecomp,"decompress") == 0

      ;PREP SOURCE DATA BUFFER
      If dataType == "BUF"
         bufSource = data
      Else
         bufSource = BinaryAlloc(size) ;size was defined towords top of function
         If dataType == "FILE"
            BinaryRead(bufSource,data)       ;read data file into buffer
         Else  ;dataType == "STRING"
            BinaryPokeStr(bufSource,0,data)  ;poke data string into buffer
         EndIf
      EndIf

      ; GET LENGTHS OF SOURCE AND DESTINATION DATA INTO BUFFERS
      sourceLen = size-15                          ;the actual buffer length is 15 bytes less than we've got
      size = BinaryPeekStr(bufSource,sourceLen,15) ;  because the last 15 bytes is actually the size of the uncompressed data.
      BinaryEodSet(bufSource,sourceLen)            ;  and we need to reset the buffer to cut off those last 15 bytes once we have the value

      ; PREP DESTINATION LENGTH BUFFER
      destLen = DllCallCDecl(dll,long:"compressBound",long:size)  ;gets a minimum amount of space to allocate for the Dest buffer, but this
                                                                         ;  value is slightly larger because zLib1.dll needs extra space for swapping
      bufDestLen = BinaryAlloc(destLen) ;create a buffer that will tell how long the destination buffer should be
      BinaryPoke4(bufDestLen,0,destLen) ;  and poke that value into the buffer

      ; PREP THE DESTINATION BUFFER
      bufDest = BinaryAlloc(destLen)  ;create a buffer that will contain the final compressed data

      ; DECOMPRESS THE SOURCE BUFFER INTO THE DESTINATION BUFFER
      ret = DllCallCDecl(dll,long:"uncompress",LPBINARY:bufDest,LPBINARY:bufDestLen,LPBINARY:bufSource,LONG:sourceLen)
      BinaryEodSet(bufDest,size)   ;truncate the extra characters from the end of the buffer to match the original size
      BinaryFree(bufDestLen)                            ;
      If dataType <> "BUF" Then BinaryFree(bufSource)   ;don't free the passed in buffer. That's for the caller to do, I should think.

      If ret != 0 Then Return(-2)   ; if there was a problem with the call to the DLL, then return (-2),
      Else Return bufDest           ; otherwise, return the uncompressed buffer
   EndIf
#EndFunction zlibUDF



;  Example(s)
; CREATE RANDOM DATA
BoxOpen("zLib","Creating random data.")
data = ""
For x = 1 To 1000
   data = StrCat(data,Random(99999999999),@CRLF)
Next ;x

; LOAD DATA INTO A BUFFER AND WRITE TO A FILE
bufData = BinaryAlloc(StrLen(data))
BinaryPokeStr(bufData,0,data)
BinaryWrite(bufData,"c:\_1-data.txt")

; COMPRESS BUFFER
buf = zLibUDF(bufData,"COMPRESS")
BinaryFree(bufData)

; WRITE COMPRESSED DATA TO A FILE
BinaryWrite(buf,"c:\_2-compressed.txt")
BinaryFree(buf)

; LOAD COMPRESSED DATA INTO BUFFER
buf = BinaryAlloc(FileSize("c:\_2-compressed.txt"))
BinaryRead(buf,"c:\_2-compressed.txt")

; UNCOMPRESS COMPRESSED DATA AND WRITE IT TO FILE
bufUn = zLibUDF(buf,"UNCOMPRESS")
BinaryFree(buf)
BinaryWrite(bufUn,"c:\_3-uncompressed.txt")

Message("Buffer Test","Check c:\_.txt for results")
Exit



Article ID:   W16712
File Created: 2005:02:18:12:21:56
Last Updated: 2005:02:18:12:21:56