WHAT'S NEW IN ARCHIVELIB 2.0? ----------------------------- Pkware support -------------- You can now work with the PKWare ZIP archive format. To work with PKZIP archives, you need to create objects of type ALPkArchive. ALPkArchive has exactly the same member functions as ALGlArchive, so you can mix and match these archive types freely. ArchiveLib 2.0 doesn't support the following ZIP features: * Extraction of PKZIP 1.0 file formats. In particular, PKZIP 1.0 used LZW compression to store files. LZW compression is covered by a patent. You probably don't want to pay royalties on your product. * Encryption. We need to sort out the export regulations on this before we attempt to add this to our product. * Disk spanning. This is our number one feature for ArchiveLib 3.0. OS/2 support ------------ ArchiveLib now comes with complete support for OS/2 console and PM applications. You can use BUILD.EXE to build examples using OS/2 libraries, from Borland and Microsoft. The examples directory contains a raft of examples named EX??CON.CPP, EX??CON.C and EX??PM.CPP that will all work with OS/2. Deflate engine -------------- We have incorporated the ZLIB deflate engine written by Marc Adler and Jean-loop Gailly into ArchiveLib. These files, found in CPP_ZLIB, implement the compression type needed to read and write ZIP files. The two engines are instantiated using the classes ALPkCompressor and ALPkDecompressor. The deflate algorithm creates two big buffers to compress data. The sliding window is a buffer with 2^(window_bits+2) bytes of storage. In other words, a window bits value of 15 means you need 128Kbytes for the sliding buffer. The second buffer is 2^(mem_level+9) bytes long. So a mem_level of 8 will consume 128Kbytes. New class hierarchy for archive ------------------------------- The archive class hierarchy is somewhat simpler than it used to be. The abstract base class of ALArchive provides some infrastructure. The two classes derived from it are ALPkArchive and ALGlArchive. They provide the mechanism to create and manipulate the two different types of archives. New class hierarchy for compression engines ------------------------------------------- In ArchiveLib 1.0, the ALCompressionEngine contained the code to both compress and decompress. In an effort to be more granular, compression and decompression engines are now separated out into two base classes: ALCompressor and ALDecompressor. If you are just using archives, you probably don't have to worry about this too much. However, if you are using the engines in a standalone mode, you do need to worry about it. Storage type binding done by entry list via toolkit --------------------------------------------------- There is an architectural problem built in to ArchiveLib. The problem is how to decide which compression engines and storage objects to include in your application. In particular, it can be tough to decide which engines to include when you are writing a routine that is going to extract objects from an archive. You might not know in advance what type of objects are going to be in the archive, in which case you probably should like in everything in sight. On the other hand, you might only be extracting files using the deflate engine. If this is the case, linking in memory objects and the Greenleaf compression engine is a waste of time. In ArchiveLib 1.0, storage object and engine linkage was accomplished by deriving new types of archive objects. class ALArchive was the default class, and it linked in just about everything. In ArchiveLib 2.0, linkage is performed by the ALEntryList object. This is a little more logical. In addition, the linkage is more flexible, and doesn't require derivation. In a nutshell, when you create an ALEntryList object, you give it a toolkit of storage objects, compression engines, and decompression engines that it will use to do its job. By default, the toolkit contains all three compression engines, and two storage object types. This is accomplished by virtue of the default value for the toolkit parameter in the ALEntryList constructor. The default value of FullTools() creates a toolkit with everything but the kitchen sink. To build a more slim and trim application, you can construct your ALEntryList object with limited toolsets. The ones we provide prebuilt in the library include: * PkTools(): File and memory storage objects, but only the deflate engines. You would use this in an application that was not using Greenleaf's engine. * PKCompressTools(): Same as above, but just the deflate compression engine. A file that just creates Zip compatible archives could save space by excluding the decompression engine. * PKDecompressTools(): Same as above, but just the deflate decompression engine. Use this in an extraction only application. Likewise, there are a corresponding set of toolkit builders known as GlTools(), GlCompressTools(), and GLDecompressTools(). Finally, you can build your own toolkit in an argument to your ALEntryList object. Just throw in copies of all the compression/decompression objects and storage objects you plan to use, like this: ALEntryList list( ALFile() + ALGlCompressor() ); Yes, you use the '+' operator to connect all these guys together into a toolkit. Some header files and class names redone ---------------------------------------- In ArchiveLib 1.0, ARCHIVE.H was used to define the Greenleaf archive class. Now we have two archiving classes, so this job is being done by two different header files. Note that the base class ALArchiveBase has been renamed to ALArchive. In 1.0, an ALArchive was a Greenleaf format archive. In 2.0, a Greenleaf format archive is an ALGlArchive. Use PKARC.H to define and use Zip compaptible archives. Use GLARC.H to define and use Greenleaf proprietary archives. ARC.H is used to define the base archive class. In 1.0, CMPENGN.H defined the base compression class, and GRENENGN.H defined the Greenleaf proprietary compression class. Now, the base class is defined in ENGN.H, with derived classes showing up in PKENGN.H, GLENGN.H, and COPYENGN.H. Our header file, STORAGE.H, conflicts with an OLE 2.0 header file found in Borland's 4.5 release. The file has been renamed as STOR.H, which means a few other header files had to have their contents renamed. Since STOR.H is automatically included by ARCLIB.H, you should be able to ignore this change. Directory and build structure redone ------------------------------------ In order to cut back on ifdefs, ArchiveLib has partitioned as much platform-specific code as possible into separate directories. For example, platform-specific user interface code is now found in directories CPP_UI.TXT, CPP_UI.WIN, and CPP_UI.PM. Similar partitioning is done for File Systems, Yield functions, and Memory. The default root directory for ArchiveLib is now AL200, to reflect the new release number. To make ArchiveLib a little more consistent with some of our other products, the directory naming scheme for compilers has been slightly modified. The directories now being used are : Borland C++ 2.0 for OS/2 AL200\B20 Borland C++ 3.1: AL200\B31 Borland C++ 4.0: AL200\B40 Borland C++ 4.5: AL200\B45 IBM CSET 2.0 AL200\I20 IBM Visual Age 3.0 AL200\I30 Microsoft C++ 7.0: AL200\C70 Symantec C++ 7.x: AL200\S7X Delphi 1.0 AL200\DELPHI.16 Visual Basic 3.0: AL200\VB30 Visual Basic 4.0 16 bit: AL200\VB40.16 Visual Basic 4.0 32 bit: AL200\VB40.32 Visual C++ 1.0/1.5: AL200\V1X Visual C++ 2.x: AL200\V2X Visual C++ 4.0: AL200\V40 Watcom 10.0: AL200\W10 New memory classes ------------------ We now have three memory based storage classes derived from the base class ALMemoryBase. ALMemory uses standard calls to malloc(), calloc() and realloc(). ALWinMemory() instead uses GlobalAlloc() and its ilk. Finally, ALHugeMemroy use _farcalloc(), _halloc, and brethren. BUILD.EXE updated ----------------- With CommLib 5.1 we modified our BUILD.EXE program slightly. Each library directory now has its own naming scheme for BUILD.EXE and BUILD.INI. For example, in the Borland C++ 4.5 directory, these two files are now named BUILDB45.EXE and BUILDB45.INI. This change was made to help with future patches. The patch program we are using, RTPATCH, isn't happy when we have multiple copies of a file with the same name. With the initial release of ArchiveLib, we included a set of files with the name MAKE*.BAT. These files were used to build demo programs. This capability has been moved to BUILD*.EXE, so the batch files are now gone. BUILD*.EXE will now let you build a demo or example using the library file of your choice. To build demos, call BUILD*.EXE with the -exe switch. For example, to build all C examples with the Borland C++ 4.0 Large Windows library, I would type this: BUILDB40 -exe LW ..\examples\ex??win.c Debug libraries aren't being shipped ------------------------------------ Debug libraries take up a ton of disk space. You usually can't use our prebuilt versions of the debug libraries anyway, because your source code path differs from ours. Until we go to CD-ROM distribution, we will just ship the release libraries. However, you can quickly build your own versions of the debug libraries using BUILD.EXE. ALArchive::AddWildCardFiles() is gone! -------------------------------------- Now this function is ALEntryList::AddWildCardFiles(). It's first arg used to be an entry list, now its an archive. When adding files to the entry list, this function uses the default storage object and compression engine recommended by the archive class. Converting your 1.0 Programs ---------------------------- You should follow these steps to convert an ArchiveLib 1.0 program to work with ArchiveLib 2.0: 1) If any of your modules include ARCHIVE.H, change the reference to GLARC.H. ARCHIVE.H no longer exists. GLARC.H describes ALGlArchive, which is the archive compatible with Version 1.0 archives. 2) Replace every declaration of ALArchive with a declaration for ALGlArchive. ALArchive is now the base class for both Greenleaf and Zip compatible archives. Replace any references to ALArchiveBase to ALArchive. 3) The compression engine used to insert new compressed objects into archives is determined by the toolkit (new term) passed to your ALEntryList object on construction. The default toolkit is the FullToolKit(), which will preferentially use the ZIP compressor. If you need your archives to be compatible with AL 1.0 archives, you need to force your compression routines to use the Greenleaf compressor. You can do this by modifying your ALEntryList constructor call to look like this: ALEntryList list( &monitor, GlTools() ); Be sure to note that you might have created an entry list with no parameter to specify a monitor. In this case, you need to pass a 0 as the monitor argument. If you are explicitly using the greenleaf engine, change every reference to GRENENGN.H to GLENGN.H. C programmers have a new batch of constructors for ALEntryList, with each variation corresponding to a particular toolkit. See the manual to figure out which one you need to be using. 4) AddWildCardFiles is a member function of the archive class in AL 1.0. In AL 2.0, this function is now a member function of the entry list class. Since the 1.0 function declaration was a static member of ALArchive, and took an ALEntryList as its first parameter, you can make the change using a fairly mechanical procedure. Just eliminate any reference to the archive object used to call the function, then remove the list reference from the first parameter position. Then take that same list reference, and set it to be the object used to call the function. For example: AL 1.0 call: archive.AddWildCardFiles( list, "input*.dat, *.bak" ); Converted to 2.0: list.AddWildCardFiles( "input*.dat, *.bak" ); Or: AL 1.0 call: ALArchive::AddWildCardFiles( list, "input*.dat, *.bak" ); Converted to 2.0: list.AddWildCardFiles( "input*.dat, *.bak" ); MakeEntriesFromListBox() has to undergo exactly the same transformation. 5) Under 1.0, the AddWildCardFiles() function also had some optional parameters that allow you to specify parameters used when creating the greenleaf compression engine. In 2.0, the decision as to what parameters are used to create the engine is now under the control of the toolkit passed to the ALEntryList object when constructed. To create a toolkit that will use the parameters you want, you will need to make one more modification to the toolkit parameter passed to the entry constructor. Just pass the desired compression level to the GlTools() function. A sample is shown here: ALEntryList list( &monitor, GlTools( AL_GREENLEAF_LEVEL_3 ) ); After you have done that, just delete the compression level parameter from the call to AddWildCardFiles. 6) AL 1.0 has compression engines with the base class ALEngine. AL 2.0 has split these two up in the interests of modularity. If you are constructing engines to perform compression or expansion by hand, you now have to decide which to use. The new engine names are: ALCopyCompressor COPYENGN.H ALCopyDecompressor COPYENGN.H ALGlCompressor GLENGN.H ALGLDecompressor GLENGN.H ALPkCompressor PKENGN.H ALPkDecompressor PKENGN.H Be sure to included the appropriate header file when constructing the engine. This change means you will need to search through your code, looking for the type ALCompressionEngine, and change it to ALCompressor or ALDecompressor. References to ALGreenleafEngine need to be changed to ALGlCompressor or ALGlDecompressor. References to ALCopyEngine need to be changed to ALCopyCompressor or ALCopyDecompressor. 7) If you are creating ALEntry objects manually, you will have to account for a change in the parameters list. In AL 1.0, ALEntry objects took a single ALCompressionEngine parameter. AL 2.0 ALEntry lists take two pointers: the first a pointer to an ALCompressor, the second a pointer to an ALDecompressor. Code that used to look like this: new ALEntry( list, new ALMemory( "buffer", buffer, strlen( buffer ) ), new ALGreenleafEngine ); Now looks like this: new ALEntry( list, new ALMemory( "buffer", buffer, strlen( buffer )), new ALGlCompressor, new ALGlDecompressor ); 8) If you are using compressed objects, you now have to pass the compressed object constructor, ALCompressedObject(), a pointer to a compressor, and a pointer to a decompressor. The objects are now passed as pointers instead of references, as well. This means you can pass a 0 for either of the engines, if your program won't be using it. 9) ALEntry objects used to have a single pointer to an engine, called mpCompressionEngine. Now there are two pointers, mpCompressor and mpDecompressor. 10) You can no longer get a copy of the MS-DOS file attributes using the member function GetDosAttributes(). Individual file attributes can now be read using these member functions: int ReadOnly(); int System(); int Hidden(); int Archive(); int Directory(); If you want to get all the bits at once, you need to call member function PackedAttributes().