compression library, Windows and Linux

Share your advanced PureBasic knowledge/code with the community.
User avatar
RocketRider
User
User
Posts: 87
Joined: Tue Aug 19, 2008 11:01 am

compression library, Windows and Linux

Post by RocketRider »

Here is a compression library, it use the zlib library.
In contrary to the PureBasic Packer functions can be so packages that were created under Windows with Linux open and vice versa. In addition, it is much faster. :wink:

Download

Code: Select all

;PACKER FUNCTIONS FOR WINDOWS AND LINUX 
;====================================== 
;I wrote these packer functions because there seems to be issues when loading compressed packages from windows on linux or vice versa. 
;These functions use same compression algorithm for linux and windows. 
;It is very similar to the packer functions of PureBasic. 
;The compression is much faster as with PureBasic commands. 
;For windows the zlib1.dll is needed. 
; 
;Feel free to do whatever you want with this code, but note that the author is not liable for any damages which are caused by this software. 

Global ZPAC_Library.l, ZPAC_createpack_file.l, ZPAC_createpack_filecount.l , ZPAC_createpack_encryption, ZPAC_lasterror.s, ZPAC_showerror.l 
Global ZPAC_readpack_file.l, ZPAC_readpack_filecount.l, ZPAC_readpack_count.l, ZPAC_readpack_encryption, ZPAC_readpack_filesize.l,*ZPAC_CompressedBuffer.l, ZPAC_CompressedBufferSize.l, *ZPAC_DeCompressedBuffer.l, ZPAC_DeCompressedBufferSize.l 

