377 lines
16 KiB
Plaintext
377 lines
16 KiB
Plaintext
|
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().
|
||
|
|