Macro __ZPAC_SetError(error) 
ZPAC_lasterror = error 
If ZPAC_showerror 
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows 
    MessageRequester("ZPAC Error:", "There was an error in the ZPAC library:" + #CRLF$ + ZPAC_lasterror, #MB_ICONERROR)      
  CompilerElse 
    MessageRequester("ZPAC Error:", "There was an error in the ZPAC library:" + #CRLF$ + ZPAC_lasterror, #PB_MessageRequester_Ok) 
  CompilerEndIf 
EndIf 
EndMacro 

;Initalizes and loads the zlib library. This command must be called before all other ZLIB commands. 
ProcedureDLL.l ZPAC_Init(lShowError.l = #False) 
  CompilerIf #PB_Compiler_OS = #PB_OS_AmigaOS 
    CompilerError "Operating System not supported!" 
  CompilerEndIf 
  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS 
    CompilerError "Operating System not supported!" 
  CompilerEndIf 
    
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows 
    ZPAC_Library = OpenLibrary(#PB_Any, "zlib1.dll") 
  CompilerElse 
    ZPAC_Library = OpenLibrary(#PB_Any, "libz.so") 
  CompilerEndIf 
  
  ZPAC_showerror = lShowError 
  ZPAC_lasterror = "" 
  ZPAC_createpack_file = #Null 
  ZPAC_createpack_filecount = 0 
  ZPAC_createpack_encryption = 0 
  
  ZPAC_readpack_file = #Null 
  ZPAC_readpack_filecount = 0 
  ZPAC_readpack_count = 0    
  ZPAC_readpack_encryption = 0 
  ZPAC_readpack_filesize = 0 
  
  *ZPAC_CompressedBuffer = #Null 
  ZPAC_CompressedBufferSize = 0 
    
  *ZPAC_DeCompressedBuffer = #Null 
  ZPAC_DeCompressedBufferSize = 0 
      
  If ZPAC_Library = #Null 
    __ZPAC_SetError("ZPAC_Init: can't find zlib library")    
  EndIf 
  ProcedureReturn ZPAC_Library 
EndProcedure 

; Frees the zlib library. This command must be called after all ZLIB commands. 
ProcedureDLL.l ZPAC_Free() 
  If ZPAC_Library  
    If *ZPAC_CompressedBuffer 
      FreeMemory(*ZPAC_CompressedBuffer) 
    EndIf 
    *ZPAC_CompressedBuffer = #Null 
        
    If *ZPAC_DeCompressedBuffer 
      FreeMemory(*ZPAC_DeCompressedBuffer) 
    EndIf 
    *ZPAC_DeCompressedBuffer = #Null 
    
    If ZPAC_createpack_file 
      CloseFile(ZPAC_createpack_file) 
    EndIf 
    
    If ZPAC_readpack_file 
      CloseFile(ZPAC_readpack_file) 
    EndIf    
    CloseLibrary(Library_zlib) 
  EndIf 
EndProcedure 

;Returns an description of the last error of the zlib library. 
;This command is very useful to find the reason for an error. 
ProcedureDLL.s ZPAC_GetLastError() 
  ProcedureReturn ZPAC_lasterror 
EndProcedure 


;Creates a pack archive. If the parameter lEncryption is 0 then there is no encryption. 
;Otherwise a simple XOR encryption based on the lEncryption parameter is used. 
;A pack file created with ZPAC_CreatePack must be closed with ZPAC_CloseCreatePack. 
Procedure ZPAC_CreatePack(sFile.s, lEncryption.l = 0) 
  If ZPAC_Library 
    If ZPAC_createpack_file 
      __ZPAC_SetError("ZPAC_CreatePack: there is already a pack file opened")    
      ProcedureReturn #False      
    EndIf 
  
    ZPAC_createpack_filecount = 0 
    ZPAC_createpack_file = CreateFile(#PB_Any, sFile.s) 
    ZPAC_createpack_encryption = lEncryption 
    If ZPAC_createpack_file 
      WriteLong(ZPAC_createpack_file, 'CAPZ') 
      WriteLong(ZPAC_createpack_file, 0) ; Write numer of files in pack 
    Else 
      __ZPAC_SetError("ZPAC_CreatePack: Can't create pack file " + sFile) 
    EndIf 
    ProcedureReturn #True 
  Else 
    __ZPAC_SetError("ZPAC_CreatePack: zlib library was not opened")    
    ProcedureReturn #False 
  EndIf 
EndProcedure 

;Opens a packed file previously created with ZPAC_CreatePack(). 
;A pack file opened with ZPAC_ReadPack must be closed with ZPAC_CloseReadPack. 
ProcedureDLL.l ZPAC_ReadPack(sFile.s, lEncryption.l = 0) 
lSuccess = #True 
  If ZPAC_Library 
    
    If ZPAC_readpack_file 
      __ZPAC_SetError("ZPAC_CreatePack: there is already a pack file opened")      
      ProcedureReturn #False 
    EndIf    
    
    ZPAC_readpack_file = ReadFile(#PB_Any, sFile.s) 
    ZPAC_readpack_encryption = lEncryption 
    ZPAC_readpack_filesize = 0 
    If ZPAC_readpack_file 
    
      FileBuffersSize(ZPAC_readpack_file, 16384) 

      lSign = ReadLong(ZPAC_readpack_file) 
      
      If lSign = 'CAPZ' 
      
        ZPAC_readpack_filecount = ReadLong(ZPAC_readpack_file) 
        ZPAC_readpack_count = 0 
        If ZPAC_readpack_filecount > 0 
          ; Pack file is ok 
          
        Else 
          __ZPAC_SetError("ZPAC_ReadPack: pack file contains nothing") 
          lSuccess = #False          
        EndIf 
      
      Else 
        __ZPAC_SetError("ZPAC_ReadPack: File " + Chr(34) + sFile + Chr(34) + " is not a valid pack file") 
        lSuccess = #False      
      EndIf 
      
    Else 
      __ZPAC_SetError("ZPAC_CreatePack: Can't read pack file " + sFile) 
      lSuccess = #False 
    EndIf 

  Else 
    __ZPAC_SetError("ZPAC_ReadPack: zlib library was not opened")    
    lSuccess = #False 
  EndIf 
  ProcedureReturn lSuccess 
EndProcedure 

;Returns the number of files in the package. 
;The command works only if a package is opened with ZPAC_ReadPack(). 
ProcedureDLL.l ZPAC_ReadPackFiles() 
  ProcedureReturn ZPAC_readpack_filecount 
EndProcedure 

;Returns the pointer to the next file in the package. 
;The command works only if a package is opened with ZPAC_ReadPack(). 
ProcedureDLL.l ZPAC_NextPackFile() 
  *lResultPtr.l = #Null 
  ZPAC_readpack_filesize = 0 
  If ZPAC_Library 
    
    If ZPAC_readpack_file 
    
      If ZPAC_readpack_count < ZPAC_readpack_filecount 
      
        ZPAC_readpack_count + 1 
        
        lOrgSize = ReadLong(ZPAC_readpack_file) 
        lPackedSize = ReadLong(ZPAC_readpack_file) 
        
        If *ZPAC_CompressedBuffer = #Null Or ZPAC_CompressedBufferSize < lPackedSize 
          If *ZPAC_CompressedBuffer 
            FreeMemory(*ZPAC_CompressedBuffer) 
          EndIf 
          *ZPAC_CompressedBuffer = AllocateMemory(lPackedSize) 
          ZPAC_CompressedBufferSize = lPackedSize 
        EndIf 
                
        If *ZPAC_DeCompressedBuffer = #Null Or ZPAC_DeCompressedBufferSize < lOrgSize 
          If *ZPAC_DeCompressedBuffer 
            FreeMemory(*ZPAC_DeCompressedBuffer) 
          EndIf 
          *ZPAC_DeCompressedBuffer = AllocateMemory(lOrgSize) 
          ZPAC_DeCompressedBufferSize = lOrgSize 
        EndIf      
      
          
        If *ZPAC_CompressedBuffer And *ZPAC_DeCompressedBuffer 
        
          ReadData(ZPAC_readpack_file, *ZPAC_CompressedBuffer, lPackedSize) 
          
          If ZPAC_readpack_encryption 
            
              RandomSeed(ZPAC_readpack_encryption) 
              *Tmp.BYTE = *ZPAC_CompressedBuffer 
              For c = 0 To lPackedSize - 1 
               *Tmp\b - c 
               *Tmp\b ! Random($FF) 
               *Tmp +1 
              Next 
            
          EndIf 
        
          ZPAC_readpack_filesize = lOrgSize 
          
          lResult.l = CallCFunction(ZPAC_Library, "uncompress", *ZPAC_DeCompressedBuffer, @lOrgSize, *ZPAC_CompressedBuffer, lPackedSize) 

          If lResult = 0 
            *lResultPtr = *ZPAC_DeCompressedBuffer 
          Else 
            ZPAC_readpack_filesize = 0 
            __ZPAC_SetError("ZPAC_NextPackFile: zlib uncompress failed with errorcode "+Str(lResult))            
          EndIf 
          
        Else 
          __ZPAC_SetError("ZPAC_NextPackFile: can't allocate needed memory")    
        EndIf  
        
      Else 
        __ZPAC_SetError("ZPAC_NextPackFile: There are no further files in this package") 
      EndIf 
            
    Else 
      __ZPAC_SetError("ZPAC_NextPackFile: No pack file was opened") 
    EndIf 

  Else 
    __ZPAC_SetError("ZPAC_NextPackFile: zlib library was not opened")    
  EndIf 
  ProcedureReturn *lResultPtr 
EndProcedure 

;Returns the size of the last package file in the package. 
;The command must be called after ZPAC_NextPackFile. 
ProcedureDLL.l ZPAC_NextPackFileSize() 
  ProcedureReturn ZPAC_readpack_filesize 
EndProcedure 

;Closes a package opened with ZPAC_CreatePack(). 
ProcedureDLL.l ZPAC_CloseCreatePack() 
  If ZPAC_Library 
    If ZPAC_createpack_file 
      FileSeek(ZPAC_createpack_file, 4) 
      WriteLong(ZPAC_createpack_file, ZPAC_createpack_filecount) ; Write numer of files in pack 
      CloseFile(ZPAC_createpack_file) 
      ZPAC_createpack_file = #Null 
      ZPAC_createpack_filecount = 0 
      ProcedureReturn #True 
    Else 
    __ZPAC_SetError("ZPAC_ClosePack: No pack file opened") 
    ProcedureReturn #False 
    EndIf 
  Else 
    __ZPAC_SetError("ZPAC_CreatePack: zlib library was not opened")    
    ProcedureReturn #False 
  EndIf 
EndProcedure 

;Closes a package opened with ZPAC_ReadPack(). 
ProcedureDLL.l ZPAC_CloseReadPack() 
  If ZPAC_Library 
    If ZPAC_readpack_file 
      CloseFile(ZPAC_readpack_file) 
      ZPAC_readpack_file = #Null 
      ZPAC_readpack_filecount = 0 
      ZPAC_readpack_count = 0    
      ZPAC_readpack_filesize = 0 
      
      If *ZPAC_CompressedBuffer 
        FreeMemory(*ZPAC_CompressedBuffer) 
      EndIf 
      *ZPAC_CompressedBuffer = #Null 
      ZPAC_CompressedBufferSize = 0 
        
      If *ZPAC_DeCompressedBuffer 
        FreeMemory(*ZPAC_DeCompressedBuffer) 
      EndIf 
      *ZPAC_DeCompressedBuffer = #Null 
      ZPAC_DeCompressedBufferSize = 0 
        
      ProcedureReturn #True 
    Else 
    __ZPAC_SetError("ZPAC_CloseReadPack: No pack file opened") 
    ProcedureReturn #False 
    EndIf 
  Else 
    __ZPAC_SetError("ZPAC_CloseReadPack: zlib library was not opened")    
    ProcedureReturn #False 
  EndIf 
EndProcedure 

;Adds a memory area to the pack file opened with ZPAC_CreatePack(). 
;The parameter lCompressionLevel can be form 0 to 9 (default is 9). 
ProcedureDLL.l ZPAC_AddMemoryPack(*MemoryPtr, lSize.l, lCompressionLevel.l = 9) 
  If ZPAC_Library 
    lSuccess = #True 
    
    If ZPAC_createpack_file And *MemoryPtr And lSize > 0 
      ZPAC_createpack_filecount + 1 
      
      DestSize = lSize * 2 + 32 
      *TmpBuffer.l = AllocateMemory(DestSize) 
      
      If *TmpBuffer 
                  
        If lCompressionLevel < 0 :lCompressionLevel = 0:EndIf 
        If lCompressionLevel > 9 :lCompressionLevel = 9:EndIf 
          
        lResult.l = CallCFunction(ZPAC_Library, "compress2", *TmpBuffer, @DestSize, *MemoryPtr, lSize, lCompressionLevel)  
        
        If lResult = 0 
        
          If ZPAC_createpack_encryption 
          
            RandomSeed(ZPAC_createpack_encryption) 
            *Tmp.BYTE = *TmpBuffer 
            For c = 0 To DestSize - 1 
             *Tmp\b ! Random($FF) 
             *Tmp\b + c 
             *Tmp +1 
            Next 
          
          EndIf 
                  
          WriteLong(ZPAC_createpack_file, lSize) 
          WriteLong(ZPAC_createpack_file, DestSize) 
          WriteData(ZPAC_createpack_file, *TmpBuffer, DestSize) 
        
        Else 
          lSuccess = #False 
          __ZPAC_SetError("ZPAC_AddMemoryPack: zlib compress failed with errorcode: "+Str(lResult))  
        EndIf 
        
        FreeMemory(*TmpBuffer) 
      
      Else 
        lSuccess = #False 
        __ZPAC_SetError("ZPAC_AddMemoryPack: Can't create temporary buffer with size "+Str(DestSize)) 
      EndIf 
      
    Else 
      lSuccess = #False 
      If ZPAC_createpack_file = #Null 
        __ZPAC_SetError("ZPAC_AddMemoryPack: No pack file was opened") 
      EndIf 
      If *MemoryPtr = #Null 
        __ZPAC_SetError("ZPAC_AddMemoryPack: declared memory pointer is null") 
      EndIf    
      If lSize = #Null 
        __ZPAC_SetError("ZPAC_AddMemoryPack: declared memory size is <= 0") 
      EndIf            
    EndIf 
  Else 
    __ZPAC_SetError("ZPAC_AddMemoryPack: zlib library was not opened")    
    lSuccess = #False 
  EndIf    
  ProcedureReturn lSuccess 
EndProcedure 


;Adds a file to the pack file opened with ZPAC_CreatePack(). 
;The parameter lCompressionLevel can be form 0 to 9. The default is 9 (best compression). 
ProcedureDLL.l ZPAC_AddFile(sFile.s, lCompressionLevel.l = 5) 
  lSuccess = #False 
  If ZPAC_Library 
    lSuccess = #True 

      tmpFile = ReadFile(#PB_Any, sFile) 
      If tmpFile 
      
        lFileSize.l = Lof(tmpFile) 
        If lFileSize > 0 
          *TmpBuffer.l = AllocateMemory(lFileSize) 
          
          If *TmpBuffer.l 
          
            ReadData(tmpFile, *TmpBuffer, lFileSize) 

            If ZPAC_AddMemoryPack(*TmpBuffer, lFileSize, lCompressionLevel) = #False 
              lSuccess = #False 
            EndIf 
          
          Else 
            lSuccess = #False 
            __ZPAC_SetError("ZPAC_AddFile: Can't create temporary buffer with size "+Chr(34) + Str(lFileSize) + Chr(34))                    
          EndIf  
          
          FreeMemory(*TmpBuffer)                  
        Else 
          lSuccess = #False 
          __ZPAC_SetError("ZPAC_AddFile: File size is incorrect "+Chr(34) + Str(lFileSize) + Chr(34))                    
        EndIf 
        
        CloseFile(tmpFile) 
      Else 
        lSuccess = #False 
        __ZPAC_SetError("ZPAC_AddFile: Can't open file "+Chr(34)+sFile+Chr(34))        
      EndIf 

  Else 
    lSuccess = #False 
    __ZPAC_SetError("ZPAC_AddFile: zlib library was not opened")    
  EndIf 
  
  ProcedureReturn lSuccess 
EndProcedure 

;Example: 

ZPAC_Init(#True) ; Use true for debugging 

ZPAC_CreatePack("Test.pak", 48729193) 

test1.s = "1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 " 
test2.s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ " 
test3.s = "aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm nnn ooo ppp qqq rrr sss ttt uuu vvv www xxx yyy zzz" 
ZPAC_AddMemoryPack(@test1.s,Len(test1), 9) 
ZPAC_AddMemoryPack(@test2.s,Len(test2), 9) 
ZPAC_AddMemoryPack(@test3.s,Len(test3), 9) 
ZPAC_CloseCreatePack() 

 ZPAC_ReadPack("Test.pak", 48729193) 

Repeat 
ptr = ZPAC_NextPackFile() 
  If ptr 
    ;Debug PeekS(ptr) 
    MessageRequester("Output",PeekS(ptr)) 
  EndIf 
Until ptr = #Null 

ZPAC_CloseReadPack() 

ZPAC_Free()
jamirokwai
Enthusiast
Enthusiast
Posts: 798
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: compression library, Windows and Linux

Post by jamirokwai »

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
CompilerError "Operating System not supported!"
CompilerEndIf
Hi,

I didn't try your code because of the above section but it seems usefull :)
I can't confirm the section about MacOS X.... Is MacOS X really not supported,
or are there other issues? AFAIK, zlib is installed on default when installing Mac OS X.

www.zlib.net/ says: zlib for Mac OS X: zlib is already included as part of Mac OS X
Regards,
JamiroKwai
User avatar
RocketRider
User
User
Posts: 87
Joined: Tue Aug 19, 2008 11:01 am

Post by RocketRider »

I could not test the code under MacOS, because of this I included the CompilerIf. Can you test it under MacOS? :D
jamirokwai
Enthusiast
Enthusiast
Posts: 798
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Post by jamirokwai »

RocketRider wrote:I could not test the code under MacOS, because of this I included the CompilerIf. Can you test it under MacOS? :D
Hi RocketRider,

I tried your code, but there is a Linker Error :(

Until now, I never tried to use libraries on MacOS, simply because there is near
to none documenation on how to use it (at least, nothing worked, what I tried...)
But I found the correct zlib-library "libz.dylib" preinstalled in "/usr/lib/". I will try
again later this week to get some logfile from pbcompile on PB 4.3a1/Mac...

Please be patient :)
Regards,
JamiroKwai
Webarion
User
User
Posts: 30
Joined: Tue Sep 14, 2021 8:50 pm

Re: compression library, Windows and Linux

Post by Webarion »

I would like to know what CAPZ means in the line WriteLong(ZPAC_createpack_file, 'CAPZ')
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: compression library, Windows and Linux

Post by jacdelad »

This is a "magic word", just to identify the file type.

Also this library is pretty old, there's some new zlib-libraries here in the forum...
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Post Reply