Archive Lib versione 1.0

git-svn-id: svn://10.65.10.50/trunk@5346 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
alex 1997-10-09 15:45:10 +00:00
parent 26e072eb99
commit 8316a950de
64 changed files with 23623 additions and 0 deletions

136
al/_debug.cpp Executable file
View File

@ -0,0 +1,136 @@
//
// _DEBUG.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// _ALAssertFailure()
//
// DESCRIPTION
//
// This file contains a support routine used by the assertion macros,
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//
// void _ALAssertFailure( const char *condition,
// const char *filename,
// int line,
// const char *message,
// ... )
//
// ARGUMENTS:
//
// condition : A character string containing the condition that failed,
// leading to the assertion.
//
// filename : The name of the file where the assertion error took place.
//
// line : The line in the file where the assertion error took place.
//
// message : The error message associated with the assertion error.
// This message is a sprintf() style format string.
//
// ... : Any additional arguments.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// The C run time library features an assert() macro, that can be used to
// abort a program if a given condition isn't true. It aborts the program
// by calling a routine that looks something like this. The AL_ASSERT()
// macro that we use is even better, because it includes a comment
// that gets displayed when the abort takes place. This routine is
// responsible for displaying that comment, along with the file name and
// the line number, then aborting the program. It is called by the
// AL_ASSERT() macro when the conditional expression argument fails.
//
// This routine is full of #ifdefs, and looks like a real mess. This
// is too bad, because it is really quite simple. Basically it has to
// quit with an abort() under MS-DOS, and a FatalAppExit() under
// windows. The error message is displayed on the console under MS-DOS,
// (hope you're not in graphics mode!) and in a MessageBox under
// Windows. Man, it would be great to have just a little bit of control
// of the formatting in the message box!
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
void AL_CFUNCTION _ALAssertFailure( const char AL_DLL_FAR *condition,
const char AL_DLL_FAR *filename,
int line,
const char AL_DLL_FAR *message,
... )
{
char buf1[ 256 ];
char buf2[ 128 ];
va_list argptr;
va_start( argptr, message );
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI )
//
// Watcom is kind of annoying in that they format their variable arguments
// just a little differently than everyone else.
//
#if defined( AL_WATCOM )
wvsprintf( buf2, message, *argptr );
#else
wvsprintf( buf2, message, argptr );
#endif
#else
vsprintf( buf2, message, argptr );
#endif
va_end( argptr );
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI )
wsprintf
#else
sprintf
#endif
( buf1,
"Assertion error, ArchiveLib is aborting the application.\n"
"Condition = %s\n"
"File = %s, line = %d\n"
"%s",
condition,
filename,
line,
buf2 );
#if defined( AL_WINDOWS_GUI )
#ifdef AL_BUILDING_DLL
MessageBox( 0, buf1, " ArchiveLib (DLL) assertion error ", MB_ICONSTOP );
#else
MessageBox( 0,
buf1,
" "
"ArchiveLib (static) assertion error"
" ",
MB_ICONSTOP );
#endif
FatalAppExit( 0, "Application terminated" );
#else
cerr << buf1 << "\n" << flush;
abort();
#endif
}

193
al/_debug.h Executable file
View File

@ -0,0 +1,193 @@
/*
* _DEBUG.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* These macros and types are all used in the debug versions of the
* ArchiveLib.
*
* MACROS
*
* _ALAssertFailure()
* AL_ASSERT()
* AL_ASSERT_OBJECT()
* AL_CLASS_TAG()
*
* PROTOTYPES:
*
* IsBadWritePtr()
*
* ENUMERATED TYPES:
*
* _ALClassTags
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef __DEBUG_H
#define __DEBUG_H
/*
* _ALAssertFailure is the function called by AL_ASSERT() and
* AL_ASSERT_OBJECT() when their assertion fails.
*/
void AL_CFUNCTION _ALAssertFailure( const char AL_DLL_FAR *condition,
const char AL_DLL_FAR *filename,
int line,
const char AL_DLL_FAR *message,
... );
#ifdef NDEBUG
/*
* In the non-debug versions, both of these macros basically go away.
* The only difficulty is trying to avoid having the compilers generate
* error messages when they see this code. Maybe in NDEBUG mode I could
* change these to inline functions that do nothing?
*/
#define AL_ASSERT( condition, message ) ((void) 0)
#define AL_ASSERT_OBJECT( pointer, class, message ) ((void) 0)
#else
/*
* In debug mode, AL_ASSERT() tests the condition, and generates
* an abort with an error message when the condition fails.
*/
#define AL_ASSERT( condition, message ) \
( ( condition ) ? \
(void) 0 : \
_ALAssertFailure( #condition, \
__FILE__, \
__LINE__, \
message ) ) \
/*
* I can only call IsBadWritePtr() if TOOLHELP.DLL is available. As far
* as I know, it won't be available with any of the DOS Extenders
* The only way we have access to TOOLHELP.DLL is if we are *really*
* running under Windows, not some bogus imitation.
*/
#if !defined( AL_WINDOWS_GUI )
#define IsBadWritePtr( p, s ) 0
#endif
/*
* AL_ASSERT_OBJECT() is a great macro. It is used to test the
* validity of an object. This is a two step process. First,
* we make sure we are dealing with a good pointer. If not, an
* asserting error is triggered. This is much better than the
* GPF you would normally get from a bad pointer. Next, we
* test the GoodTag() macro, which verifies that this is
* a properly constructed object from the specified class. Of
* course, in NDEBUG mode this all goes away.
*
*/
#define AL_ASSERT_OBJECT( pointer, class, message ) \
( pointer == 0 || IsBadWritePtr( pointer, sizeof( class ) ) ) ? \
_ALAssertFailure( "IsBadWritePtr()", \
__FILE__, \
__LINE__, \
"%s: Bad pointer to object of class %s", \
message, \
#class ) \
: \
( ( (class *)pointer)->GoodTag() ? \
(void) 0 \
: \
_ALAssertFailure( #pointer "->GoodTag()", \
__FILE__, \
__LINE__, \
"%s: %s is not an object of class %s", \
message, \
#pointer, \
#class ) )
#endif
/*
* The AL_CLASS_TAG() macro assigns a new debug class and data
* member to each of the classes in ArchiveLib. Each of these
* debug classes uses a special integer tag (stored in the data member)
* to uniquely identify itself. These are the integer values of
* these integers.
*/
enum _ALClassTags {
_ALDeletedObjectTag = 0,
_ALStorageTag,
_ALFileTag,
_ALMemoryTag,
_ALEntryTag,
_ALEntryListTag,
_ALArchiveBaseTag,
_ALArchiveTag,
_ALMonitorTag,
_ALBarGraphTag,
_ALSpinnerTag,
_ALWindowsMessageTag,
_ALCompressionEngineTag,
_ALCopyEngineTag,
_ALGreenleafEngineTag,
_ALCompressedObjectTag,
_ALNameTag,
_ALWildCardExpanderTag,
};
/*
* AL_CLASS_TAG( x ) is a macro that is used to help debug
* ArchiveLib. The insertion of this macro in a class definition
* adds a new data member and member function to the class. The
* data member is an object of a class uniquely created by the
* macro. The reason the data member is a class object instead
* of a simple integer or character tag is this: By making it a
* class object, we can automatically assign it a valid value
* when constructed, and an invalid value when destroyed.
*
* The member function added to the class is called GoodTag().
* Once you have added AL_CLASS_TAG( x ) to your class definition,
* you can call object.GoodTag() anytime you want. It will return
* a true value only if the data member has the correct value,
*
* We make use of this function in AL_ASSERT_OBJECT(). It
* checks the value of this object frequently in member functions
* and destructors, generating an assertion failure if the object
* doesn't look like the correct type.
*
* Note that the ASSERT_OBJECT() statements generate no code when the
* library is compiled with NDEBUG, so this class will not be
* generating much low overhead. However, the data member will
* still be taking up a single byte in each instance.
*
* If you want to eliminate class tags, this line in will do it
* You will save one byte per instance. The best way to accomplish this
* is to define the macro in ALCUSTOM.H, then rebuild the library with
* macro AL_CUSTOM defined in your project. After you build this new
* version of the library, you must absolutely, positively, be sure
* that you continue to use AL_CUSTOM and ALCUSTOM.H when working
* with the library. If you don't, your library and your application
* will think that most classes in ArchiveLib are different sizes, and
* *nothing* will work.
*
*#define AL_CLASS_TAG( x ) int GoodTag(){ return 1; }
*/
#if defined( NDEBUG ) && !defined( AL_CLASS_TAG )
#define AL_CLASS_TAG( x ) class AL_CLASS_TYPE _ALTag##x { \
public : \
unsigned char mucTagVal; \
} mMyTag; \
int AL_PROTO GoodTag(){ return 1; }
#endif /* #if defined( NDEBUG ) && !defined( AL_CLASS_TAG ) */
#if !defined( NDEBUG ) && !defined( AL_CLASS_TAG )
#define AL_CLASS_TAG( x ) class AL_CLASS_TYPE _ALTag##x { \
public : \
AL_PROTO _ALTag##x(){ mucTagVal = x; } \
AL_PROTO ~_ALTag##x(){ mucTagVal = _ALDeletedObjectTag; } \
unsigned char mucTagVal; \
} mMyTag; \
int AL_PROTO GoodTag(){ return mMyTag.mucTagVal == x; }
#endif /* #if !defined( NDEBUG ) && !defined( AL_CLASS_TAG ) */
#endif /* #ifndef __DEBUG_H */

623
al/_match.cpp Executable file
View File

@ -0,0 +1,623 @@
//
// _MATCH.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// is_pattern()
// is_valid_pattern()
// matche()
// matche_after_star()
// match()
// main() (For testing, w/conditional compile)
//
// DESCRIPTION
//
// Some nice code written by J. Kercheval, in the public domain.
// This code provides us with the pattern matching functions used
// by the ALName functions. It all seems to work without any trouble
// at all.
//
// I tried to change this file as little as possible. I modified the
// name of the file, and removed BOOLEAN, TRUE, and FALSE from the
// header file. Other than that, it is just as I found it.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
/*
EPSHeader
File: match.c
Author: J. Kercheval
Created: Sat, 01/05/1991 22:21:49
*/
/*
EPSRevision History
J. Kercheval Wed, 02/20/1991 22:29:01 Released to Public Domain
J. Kercheval Fri, 02/22/1991 15:29:01 fix '\' bugs (two :( of them)
J. Kercheval Sun, 03/10/1991 19:31:29 add error return to matche()
J. Kercheval Sun, 03/10/1991 20:11:11 add is_valid_pattern code
J. Kercheval Sun, 03/10/1991 20:37:11 beef up main()
J. Kercheval Tue, 03/12/1991 22:25:10 Released as V1.1 to Public Domain
J. Kercheval Thu, 03/14/1991 22:22:25 remove '\' for DOS file parsing
J. Kercheval Mon, 05/13/1991 21:49:05 ifdef full match code
J. Kercheval Mon, 01/06/1992 21:31:44 add match character defines
*/
/*
* Wildcard Pattern Matching
*/
#include "arclib.h"
#include "_match.h"
//
// The next five lines used to be in the header file
//
#ifndef BOOLEAN
#define BOOLEAN int
#define TRUE 1
#define FALSE 0
#endif
/* character defines */
#define MATCH_CHAR_SINGLE '?'
#define MATCH_CHAR_KLEENE_CLOSURE '*'
#define MATCH_CHAR_RANGE_OPEN '['
#define MATCH_CHAR_RANGE '-'
#define MATCH_CHAR_RANGE_CLOSE ']'
#define MATCH_CHAR_LITERAL '\\'
#define MATCH_CHAR_NULL '\0'
#define MATCH_CHAR_CARAT_NEGATE '^'
#define MATCH_CHAR_EXCLAMATION_NEGATE '!'
/* forward function prototypes */
int matche_after_star( register const char *pattern, register char *text);
int fast_match_after_star(register char *pattern, register char *text);
/*----------------------------------------------------------------------------
*
* Return TRUE if PATTERN has any special wildcard characters
*
---------------------------------------------------------------------------*/
BOOLEAN is_pattern( const char *p )
{
while (*p) {
switch (*p++) {
case MATCH_CHAR_SINGLE:
case MATCH_CHAR_KLEENE_CLOSURE:
case MATCH_CHAR_RANGE_OPEN:
#ifndef FILE_MATCH
case MATCH_CHAR_LITERAL:
#endif
return TRUE;
}
}
return FALSE;
}
/*----------------------------------------------------------------------------
*
* Return TRUE if PATTERN has is a well formed regular expression according
* to the above syntax
*
* error_type is a return code based on the type of pattern error. Zero is
* returned in error_type if the pattern is a valid one. error_type return
* values are as follows:
*
* PATTERN_VALID - pattern is well formed
#ifndef FILE_MATCH
* PATTERN_ESC - pattern has invalid escape ('\' at end of pattern)
#endif
* PATTERN_RANGE - [..] construct has a no end range in a '-' pair (ie [a-])
* PATTERN_CLOSE - [..] construct has no end bracket (ie [abc-g )
* PATTERN_EMPTY - [..] construct is empty (ie [])
*
---------------------------------------------------------------------------*/
BOOLEAN is_valid_pattern( const char *p, int *error_type )
{
/* init error_type */
*error_type = PATTERN_VALID;
/* loop through pattern to EOS */
while (*p) {
/* determine pattern type */
switch (*p) {
#ifndef FILE_MATCH
/* check literal escape, it cannot be at end of pattern */
case MATCH_CHAR_LITERAL:
if (!*++p) {
*error_type = PATTERN_ESC;
return FALSE;
}
p++;
break;
#endif
/* the [..] construct must be well formed */
case MATCH_CHAR_RANGE_OPEN:
p++;
/* if the next character is ']' then bad pattern */
if (*p == MATCH_CHAR_RANGE_CLOSE) {
*error_type = PATTERN_EMPTY;
return FALSE;
}
/* if end of pattern here then bad pattern */
if (!*p) {
*error_type = PATTERN_CLOSE;
return FALSE;
}
/* loop to end of [..] construct */
while (*p != MATCH_CHAR_RANGE_CLOSE) {
/* check for literal escape */
if (*p == MATCH_CHAR_LITERAL) {
p++;
/* if end of pattern here then bad pattern */
if (!*p++) {
*error_type = PATTERN_ESC;
return FALSE;
}
}
else
p++;
/* if end of pattern here then bad pattern */
if (!*p) {
*error_type = PATTERN_CLOSE;
return FALSE;
}
/* if this a range */
if (*p == MATCH_CHAR_RANGE) {
/* we must have an end of range */
if (!*++p || *p == MATCH_CHAR_RANGE_CLOSE) {
*error_type = PATTERN_RANGE;
return FALSE;
}
else {
/* check for literal escape */
if (*p == MATCH_CHAR_LITERAL)
p++;
/* if end of pattern here then bad pattern */
if (!*p++) {
*error_type = PATTERN_ESC;
return FALSE;
}
}
}
}
break;
/* all other characters are valid pattern elements */
case MATCH_CHAR_KLEENE_CLOSURE:
case MATCH_CHAR_SINGLE:
default: /* "normal" character */
p++;
break;
}
}
return TRUE;
}
/*----------------------------------------------------------------------------
*
* Match the pattern PATTERN against the string TEXT;
*
* returns MATCH_VALID if pattern matches, or an errorcode as follows
* otherwise:
*
* MATCH_PATTERN - bad pattern
#ifndef FILE_MATCH
* MATCH_LITERAL - match failure on literal mismatch
#endif
* MATCH_RANGE - match failure on [..] construct
* MATCH_ABORT - premature end of text string
* MATCH_END - premature end of pattern string
* MATCH_VALID - valid match
*
*
* A match means the entire string TEXT is used up in matching.
*
* In the pattern string:
* `*' matches any sequence of characters (zero or more)
* `?' matches any character
* [SET] matches any character in the specified set,
* [!SET] or [^SET] matches any character not in the specified set.
* \ is allowed within a set to escape a character like ']' or '-'
*
* A set is composed of characters or ranges; a range looks like character
* hyphen character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of
* characters allowed in the [..] pattern construct. Other characters are
* allowed (ie. 8 bit characters) if your system will support them.
*
* To suppress the special syntactic significance of any of `[]*?!^-\', and
* match the character exactly, precede it with a `\'.
*
---------------------------------------------------------------------------*/
int matche( const char *p, char *t)
{
register char range_start, range_end; /* start and end in range */
BOOLEAN invert; /* is this [..] or [!..] */
BOOLEAN member_match; /* have I matched the [..] construct? */
BOOLEAN loop; /* should I terminate? */
for (; *p; p++, t++) {
/* if this is the end of the text then this is the end of the match */
if (!*t) {
return (*p == MATCH_CHAR_KLEENE_CLOSURE &&
*++p == MATCH_CHAR_NULL) ?
MATCH_VALID : MATCH_ABORT;
}
/* determine and react to pattern type */
switch (*p) {
/* single any character match */
case MATCH_CHAR_SINGLE:
break;
/* multiple any character match */
case MATCH_CHAR_KLEENE_CLOSURE:
return matche_after_star(p, t);
/* [..] construct, single member/exclusion character match */
case MATCH_CHAR_RANGE_OPEN:{
/* move to beginning of range */
p++;
/* check if this is a member match or exclusion match */
invert = FALSE;
if (*p == MATCH_CHAR_EXCLAMATION_NEGATE ||
*p == MATCH_CHAR_CARAT_NEGATE) {
invert = TRUE;
p++;
}
/* if closing bracket here or at range start then we have
* a malformed pattern */
if (*p == MATCH_CHAR_RANGE_CLOSE) {
return MATCH_PATTERN;
}
member_match = FALSE;
loop = TRUE;
while (loop) {
/* if end of construct then loop is done */
if (*p == MATCH_CHAR_RANGE_CLOSE) {
loop = FALSE;
continue;
}
/* matching a '!', '^', '-', '\' or a ']' */
if (*p == MATCH_CHAR_LITERAL) {
range_start = range_end = *++p;
}
else {
range_start = range_end = *p;
}
/* if end of pattern then bad pattern (Missing ']') */
if (!*p)
return MATCH_PATTERN;
/* check for range bar */
if (*++p == MATCH_CHAR_RANGE) {
/* get the range end */
range_end = *++p;
/* if end of pattern or construct then bad
* pattern */
if (range_end == MATCH_CHAR_NULL ||
range_end == MATCH_CHAR_RANGE_CLOSE)
return MATCH_PATTERN;
/* special character range end */
if (range_end == MATCH_CHAR_LITERAL) {
range_end = *++p;
/* if end of text then we have a bad pattern */
if (!range_end)
return MATCH_PATTERN;
}
/* move just beyond this range */
p++;
}
/* if the text character is in range then match
* found. make sure the range letters have the proper
* relationship to one another before comparison */
if (range_start < range_end) {
if (*t >= range_start && *t <= range_end) {
member_match = TRUE;
loop = FALSE;
}
}
else {
if (*t >= range_end && *t <= range_start) {
member_match = TRUE;
loop = FALSE;
}
}
}
/* if there was a match in an exclusion set then no match */
/* if there was no match in a member set then no match */
if ((invert && member_match) ||
!(invert || member_match))
return MATCH_RANGE;
/* if this is not an exclusion then skip the rest of the
* [...] construct that already matched. */
if (member_match) {
while (*p != MATCH_CHAR_RANGE_CLOSE) {
/* bad pattern (Missing MATCH_CHAR_RANGE_CLOSE) */
if (!*p)
return MATCH_PATTERN;
/* skip exact match */
if (*p == MATCH_CHAR_LITERAL) {
p++;
/* if end of text then we have a bad pattern */
if (!*p)
return MATCH_PATTERN;
}
/* move to next pattern char */
p++;
}
}
break;
}
#ifndef FILE_MATCH
/* next character is quoted and must match exactly */
case MATCH_CHAR_LITERAL:
/* move pattern pointer to quoted char and fall through */
p++;
/* if end of text then we have a bad pattern */
if (!*p)
return MATCH_PATTERN;
#endif
/* must match this character exactly */
default:
if (*p != *t)
return MATCH_LITERAL;
}
}
/* if end of text not reached then the pattern fails */
if (*t)
return MATCH_END;
else
return MATCH_VALID;
}
/*----------------------------------------------------------------------------
*
* recursively call matche() with final segment of PATTERN and of TEXT.
*
---------------------------------------------------------------------------*/
int matche_after_star( register const char *p, register char *t)
{
register int match = 0;
register nextp;
/* pass over existing ? and * in pattern */
while (*p == MATCH_CHAR_SINGLE ||
*p == MATCH_CHAR_KLEENE_CLOSURE) {
/* take one char for each ? and + */
if (*p == MATCH_CHAR_SINGLE) {
/* if end of text then no match */
if (!*t++) {
return MATCH_ABORT;
}
}
/* move to next char in pattern */
p++;
}
/* if end of pattern we have matched regardless of text left */
if (!*p) {
return MATCH_VALID;
}
/* get the next character to match which must be a literal or '[' */
nextp = *p;
#ifndef FILE_MATCH
if (nextp == MATCH_CHAR_LITERAL) {
nextp = p[1];
/* if end of text then we have a bad pattern */
if (!nextp)
return MATCH_PATTERN;
}
#endif
/* Continue until we run out of text or definite result seen */
do {
/* a precondition for matching is that the next character in the
* pattern match the next character in the text or that the next
* pattern char is the beginning of a range. Increment text pointer
* as we go here */
if (nextp == *t || nextp == MATCH_CHAR_RANGE_OPEN) {
match = matche(p, t);
}
/* if the end of text is reached then no match */
if (!*t++)
match = MATCH_ABORT;
} while (match != MATCH_VALID &&
match != MATCH_ABORT &&
match != MATCH_PATTERN);
/* return result */
return match;
}
/*----------------------------------------------------------------------------
*
* match() is a shell to matche() to return only BOOLEAN values.
*
---------------------------------------------------------------------------*/
BOOLEAN match( char *p, char *t)
{
int error_type;
error_type = matche(p, t);
return (error_type == MATCH_VALID) ? TRUE : FALSE;
}
#ifdef TEST
/*
* This test main expects as first arg the pattern and as second arg
* the match string. Output is yaeh or nay on match. If nay on
* match then the error code is parsed and written.
*/
#include <stdio.h>
int main(int argc, char *argv[])
{
int error;
int is_valid_error;
if (argc != 3) {
printf("Usage: MATCH Pattern Text\n");
}
else {
printf("Pattern: %s\n", argv[1]);
printf("Text : %s\n", argv[2]);
if ( !is_pattern(argv[1])) {
printf(" First Argument Is Not A Pattern\n");
}
else {
#ifdef FILE_MATCH
match(argv[1], argv[2]) ? printf("TRUE") : printf("FALSE");
#endif
error = matche(argv[1], argv[2]);
is_valid_pattern(argv[1], &is_valid_error);
switch (error) {
case MATCH_VALID:
printf(" Match Successful");
if (is_valid_error != PATTERN_VALID)
printf(" -- is_valid_pattern() is complaining\n");
else
printf("\n");
break;
#ifndef FILE_MATCH
case MATCH_LITERAL:
printf(" Match Failed on Literal\n");
break;
#endif
case MATCH_RANGE:
printf(" Match Failed on [..]\n");
break;
case MATCH_ABORT:
printf(" Match Failed on Early Text Termination\n");
break;
case MATCH_END:
printf(" Match Failed on Early Pattern Termination\n");
break;
case MATCH_PATTERN:
switch (is_valid_error) {
case PATTERN_VALID:
printf(" Internal Disagreement On Pattern\n");
break;
#ifndef FILE_MATCH
case PATTERN_ESC:
printf(" Literal Escape at End of Pattern\n");
break;
#endif
case PATTERN_RANGE:
printf(" No End of Range in [..] Construct\n");
break;
case PATTERN_CLOSE:
printf(" [..] Construct is Open\n");
break;
case PATTERN_EMPTY:
printf(" [..] Construct is Empty\n");
break;
default:
printf(" Internal Error in is_valid_pattern()\n");
}
break;
default:
printf(" Internal Error in matche()\n");
break;
}
}
}
return (0);
}
#endif

158
al/_match.h Executable file
View File

@ -0,0 +1,158 @@
/*
* _MATCH.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file is for the internal support routines
* that perform wild card matching. This code is public domain
* code that I lifted. It will not be documented!
*
* I tried to change this file as little as possible. I modified the
* name of the file, and removed BOOLEAN, TRUE, and FALSE from the
* header file. Other than that, it is unchanged.
*
* MACROS
*
* All of the MATCH_xxx macros are defined in this header file.
*
* PROTOTYPES:
*
* match()
* matche()
* is_pattern()
* is_valid_pattern()
*
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
/*
EPSHeader
File: match.h
Author: J. Kercheval
Created: Sat, 01/05/1991 22:27:18
*/
/*
EPSRevision History
J. Kercheval Wed, 02/20/1991 22:28:37 Released to Public Domain
J. Kercheval Sun, 03/10/1991 18:02:56 add is_valid_pattern
J. Kercheval Sun, 03/10/1991 18:25:48 add error_type in is_valid_pattern
J. Kercheval Sun, 03/10/1991 18:47:47 error return from matche()
J. Kercheval Tue, 03/12/1991 22:24:49 Released as V1.1 to Public Domain
J. Kercheval Thu, 03/14/1991 22:25:00 remove '\' for DOS file matching
J. Kercheval Thu, 03/28/1991 21:03:59 add in PATTERN_ESC & MATCH_LITERAL
J. Kercheval Mon, 05/13/1991 21:34:02 ifdef the full match code
*/
/*
* Wildcard Pattern Matching
*/
/*
* if FILE_MATCH is defined then the match routine will compile without
* allowing the literal escape character in the pattern string except within
* the [..] construct. The literal escape character '\' is an MSDOS special
* character and thus is not allowed for file globbing except as a path
* follow.
*/
#define FILE_MATCH
/* match defines */
#define MATCH_PATTERN 6 /* bad pattern */
#define MATCH_LITERAL 5 /* match failure on literal match */
#define MATCH_RANGE 4 /* match failure on [..] construct */
#define MATCH_ABORT 3 /* premature end of text string */
#define MATCH_END 2 /* premature end of pattern string */
#define MATCH_VALID 1 /* valid match */
/* pattern defines */
#define PATTERN_VALID 0 /* valid pattern */
#define PATTERN_ESC -1 /* literal escape at end of pattern */
#define PATTERN_RANGE -2 /* malformed range in [..] construct */
#define PATTERN_CLOSE -3 /* no end bracket in [..] construct */
#define PATTERN_EMPTY -4 /* [..] contstruct is empty */
/*----------------------------------------------------------------------------
*
* Match the pattern PATTERN against the string TEXT;
*
* match() returns TRUE if pattern matches, FALSE otherwise.
* matche() returns MATCH_VALID if pattern matches, or an errorcode
* as follows otherwise:
*
* MATCH_PATTERN - bad pattern
#ifndef FILE_MATCH
* MATCH_LITERAL - match failure on literal mismatch
#endif
* MATCH_RANGE - match failure on [..] construct
* MATCH_ABORT - premature end of text string
* MATCH_END - premature end of pattern string
* MATCH_VALID - valid match
*
*
* A match means the entire string TEXT is used up in matching.
*
* In the pattern string:
* `*' matches any sequence of characters (zero or more)
* `?' matches any character
* [SET] matches any character in the specified set,
* [!SET] or [^SET] matches any character not in the specified set.
*
* A set is composed of characters or ranges; a range looks like character
* hyphen character (as in 0-9 or A-Z). [0-9a-zA-Z_] is the minimal set of
* characters allowed in the [..] pattern construct. Other characters are
* allowed (ie. 8 bit characters) if your system will support them.
*
* To suppress the special syntactic significance of any of `[]*?!^-\', and
* match the character exactly, precede it with a `\'.
*
---------------------------------------------------------------------------*/
int match(char *pattern, char *text);
int matche( const char *pattern, char *text );
/*----------------------------------------------------------------------------
*
* Return TRUE if PATTERN has any special wildcard characters
*
----------------------------------------------------------------------------*/
int is_pattern( const char *pattern);
/*----------------------------------------------------------------------------
*
* Return TRUE if PATTERN has is a well formed regular expression according
* to the above syntax
*
* error_type is a return code based on the type of pattern error. Zero is
* returned in error_type if the pattern is a valid one. error_type return
* values are as follows:
*
* PATTERN_VALID - pattern is well formed
#ifndef FILE_MATCH
* PATTERN_ESC - pattern has invalid escape ('\' at end of pattern)
#endif
* PATTERN_RANGE - [..] construct has a no end range in a '-' pair (ie [a-])
* PATTERN_CLOSE - [..] construct has no end bracket (ie [abc-g )
* PATTERN_EMPTY - [..] construct is empty (ie [])
*
---------------------------------------------------------------------------*/
int is_valid_pattern( const char *pattern, int *error_type );

367
al/_new.cpp Executable file
View File

@ -0,0 +1,367 @@
//
// _NEW.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// PointerInHeap()
// operator new()
// operator delete()
//
// DESCRIPTION
//
// One of the defensive programming measures we have taken in this
// library is to provide versions of ::new and ::delete that do a
// little extra work. Of course, these all go away if _DEBUG isn't
// defined.
//
// Basically, there are a couple of things at work here. First, we
// have taken over the new operator and delete operator, so we are
// guaranteed that all C++ memory allocation will take place through
// these routines. Therefore, we can take certain liberties with
// them.
//
// The most important thing we do when someone wants to allocate
// memory is to allocate an extra 12 bytes of data beyond what has
// been requested. We use 8 bytes at the start of the block and
// 4 bytes at the end of the block for our own purposes. The pointer
// we return to the requester is actually at the start of the block
// plus eight bytes.
//
// The first four bytes at the start of the block are used to store
// the size of the block. The next four bytes hold a long word containing
// a leading picket, which is just a special word four bytes long.
// If the user underwrites the block of data for some reason, one of
// those four bytes will probably be corrupted. At the end of the block,
// we store a trailing picket that has the same purpose. It holds
// a special pattern of four bytes. If the user overwrites the block
// of data, those four bytes will be corrupted.
//
// We check the pickets when the ::delete operator is called. That way,
// when an object is going to be freed, we can instantly detect if it
// has been abused in some fashion.
//
// The ::delete operator here also attempts to make sure that the pointer
// being deleted points to a block that is actually in the heap. This
// isn't always possible, but it works under most MS-DOS models, and
// works under Windows small and medium models. Under Windows large
// memory models, we can walk the global heap to look for pointers,
// but we might not find them, since the RTL might be using a subsegment
// allocation scheme.
//
// In addition to checking the heap, under Windows the ::delete function
// can also call the IsBadWritePtr() function to see if this is just
// a completely hosed up pointer.
//
// Note that it is kind of obtrusive to redefine ::new and ::delete. There
// is an excellent chance that this will interfere with other libraries,
// such as MFC. Fortunately, we have made it easy to get around this.
// First, it is relatively simple to just delete this module from your
// library, using: LIB ALXX-_NEW; If you don't want to go to that
// trouble, you can also define AL_DISABLE_NEW and rebuild this module,
// which should also make it go away. But if you don't need to make
// this code disappear, you ought to leave it in, it might save you a lot
// of trouble some day.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <stdio.h>
#include <stdlib.h>
//
// The MS-DOS heapwalk functions are in different header files depending
// on who you are. Note that I don't walk the heap under MS-DOS with
// Symantec or Watcom. Not sure if I can.
//
#if defined( AL_BORLAND )
#include <alloc.h>
#elif defined( AL_MICROSOFT )
#include <malloc.h>
#endif
//
// Walking the Windows heap requires TOOLHELP.DLL. It would be great
// if Borland provided the TOOLHELP API under their DPMI extenders, but
// I don't think they do. I don't think the heap walk functions are
// available under Win 32s either.
//
#if defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
#include <toolhelp.h>
#endif
/*
* To completely eliminate this stuff, all you have to do is define
* AL_DISABLE_NEW before rebuilding the library.
*/
#ifndef AL_DISABLE_NEW
//
// When I pop up an error message, it sometimes helps to know where it came
// from. This definition is used to create the message box.
//
#if defined( AL_BUILDING_DLL )
#define LIB_TYPE "DLL"
#else
#define LIB_TYPE "Static"
#endif
//
// If Debug is not turned on, none of this stuff happens. I also don't
// work with Microsoft huge model, things get nasty in there.
//
#if defined( _DEBUG ) && !( defined( AL_MICROSOFT ) && defined( _M_I86HM ) )
//
// int PointerInHeap( void *p )
//
// ARGUMENTS:
//
// p : The pointer under test.
//
// RETURNS
//
// An integer, true or false.
//
// DESCRIPTION
//
// This function is called by ::delete() to see if the pointer we are
// trying to delete is in fact in the heap. If it isn't, we could cause
// quite a bit of trouble if we try to delete it.
//
// Under MS-DOS, this function just executes the normal heapwalk functions
// supported by Microsoft and Borland. Under Windows small memory
// models, we use the Toohelp API to walk the local heap. Under all
// other circumstances, we just give up and always return a true value.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
// This is the Microsoft MS-DOS version. It also looks like it is set
// up to work with Win 32s, but I'm not sure why, since we haven't
// released support for it yet. I think that is a typo.
//
// This function just uses the heapwalk RTL function to check for the
// presence of the pointer in the heap.
//
#if defined( AL_MICROSOFT ) && ( !defined( AL_WINDOWS_MEMORY ) || defined( AL_FLAT_MODEL ) )
int PointerInHeap( void *p )
{
AL_ASSERT( _heapchk() == _HEAPOK, "Heap fails internal consistency check" );
_HEAPINFO heapinfo;
heapinfo._pentry = 0;
while ( _heapwalk( &heapinfo ) == _HEAPOK )
if ( heapinfo._pentry == (int __far *) p )
return 1;
return 0;
}
//
// This is the Borland MS-DOS version. It looks like it also works under
// Win 32s, which might be more reasonable, since we do support Borland
// in that mode.
//
// Like the previous function, this guy just uses the heapwalk API to
// check the local heap for the presence of the pointer.
//
#elif defined( AL_BORLAND ) && ( !defined( AL_WINDOWS_MEMORY ) || defined( AL_FLAT_MODEL ) )
int PointerInHeap( void *p )
{
AL_ASSERT( heapcheck() == _HEAPOK,
LIB_TYPE " heap fails internal consistency check" );
struct heapinfo info;
info.ptr = 0;
while ( heapwalk( &info ) == _HEAPOK )
#if defined( AL_LARGE_DATA ) && !defined( AL_FLAT_MODEL )
if ( info.ptr == (void huge *) p )
return 1;
#else
if ( info.ptr == p )
return 1;
#endif
return 0;
}
//
// Microsoft is nice enough to support the heapwalk API under Windows
// large memory models also. This is good, since the TOOLHELP API would
// flounder when confronted with a subsegment allocation strategy.
//
#elif defined( AL_MICROSOFT ) && defined( AL_WINDOWS_MEMORY ) && defined( AL_LARGE_DATA )
int PointerInHeap( void *p )
{
AL_ASSERT( _fheapchk() == _HEAPOK,
LIB_TYPE " heap fails internal consistency check" );
_HEAPINFO heapinfo;
heapinfo._pentry = 0;
while ( _fheapwalk( &heapinfo ) == _HEAPOK )
if ( heapinfo._pentry == p )
return 1;
return 0;
}
//
// Under Windows small and medium memory models, the TOOLHELP API lets
// us walk the local heap, looking for an entry. No subsegment allocation
// scheme will get in the way.
//
// I should be able to use this with Watcom, but I am using a little bit of
// inline assembly to get my data segment. This inline assembly won't
// work with Watcom, so someday I will have to add a little code to
// get things working right with them also.
//
#elif defined( AL_WINDOWS_MEMORY ) && !defined( AL_FLAT_MODEL ) && !defined( AL_LARGE_DATA ) && !defined( AL_WATCOM )
int PointerInHeap( void *p )
{
LOCALENTRY LEntry;
WORD wHeap;
//
// I need to search the local heap that is in my data segment.
//
_asm mov ax,ds
_asm mov wHeap,ax
LEntry.dwSize = sizeof( LOCALENTRY );
if ( LocalFirst( &LEntry, (HGLOBAL) wHeap ) ) {
do {
if ( LEntry.wAddress == (WORD) p )
return 1;
} while ( LocalNext( &LEntry ) );
}
return 0;
}
//
// When all else fails, give up!
//
#else
int PointerInHeap( void * ){ return 1; }
#endif
//
// void *operator new( size_t size )
//
// ARGUMENTS:
//
// size : The amount of memory being requested.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or a 0 in the event
// of failure.
//
// DESCRIPTION
//
// This version of ::new() does what I described at the top of the file.
// It allocates a block of memory as requested, and includes eight
// extra bytes. Four bytes are reserved at the start and end of the memory
// block for our "pickets". These pickets hold a fixed pattern in memory
// that can be tested for accidental modification. When ::delete() is
// called, we check the area to see if the caller munged it, and
// cause an assertion error if they did. The other four bytes are needed
// to keep the size of the block on hand. Otherwise I wouldn't know how
// to get to the end of the block to check the trailing picket.
//
// Note that if you are using set_new_handler() or exceptions, this stuff
// is probably going to hose you up badly.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
void *operator new( size_t size )
{
if ( ( (long) size + 12 ) > 65535L )
return 0;
char *p = (char *) malloc( size + 12 );
if ( !p )
return 0;
( (long *) p)[ 0 ] = (long) size;
( (long *) p)[ 1 ] = 0x12345678L;
( (long *)(p + 8 + size))[ 0 ] = 0xfedcba98L;
return p + 8;
}
//
// void operator delete( void *ptr )
//
// ARGUMENTS:
//
// ptr : A pointer to the memory block the user wishes to delete.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// After the user has had the chance to muck with this memory block for
// a while, he or she will want to return it to the heap. We do a bunch
// of checks here before that happens, to see if any serious mistakes have
// been made. If we detect any serious mistakes, we just abort the
// program with an assertion error.
//
// First we check to see if Windows thinks it is even a valid pointer. If
// we don't do this, some of the other code here will GPF if you call delete
// with a really bad pointer. Those GPFs are a lot less informative than
// our nice assertion failures.
//
// If it looks like it is a valid pointer, the next thing we do is try to
// see if the pointer is in our heap. A common mistake is trying to free
// a pointer twice, or freeing a pointer that has been incremented or
// decremented. Either of these can royally foul the heap.
//
// If it looks like the pointer really is in the heap, there is still one
// last thing to check. I take a quick glance at both the leading and
// trailing pickets to see if either of them have been mangled. A simple
// overwrite or underwrite by just one byte can be catastrophic, but we
// detect it easily here.
//
// If all of that goes as expected, we are free to finally return the
// storage to the heap. Just for good luck, I clear it out first. That
// way if anyone is foolish enough to try and use the data after it has
// been deleted, they will at least see that there is nothing intelligent
// store there.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
void operator delete( void *ptr )
{
#if defined( AL_WINDOWS_MEMORY ) && !defined( AL_FLAT_MODEL )
AL_ASSERT( !IsBadWritePtr( ptr, 1 ), "delete: delete called for ptr Windows doesn't like" );
#endif
char *p = (char *) ptr;
AL_ASSERT( PointerInHeap( p - 8 ),
"delete: delete called for pointer not found in the " LIB_TYPE " heap" );
AL_ASSERT( ( (long *) p )[ -1 ] == 0x12345678L,
"delete : Data corrupted in object's leading picket in the " LIB_TYPE " heap" );
size_t size = (size_t) ( (long *) p )[ -2 ];
char *ep = p + size;
AL_ASSERT( ( (long *) ep )[ 0 ] == 0xfedcba98L,
"delete : Data corrupted in object's trailing picket in the " LIB_TYPE " heap" );
memset( p - 8, size + 12, 0 ); //Clear it before freeing it
free( ((char *) p - 8 ) );
}
#endif //#ifdef _DEBUG etc.
#endif // #ifdef AL_DISABLE_NEW

314
al/_openf.cpp Executable file
View File

@ -0,0 +1,314 @@
//
// _OPENF.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALOpenInputFile::operator new()
// ALOpenOutputFile::operator new()
// ALOpenFiles::operator new()
// ALOpenInputFile::ALOpenInputFile()
// ALOpenInputFile::~ALOpenInputFile()
// ALOpenOutputFile::ALOpenOutputFile()
// ALOpenOutputFile::~ALOpenOutputFile()
// ALOpenFiles::ALOpenFiles()
// ALOpenFiles::~ALOpenFiles()
//
// DESCRIPTION
//
// The ALOpenInputFile, ALOpenOutputFile, and ALOpenFiles objects
// are all just simple little devices I use in functions to open files,
// then automatically close them when the function exits. Even better,
// if the storage object was already open when we enter the function,
// when we exit, we leave it open!
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "_openf.h"
//
// void * ALOpenInputFile::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The size of the object being created.
//
// RETURNS
//
// A pointer to the storage allocated for the object.
//
// DESCRIPTION
//
// When we construct an object when using the DLL, trouble can arise.
// The main bad thing is that when we call the constructor from an
// EXE, we allocate the storage for the new object from inside our EXE.
// When we destroy the same object, the destructor frees up the memory
// inside the DLL. This is bad, because you can mangle the heap inside
// the DLL by trying to free an object that doesn't belong to it.
//
// The fix to this conundrum is to allocate the object inside the DLL,
// and we can make this happen by overloading the new operator. We don't
// bother unless it's a DLL deal.
//
// This lecture will be repeated at times throughout the source in this
// project.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALOpenInputFile::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// void * ALOpenOutputFile::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The size of the object being created.
//
// RETURNS
//
// A pointer to the storage allocated for the object.
//
// DESCRIPTION
//
// See the function directly above.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALOpenOutputFile::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// void * ALOpenFiles::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The size of the object being created.
//
// RETURNS
//
// A pointer to the storage allocated for the object.
//
// DESCRIPTION
//
// See the function directly above.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALOpenFiles::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALOpenInputFile::ALOpenInputFile( ALStorage &file )
//
// ARGUMENTS:
//
// file : The storage object that has to opened.
//
// RETURNS
//
// Nothing, this is a constructor.
//
// DESCRIPTION
//
// You can stick this constructor at the start of a function, and it
// opens up an ALStorage object for you. You can then take it for
// granted that it is open. You can also take it for granted that
// the storage object will be closed by the destructor when the
// function exits. All of this saves a lot of repetitive code.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALOpenInputFile::ALOpenInputFile( ALStorage AL_DLL_FAR &file )
{
mpFile = &file;
miFileWasOpen = file.IsOpen();
if ( !miFileWasOpen )
file.Open();
}
//
// ALOpenInputFile::~ALOpenInputFile()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// None, it is a destructor.
//
// DESCRIPTION
//
// At the end of the function, it is time to close the storage object.
// But only if it wasn't open when the constructor was called.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALOpenInputFile::~ALOpenInputFile()
{
if ( !miFileWasOpen )
mpFile->Close();
}
//
// ALOpenOutputFile::ALOpenOutputFile( ALStorage &file )
//
// ARGUMENTS:
//
// file : The ALStorage object that needs to be created.
//
// RETURNS
//
// Nothing, it is a constructor.
//
// DESCRIPTION
//
// This is just like ALOpenInputFile, except instead of calling
// ALStorage::Open(), it calls ALStorage::Create(). Note that if
// the file is already open, we keep track of the fact and leave it
// alone.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALOpenOutputFile::ALOpenOutputFile( ALStorage AL_DLL_FAR &file )
{
mpFile = &file;
miFileWasOpen = file.IsOpen();
if ( !miFileWasOpen )
file.Create();
}
//
// ALOpenOutputFile::~ALOpenOutputFile()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// If the file was closed when the constructor was called, we close
// it in the constructor.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALOpenOutputFile::~ALOpenOutputFile()
{
if ( !miFileWasOpen )
mpFile->Close();
}
//
// ALOpenFiles::ALOpenFiles( ALStorage &input,
// ALStorage &output )
//
// ARGUMENTS:
//
// input : The storage object that needs to be opened, maybe.
//
// output : The storage object that needs to be created, maybe.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This is just a combination of the ALOpenOutputFile() and
// ALOpenInputFile() guys rolled into one. To combine them, we
// just create this object that contains one of both objects.
//
// So this guy takes care of opening an input file and an output
// file right there at the same time. The most exciting part of it
// is that they both get closed up in the destructor.
//
// So all the constructor has to do here is call the other two
// constructors in an initializer list.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALOpenFiles::ALOpenFiles( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output )
: mInputFile( input ), mOutputFile( output )
{
}
//
// ALOpenFiles::~ALOpenFiles()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This guy closes the two files, if they were closed when the constructor
// was called. We don't have to do anything explicitly, because the
// two data members of this object do so in their destructors.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALOpenFiles::~ALOpenFiles()
{
}

196
al/_openf.h Executable file
View File

@ -0,0 +1,196 @@
/*
* _OPENF.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* These three classes are utility classes used inside ArchiveLib.
* All they do is let me open a file(s) at the start of a routine and
* then automatically close it when I exit. It gets closed when
* the destructor for this class gets called. If the file was
* already open when the routine was entered, this class leave
* it open when the destructor gets called. These classes will generally
* get used like this:
*
* int foo( ALStorage &input_file )
* {
* ALOpenInputFile file( input_file )
* ...
* do stuff with input file
* ...
* } The destructor gets called here and the file is closed.
*
* This may seem like a lot of work, creating a class just to make
* sure files get closed, but it replaces a *lot* of code. Every
* routine that uses a file can use one of these classes.
*
*
* CLASS DEFINITIONS:
*
* ALOpenInputFile
* ALOpenOutputFile
* ALOpenFiles
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef __OPENF_H
#define __OPENF_H
#include "arclib.h"
/*
* class ALOpenInputFile
*
* DESCRIPTION
*
* This is a utility class. The constructor opens a file for input,
* and keeps track of whether it was already open or not. The destructor
* will automatically close the file if it was closed when the
* ctor was invoked.
*
* DATA MEMBERS
*
* miFileWasOpen : The flag that keeps track of the file's state
* at the start of the routine.
*
* mpFile : A pointer to the file, so we can close it in the dtor.
*
* MEMBER FUNCTIONS
*
* ALOpenInputFile : The constructor, opens the file.
* ~ALOpenInputFile : The destructor, can close the file.
* operator new : This operator is used in the Win16
* DLL version of ArchiveLib.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALOpenInputFile {
public :
AL_PROTO ALOpenInputFile( ALStorage AL_DLL_FAR &file );
AL_PROTO ~ALOpenInputFile();
#if defined( AL_BUILDING_DLL ) || defined( AL_USING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Prevent the compiler from generating these members.
*/
protected :
AL_PROTO ALOpenInputFile( ALOpenInputFile AL_DLL_FAR &);
ALOpenInputFile AL_DLL_FAR & operator=( ALOpenInputFile AL_DLL_FAR & );
protected :
int miFileWasOpen;
ALStorage AL_DLL_FAR *mpFile;
};
/*
* class ALOpenOutputFile
*
* DESCRIPTION
*
* This is a utility class. The constructor opens a file for output,
* and keeps track of whether it was already open or not. The destructor
* will automatically close the file if it was closed when the
* ctor was invoked.
*
* DATA MEMBERS
*
* miFileWasOpen : The flag that keeps track of the file's state
* at the start of the routine.
*
* mpFile : A pointer to the file, so we can close it in the dtor.
*
* MEMBER FUNCTIONS
*
* ALOpenOutputFile : The constructor, opens the file.
* ~ALOpenOutputFile : The destructor, can close the file.
* operator new : This operator is used in the Win16
* DLL version of ArchiveLib.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALOpenOutputFile {
public :
AL_PROTO ALOpenOutputFile( ALStorage AL_DLL_FAR &file );
AL_PROTO ~ALOpenOutputFile();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Prevent the compiler from generating these members.
*/
protected :
AL_PROTO ALOpenOutputFile( ALOpenOutputFile AL_DLL_FAR &);
ALOpenOutputFile AL_DLL_FAR & operator=( ALOpenOutputFile AL_DLL_FAR & );
protected :
int miFileWasOpen;
ALStorage AL_DLL_FAR *mpFile;
};
/*
* class ALOpenFiles
*
* DESCRIPTION
*
* This is a utility class. The constructor opens the first file for
* input, and the second for output. It does so using the previous
* two classes, so it doesn't have to keep track of anything.
*
* DATA MEMBERS
*
* mInputFile : The input file open object. It does all the work
* related to the input file.
*
* mOutputFile : The output file open object. It does all the work
* related to the output file.
*
* MEMBER FUNCTIONS
*
* ALOpenFiles : The constructor, opens both files.
*
* ~ALOpenFiles : The destructor, can close one or both files.
*
* operator new : This operator is used in the Win16
* DLL version of ArchiveLib.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALOpenFiles {
public :
AL_PROTO ALOpenFiles( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output );
AL_PROTO ~ALOpenFiles();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Prevent the compiler from generating these members.
*/
protected :
AL_PROTO ALOpenFiles( ALOpenFiles AL_DLL_FAR & );
ALOpenFiles AL_DLL_FAR & operator=( ALOpenFiles AL_DLL_FAR & );
protected :
ALOpenInputFile mInputFile;
ALOpenOutputFile mOutputFile;
};
#endif /* #ifndef __OPENF_H */

93
al/_r.h Executable file
View File

@ -0,0 +1,93 @@
/*
* _R.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This source code is shrouded.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _60
#define _60
#include <limits.h>
#include "arclib.h"
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned int uint;
#define _132 (CHAR_BIT * sizeof(ushort))
#define _133 16
#define _134 '\0'
#define _135 3
#define _136 16384
#define _137 14
#define _138 10
#define _139 8
#define _140 256
#define _141 (UCHAR_MAX + 1 + _140 - _135 + 1 + 1)
#define _142 (_137 + 1)
#define _143 9
#define _144 (_140 + 1)
#define _145 (_133 + 3)
#define _146 5
#define _147 5
#define _148 4096
#define _149 256
#if (1U << _146) <= _142
#error _146 _150 _151
#endif
#if (1U << _147) <= _145
#error _147 _150 _151
#endif
#if _145 > _142
#define _152 _145
#else
#define _152 _142
#endif
#define _153 4096
#define _154 4
#define _155 8192
#define _156 512
#define _157 (-1)
#define _158 128
#define _159 512
class RCompress{ private: ALStorage *_161;ALStorage *_162;
#if defined( AL_LARGE_DATA ) || defined( AL_FLAT_MODEL )
short *_163;short *_164;uchar *_165;
#else
short _far *_163;short _far *_164;uchar _far *_165;
#endif
uchar *_166;ushort _167[ 17 ];short _168;short _169;short _170;short _171;
short _172;short _173;short _174;short _175;short _176;short *_177;uchar *_178;
uchar *_179;uchar *_180;uchar *_181;ushort _182;ushort _183;ushort _184;
ushort _185;ushort _186;ushort *_187;ushort *_188;ushort *_189;ushort *_190;
ushort *_191;ushort *_192;ushort *_193;ushort *_194;int _531;private :
void _196();void _197();void _198();void _199( short _200, short _201 );
void _202( ushort _203, ushort _204 );void _205();void _206();void _207();
void _208( int _209, ushort _203 );void _210();int _211( int _212,
ushort *_213,uchar *_214,ushort *_215 );void _216( ushort *_217 );
void _218( short _219, short _220, short _221 );void _222();
void _223( short _203 );void _224( ushort _204 );void _225( int _226,
ushort *_187, short *_177, short _227 );void _228( int _229 );void _230(
int _219, uchar *_209, ushort *_231 );void _232( int _226 );public :
RCompress( ALStorage& _233,ALStorage& _202,int _234,int _235 );~RCompress();
int Compress();ALStatus mStatus;protected :RCompress( RCompress & );
RCompress & operator=(RCompress&);};class RExpand {private :ALStorage *_161;
ALStorage *_162;short _175;short _176;uchar *_166;ushort *_240;ushort *_241;
uchar *_242;ushort *_189;ushort *_190;uchar *_180;uchar *_181;short _243;
ushort _244;ushort _182;short _172;uchar _245;short _246;uchar *_247;
long _248;ushort _249();ushort _250();void _251();ushort _252( int _219 );
void _253( short _254, short _220, short _221 );void _255();void _256( int
_219 );void _257();void _258( int _259,uchar *_260,int _261,ushort *_262,
ushort _263 );public :RExpand( ALStorage& _233,ALStorage& _202,long _264,
int _234 );~RExpand();int Expand();ALStatus mStatus;protected :RExpand(
RExpand &);RExpand& operator=(RExpand&);};
#endif

190
al/_rc.cpp Executable file
View File

@ -0,0 +1,190 @@
//
// _RC.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// All shrouded.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#ifdef AL_SYMANTEC
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include "_r.h"
#define _519 "Incorrect compression level parameter passed to compressor. Compression level = %d"
#define _520 "Memory allocation failure in compression startup"
#define _445( _200, _446 ) ((short) ( (_446 << _154 ) ^ ( _278[ _200 + 2 ] ) ) & ( _153 - 1 ))
#define _447( _200, _201 ){short _204;if ((_204=_163[_201])!=_157)_164[_204]\
=_200;_164[_200]=_201;_163[_200]=_204;_163[_201]=_200;}
#define _448(s){short _204;if((_204=_164[s])!=_157){_164[s]=_157;_163[_204]\
=_157;}}
RCompress::RCompress(ALStorage&_266, ALStorage&_267, int _269, int _235) {
_161=&_266; _162=&_267; _531=_235;if(_269>_137||_269<_138){
mStatus.SetError(AL_ILLEGAL_PARAMETER,_519,_269-10); _175=2; }else
_175=(short)(1<<_269); _176=(short)(_175-1); if((_166=new
uchar[_175+_140+2])!=0) memset(_166,0,(_175+_140+2)*sizeof(uchar));
#if defined(AL_LARGE_DATA)||defined(AL_FLAT_MODEL)
if((_163=new short[_175+_153])!=0) memset(_163,0,(_175+_153)*sizeof(short));
if((_164=new short[_175])!=0) memset(_164,0,_175*sizeof(short)); _165=new
uchar[_155];
#else
_163=(short _far*)_fcalloc(_175+_153,sizeof(short )); _164=(short
_far*)_fcalloc(_175,sizeof(short)); _165=(uchar
_far*)_fcalloc(_155,sizeof(uchar));
#endif
_179=new uchar[_156]; if((_189=new ushort[2*_141-1])!=0)
memset(_189,0,(2*_141-1)*sizeof(ushort)); if((_190=new ushort[2*_141-1])!=0)
memset(_190,0,(2*_141-1)*sizeof(ushort)); if((_177=new short[_141+1])!=0)
memset(_177,0,(_141+1)*sizeof(short)); _180=new uchar[_141]; if((_191=new
ushort[2*_141-1])!=0) memset(_191,0,(2*_141-1)*sizeof(ushort)); if((_192=new
ushort[_141])!=0) memset(_192,0,_141*sizeof(ushort)); _181=new uchar[_152];
if((_193=new ushort[2*_142-1])!=0) memset(_193,0,(2*_142-1)*sizeof(ushort));
if((_194=new ushort[_152])!=0) memset(_194,0,_152*sizeof(ushort)); if(!_166||
!_163|| !_164|| !_165|| !_179|| !_189|| !_190|| !_177|| !_180|| !_191||
!_192|| !_181|| !_193|| !_194){
mStatus.SetError(AL_CANT_ALLOCATE_MEMORY,_520); } }RCompress::~RCompress() {
if(_166) delete[]_166;
#if defined(AL_LARGE_DATA)||defined(AL_FLAT_MODEL)
if(_163) delete[]_163; if(_164) delete[]_164; if(_165) delete[]_165;
#else
_ffree(_163); _ffree(_164); _ffree(_165);
#endif
if(_179) delete[]_179;
if(_189) delete[]_189; if(_190) delete[]_190; if(_177) delete[]_177; if(_180)
delete[]_180; if(_191) delete[]_191; if(_192) delete[]_192; if(_181)
delete[]_181; if(_193) delete[]_193; if(_194) delete[]_194; }inline void
RCompress::_223(short _203) { _208(_180[_203],_192[_203]); }int
RCompress::Compress() { short _209; short _201; short _200; short s; int
_231; uchar *_278; short _280; short _279;_278=_166; _280=_176;
_279=_175;_231=0; _196(); _198();_200=0;
s=0;_209=(short)_161->ReadBuffer(_278,_279); s=(short)(_209&_280); _169=0;
_168=0;_201=(short)(((_278[_200]<<_154)^(_278[_200+1]))&(_153-1));
_201=(short)(_445(_200,_201)+_279);while(_209>_140+4&&!_170){
_199(_200,_201); if(_168<_135){ _202(_278[_200],0); _447(_200,_201); _200++;
_201=(short)(_445(_200,_201)+_279); _209--; }else{ _209-=_168;
_202((ushort)(_168+(UCHAR_MAX+1-_135)),_169); while(--_168>=0){
_447(_200,_201); _200++; _201=(short)(_445(_200,_201)+_279); } }
}for(;_209<_140;_209++){ int _203=_161->ReadChar(); if(_203<0) break;
_278[s]=(unsigned char)_203; if(s<_140-1) _278[s+_279]=_278[s]; _448(s);
s=(short)((s+1)&(_280)); }while(_209>0&&!_170){ _199(_200,_201);
if(_168>_209) _168=_209; if(_168<_135){ _168=1; _202(_278[_200],0); }else
_202((ushort)(_168+(UCHAR_MAX+1-_135)), _169); while(--_168>=0){ int
_203=_161->ReadChar(); if(_203<0) break; else _278[s]=(unsigned char)_203;
if(s<_140-1) _278[s+_279]=_278[s]; _448(s);
s=(short)((s+1)&(_280));_447(_200,_201); _200=(short)((_200+1)&(_280));
_201=(short)(_445(_200,_201)+_279); } while(_168-->=0){ _447(_200,_201);
_200=(short)((_200+1)&_280); _201=(short)(_445(_200,_201)+_279); _209--; }
if(_162->mStatus<0) return 1; }if(!_170) _202(_144+(UCHAR_MAX+1-_135),0);
_197(); if(_170) _231=1;return _231; }void RCompress::_196() { int
_226;for(_226=0;_226<_141;_226++) _191[_226]=0; for(_226=0;_226<_142;_226++)
_193[_226]=0; _173=0; _205(); _170=0; _185=1; _184=0; _186=0; _165[0]=0;
_183=_155; _183-=(ushort)((3*CHAR_BIT)+6); }void RCompress::_197() {
if(!_170) _207(); _206(); _183=0; _184=0; }void RCompress::_198() {
#if defined(AL_FLAT_MODEL)
register short *_450;
#else
register short
_far*_450;
#endif
register short _226;_450=&_163[_175];
for(_226=_153;_226>0;_226--) *_450++=_157; _450=_164;
for(_226=_175;_226>0;_226--) *_450++=_157; }void RCompress::_199(short
_200,short _201) { register uchar *_451; register uchar *_278; short
_226,_452,_204,_453;_452=_158; _168=0; _451=&_166[_200]; _204=_201;
while((_204=_163[_204])!=_157){ if(--_452<0) break; _278=&_166[_204];
if(_451[_168]!=_278[_168]) continue; if(_451[0]!=_278[0]) continue;
if(_451[1]!=_278[1]) continue; if(_451[2]!=_278[2]) continue;
for(_226=3;_226<_140;_226++) if(_451[_226]!=_278[_226]) break; if(_226>_168){
_453=(short)(_200-_204-1); if(_453<0) _453+=_175; if(_453>=_175){ break; }
_169=_453; if((_168=_226)>=_140) break; } } }void RCompress::_202(ushort
_203,ushort _204) { if((_185>>=1)==0){ _185=1U<<(CHAR_BIT-1); if(_184>=_183){
_207(); if(_170) return; _184=0; } _186=_184++; _165[_186]=0; }
_165[_184++]=(uchar)_203; _191[_203]++; if(_203>=(1U<<CHAR_BIT)){
_165[_186]|=(uchar)_185; _165[_184++]=(uchar)_204;
_165[_184++]=(uchar)(_204>>CHAR_BIT); _203=0; while(_204){ _203++; _204>>=1;
} _193[_203]++; } }void RCompress::_205() { _172=0; _182=0; _171=0; }void
RCompress::_206() { if(!_170){ _208(CHAR_BIT-1,0); if(_171) _210(); } _171=0;
}void RCompress::_207() { uint _226,_289,_229,_454,_455; uint _456=0; ushort
_217[2*_145-1];_229=_211(_141,_191,_180,_192); _455=_191[_229];
_208(16,(ushort)_455); if(_229>=_141){ _216(_217);
_229=_211(_145,_217,_181,_194); if(_229>=_145){ _218(_145,_147,3); }else{
_208(_147,0); _208(_147,(ushort)_229); } _222(); }else{ _208(_147,0);
_208(_147,0); _208(_143,0); _208(_143,(ushort)_229); }
_229=_211(_142,_193,_181,_194); if(_229>=_142){ _218(_142,_146,-1); }else{
_208(_146,0); _208(_146,(ushort)_229); } _454=0;
for(_226=0;_226<_455;_226++){ if(_226%CHAR_BIT==0) _456=_165[_454++]; else
_456<<=1; if(_456&(1U<<(CHAR_BIT-1))){
_223((short)(_165[_454++]+(1U<<CHAR_BIT))); _289=_165[_454++];
_289+=_165[_454++]<<CHAR_BIT; _224((short)_289); }else _223(_165[_454++]);
if(_170) return; } for(_226=0;_226<_141;_226++) _191[_226]=0;
for(_226=0;_226<_142;_226++) _193[_226]=0; }void RCompress::_208(int
_209,ushort _203) { _203<<=_133-_209; _182|=(ushort)(_203>>_172);
if((_172+=(short)_209)>=8){ if(_171>=_156) _210();
_179[_171++]=(uchar)(_182>>CHAR_BIT);
if((_172=(ushort)(_172-CHAR_BIT))<CHAR_BIT) _182<<=CHAR_BIT; else{
if(_171>=_156) _210(); _179[_171++]=(uchar)_182;
_172=(ushort)(_172-CHAR_BIT); _182=(ushort)(_203<<(_209-_172)); } } }void
RCompress::_210() { if(_171<=0) return; _162->WriteBuffer(_179,_171); _171=0;
}int RCompress::_211(int _212, ushort *_213, uchar *_214, ushort *_215) { int
_226,_276,_289,_292; short _227;_174=(short)_212; _187=_213; _178=_214;
_292=_174; _227=0; _177[1]=0; for(_226=0;_226<_174;_226++){ _178[_226]=0;
if(_187[_226]) _177[++_227]=(short)_226; } if(_227<2){ _215[_177[1]]=0;
return _177[1]; } for(_226=_227/2;_226>=1;_226--) _225(_226,_187,_177,_227);
_188=_215; do{ _226=_177[1]; if(_226<_174) *_188++=(ushort)_226;
_177[1]=_177[_227--]; _225(1,_187,_177,_227); _276=_177[1]; if(_276<_174)
*_188++=(ushort)_276; _289=_292++;
_187[_289]=(ushort)(_187[_226]+_187[_276]); _177[1]=(short)_289;
_225(1,_187,_177,_227); _189[_289]=(ushort)_226; _190[_289]=(ushort)_276;
}while(_227>1); _188=_215; _228(_289); _230(_212,_214,_215); return _289;
}void RCompress::_216(ushort *_217) { short
_226,_289,_219,_277;for(_226=0;_226<_145;_226++) _217[_226]=0; _219=_141;
while(_219>0&&_180[_219-1]==0) _219--; _226=0; while(_226<_219){
_289=_180[_226++]; if(_289==0){ _277=1; while(_226<_219&&_180[_226]==0){
_226++; _277++; } if(_277<=2) _217[0]+=_277; else if(_277<=18) _217[1]++;
else if(_277==19){ _217[0]++; _217[1]++; }else _217[2]++; }else
_217[_289+2]++; } }void RCompress::_218(short _219,short _220,short _221) {
short _226,_289;while(_219>0&&_181[_219-1]==0) _219--; _208(_220,_219);
_226=0; while(_226<_219){ _289=_181[_226++]; if(_289<=6){ _208(3,_289); }else
_208(_289-3,(ushort)(USHRT_MAX<<1)); if(_226==_221){
while(_226<6&&_181[_226]==0) _226++; _208(2,(ushort)(_226-3)); } } }void
RCompress::_222() { short _226,_289,_219,_277;_219=_141;
while(_219>0&&_180[_219-1]==0) _219--; _208(_143,_219); _226=0;
while(_226<_219){ _289=_180[_226++]; if(_289==0){ _277=1;
while(_226<_219&&_180[_226]==0){ _226++; _277++; } if(_277<=2){
for(_289=0;_289<_277;_289++) _208(_181[0],_194[0]); }else if(_277<=18){
_208(_181[1],_194[1]); _208(4,(ushort)(_277-3)); }else if(_277==19){
_208(_181[0],_194[0]); _208(_181[1],_194[1]); _208(4,15); }else{
_208(_181[2],_194[2]); _208(_143,(ushort)(_277-20)); } }else
_208(_181[_289+2],_194[_289+2]); } }void RCompress::_224(ushort _204) {
ushort _203,_457;_203=0; _457=_204; while(_457){ _203++; _457>>=1; }
_208(_181[_203],_194[_203]); if(_203>1) _208(_203-1,_204); }void
RCompress::_225(int _226,ushort *_187,short *_177,short _227){int
_276,_289;_289=_177[_226]; while((_276=2*_226)<=_227){
if(_276<_227&&_187[_177[_276]]>_187[_177[_276+1]]) _276++;
if(_187[_289]<=_187[_177[_276]]) break; _177[_226]=_177[_276]; _226=_276; }
_177[_226]=(ushort)_289; }void RCompress::_228(int _229) { int _226,_289;
uint _458;for(_226=0;_226<=16;_226++) _167[_226]=0; _232(_229); _458=0;
for(_226=16;_226>0;_226--) _458+=_167[_226]<<(16-_226);
while(_458!=(1U<<16)){ _167[16]--; for(_226=15;_226>0;_226--){
if(_167[_226]!=0){ _167[_226]--; _167[_226+1]=(ushort)(_167[_226+1]+2);
break; } } _458--; } for(_226=16;_226>0;_226--){ _289=_167[_226];
while(--_289>=0) _178[*_188++]=(uchar)_226; } }void RCompress::_230(int
_219,uchar *_209,ushort *_231) { int _226; ushort _288[18];_288[1]=0;
for(_226=1;_226<=16;_226++)
_288[_226+1]=(ushort)((_288[_226]+_167[_226])<<1);
for(_226=0;_226<_219;_226++) _231[_226]=_288[_209[_226]]++; }void
RCompress::_232(int _226){ if(_226<_174) _167[(_173<16)?_173:16]++; else{
_173++; _232(_189[_226]); _232(_190[_226]); _173--; } }

113
al/_re.cpp Executable file
View File

@ -0,0 +1,113 @@
//
// _RE.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// All shrouded.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "_r.h"
#define _519 "Incorrect compression level parameter passed to compressor. Compression level = %d"
#define _520 "Memory allocation failure in expansion startup"
#define _521 "Internal 1 error in Greenleaf Decompression routine"
#define _522 "Internal 2 error in Greenleaf Decompression routine"
RExpand::RExpand(ALStorage&_266, ALStorage&_267, long _268, int _269) {
_161=&_266; _162=&_267; _248=_268;;if(_269>_137||_269<_138){
mStatus.SetError(AL_ILLEGAL_PARAMETER, _519, _269-10); _175=2; }else
_175=(short)(1<<_269); _176=(short)(_175-1);_166=new uchar[_175+2];
if(_166) memset(_166,0,(_175+2)*sizeof(uchar)); _240=new ushort[_148];
if(_240) memset(_240,0,_148*sizeof(ushort)); _241=new ushort[_149];
if(_241) memset(_241,0,_149*sizeof(ushort)); _242=new uchar[_159];
if(_242) memset(_242,0,_159*sizeof(uchar)); _189=new ushort[2*_141-1];
if(_189) memset(_189,0,(2*_141-1)*sizeof(ushort)); _190=new
ushort[2*_141-1]; if(_190) memset(_190,0,(2*_141-1)*sizeof(ushort));
_180=new uchar[_141]; _181=new uchar[_152]; if(!_166|| !_240|| !_241||
!_242|| !_189|| !_190|| !_180|| !_181){
mStatus.SetError(AL_CANT_ALLOCATE_MEMORY,_520); } }RExpand::~RExpand() {
if(_166) delete[]_166; if(_240) delete[]_240; if(_241) delete[]_241;
if(_242) delete[]_242; if(_189) delete[]_189; if(_190) delete[]_190;
if(_180) delete[]_180; if(_181) delete[]_181; }int RExpand::Expand() {
int _231; short _226; short _276; short _203; short _200; long _277;
uchar *_278; short _279; short _280;_278=_166; _279=_175;
_280=_176;_231=0; _243=0;_251();_277=0; _200=0;while(_243<5){
if((_203=_249())<=UCHAR_MAX){ _278[_200]=(uchar)_203; _277++;
if(++_200>=_279){ _200=0; if((short)_162->WriteBuffer(_278,_279)!=_279)
goto _282; } }else{ _276=(short)(_203-(UCHAR_MAX+1-_135));
if(_276==_144) break; _277+=_276; _226=(short)((_200-_250()-1)&_280);
if(_226<_279-_140-1&&_200<_279-_140-1){ while(--_276>=0)
_278[_200++]=_278[_226++]; }else{ while(--_276>=0){
_278[_200]=_278[_226]; if(++_200>=_279){ _200=0;
if((short)_162->WriteBuffer(_278,_279)!=_279) goto _282; }
_226=(short)((_226+1)&_280); } } } } if(_200!=0)
_162->WriteBuffer(_278,_200); _282: return _231; }ushort RExpand::_249()
{ ushort _276,_283;if(_244==0){ _244=_252(16); _253(_145,_147,3);
_255(); _253(_142,_146,-1); if(mStatus<0) return 0; } _244--;
_276=_240[_182>>4]; if(_276>=_141){ _283=1U<<3; do{ if(_182&_283)
_276=_190[_276]; else _276=_189[_276]; _283>>=1; }while(_276>=_141); }
_256(_180[_276]); return _276; }ushort RExpand::_250() { ushort
_276,_283;_276=_241[_182>>8]; if(_276>=_142){ _283=1U<<7; do{
if(_182&_283) _276=_190[_276]; else _276=_189[_276]; _283>>=1;
}while(_276>=_142); } _256(_181[_276]); if(_276!=0){ _276--;
_276=(short)((1U<<_276)+_252(_276)); } return _276; }void
RExpand::_251() { _244=0; _257(); }ushort RExpand::_252(int _219) {
ushort _284;_284=(ushort)(_182>>(2*CHAR_BIT-_219)); _256(_219); return
_284; }void RExpand::_253(short _254,short _220,short _221) { short
_226,_203,_219; ushort _283;_219=_252(_220); if(_219==0){
_203=_252(_220); for(_226=0;_226<_254;_226++) _181[_226]=0;
for(_226=0;_226<256;_226++) _241[_226]=_203; }else{ _226=0;
while(_226<_219){ _203=(short)(_182>>13); if(_203==7){ _283=1U<<12;
while(_283&_182){ _283>>=1; _203++; } } _256((_203<7)?3:_203-3);
_181[_226++]=(uchar)_203; if(_226==_221){ _203=_252(2); while(--_203>=0)
_181[_226++]=0; } } while(_226<_254) _181[_226++]=0;
_258(_254,_181,8,_241,_149); } }void RExpand::_255() { short
_226,_203,_219; ushort _283;_219=_252(_143); if(_219==0){
_203=_252(_143); for(_226=0;_226<_141;_226++) _180[_226]=0;
for(_226=0;_226<_148;_226++) _240[_226]=_203; }else{ _226=0;
while(_226<_219){ _203=_241[_182>>8]; if(_203>=_145){ _283=1U<<7; do{
if(_182&_283) _203=_190[_203]; else _203=_189[_203]; _283>>=1;
}while(_203>=_145); } _256(_181[_203]); if(_203<=2){ if(_203==0) _203=1;
else if(_203==1) _203=(short)(_252(4)+3); else
_203=(short)(_252(_143)+20); while(--_203>=0) _180[_226++]=0; }else
_180[_226++]=(uchar)(_203-2); } while(_226<_141) _180[_226++]=0;
_258(_141,_180,12,_240,_148); } }void RExpand::_256(int _219){
while(_219>_172){ _219-=_172;
_182=(ushort)((_182<<_172)+(_245>>(CHAR_BIT-_172))); if(_246<=0){
_247=_242; if(_248>=0&&_248<_159){
_246=(short)_161->ReadBuffer(_242,(size_t)_248); _248-=_246; }else
_246=(short)_161->ReadBuffer(_242,_159); if(_246<=0) _243++; }
_245=*_247++; _246--; _172=CHAR_BIT; } _172=(short)(_172-_219);
_182=(ushort)((_182<<_219)+(_245>>(CHAR_BIT-_219))); _245<<=_219; }void
RExpand::_257() { _182=0; _245=0; _172=0; _246=0; _256(2*CHAR_BIT);
}void RExpand::_258(int _259, uchar *_260, int _261, ushort *_262,
ushort _263) { ushort _277[17],_287[17],_288[18],*_204; uint
_226,_289,_209,_290,_291,_292,_293,_283;for(_226=1;_226<=16;_226++)
_277[_226]=0; for(_226=0;(int)_226<_259;_226++)
_277[_260[_226]]++;_288[1]=0; for(_226=1;_226<=16;_226++)
_288[_226+1]=(ushort)(_288[_226]+(_277[_226]<<(16-_226)));
if(_288[17]!=(ushort)(1U<<16)){
mStatus.SetError(AL_INTERNAL_ERROR,_521); _243=10; return;
}_291=16-_261; for(_226=1;(int)_226<=_261;_226++){ _288[_226]>>=_291;
_287[_226]=(ushort)(1U<<(_261-_226)); } while(_226<=16){
_287[_226]=(ushort)(1U<<(16-_226)); _226++; }_226=_288[_261+1]>>_291;
if(_226!=(ushort)(1U<<16)){ _289=1U<<_261; while(_226!=_289)
_262[_226++]=0; }_292=_259; _283=1U<<(15-_261);
for(_290=0;(int)_290<_259;_290++){ if((_209=_260[_290])==0) continue;
_293=_288[_209]+_287[_209]; if((int)_209<=_261){ if(_293>_263){
mStatus.SetError(AL_INTERNAL_ERROR,_522); _243=10; return; }
for(_226=_288[_209];_226<_293;_226++) _262[_226]=(ushort)_290; }else{
_289=_288[_209]; _204=&_262[_289>>_291]; _226=_209-_261; while(_226!=0){
if(*_204==0){ _190[_292]=_189[_292]=0; *_204=(ushort)_292++; }
if(_289&_283) _204=&_190[*_204]; else _204=&_189[*_204]; _289<<=1;
_226--; } *_204=(ushort)_290; } _288[_209]=(ushort)_293; } }

55
al/al.h Executable file
View File

@ -0,0 +1,55 @@
/*
* AL.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This is the master file that you can use to include
* all of the ArchiveLib headers. If you are using precompiled
* headers with your compiler, this might be the file you want
* included first in all your source files.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _AL_H
#define _AL_H
#include "arclib.h"
/*
* Derived classes
*/
#include "filestor.h"
#include "memstore.h"
#include "copyengn.h"
#include "grenengn.h"
#include "archive.h"
/*
* Demo classes and functions
*/
#if defined( AL_WINDOWS_GUI )
#include "winmon.h"
#include "algauge.h"
#include "alstream.h"
#else
#include "bargraph.h"
#include "spinner.h"
#endif
/*
* Additional classes
*/
#include "wildcard.h"
#endif /* #ifdef _AL_H */

489
al/alcxl.h Executable file
View File

@ -0,0 +1,489 @@
/*
* ALCXL.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This is the header file that C programmers need to include
* to have access to all of the C and VB translation functions.
*
* MACROS
*
* DECLARE_AL_HANDLE()
*
* PROTOTYPES:
*
* All C and VB translation functions.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ALCXL_H
#define _ALCXL_H
#include <time.h>
#include "aldefs.h"
/*
* The deal with these bogus structures is simply a convoluted way
* to provide some type checking when using these handles. As far
* as the C compiler can be concerned, they might as well all be
* void*, but then we wouldn't have as much type safety. This
* method is a lot like that used with STRICT in <windows.h>
* All we are doing is creating a purely arbitrary pointer type
* that will be used to communicate with C++ functions in ArchiveLib.
* As soon as we get inside ArchiveLib, we cast it to a more
* useful type.
*/
#define DECLARE_AL_HANDLE( x ) \
struct x##_bogus_struct { \
int x##_bogus_unused_member; \
}; \
typedef struct x##_bogus_struct AL_DLL_FAR * x
DECLARE_AL_HANDLE( hALArchive );
DECLARE_AL_HANDLE( hALMonitor );
DECLARE_AL_HANDLE( hALEntryList );
DECLARE_AL_HANDLE( hALEntry );
DECLARE_AL_HANDLE( hALStorage );
DECLARE_AL_HANDLE( hALExpander );
DECLARE_AL_HANDLE( hALEngine );
DECLARE_AL_HANDLE( hALCompressed );
#ifdef __cplusplus
extern "C" {
#endif
/*
* ALEngine functions
*/
void AL_FUNCTION deleteALEngine( hALEngine this_object );
int AL_FUNCTION ALEngineCompress( hALEngine this_object,
hALStorage input_object,
hALStorage output_object );
int AL_FUNCTION ALEngineDecompress( hALEngine this_object,
hALStorage input_object,
hALStorage output_object,
long compressed_length );
int AL_FUNCTION ALEngineGetTypeCode( hALEngine this_object );
char AL_DLL_FAR * AL_FUNCTION ALEngineGetTypeString( hALEngine this_object );
int AL_FUNCTION ALEngineGetStatusCode( hALEngine this_object );
int AL_FUNCTION ALEngineSetError( hALEngine this_object,
int error_code,
char AL_DLL_FAR *text );
char AL_DLL_FAR * AL_FUNCTION ALEngineGetStatusString( hALEngine this_object );
char AL_DLL_FAR * AL_FUNCTION ALEngineGetStatusDetail( hALEngine this_object );
/*
* ALEngine functions for Visual Basic only.
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION ALEngineGetTypeStringVB( hALEngine this_object );
long AL_FUNCTION ALEngineGetStatusStringVB( hALEngine this_object );
long AL_FUNCTION ALEngineGetStatusDetailVB( hALEngine this_object );
#endif
/*
* ALCopyEngine
*/
hALEngine AL_FUNCTION newALCopyEngine( void );
/*
* ALGreenleafEngine
*/
hALEngine AL_FUNCTION newALGreenleafEngine( int level );
/*
* ALStorage functions
*/
void AL_FUNCTION deleteALStorage( hALStorage this_object );
int AL_FUNCTION ALStorageCompare( hALStorage this_object,
hALStorage test_object );
int AL_FUNCTION ALStorageIsOpen( hALStorage this_object );
int AL_FUNCTION ALStorageReadChar( hALStorage this_object );
int AL_FUNCTION ALStorageReadShort( hALStorage this_object,
short int AL_DLL_FAR *short_data );
int AL_FUNCTION ALStorageReadLong( hALStorage this_object,
long AL_DLL_FAR *long_data );
int AL_FUNCTION ALStorageWriteLong( hALStorage this_object, long long_data );
int AL_FUNCTION ALStorageWriteShort( hALStorage this_object,
short int short_data );
int AL_FUNCTION ALStorageWriteString( hALStorage this_object,
char AL_DLL_FAR *string_data );
long AL_FUNCTION ALStorageGetCrc32( hALStorage this_object );
long AL_FUNCTION ALStorageGetSize( hALStorage this_object );
long AL_FUNCTION ALStorageTell( hALStorage this_object );
size_t AL_FUNCTION ALStorageReadBuffer( hALStorage this_object,
unsigned char AL_DLL_FAR *buffer,
size_t length );
size_t AL_FUNCTION ALStorageWriteBuffer( hALStorage this_object,
unsigned char AL_DLL_FAR *buffer,
size_t length );
void AL_FUNCTION ALStorageInitCrc32( hALStorage this_object, long seed );
int AL_FUNCTION ALStorageClose( hALStorage this_object );
int AL_FUNCTION ALStorageCreate( hALStorage this_object );
int AL_FUNCTION ALStorageDelete( hALStorage this_object );
int AL_FUNCTION ALStorageFlushBuffer( hALStorage this_object );
int AL_FUNCTION ALStorageLoadBuffer( hALStorage this_object, long address );
int AL_FUNCTION ALStorageOpen( hALStorage this_object );
int AL_FUNCTION ALStorageRename( hALStorage this_object,
char *new_name,
int delete_on_clash );
int AL_FUNCTION ALStorageRenameToBackup( hALStorage this_object,
int delete_on_clash );
int AL_FUNCTION ALStorageSeek( hALStorage this_object, long address );
int AL_FUNCTION ALStorageUnRename( hALStorage this_object,
int delete_on_clash );
int AL_FUNCTION ALStorageWriteChar( hALStorage this_object, int c );
int AL_FUNCTION ALStorageGetType( hALStorage this_object );
void AL_FUNCTION ALStorageSetMonitor( hALStorage this_object,
hALMonitor monitor );
long AL_FUNCTION ALStorageGetUnixTime( hALStorage this_object );
long AL_FUNCTION ALStorageToJulian( hALStorage this_object );
void AL_FUNCTION ALStorageFromJulian( hALStorage this_object, long jdn );
void AL_FUNCTION
ALStorageSetTimeDateFromStruc( hALStorage this_object,
struct tm AL_DLL_FAR * time_struct );
void AL_FUNCTION ALStorageSetTimeDateFromUnix( hALStorage this_object,
long unix_time );
void AL_FUNCTION
ALStorageGetStrucFromTimeDate( hALStorage this_object,
struct tm AL_DLL_FAR * time_struct );
unsigned short int AL_FUNCTION
ALStoragePackedAttributes( hALStorage this_object );
void AL_FUNCTION
ALStorageSetFromDosAttributes( hALStorage this_object,
unsigned short int dos_attributes );
void AL_FUNCTION
ALStorageSetFromPackedAtts( hALStorage this_object,
unsigned short int packed_attributes );
char AL_DLL_FAR * AL_FUNCTION ALStorageGetName( hALStorage this_object );
void AL_FUNCTION ALStorageSetName( hALStorage this_object,
char AL_DLL_FAR *object_name );
int AL_FUNCTION ALStorageWildCardMatch( hALStorage this_object,
char AL_DLL_FAR *pattern );
char AL_DLL_FAR * AL_FUNCTION
ALStorageChangeExtension( hALStorage this_object,
char AL_DLL_FAR *new_extension );
char AL_DLL_FAR * AL_FUNCTION
ALStorageChangeTrailingChar( hALStorage this_object,
char new_char );
char AL_DLL_FAR * AL_FUNCTION ALStorageGetOldName( hALStorage this_object );
int AL_FUNCTION ALStorageGetStatusCode( hALStorage this_object );
int AL_FUNCTION ALStorageSetError( hALStorage this_object,
int error_code,
char AL_DLL_FAR * text );
char AL_DLL_FAR * AL_FUNCTION
ALStorageGetStatusString( hALStorage this_object );
char AL_DLL_FAR * AL_FUNCTION
ALStorageGetStatusDetail( hALStorage this_object );
unsigned short int AL_FUNCTION ALStorageGetDosTime( hALStorage this_object );
unsigned short int AL_FUNCTION ALStorageGetDosDate( hALStorage this_object );
int AL_FUNCTION ALStorageValidTimeDate( hALStorage this_object );
#if defined( AL_WIN32S )
DWORD AL_FUNCTION ALStorageGetWin32Attributes( hALStorage this_object );
#endif
#if !defined( AL_WIN32S )
unsigned short int AL_FUNCTION ALStorageGetDosAttributes( hALStorage this_object );
#endif
/*
* ALStorage functions for Visual Basic only.
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION
ALStorageChangeExtensionVB( hALStorage this_object,
char AL_DLL_FAR *new_extension );
long AL_FUNCTION
ALStorageChangeTrailingCharVB( hALStorage this_object,
char new_char );
long AL_FUNCTION ALStorageGetNameVB( hALStorage this_object );
long AL_FUNCTION ALStorageGetOldNameVB( hALStorage this_object );
long AL_FUNCTION ALStorageGetStatusStringVB( hALStorage this_object );
long AL_FUNCTION ALStorageGetStatusDetailVB( hALStorage this_object );
#endif
/*
* ALFile functions
*/
hALStorage AL_FUNCTION newALFile( char AL_DLL_FAR *file_name );
/*
* ALMemory Functions
*/
#ifdef AL_WINDOWS_MEMORY
hALStorage AL_FUNCTION newALMemory( char AL_DLL_FAR *buffer_name,
char AL_HUGE *user_buffer,
DWORD user_buffer_size );
UINT AL_FUNCTION ALMemoryGetHandle( hALStorage this_object );
long AL_FUNCTION ALMemoryGetBufferSize( hALStorage this_object );
char AL_HUGE *AL_FUNCTION ALMemoryGetBuffer( hALStorage this_object );
#else
hALStorage AL_FUNCTION newALMemory( char AL_DLL_FAR *buffer_name,
char AL_DLL_FAR *user_buffer,
int user_buffer_size );
size_t AL_FUNCTION ALMemoryGetBufferSize( hALStorage this_object );
char AL_DLL_FAR *AL_FUNCTION ALMemoryGetBuffer( hALStorage this_object );
#endif
int AL_FUNCTION ALMemoryGetBufferOwner( hALStorage this_object );
void AL_FUNCTION ALMemorySetBufferOwner( hALStorage this_object,
int user_owns_buffer );
/*
* ALMonitor functions
*/
void AL_FUNCTION deleteALMonitor( hALMonitor this_object );
long AL_FUNCTION ALMonitorSetObjectSize( hALMonitor this_object,
long object_size );
long AL_FUNCTION ALMonitorSetObjectStart( hALMonitor this_object,
long object_start );
long AL_FUNCTION ALMonitorSetJobSize( hALMonitor this_object, long job_size );
long AL_FUNCTION ALMonitorSetJobSoFar( hALMonitor this_object,
long job_so_far );
#if defined( AL_WINDOWS_GUI )
hALMonitor AL_FUNCTION
newALWindowsMessage( enum ALMonitorType monitor_type,
HWND progress_text_window,
enum ALWindowsMessageType message_type,
HWND progress_number_window,
UINT windows_message );
#else
hALMonitor newALBarGraph( enum ALMonitorType monitor_type );
hALMonitor newALSpinner( enum ALMonitorType );
#endif
/*
* ALEntry functions
*/
hALEntry AL_FUNCTION newALEntry( hALEntryList list,
hALStorage storage,
hALEngine engine );
void AL_FUNCTION deleteALEntry( hALEntry this_object );
int AL_FUNCTION ALEntryDuplicate( hALEntry this_object, hALEntryList list );
int AL_FUNCTION ALEntryCompressionRatio( hALEntry this_object );
int AL_FUNCTION ALEntryGetMark( hALEntry this_object );
int AL_FUNCTION ALEntrySetComment( hALEntry this_object,
char AL_DLL_FAR *comment );
long AL_FUNCTION ALEntryGetCompressedSize( hALEntry this_object );
long AL_FUNCTION ALEntryGetCrc32( hALEntry this_object );
hALEntry AL_FUNCTION ALEntryGetNextEntry( hALEntry this_object );
char AL_DLL_FAR *AL_FUNCTION ALEntryGetComment( hALEntry this_object );
void AL_FUNCTION ALEntryClearMark( hALEntry this_object );
void AL_FUNCTION ALEntrySetMark( hALEntry this_object );
void AL_FUNCTION ALEntrySetMarkState( hALEntry this_object,
short int new_state );
hALStorage AL_FUNCTION ALEntryGetStorage( hALEntry this_object );
void AL_FUNCTION ALEntrySetStorage( hALEntry this_object,
hALStorage storage_object );
hALEngine AL_FUNCTION ALEntryGetEngine( hALEntry this_object );
void AL_FUNCTION ALEntrySetEngine( hALEntry this_object, hALEngine engine );
/*
* ALEntry functions for Visual Basic only.
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION ALEntryGetCommentVB( hALEntry this_object );
#endif
/*
* ALEntryList functions
*/
hALEntryList AL_FUNCTION newALEntryList( hALMonitor monitor );
void AL_FUNCTION deleteALEntryList( hALEntryList this_object );
int AL_FUNCTION ALEntryListClearMarks( hALEntryList this_object,
char AL_DLL_FAR *pattern );
int AL_FUNCTION ALEntryListDeleteUnmarked( hALEntryList this_object );
int AL_FUNCTION ALEntryListSetMarks( hALEntryList this_object,
char AL_DLL_FAR *pattern );
int AL_FUNCTION ALEntryListToggleMarks( hALEntryList this_object );
void AL_FUNCTION ALEntryListUnmarkDuplicates( hALEntryList this_object,
hALEntryList list, char
AL_DLL_FAR *error_message );
hALEntry AL_FUNCTION ALEntryListGetFirstEntry( hALEntryList this_object );
int AL_FUNCTION ALEntryListGetStatusCode( hALEntryList this_object );
char AL_DLL_FAR * AL_FUNCTION
ALEntryListGetStatusString( hALEntryList this_object );
char AL_DLL_FAR * AL_FUNCTION
ALEntryListGetStatusDetail( hALEntryList this_object );
int AL_FUNCTION ALEntryListAddWildCardFiles( hALEntryList this_object,
char AL_DLL_FAR *pattern,
int traverse );
/*
* ALEntry functions for Visual Basic only.
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION ALEntryLisGetStatusStringVB( hALEntryList this_object );
long AL_FUNCTION ALEntryListGetStatusDetailVB( hALEntryList this_object );
#endif
#if defined( AL_WINDOWS_GUI )
int AL_FUNCTION ALEntryListAddFromDialog( hALEntryList this_object,
HWND hWnd,
int list_box_id );
int AL_FUNCTION ALEntryListAddFromWindow( hALEntryList this_object,
HWND hWnd );
int AL_FUNCTION ALEntryListSetMarksFromDialog( hALEntryList this_object,
HWND hWnd,
int id );
int AL_FUNCTION ALEntryListSetMarksFromWindow( hALEntryList this_object,
HWND hWnd );
int AL_FUNCTION ALEntryListFillListBoxWindow( hALEntryList this_object,
HWND hWnd );
int AL_FUNCTION ALEntryListFillListBoxDialog( hALEntryList this_object,
HWND hDlg,
int list_box_id );
#endif
/*
* ALArchiveBase Functions
*/
void AL_FUNCTION deleteALArchive( hALArchive this_object );
int AL_FUNCTION ALArchiveCreate( hALArchive this_object, hALEntryList list );
int AL_FUNCTION ALArchiveCreateFromArchive( hALArchive this_object,
hALArchive source_archive,
hALEntryList source_list );
int AL_FUNCTION ALArchiveAppend( hALArchive this_object, hALEntryList list );
int AL_FUNCTION ALArchiveAppendFromArchive( hALArchive this_object,
hALArchive source_archive,
hALEntryList source_list );
int AL_FUNCTION ALArchiveExtract( hALArchive this_object, hALEntryList list );
int AL_FUNCTION ALArchiveDelete( hALArchive this_object,
hALEntryList list,
hALArchive destination_archive );
char AL_DLL_FAR * AL_FUNCTION ALArchiveGetComment( hALArchive this_object );
int AL_FUNCTION ALArchiveSetComment( hALArchive this_object,
char AL_DLL_FAR *comment );
int AL_FUNCTION ALArchiveReadDirectory( hALArchive this_object,
hALEntryList list );
int AL_FUNCTION ALArchiveWriteDirectory( hALArchive this_object,
hALEntryList list );
int AL_FUNCTION ALArchiveGetVersion( hALArchive this_object );
hALStorage AL_FUNCTION ALArchiveGetStorage( hALArchive this_object );
int AL_FUNCTION ALArchiveGetStatusCode( hALArchive this_object );
int AL_FUNCTION ALArchiveSetError( hALArchive this_object,
int error_code,
char AL_DLL_FAR *text );
char AL_DLL_FAR * AL_FUNCTION
ALArchiveGetStatusString( hALArchive this_object );
char AL_DLL_FAR * AL_FUNCTION
ALArchiveGetStatusDetail( hALArchive this_object );
/*
* ALArchiveBase functions for Visual Basic only.
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION ALArchiveGetCommentVB( hALArchive this_object );
long AL_FUNCTION ALArchiveGetStatusStringVB( hALArchive this_object );
long AL_FUNCTION ALArchiveGetStatusDetailVB( hALArchive this_object );
#endif
#if defined( AL_WINDOWS_GUI )
int AL_FUNCTION ALArchiveFillListBoxDialog( hALArchive this_object,
HWND hDlg,
int list_box);
int AL_FUNCTION ALArchiveFillListBoxWindow( hALArchive this_object,
HWND hWnd );
#endif
/*
* ALArchive functions
*/
hALArchive AL_FUNCTION newALArchive( char AL_DLL_FAR *file_name );
hALArchive AL_FUNCTION newALArchiveFromStorage( hALStorage object );
/*
* Note: this function has been replaced by the more properly
* named ALEntryListAddWildCardFiles. Calls the same C++ member fn.
*/
int AL_FUNCTION ALArchiveAddFilesToList( hALArchive this_object,
hALEntryList list,
char AL_DLL_FAR * pattern,
int traverse_flag );
/*
* ALCompressed functions
*/
hALCompressed AL_FUNCTION newALCompressed( hALStorage storage,
hALEngine engine );
void AL_FUNCTION deleteALCompressed( hALCompressed this_object );
int AL_FUNCTION ALCompressedExtract( hALCompressed this_object,
hALStorage output_object );
int AL_FUNCTION ALCompressedInsert( hALCompressed this_object,
hALStorage input_object );
int AL_FUNCTION ALCompressedGetStatusCode( hALCompressed this_object );
int AL_FUNCTION ALCompressedSetError( hALCompressed this_object,
int error_code,
char AL_DLL_FAR *text );
char AL_DLL_FAR * AL_FUNCTION
ALCompressedGetStatusString( hALCompressed this_object );
char AL_DLL_FAR * AL_FUNCTION
ALCompressedGetStatusDetail( hALCompressed this_object );
/*
* ALCompressed functions for Visual Basic only.
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION ALCompressedGetStatusStringVB( hALCompressed this_object );
long AL_FUNCTION ALCompressedGetStatusDetailVB( hALCompressed this_object );
#endif
/*
* ALWildCardExpander functions
*/
hALExpander AL_FUNCTION newALExpander( char AL_DLL_FAR *file_list,
int traverse_flag,
enum ALCase name_case );
void AL_FUNCTION deleteALExpander( hALExpander this_object );
char AL_DLL_FAR * AL_FUNCTION ALExpanderGetNextFile( hALExpander this_object );
/*
* ALWildCardExpander functions for Visual Basic only.
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION ALExpanderGetNextFileVB( hALExpander this_object );
#endif
/*
* Utility
*/
char AL_DLL_FAR * AL_FUNCTION StripFileName( char AL_DLL_FAR *file_name );
char AL_DLL_FAR * AL_FUNCTION StripPath( char AL_DLL_FAR *file_name );
/*
* Utility functions for Visual Basic only
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
long AL_FUNCTION StripFileNameVB( char AL_DLL_FAR *file_name );
long AL_FUNCTION StripPathVB( char AL_DLL_FAR *file_name );
#endif
#if defined( AL_WINDOWS_GUI )
void AL_CFUNCTION EditDisplay( HWND hDlg, int id, char AL_DLL_FAR *fmt, ... );
#endif
/*
* Internal use for VB only
*/
#if defined( AL_BUILDING_DLL ) && !defined( AL_FLAT_MODEL )
extern "C" long _far _pascal ALCreateVBString( const char _far *string, unsigned short int length );
#endif
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _ALCXL_H */

427
al/aldefs.h Executable file
View File

@ -0,0 +1,427 @@
/*
* ALDEFS.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This is the setup file for ArchiveLib. Everyone else has to include
* it, because all of the macros defined in here help to control
* how the library operates. Normally you will never have to include
* this header file, because it is included by ARCLIB.H, and consequently,
* everyone else.
*
* MACROS
*
* These are all calculated automatically for supported compilers.
*
* AL_WINDOWS_GUI : This library uses the Windows GUI API
* AL_WINDOWS_MEMORY : This library uses the Windows Memory API
* AL_FLAT_MODEL : This library uses 386 Flat Model
* AL_LARGE_DATA : Data uses 16:16 data pointer
* AL_OS2 : Some day.
* AL_UNIX : Some day.
*
* AL_BUILDING_DLL : Building the Windows DLL
* AL_USING_DLL : Linking to the Windows DLL
*
* AL_SYMANTEC : Compiler selection
* AL_BORLAND : Compiler selection
* AL_MICROSOFT : Compiler selection
* AL_WATCOM : Compiler selection
*
* Based on those settings, we can set this:
*
* AL_WIN32S : This is NT or Win32s
*
* AL_WINDOWS_GUI AL_WINDOWS_MEMORY AL_FLAT_MODEL
* Vanilla DOS NO NO NO
* Borland DPMI16 NO YES NO
* Borland DPMI32 NO YES YES
* Symantec DOSX NO NO YES
* Win32s YES YES YES
* Vanilla Windows YES YES NO
*
* Finally, we use those to create these things used in prototypes:
*
* AL_CLASS_TYPE : Sometimes "export", for classes in DLLs
* AL_PROTO : Sometimes "export", for functions in DLLs
* AL_DLL_FAR : Sometimes "far", for arguments being passed to DLLs
* AL_FUNCTION : Vanilla exported functions are "_export pascal"
* AL_CFUNCTION : Variable argument export functions are "_export cdecl"
*
* PROTOTYPES:
*
*
* ENUMERATED TYPES:
*
* ALMonitorType : Used to indicate whether a monitor
* is watching objects or an entire job.
*
* ALWindowsMessageType : To indicate whether an object of
* class ALMonitor is supposed to be
* sending total byte counts or
* percentage complete ratios.
*
* ALErrors : The global list of errors.
*
* ALCase : Used by ALName to indicate case
* sensitivity/handling
*
* ALGreenleafCompressionLevels : The five levels used by ALGreenleafEngine.
*
* ALTraverseSetting : Used to indicate whether class
* ALWildCardExpander will traverse
* subdirectories when searching.
*
* ALStorageType : The type of a storage engine.
*
* ALCompressionType : The type of a compression engine.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ALDEFS_H
#define _ALDEFS_H
/*
* The next long set of definitions and tests are all here simply to
* determine which compiler we are using, and what sort of target
* configuration we are trying to build/use.
*/
#if defined(__BORLANDC__) || defined(__TURBOC__)
#if defined( __WIN32__ )
#define AL_FLAT_MODEL
#endif
#if !defined( __BORLANDC__ )
#define AL_BORLAND __TURBOC__
#else
#define AL_BORLAND __BORLANDC__
#endif
#if sizeof( void * ) == 4
#define AL_LARGE_DATA
#endif
#if defined( _Windows )
#define AL_WINDOWS_MEMORY
#ifdef __DLL__
#define AL_BUILDING_DLL
#endif
#if !defined( __DPMI16__ ) && !defined( __CONSOLE__ )
#define AL_WINDOWS_GUI
#endif
#endif
#elif defined( __SC__ )
#define AL_SYMANTEC _MSC_VER
#if defined( __NT__ )
#define AL_FLAT_MODEL
#define AL_WINDOWS_MEMORY
#define AL_WINDOWS_GUI
#endif
#if defined( _M_I86HM ) || defined( _M_I86CM ) || defined( _M_I86LM )
#define AL_LARGE_DATA
#endif
/*
* The _WINDOWS and _WINDLL macros are only documented in LIBRARY.TXT
*/
#ifdef _WINDOWS
#define AL_WINDOWS_MEMORY
#define AL_WINDOWS_GUI
#ifdef _WINDLL
#define AL_BUILDING_DLL
#ifndef M_I86LM
#error All DLLs must be built using Large Model!
#endif
#endif
#endif
#elif defined( _MSC_VER )
#define AL_MICROSOFT _MSC_VER
#if defined( _M_I86HM ) || defined( _M_I86CM ) || defined( _M_I86LM )
#define AL_LARGE_DATA
#endif
#if ( AL_MICROSOFT >= 800 )
/*
* I really don't want MSC to tell me when it is using a precompiled
* header file. What is really dumb is that I probably do want it
* to tell me when it is creating one, but they generate the same
* warning!
*/
#pragma warning( disable : 4699 )
/*
* This error occurs if you have inline functions in a header file and
* they don't get used in a particular file. Bogus.
*/
#pragma warning( disable : 4505 )
/*
* This warning occurs if you are using assert() macros with NDEBUG and /Ox
* it is bogus
*/
#pragma warning( disable : 4705 )
/*
* This gives a warning for cout << setw( x )
*/
#pragma warning( disable : 4270 )
/*
* This is informational, it tells me when a function has been
* chosen for inlining.
*/
#pragma warning( disable : 4711 )
/*
* This is informational, it tells me when a function has been
* rejected for inlining. The funny part is that it gives
* me this message even if I don't select inlining for that
* particular function???
*/
#pragma warning( disable : 4710 )
#else /*#if ( AL_MICROSOFT >= 800 ) */
/*
* Microsoft C 7.0 has a major linker problems if a symbol exceeds
* 64 characters. Unfortunately, with full decoration, we have
* a couple of functions that hit that wall. So I have to redefine
* a couple of innocuous class names. I am trying to use similar
* names so that if you hit them in the debugger you will be able
* to understand what they mean.
*
* #if defined( _WINDLL )
* #define ALWindowsMessage ALWinMsg_
* #define ALCompressionEngine ALEngine_
* #endif NOTE: Fixing problem with /H64 in BUILD.INI! */
#endif /*#if ( AL_MICROSOFT >= 800 ) ... #else */
#ifdef _WINDOWS
#define AL_WINDOWS_MEMORY
#define AL_WINDOWS_GUI
#ifdef _WINDLL
#define AL_BUILDING_DLL
#ifndef M_I86LM
#error All DLLs must be built using Large Model!
#endif
#endif
#endif
#elif defined( __WATCOMC__ ) && defined( __386__ )
#define AL_FLAT_MODEL
#ifdef __WINDOWS__
#define AL_WINDOWS_MEMORY
#define AL_WINDOWS_GUI
#endif
#pragma warning 690 9 /* Warning for AL_ASSERT() at /w3 */
#pragma warning 549 9 /* Warning for sizeof() on class */
#elif defined( __GNUC__ )
#define AL_FLAT_MODEL
#ifdef __WINDOWS__
#define AL_WINDOWS_MEMORY
#define AL_WINDOWS_GUI
#endif
#elif defined( __WATCOMC__ ) && !defined( __386__ )
#define AL_WATCOM
#ifdef __WINDOWS__
#define AL_WINDOWS_MEMORY
#define AL_WINDOWS_GUI
#ifdef __SW_ZU
#define AL_BUILDING_DLL
#ifndef M_I86LM
#error All DLLs must be built using Large Model!
#endif
#endif
#endif
#if defined( _M_I86HM ) || defined( _M_I86CM ) || defined( _M_I86LM )
#define AL_LARGE_DATA
#endif
#pragma warning 549 9 /* Warning for sizeof() on class */
#elif defined( __IBMC__ ) || defined( __IBMCPP__ )
#define AL_IBM
#define AL_OS2
#define AL_FLAT_MODEL
#else
#error "Unknown compiler!"
#endif
#if defined( AL_WINDOWS_MEMORY ) || defined( AL_WINDOWS_GUI )
#define STRICT
#include <windows.h>
#ifdef AL_FLAT_MODEL
#define AL_HUGE
#else
#define AL_HUGE _huge
#endif
#else
#define WORD unsigned int
#define DWORD unsigned long
#endif
#if defined( AL_WINDOWS_GUI ) && defined( AL_WINDOWS_MEMORY ) && defined( AL_FLAT_MODEL )
#define AL_WIN32S
#endif
#if defined( AL_BUILDING_DLL )
#if defined( AL_FLAT_MODEL )
#define AL_CLASS_TYPE _export
#define AL_PROTO _export
#define AL_DLL_FAR
#define AL_FUNCTION _export pascal
#define AL_CFUNCTION _export cdecl
#elif defined( AL_WATCOM )
#define AL_CLASS_TYPE
#define AL_PROTO _export
#define AL_DLL_FAR
#define AL_FUNCTION _export _far pascal
#define AL_CFUNCTION _export _far cdecl
#else
#define AL_CLASS_TYPE _export
#define AL_PROTO _far
#define AL_DLL_FAR _far
#define AL_FUNCTION _export _far pascal
#define AL_CFUNCTION _export _far cdecl
#endif
#elif defined( AL_USING_DLL )
#if defined( AL_FLAT_MODEL ) && defined( AL_BORLAND )
#define AL_CLASS_TYPE _import
#define AL_PROTO _import
#define AL_DLL_FAR
#define AL_FUNCTION _import pascal
#define AL_CFUNCTION _import cdecl
#elif defined( AL_FLAT_MODEL ) && defined( AL_SYMANTEC )
#define AL_CLASS_TYPE _export
#define AL_PROTO _export
#define AL_DLL_FAR
#define AL_FUNCTION _export pascal
#define AL_CFUNCTION _export cdecl
#elif defined( AL_WATCOM )
#define AL_PROTO
#define AL_DLL_FAR
#define AL_CLASS_TYPE
#define AL_FUNCTION _far _pascal
#define AL_CFUNCTION _far cdecl
#else
#define AL_PROTO _far
#define AL_DLL_FAR _far
#ifdef AL_BORLAND
#if ( AL_BORLAND >= 0x450 )
#define AL_CLASS_TYPE _import
#else
#define AL_CLASS_TYPE _huge
#endif
#else
#define AL_CLASS_TYPE _export
#endif
#define AL_FUNCTION _export _far _pascal
#define AL_CFUNCTION _export _far cdecl
#endif
#else
#define AL_PROTO
#define AL_CLASS_TYPE
#define AL_DLL_FAR
#define AL_FUNCTION
#define AL_CFUNCTION
#endif
/*
* All objects of type ALMonitor are set up to monitor jobs or objects.
* This enum is passed to the constructor to select which one is desired.
*/
enum ALMonitorType {
AL_MONITOR_OBJECTS,
AL_MONITOR_JOB
};
/*
* An ALMonitor object can either send out byte counts or percentage
* complete ratios. When constructing the object, this enum indicates
* which strategy is going to be used.
*/
enum ALWindowsMessageType {
AL_SEND_BYTE_COUNT,
AL_SEND_RATIO,
};
/*
* Global enumerated error codes
*/
enum ALErrors {
AL_CANT_OPEN_BUFFER = -1200,
AL_CANT_ALLOCATE_MEMORY,
AL_CANT_CREATE_ENGINE,
AL_CANT_CREATE_STORAGE_OBJECT,
AL_RENAME_ERROR,
AL_CANT_OPEN_FILE,
AL_SEEK_ERROR,
AL_READ_ERROR,
AL_WRITE_ERROR,
AL_DELETE_ERROR,
AL_ILLEGAL_PARAMETER,
AL_INTERNAL_ERROR,
AL_USER_ABORT,
AL_SERVER_NOT_PRESENT,
AL_COMPRESSION_TYPE_MISMATCH,
AL_NEED_LENGTH,
AL_CRC_ERROR,
AL_COMPARE_ERROR,
AL_UNKNOWN_COMPRESSION_TYPE,
AL_UNKNOWN_STORAGE_OBJECT,
AL_INVALID_ARCHIVE,
AL_LOGIC_ERROR,
AL_BACKUP_FAILURE,
AL_GETSEL_ERROR,
AL_DUPLICATE_ENTRY,
AL_END_OF_FILE = -1,
AL_SUCCESS = 0
};
/*
* Enum used by ALName guys. Names can either be forced to upper
* or lower case, or support normal mixed case representations. Objects
* like MS-DOS file names should be forced to upper or lower, since the
* O/S keeps the names as case insensitive.
*/
enum ALCase {
AL_UPPER,
AL_LOWER,
AL_MIXED
};
/*
* Compressing levels used by the Greenleaf Engine. In the archive, this
* ratio is stored in the engine private data.
*/
enum ALGreenleafCompressionLevels {
AL_GREENLEAF_COPY = -1,
AL_GREENLEAF_LEVEL_0 = 0,
AL_GREENLEAF_LEVEL_1,
AL_GREENLEAF_LEVEL_2,
AL_GREENLEAF_LEVEL_3,
AL_GREENLEAF_LEVEL_4,
};
/*
* Used when constructing ALWildCardExpander objects. It decides whether
* the expander will traverse the entire subdirectory tree, or just stay
* on the current level.
*/
enum ALTraverseSetting {
AL_TRAVERSE = 1,
AL_DONT_TRAVERSE = 0,
};
/*
* The type of storage object. This is stored in the base class, ALStorage,
* and is initialized in the constructor.
*/
enum ALStorageType {
AL_UNDEFINED = -1,
AL_MEMORY_OBJECT = 0,
AL_FILE_OBJECT = 1 };
/*
* The type of compression engine. This is stored in the base class,
* ALEngine, and is initialized in the constructor.
*/
enum ALCompressionType {
AL_COMPRESSION_COPY = 0,
AL_COMPRESSION_GREENLEAF = 1
};
#endif

91
al/algauge.h Executable file
View File

@ -0,0 +1,91 @@
/*
* ALGAUGE.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file and ALGauge.CPP are derived from Microsoft's zYzGauge
* file posted on CompuServe.
*
* You have to include this header file if you are going to use the
* percentage gauge file. The percentage gauge is not a C++ class, it
* is some straight C Windows code that Microsoft posted on Compuserve.
* The end user has to create a control and assign it class "ALGauge"
* in Resource Workshop or App Studio. The initialization function
* defined in this header file then has to be called to set up the
* control. After that, it is simply a matter of sending a number
* between 0 and 100 to the control, using the ALGaugeSetPosition
* command. The actual format used for this control is:
*
* SendMessage( window_handle, ALGaugeSetPosition, ratio, 0 )
*
* PROTOTYPES:
*
* ALGaugeInit() : Public initialization for the entire class
* of gauge objects.
*
* ENUMERATED TYPES:
*
* typedef ALGaugeMessages : Messages that you can send to a
* gauge control.
*
* typedef ALGaugeOrientation : The physical orientation of the
* gauge on your screen. I like left
* to right best.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ALGAUGE_H
#define _ALGAUGE_H
/*
* These are all the different messages you can send to
* an ALGauge object. Our demo programs don't use any of these
* except ALGaugeSetPosition, so most of these aren't even tested.
*/
typedef enum {
ALGaugeSetRange = WM_USER,
ALGaugeGetRange,
ALGaugeSetPosition,
ALGaugeGetPosition,
ALGaugeSetOrientation,
ALGaugeGetOrientation,
ALGaugeSetForegroundColor,
ALGaugeGetForegroundColor,
ALGaugeSetBackgroundColor,
ALGaugeGetBackgroundColor,
ALGaugeSetDeltaPosition,
} ALGaugeMessages;
/*
* Send one of these with ALGaugeSetOrientation, to determined which
* direction the flood fill progresses.
*/
typedef enum {
ALGaugeOrientLeftToRight,
ALGaugeOrientRightToLeft,
ALGaugeOrientBottomToTop,
ALGaugeOrientTopToBottom,
} ALGaugeOrientation;
/*
* public function prototypes
*/
#ifdef __cplusplus
extern "C"
#endif
int AL_FUNCTION ALGaugeInit( HINSTANCE hInstance, HINSTANCE hPrevInstance );
#endif /* #ifdef _ALGAUGE_H */

193
al/alstream.h Executable file
View File

@ -0,0 +1,193 @@
/*
* ALSTREAM.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* These macros and types are all used in the debug versions of the
* ArchiveLib.
* This is a utility class that is used in some of the demos.
* It is a simple implementation of a C++ iostream that writes
* to a multiline edit control. The constructor wants a window
* handle and a control ID. In the implementations in the demos,
* the window handle is that of the dialog box, and the control
* ID is that of the multiline edit control. This class
* works pretty well, but it is by no means bulletproof. For one
* thing, it won't work from inside a DLL, because of far/near
* problems. So if you link to the DLL, you are still going to
* have to link to the static library to get this class. That
* is why the class isn't defined with the usual AL_CLASS_TYPE
* and AL_PROTO macros.
*
* Note that _ALControlStream is used internally as a helper.
* ALEditControlStream is what the programmer uses, but when
* creating an ALEditControlStream, we have to create an
* _ALControlStream object to do some of the work.
*
* CLASS DEFINITIONS:
*
* _ALControlStream : The streambuf used by ALEditControlStream
*
* ALEditControlStream : The ostream that writes to multiline edit
* controls.
* PROTOTYPES:
*
* ostream& gfendl( ostream &s ) : Used to generate a newline and
* a flush for ALEditControlStream.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ALSTREAM_H
#define _ALSTREAM_H
#define STRICT
#include <windows.h>
#include "arclib.h"
#if defined( __cplusplus )
/* Won't work in a DLL! */
#if !defined( AL_BUILDING_DLL )
#include <iostream.h>
/*
* class _ALControlStream
*
* DESCRIPTION
*
* This is a class derived from streambuf. We attach this to an
* ALEditControlStream, and it will write to the edit control
* specified in the constructor.
*
* DATA MEMBERS
*
* hWindow : The handle of the edit control.
*
* MEMBER FUNCTIONS
*
* _ALControlStream() : The constructor, called by the ALEditControlStream
* constructor.
*
* ~_ALControlStream() : The virtual destructor.
*
* overflow() : Called by the base class when the buffer is about
* to overflow. This is our cue to send bytes out
* to the edit control.
*
* underflow() : Called by the base class when the more data is
* needed by the buffer for reading. We don't
* supply any data, this is a stub.
*
* sync() : Base class calls this when it feels like flushing
* the buffers.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class _ALControlStream : public streambuf {
/*
* Constructors, destructors, friend declarations
*/
friend class ALEditControlStream;
public :
_ALControlStream( HWND hwnd, int control );
virtual ~_ALControlStream();
/*
* The copy constructor and assignment operator are not supported. I
* declare them here because I don't want the compiler to generate
* default versions for me.
*/
protected :
operator=( _ALControlStream& );
_ALControlStream( _ALControlStream& );
/*
* Member functions and overloaded operators
*/
protected :
virtual int overflow( int );
virtual int underflow();
virtual int sync();
/*
* Data members
*/
protected :
HWND hWindow;
};
/*
* class ALEditControlStream
*
* DESCRIPTION
*
* This is the demo class that actually performs output to the
* edit control. It doesn't really have to do anything other than
* create itself and then create the streambuf derivative, because
* the streambuf does al the work.
*
* DATA MEMBERS
*
* mpControlStream : A pointer to the streambuf object we create,
* because without him I am nothing.
*
* MEMBER FUNCTIONS
*
* ALEditControlStream() : The constructor.
* ~ALEditControlStream() : The destructor.
*
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class ALEditControlStream : public ostream
{
/*
* Constructors, destructors, and friends
*/
public :
ALEditControlStream( HWND handle, int control_id = -1 );
~ALEditControlStream();
/*
* The copy constructor and assignment operator are not supported. I
* declare them here because I don't want the compiler to generate
* default versions for me.
*/
protected :
operator=( ALEditControlStream& );
ALEditControlStream( ALEditControlStream& );
/*
* Data members
*/
_ALControlStream mpControlStream;
};
/*
* The gfendl manipulator is used to send an eol and flush the buffer
* when writing to an ALEditControlStream. It serves the same purpose
* as an endl written to a normal stream. The difference is that an
* eol on a regular stream has a "/n/r" pair, and this guy doesn't.
*/
ostream& gfendl( ostream &s );
#endif /* #if !defined( AL_BUILDING_DLL ) */
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _ALSTREAM_H */

913
al/arcentry.cpp Executable file
View File

@ -0,0 +1,913 @@
//
// ARCENTRY.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALEntry::operator new()
// ALEntryList::operator new()
// ALEntry::ALEntry()
// ALEntry::~ALEntry()
// ALEntry::Duplicate()
// ALEntry::InsertBefore()
// ALEntry::SetComment()
// ALEntry::CompressionRatio()
// ALEntryList::ALEntryList()
// ALEntryList::~ALEntryList()
// ALEntryList::SetMarkState()
// ALEntryList::ToggleMarks()
// ALEntry::GetNextEntry()
// ALEntryList::UnmarkDuplicates()
// ALEntryList::DeleteUnmarked()
// ALEntryList::FillListBox() //Windows GUI only
// ALEntryList::SetMarksFromListBox() //Windows GUI only
//
// DESCRIPTION
//
// This file contains the source code for two class, ALEntry and
// ALEntryList. They are so tightly bound together that it made
// sense to go ahead and stick them both in the same file.
//
// Class ALEntry describes the state of an object that is in an archive.
// It contains a pointer to a storage object and a compression engine,
// which define what goes in the archive and how it is put there. It
// also defines how to extract it. The ALEntry object also contains
// miscellaneous items that go with the object in the archive, such
// as its time/date stamp, its CRC, and its comment.
//
// You have to create an ALEntry *before* you put an object into an
// archive. The archiving class member function figure out what you want
// to do by looking at objects of the ALEntry. You also have to read
// the contents of the archive into a list of ALEntry objects before you
// can extract anything.
//
// ALEntryList is simply a class that is used to keep a linked list of
// ALEntry objects together. ALEntryList objects are passed to the high
// level ALArchiveBase functions for common operations, such as Create()
// Extract(), and so on. You get an ALEntryList back when you read the
// directory of an archive. The ALEntryList object tells you everything
// there is to know about the object stored in the archive.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
//
// void * ALEntry::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALEntry object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to create a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation schemed, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALEntry::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// void * ALEntryList::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes that are going to need to be allocated
// to create a new ALEntryList object.
//
// RETURNS
//
// A pointer to the newly allocated storage area. A 0 is returned if no
// storage could be found.
//
// DESCRIPTION
//
// Look at the explanation for ALEntry::operator new(), directly above
// this guy. The description is identical.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALEntryList::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALEntry::ALEntry( ALEntryList &list,
// ALStorage *object,
// ALCompressionEngine *engine )
//
// ARGUMENTS:
//
// list : A reference to the list the ALEntry object is going to
// be linked into. ALEntry objects aren't allowed to exist
// without being in a list.
//
// object : A pointer to the storage object that is attached to this
// entry. Remember, this is an unopened storage object,
// so it is not consuming very much space. It is okay
// to have a zillion or so of these just lying around.
// Don't forget that the ALEntry dtor is going to destroy
// this guy for you, don't you dare try it!.
//
// engine : A pointer to the compression engine that is going to
// be used to create/insert/extract the storage object
// to/from the archive. Just like with the compression
// engine, it is a low cost object, and you can keep lots
// of them on hand. This engine will be destroyed in the
// ALEntry dtor, so be sure to give up any claim you might
// have on this guy.
//
// RETURNS
//
// Nothing, this is a ctor.
//
// DESCRIPTION
//
// This ctor creates a new ALEntry object. You can do this by hand, but
// frequently you will ask ArchiveLib to create ALEntry objects for you,
// maybe by pulling them out of a list box, or reading them in from and
// archive. Note that ALEntry objects aren't allowed to ever exist
// outside a list, each entry absolutely has to appear in a list.
//
// dtor issues relating to the ALEntry object are very important. Since
// ALEntry objects always are part of a list, it made sense for the
// ALEntryList destructor to clean up all the entries in its list. So
// even though you might have created this ALEntry object, you don't get to
// delete it, that will be done for you.
//
// Also, the storage object and compression engine in the ALEntry object
// are going to be automatically destroyed by the ALEntry dtor. Don't
// even think about trying it yourself!
//
// You can think of an ALEntryList as a directory of an archive, and each
// ALEntry object in the list is a single entry in that directory.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALEntry::ALEntry( ALEntryList &list,
ALStorage *object,
ALCompressionEngine *engine )
: mrList( list ) // Initialize our own pointer to the list we will
// be a member of.
{
mpNextItem = this;
mpPreviousItem = this;
mpStorageObject = object;
mpCompressionEngine = engine;
mlCompressedSize = -1;
mlCompressedObjectPosition = -1;
miMark = 1; //Always construct with the mark turned on
mszComment = 0;
//
// I check for the object member to be non-zero because of a clunky design
// choice I made a while back. Each ALEntryList has an ALEntry member that
// points to the first and last members of the list. I could have (and
// probably should have) made the root of the list just be a pair of pointers,
// instead of a dummy ALEntry. Anyway, I can tell that dummy entry apart
// from the valid entries by virtue of the fact that it has a null
// pointer in its object pointer.
//
// So anyway, when I create this dummy object, I don't want to try to add
// it to the list, because by definition it is already in the list. So
// I do a check before adding any ALEntry to the list.
//
if ( object )
InsertBefore( *list.mpListHead );
}
//
// ALEntry::~ALEntry()
//
// ARGUMENTS:
//
// Nothing.
//
// RETURNS
//
// Nothing, this is a destructor.
//
// DESCRIPTION
//
// This destructor should normally be called by the ALEntryList dtor. The
// list that owns an entry will always try to delete it when the list
// is deleted.
//
// The ALEntry object tries to delete three dynamically allocated objects
// that it has control over: the storage object, the compression engine,
// and the comment. In each case it won't do it if the object pointer
// is 0. This provides a convenient mechanism for you to steal a storage
// object from an ALEntry. All you have to do is take the pointer, and
// then sent ALEntry::mpStorageObject to 0. This is an especially useful
// thing to do for ALMemory objects.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALEntry::~ALEntry()
{
AL_ASSERT( GoodTag(), "~ALEntry: Attempting to delete invalid object" );
if ( mszComment )
delete[] mszComment;
if ( mpStorageObject != 0 )
delete mpStorageObject;
if ( mpCompressionEngine != 0 )
delete mpCompressionEngine;
AL_ASSERT( mpNextItem != 0 ,"~ALEntry: next item is null" );
AL_ASSERT( mpPreviousItem != 0, "~ALEntry: previous item is null" );
ALEntry *next_job = mpNextItem;
ALEntry *previous_job = mpPreviousItem;
if ( next_job != this ) {
next_job->mpPreviousItem = previous_job;
previous_job->mpNextItem = next_job;
}
//
// Note that I check the object twice, one at the start of the dtor, and
// once again at the end. With all the linked list and dynamic deletion
// being done here, it seems like it would be really easy to hose things
// up if any mistakes were made.
//
AL_ASSERT( GoodTag(), "~ALEntry: Attempting to delete invalid object" );
}
//
// int ALEntry::Duplicate( ALEntryList &list )
//
// ARGUMENTS:
//
// list : A list of ALEntry objects to scan.
//
// RETURNS
//
// 0 if the entry is not duplicated, 1 if it is.
//
// DESCRIPTION
//
// This function is used to scan a list of ALEntry objects to see if
// any of them have the same name as this. Unmarked objects are ignored.
// All the function does is zip through the ALEntryList, checking each
// marked member for an ASCII match with the name of the storage object
// pointed to by this. You can see that the case sensitivity of this
// is observed when making the comparison.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALEntry::Duplicate( ALEntryList &list )
{
char *name = mpStorageObject->mName;
int case_sensitive = mpStorageObject->mName.mCase == AL_MIXED;
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->GetMark() && job != this ) {
if ( case_sensitive ) {
if ( strcmp( name, job->mpStorageObject->mName ) == 0 )
return 1;
} else {
if ( stricmp( name, job->mpStorageObject->mName ) == 0 )
return 1;
}
}
job = job->GetNextEntry();
}
return 0;
}
//
// PROTECTED FUNCTION
//
// void ALEntry::InsertBefore( ALEntry &job )
//
// ARGUMENTS:
//
// job : A reference to another job in the target list.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function is used inside the ALEntryList class to add a new ALEntry
// object to an ALEntryList. Since the list is a doubly linked list, the
// code to do the job is pretty simple. It would have been a little more
// complicated if I used a pair of pointers in the ALEntryList to start
// the list, instead of a dummy ALEntry object.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
void AL_PROTO ALEntry::InsertBefore( ALEntry &job )
{
mpNextItem = &job;
mpPreviousItem = job.mpPreviousItem;
(job.mpPreviousItem)->mpNextItem = this;
job.mpPreviousItem = this;
}
//
// int ALEntry::SetComment( const char *comment )
//
// ARGUMENTS:
//
// comment : The new comment that is going to be associated with the
// ALEntry object.
//
// RETURNS
//
// AL_SUCCESS if the new comment was set, < 0 if an error occurred.
//
// DESCRIPTION
//
// Before adding an object to an archive, you may want to change or set
// its comment. You do so by calling this function before performing any
// operation that will write the directory, such as Create() or
// WriteDirectory(). It has to dynamically allocate the space in the
// ALEntry object in order to store the new comment. This is good for
// you, because it means you don't have to worry about who owns the comment
// you just passed in.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALEntry::SetComment( const char AL_DLL_FAR *comment )
{
if ( mszComment )
delete[] mszComment;
if ( comment ) {
mszComment = new char[ strlen( comment ) + 1 ];
if ( mszComment )
strcpy( mszComment, comment );
else
return mrList.mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Failed to allocate memory when "
"adding comment to storage object %s",
(char *) mpStorageObject->mName );
} else
mszComment = 0;
return AL_SUCCESS;
}
//
// int ALEntry::CompressionRatio()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// The integer representing the compression ratio. The ration is a number
// from 0 to 100 (or maybe more) with 0 being perfect compression.
//
// It is possible to get a -1 back from this routine if the compression
// ratio is not presently known. This will be the case if you have
// not created the archive yet, or have a new object that hasn't been
// inserted yet.
//
// DESCRIPTION
//
// This calculates and returns the compression ratio. We don't store the
// ratio in ALEntry, because it is so darned easy to calculate when
// we need it. However, there are going to be times when we don't have
// it.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALEntry::CompressionRatio()
{
long uncompressed_size = mpStorageObject->GetSize();
if ( uncompressed_size <= 0 )
return -1;
if ( mlCompressedSize <= 0 )
return -1;
return (int) ( 100 * mlCompressedSize / uncompressed_size );
}
//
// ALEntryList::ALEntryList( ALMonitor * monitor = 0 )
//
// ARGUMENTS:
//
// monitor : A pointer to a monitor that will be used whenever we are
// processing objects in the list. If no argument is supplied,
// the default argument value of 0 is used. When the ctor sees
// that the value of the monitor pointer is 0, it assigns the
// default monitor instead.
//
// RETURNS
//
// No returns from constructors.
//
// DESCRIPTION
//
// Constructing an ALEntryList object doesn't take much work. I have to
// initialize two data members. The first is the pointer to the monitor
// that will be used when processing objects in the list. The second is
// the root of the linked list, which is a dummy ALEntry object. Note
// that the root is created as a dummy by setting the storage object pointer
// to 0.
//
// The default monitor is defined below. If you don't specify a real
// monitor, you get the default, which is a do nothing function. Everyone
// can share one instance of the default monitor, because it doesn't have
// any data members to be concerned about.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
ALMonitor ALDefaultMonitor( AL_MONITOR_OBJECTS );
AL_PROTO ALEntryList::ALEntryList( ALMonitor AL_DLL_FAR * monitor /* = 0 */ )
: mrMonitor( monitor ? *monitor : ALDefaultMonitor )
{
mpListHead = new ALEntry( *this, 0, 0 );
}
//
// ALEntryList::~ALEntryList()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// None, destructors don't get to return anything.
//
// DESCRIPTION
//
// The destructor for ALEntryList goes through the list and deletes every
// ALEntry object it finds. Note that this also causes the ALEntry
// object to destroy its storage object and compression engine. Once
// the whole list is obliterated, the list head ALEntry object can be
// safely deleted. Then the whole thing is done.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALEntryList::~ALEntryList()
{
AL_ASSERT( GoodTag(), "~ALEntryList: attempting to delete invalid object" );
ALEntry *job = GetFirstEntry();
while ( job ) {
ALEntry *next_job = job->GetNextEntry();
delete job;
job = next_job;
}
if ( mpListHead )
delete mpListHead;
AL_ASSERT( GoodTag(), "~ALEntryList: attempting to delete invalid object" );
}
// PROTECTED FUNCTION
//
// int ALEntryList::SetMarkState( const char *name,
// short int new_state )
//
// ARGUMENTS:
//
// name : The object name, specifying which storage objects are
// to have their state set. This name can include
// wild card characters. Note that passing a null
// pointer here will cause a match to *every* object name.
//
// new_state : The new state that the ALEntry mark should be set to.
//
// RETURNS
//
// A count of the number of ALEntry objects whose state was changed.
//
// DESCRIPTION
//
// This protected function is used internally to help out a couple of the
// public functions. It rips through every entry of the list, checks to
// see if storage object associate with the entry has a name that matches
// the wildcard specification, and sets the mark if it does.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALEntryList::SetMarkState( const char AL_DLL_FAR *name,
short int new_state )
{
int count = 0;
ALEntry *job = GetFirstEntry();
while ( job ) {
if ( name ) {
if ( job->mpStorageObject->mName.WildCardMatch( name ) ) {
job->SetMarkState( new_state );
count++;
}
} else {
job->SetMarkState( new_state );
count++;
}
job = job->GetNextEntry();
}
return count;
}
//
// int ALEntryList::ToggleMarks()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A count of the number of entries whose mark was changed.
// (Just the total number of entries.)
//
// DESCRIPTION
//
// This simple member function just goes through the entire list,
// toggling the mark state of every entry. In other words, if the mark
// was previously set, it will now be cleared, and vice versa.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALEntryList::ToggleMarks()
{
int count = 0;
ALEntry *job = GetFirstEntry();
while ( job ) {
job->SetMarkState( (short int) !job->GetMark() );
job = job->GetNextEntry();
count++;
}
return count;
}
//
// ALEntry * ALEntry::GetNextEntry()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A pointer to the next entry in the list. If the next entry is the
// list head, it means we have reached the end of the list, and a value
// of 0 is returned.
//
// DESCRIPTION
//
// This function is used to iterate through the list. Each entry has
// a pointer to the next and previous entries, so this function is really
// simple. The only complications comes from trying to detect the end of
// the list, which is denoted by the list head instance of ALEntry. We
// can tell it apart from all the legitimate entries by the fact that
// its storage object is 0.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
ALEntry AL_DLL_FAR * AL_PROTO ALEntry::GetNextEntry()
{
ALEntry *next_entry = this->mpNextItem;
//
// The list head has the special case where both the compression engine
// and storage object pointers are 0, and that makes the end of the list.
//
if ( mpNextItem->mpStorageObject == 0 )
return 0;
else
return next_entry;
}
//
// ALEntry * ALEntryList::GetFirstEntry()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A pointer to the first valid ALEntry object in the list, or 0 if there
// are no entries.
//
// DESCRIPTION
//
// If you are going to iterate through the entire list, this function is
// used to start you off. It gets the first entry in the list by call
// GetNextEntry() for the list head. Don't worry about what happens if
// the list is empty, the GetNextEntry() code figures that out with no
// problem, and returns a 0.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
ALEntry AL_DLL_FAR * AL_PROTO ALEntryList::GetFirstEntry()
{
return mpListHead->GetNextEntry();
}
//
// void ALEntryList::UnmarkDuplicates( ALEntryList &list,
// const char *error_message = 0 )
//
// ARGUMENTS:
//
// list : The list that is going to be compared to this.
//
// error_message : Each entry in this that turns out to have a duplicate
// entry in the list argument will not only be unmarked,
// it will also have its error status set, if an error
// message is provide.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// I think this function is a little confusing. At first blush, you would
// probably expect this function to scan all the items in a single list,
// and unmark any object that turn out to have duplicates elsewhere
// in the list. Unfortunately, it doesn't work that way.
//
// Instead, this function goes through the list specified by this, and
// checks to see if each entry in this appears in the list specified by
// the list parameter. This means that we are working with two different
// lists, which certainly offers plenty of chances to get confused.
//
// Anyway, each entry in this that turns out to have a duplicate gets its
// mark cleared. If the calling program specifies and error message,
// the entry also gets its mStatus error member set to flag this as an
// error.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
void AL_PROTO ALEntryList::UnmarkDuplicates( ALEntryList &list,
const char *error_message /* = 0 */ )
{
ALEntry *job = GetFirstEntry();
while ( job ) {
if ( job->GetMark() ) {
if ( job->Duplicate( list ) ) {
job->ClearMark();
if ( error_message && error_message[ 0 ] != '\0' )
job->mpStorageObject->mStatus.SetError(
AL_DUPLICATE_ENTRY,
error_message );
}
}
job = job->GetNextEntry();
}
}
//
// int ALEntryList::DeleteUnmarked()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// The number of entries that are deleted.
//
// DESCRIPTION
//
// Sometimes you may have a list with a whole bunch of unmarked entries.
// Those unmarked entries are just sitting there taking up space, so it
// would be handle to be able to just delete them. That is what this
// function does.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALEntryList::DeleteUnmarked()
{
ALEntry *job;
int count = 0;
job = GetFirstEntry();
while ( job ) {
ALEntry *next_job = job->GetNextEntry();
if ( job->GetMark() == 0 ) {
count++;
delete job;
}
job = next_job;
}
return count;
}
//
// in ALEntryList::FillListBox( HWND hDlg, int list_box = -1 )
//
// ARGUMENTS:
//
// hDlg : The handle of the dialog box that contains the list box
// control. If the list box is not a control in a dialog,
// set the next parameter to -1, and just pass the handle
// of the list box in this argument.
//
// list_box : The ID of the list box, if and only if the list box is
// in a dialog box specified by by the hDlg argument.
//
// RETURNS
//
// The number of entries that were stuffed into the list box.
//
// DESCRIPTION
//
// This function is a handy helper when using the Windows GUI. It goes
// through an ALEntryList, and finds all the marked entries. For every
// marked entry, it stuffs the name of the storage object into the list box.
// This means that if you are planning on letting the user select a list
// of storage objects, you can initialize the list with just one
// function call.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
int AL_PROTO ALEntryList::FillListBox( HWND hDlg, int list_box /* = -1 */ )
{
HWND window;
if ( list_box != -1 )
window = GetDlgItem( hDlg, (short int) list_box );
else
window = hDlg;
SendMessage( window, LB_RESETCONTENT, 0, 0 );
ALEntry *job = GetFirstEntry();
int count = 0;
while ( job ) {
if ( job->GetMark() ) {
count++;
SendMessage( window,
LB_ADDSTRING,
0,
(LPARAM)( (LPSTR) job->mpStorageObject->mName ) );
}
job = job->GetNextEntry();
}
if ( count == 0 )
SendMessage( window,
LB_ADDSTRING,
0,
(LPARAM)( (LPSTR) "<none>" ) );
return count;
}
//
// int ALEntryList::SetMarksFromListBox( HWND hDlg, int list_box = - 1 )
//
// ARGUMENTS:
//
// hDlg : The handle of the dialog box that contains the list box.
// If the list box control is standalone window, this parameter
// can be its handle, if the list_box argument is set to -1.
//
// list_box : The ID of the list box, if and only if it is contained in
// a dialog box whose handle is specified in the hDlg param.
//
// RETURNS
//
// A count of the number of items whose marks were set.
//
// DESCRIPTION
//
// This function is called after you have given a user the opportunity
// to set and clear items in a multiselection list box. Once the user
// has done so, you can call this function, which will go through the
// list and set all the marks that have been set in the list box by the
// user. Note that it will not clear the marks on any of the ALEntry
// objects in the list, you might want to do that first.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALEntryList::SetMarksFromListBox( HWND hDlg, int list_box /* = -1 */ )
{
HWND window;
if ( list_box != -1 )
window = GetDlgItem( hDlg, (short int) list_box );
else
window = hDlg;
WORD count = (WORD) SendMessage( window, LB_GETSELCOUNT, 0, 0L );
int *items = new int[ count ];
if ( items == 0 )
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Memory allocation failure in SetMarksFromListBox()" );
#ifdef AL_FLAT_MODEL
if ( count != (WORD) SendMessage( window, LB_GETSELITEMS, count, (LPARAM) ( items ) ) ) {
#else
if ( count != (WORD) SendMessage( window, LB_GETSELITEMS, count, (LPARAM) ( (int _far * ) items ) ) ) {
#endif
mStatus.SetError( AL_LOGIC_ERROR,
"Logic error in SetMarksFromListBox()."
"Mismatch in select count from list box." );
delete[] items;
return AL_LOGIC_ERROR;
}
for ( WORD i = 0 ; i < count ; i++ ) {
WORD length = (WORD) SendMessage( window, LB_GETTEXTLEN, (short int) items[ i ], 0L );
AL_ASSERT( length != (WORD) LB_ERR, "SetMarksFromListBox: LB_ERR returned from list box" );
if ( length > 0 ) {
char *name = new char[ length + 1 ];
if ( name ) {
if ( SendMessage( window, LB_GETTEXT, (short int) items[ i ], (LPARAM)( (LPSTR) name ) ) >= 0 )
SetMarks( name );
delete[] name;
}
}
}
delete[] items;
return count;
}
#endif

352
al/arcentry.h Executable file
View File

@ -0,0 +1,352 @@
/*
* ARCENTRY.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the definitions for two closely related
* classes, ALEntry and ALEntryList. An ALEntry
* object describes a storage object found in an archive. These
* objects are always carried around in a list. These lists are
* what get passed to archive member functions such as Create,
* Delete, and Append. They are also what comes back
* from ReadDirectory.
*
* In addition to the information about a file that is either in an
* archive or is going to go into an archive, the job entry also
* has a special mark. Each job entry is created in the marked state.
* All of the archive functions that accept a list as an argument only
* work on marked files, they ignore items in the list that aren't marked.
* Various member functions can be used to clear or set marks on files.
* There are several criteria you might use to clear or set marks,
* such as matching a wild card specification, being older than a
* certain date, or being a certain size.
*
* CLASS DEFINITIONS:
*
* ALEntry : A description of an entry in an Archive.
*
* ALEntryList : A list of ALEntry objects.
*
* FUNCTIONS
*
* ALEntryList::SetMarks()
* ALEntryList::ClearMarks()
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ARCENTRY_H
#define _ARCENTRY_H
#if defined( __cplusplus )
/*
* Forward declarations.
*/
class AL_CLASS_TYPE ALEntryList;
class AL_CLASS_TYPE ALArchiveBase;
class AL_CLASS_TYPE ALMonitor;
/*
* class ALEntry
*
* DESCRIPTION
*
* ALEntry objects describe an entry in an archive. When you read in
* the directory from an archive, it consists of a list of ALEntry
* objects. The description can also refer to objects that you
* want to put in an archive.
*
* An ALEntry object has pointers to both a compression engine and
* a storage object. It also has the position of an object in an archive,
* its CRC-32, and more. Some of this data will not be filled in when
* you pass a list of these objects as an argument to an Archive command
* like Create().
*
*
* DATA MEMBERS
*
* mszComment : The comment stored with the archive.
*
* mpNextItem : A pointer to the next ALEntry object in
* the list. (Note that ALEntry items are
* always in a list.)
*
* mpPreviousItem : A pointer to the previous item in the list.
*
* mrList : A reference to the list that the ALEntry
* guy is a member of.
*
* mlCompressedSize : How big the object is after it is compressed.
* If you are inserting an object for the first
* time, you will have to wait for the ALArchiveBase
* member function to fill this guy in after
* the insertion takes place.
*
* mlCompressedObjectPosition : Where the object is found in the archive.
* Another field that gets filled in during
* insertion.
*
* mlCrc32 : The CRC-32 of the uncompressed object. This
* gets filled in during compression.
*
* miMark : The object's mark. If the mark is not set,
* most of the archive commands will ignore
* this entry.
*
*
* mpStorageObject : A pointer to the storage object associated
* with this entry. This is a public member,
* so you can dink with it. It will be destroyed
* by the ALEntry destructor!
*
* mpCompressionEngine : A pointer to the compression engine associated
* with this archive entry.
*
* MEMBER FUNCTIONS
*
* ALEntry() : The constructor.
* ~ALEntry() : The destructor.
* operator new() : Memory allocation operator, only used when the
* constructor is inside the DLL.
* InsertBefore() : A private function used when updating an
* ALEntrylist
* GetNextEntry() : A routine used when interating an ALEntrylist.
* GetCompressedSize() : An access routine to get a protected member.
* GetCrc32() : An access routine to get a protected member.
* GetComment() : An access routine to get a protected member.
* SetMark() : Set the mark for an ALEntry, the default state is set.
* ClearMark() : Clear the mark for an ALEntry.
* SetMarkState() : Private function to set or clear the mark.
* SetComment() : Set the comment for an entry.
* GetMark() : Get the current state of the mark.
* CompressionRatio() : Calculate the compression ratio for an object.
* Duplicate() : Test to see if an entry is found in a list.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALEntry {
/*
* Constructors, destructors, friends
*/
friend class AL_CLASS_TYPE ALArchiveBase;
public :
AL_PROTO ALEntry( ALEntryList AL_DLL_FAR &,
ALStorage AL_DLL_FAR *,
ALCompressionEngine AL_DLL_FAR * );
AL_PROTO ~ALEntry();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* The copy constructor and assignment operator are not supported. I
* declare them here because I don't want the compiler to generate
* default versions for me.
*/
protected :
AL_PROTO operator=( ALEntry AL_DLL_FAR & );
AL_PROTO ALEntry( ALEntry AL_DLL_FAR & );
/*
* Member functions
*/
protected :
void AL_PROTO InsertBefore( ALEntry AL_DLL_FAR & );
public :
ALEntry AL_DLL_FAR * AL_PROTO GetNextEntry();
long AL_PROTO GetCompressedSize() const { return mlCompressedSize; }
long AL_PROTO GetCrc32() const { return mlCrc32; }
const char AL_DLL_FAR * AL_PROTO GetComment(){ return mszComment; }
void AL_PROTO SetMark(){ miMark = 1; }
void AL_PROTO ClearMark(){ miMark = 0; }
void AL_PROTO SetMarkState( short int new_state ){ miMark = new_state; }
int AL_PROTO SetComment( const char AL_DLL_FAR *comment );
int AL_PROTO GetMark(){ return miMark; }
int AL_PROTO CompressionRatio();
int AL_PROTO Duplicate( ALEntryList AL_DLL_FAR &list );
/*
* Data members
*/
protected :
char AL_DLL_FAR *mszComment;
ALEntry AL_DLL_FAR *mpNextItem;
ALEntry AL_DLL_FAR *mpPreviousItem;
ALEntryList AL_DLL_FAR &mrList;
long mlCompressedSize;
long mlCompressedObjectPosition;
long mlCrc32;
short int miMark;
public :
ALStorage AL_DLL_FAR *mpStorageObject;
ALCompressionEngine AL_DLL_FAR *mpCompressionEngine;
AL_CLASS_TAG( _ALEntryTag );
};
/*
* class ALEntryList
*
* DESCRIPTION
*
* This class is simply a list of ALEntry objects. There are
* quite a few member functions that operate on this list.
* ALEntryList objects are passed as arguments to many of the
* archive functions, such as ReadDirectory(), Create(), Extract(),
* and more.
*
* DATA MEMBERS
*
* mpListHead : The head of the list is a dummy entry that is a
* placeholder.
*
* &mrMonitor : A reference to the monitor associated with this list.
* The monitor will take care of generating all the
* user interface activity to go with this list.
*
* mStatus : A standard status member, the status of the whole list.
*
* MEMBER FUNCTIONS
*
* ALEntryList() : The constructor
* ~ALEntryList() : The destructor.
* operator new() : Memory allocation for the class, only used
* when the ctor is in a DLL.
* SetMarkState() : Set the marks of items in the list to 1 or 0
* GetFirstEntry() : A list iterator function, starts the iteration
* SetMarks() : Set some of the marks in the list
* ClearMarks( : Clear some of the marks in the list
* DeleteUnmarked() : Delete list entries that aren't marked
* ToggleMarks() : Toggle every mark in the list
* UnmarkDuplicates() : Use this to avoid processing duplicates
* FillListBox() : Fill a list box up with a list
* SetMarksFromListBox() : Use list feedback to set marks
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALEntryList {
/*
* Constructors, destructors, friends
*/
friend class AL_CLASS_TYPE ALEntry;
public :
AL_PROTO ALEntryList( ALMonitor AL_DLL_FAR * = 0 );
AL_PROTO ~ALEntryList();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* The copy constructor and assignment operator are not supported. I
* declare them here because I don't want the compiler to generate
* default versions for me.
*/
protected :
AL_PROTO operator=( ALEntryList AL_DLL_FAR & );
AL_PROTO ALEntryList( ALEntryList AL_DLL_FAR & );
/*
* Member Functions
*/
protected :
int AL_PROTO SetMarkState( const char AL_DLL_FAR *name, short int state );
public :
ALEntry AL_DLL_FAR * AL_PROTO GetFirstEntry();
int AL_PROTO SetMarks( const char AL_DLL_FAR *pattern = 0 );
int AL_PROTO ClearMarks( const char AL_DLL_FAR *pattern = 0 );
int AL_PROTO DeleteUnmarked();
int AL_PROTO ToggleMarks();
void AL_PROTO UnmarkDuplicates( ALEntryList AL_DLL_FAR &list,
const char AL_DLL_FAR *error_message = 0 );
/*
* A windows utility function
*/
#if defined( AL_WINDOWS_GUI )
int AL_PROTO FillListBox( HWND hDlg, int list_box = -1 );
int AL_PROTO SetMarksFromListBox( HWND hDlg, int list_box = -1 );
#endif
/*
* Data members
*/
protected :
ALEntry *mpListHead; /* The head is never used */
public :
ALMonitor AL_DLL_FAR &mrMonitor;
ALStatus mStatus;
AL_CLASS_TAG( _ALEntryListTag );
};
/*
* inline int ALEntryList::SetMarks( const char *name )
*
* ARGUMENTS:
*
* name : A wild care file spec.
*
* RETURNS
*
* The number of entries that matched the wild card.
*
* DESCRIPTION
*
* This function sets the mark for every entry in the list object
* that matches the wild card specification.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*/
inline int AL_PROTO ALEntryList::SetMarks( const char AL_DLL_FAR *name )
{
return SetMarkState( name, 1 );
}
/*
* inline int ALEntryList::ClearMarks( const char *name )
*
* ARGUMENTS:
*
* name : A wild care file spec.
*
* RETURNS
*
* The number of entries that matched the wild card.
*
* DESCRIPTION
*
* This function clears the mark for every entry in the list object
* that matches the wild card specification.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*/
inline int AL_PROTO ALEntryList::ClearMarks( const char AL_DLL_FAR *name )
{
return SetMarkState( name, 0 );
}
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _ARCENTRY_H */

433
al/archive.cpp Executable file
View File

@ -0,0 +1,433 @@
//
// ARCHIVE.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALArchive::operator new()
// ALArchive::ALArchive()
// ALArchive::~ALArchive()
// ALArchive::CreateCompressionEngine()
// ALArchive::CreateStorageObject()
// ALArchive::AddWildCardFiles()
// ALArchive::MakeEntriesFromListBox()
//
// DESCRIPTION
//
// This file contains all the source code for class ALArchive. ALArchive
// is a class derived from ALArchiveBase that knows how to create ALFile
// and ALMemory objects. Remember that ALArchiveBase doesn't know how
// to create any kind of storage object, so we need derived classes to
// bind ourselves to certain types of objects.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "archive.h"
#include "grenengn.h"
#include "copyengn.h"
#include "filestor.h"
#include "memstore.h"
#include "wildcard.h"
//
// void * ALArchive::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALArchive object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to create a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALArchive::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALArchive::ALArchive( const char *file_name )
//
// ARGUMENTS:
//
// name : The name of the ALFile object that is going to hold the
// ALArchive.
//
// RETURNS
//
// Nothing, this is a constructor.
//
// DESCRIPTION
//
// This is one of two constructors for ALArchive. (The other one
// follows immediately in this source file.) It is used
// when the archive you are working with or are going to create will
// reside in an ALFile object, which should be often. It simply
// calls the constructor for the base class with the appropriately
// created ALFile object and returns. It doesn't have to initialize
// any data members of its own, so life is really simple.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALArchive::ALArchive( const char AL_DLL_FAR *file_name )
: ALArchiveBase( new ALFile( file_name ), 1 )
{
}
//
// ALArchive::ALArchive( ALStorage &so )
//
// ARGUMENTS:
//
// so : A storage object that will used as the storage for the archive.
//
// RETURNS
//
// Nothing, this is a constructor.
//
// DESCRIPTION
//
// This is one of two constructors for ALArchive. (The other one
// immediately precedes this function in the same source file.) It is used
// when the archive you are working with or are going to create will
// reside in an object that you have already constructed.
// It doesn't have to initialize any data members of its own, so
// all it does is call the base class constructor from an
// initializer list, and then return.
//
// The storage object used for this archive is your responsibility to delete.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALArchive::ALArchive( ALStorage AL_DLL_FAR &so )
: ALArchiveBase( &so, 0 )
{
}
//
// ALArchive::~ALArchive()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Nothing, destructor.
//
// DESCRIPTION
//
// This destructor has an easy life of it, since it has no data
// members to clean up after. Instead, it leaves all of the heavy
// lifting to the base class destructor. In debug mode we at least
// do *something*, which is just to verify that this is the correct
// type of object.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALArchive::~ALArchive()
{
AL_ASSERT( GoodTag(), "~ALArchive: attempt to delete invalid object" );
}
//
// ALCompressionEngine *ALArchive::CreateCompressionEngine( int engine_type )
//
// ARGUMENTS:
//
// engine_type : An integer from ALDEFS.H that defines the type of compression
// to be created.
//
// RETURNS
//
// A pointer to a newly created compression engine. If things go bad,
// a value of 0 is possible.
//
// DESCRIPTION
//
// ALArchiveBase doesn't know how to create compression engines or
// storage objects. That knowledge is left up to derived classes like
// this one. When extracting objects from an archive, this class has
// to be able to create a compression engine with no more information
// than the integer engine type stored in the archive directory.
// This is where we do it.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
ALCompressionEngine AL_DLL_FAR *
AL_PROTO ALArchive::CreateCompressionEngine( int engine_type )
{
switch ( engine_type ) {
case AL_COMPRESSION_COPY :
return new ALCopyEngine();
case AL_COMPRESSION_GREENLEAF :
return new ALGreenleafEngine();
default :
mStatus.SetError( AL_UNKNOWN_COMPRESSION_TYPE,
"Unknown compression type (%d) found in archive",
engine_type );
break; //Break instead of return because of bogus warnings
}
return 0;
}
//
// ALStorage * ALArchive::CreateStorageObject( const char *name,
// int object_type )
//
// ARGUMENTS:
//
// name : The name of the storage object to be created.
//
// object_type : The object type, from ALStorageType in STORAGE.H.
//
// RETURNS
//
// A pointer to a newly storage object. If things go bad,
// a value of 0 is possible.
//
// DESCRIPTION
//
// ALArchiveBase doesn't know how to create compression engines or
// storage objects. That knowledge is left up to derived classes like
// this one. When extracting objects from an archive, this class has
// to be able to create a storage object with no more information
// than the integer object type stored in the archive directory.
// This is where we do it.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
ALStorage AL_DLL_FAR * AL_PROTO
ALArchive::CreateStorageObject( const char AL_DLL_FAR *name,
int object_type )
{
switch ( object_type ) {
case AL_MEMORY_OBJECT :
return new ALMemory( name );
case AL_FILE_OBJECT :
return new ALFile( name );
default :
mStatus.SetError( AL_UNKNOWN_STORAGE_OBJECT,
"Unknown storage object type (%d) "
"found in archive",
object_type );
break;
}
return 0;
}
// STATIC MEMBER FUNCTION
//
// int ALArchive::AddWildCardFiles(
// ALEntryList & list,
// const char *wild_spec = "*.*",
// int traverse_flag = 0,
// short int compression_level = AL_GREENLEAF_LEVEL_2 )
//
// ARGUMENTS:
//
// list : The list that is going to receive the newly created
// ALEntry objects.
//
// wild_spec : The wild card file spec to expand into a list of
// files. Note that this string can contain multiple
// file specs, separated by commas or spaces.
//
// traverse_flag : A flag to indicate whether wild card expansion
// should traverse subdirectories.
//
// compression_level : The compression level that will be used to create
// compression engines for the new entries.
//
// RETURNS
//
// The number of entries created by the wild card expansion.
//
// DESCRIPTION
//
// It is handy to have a function that will create a bunch of ALEntry
// objects and add them to a list of your choosing. We can't do this
// in the base class of ALArchiveBase, because it doesn't know anything
// about specific storage objects or compression engines. So the
// logical place to turn is to this derived class, which does know about
// ALFile and ALMemory.
//
// The only bad thing here is that this is a static public functions,
// so it is kind of confusing. You might think that this ought to be
// a member function of ALEntryList. The problem is, we don't want
// ALEntryList to know about specific engines or compression classes,
// because then they would get linked in to any application created
// with ArchiveLib.
//
// So anyway, this function creates a bunch of new ALEntry objects,
// with the storage object being an instance of class ALFile, and the
// compression engine being an object of class ALGreenleafEngine. It
// then adds the new ALEntry to the specified ALEntryList, so you don't
// have to do any work at all.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO
ALArchive::AddWildCardFiles( ALEntryList AL_DLL_FAR & list,
const char AL_DLL_FAR *wild_spec /* = "*.*" */,
int traverse_flag /* = 0 */,
short int compression_level /* = AL_GREENLEAF_LEVEL_2 */ )
{
AL_ASSERT( wild_spec != 0, "AddWildCardFiles: null parameter for wild_spec" );
ALWildCardExpander files( wild_spec, traverse_flag );
int count = 0;
char *new_name;
while ( ( new_name = files.GetNextFile() ) != 0 ) {
new ALEntry( list,
new ALFile( new_name ),
new ALGreenleafEngine( compression_level ) );
count++;
}
return count;
}
//
// int ALArchive::MakeEntriesFromListBox( ALEntryList &list,
// HWND hDlg,
// int list_box /* = -1 */ )
//
// ARGUMENTS:
//
// list : The list that is going to get the new entries.
//
// hDlg : The handle of the dialog box that contains the list box
// control. If you aren't using a dialog box, you can pass
// the handle of the list box control directly, and set
// the list_box parameter to -1.
//
// list_box : The id of the list box control in the dialog box. If this
// parameter is set to -1, it means that hDlg doesn't refer
// to a dialog, it refers to the actual handle of a list box
// control.
//
// RETURNS
//
// The number of new entries created from the list box.
//
// DESCRIPTION
//
// This function goes through a list box, and picks out all the
// highlighted entries. It creates a new ALEntry object for each
// of the marked entires, using ALFile and ALGreenleafEngine objects.
// For purposes of orthogonality, I probably should have had a
// compression_level parameter here, but I neglected to include that.
// We could do it in the next release using a default parameter and
// nobody would even notice.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
int AL_PROTO ALArchive::
MakeEntriesFromListBox( ALEntryList AL_DLL_FAR &list,
HWND hDlg,
int list_box /* = -1 */ )
{
HWND window;
if ( list_box != -1 )
window = GetDlgItem( hDlg, (short int) list_box );
else
window = hDlg;
int count = (WORD) SendMessage( window, LB_GETSELCOUNT, 0, 0L );
if ( count == LB_ERR )
return AL_GETSEL_ERROR;
int *items = new int[ count ];
if ( items == 0 )
return AL_CANT_ALLOCATE_MEMORY;
#ifdef AL_FLAT_MODEL
if ( count != SendMessage( window, LB_GETSELITEMS, (short int) count, (LPARAM) items ) ) {
#else
if ( count != SendMessage( window, LB_GETSELITEMS, (short int) count, (LPARAM)(int _far *) items ) ) {
#endif
delete items;
return AL_GETSEL_ERROR;
}
for ( WORD i = 0 ; i < (WORD) count ; i++ ) {
WORD length = (WORD) SendMessage( window, LB_GETTEXTLEN, (short int) items[ i ], 0L );
if ( length > 0 ) {
char *name = new char[ length + 1 ];
if ( name ) {
if ( SendMessage( window, LB_GETTEXT, (short int) items[ i ], (LPARAM)( (LPSTR) name ) ) >= 0 ) {
new ALEntry( list,
new ALFile( name ),
new ALGreenleafEngine() );
}
delete name;
SendMessage( window,
LB_SETSEL,
0,
items[ i ] );
}
}
}
delete items;
return count;
}
#endif //#ifdef AL_WINDOWS_GUI

135
al/archive.h Executable file
View File

@ -0,0 +1,135 @@
/*
* ARCHIVE.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class definition for ALArchive, the
* standard archiving class derived from ALArchiveBase.
*
* ALArchive is the default archive class used in the
* library. The base class, ALArchiveBase, doesn't know which storage
* objects and compression engines to use when extracting files. (This is so
* you don't have to link in *every* storage and compression class if
* you want to create your own archive class). This derived class
* takes care of creating two different storage types, ALFile and
* ALMemory. It knows how to create two different types of
* compression engines also: ALGreenleafEngine and ALCopyEngine. All
* of this is the result of the two virtual functions that override
* the base class: CreateCompressionEngine() and CreateStorageObject().
*
* CLASS DEFINITIONS:
*
* class ALArchive
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ARCHIVE_H
#define _ARCHIVE_H
#include "arclib.h"
#if defined( __cplusplus )
#include "filestor.h"
#include "grenengn.h"
/*
* class ALArchive : public ALArchiveBase
*
* DESCRIPTION
*
* ALArchive is a class derived from ALArchiveBase. It is the
* class we use most often for standard archiving use.
*
* DATA MEMBERS
*
* None.
*
* MEMBER FUNCTIONS
*
* ALArchive(char *) : A constructor that creates the storage
* object for you.
* ALArchive(ALStorage&) : Constructor using a storage object that
* you have created.
* ~ALArchive() : Virtual destructor.
* operator new() : Memory allocation when inside a DLL.
* CreateCompressionEngine() : Virtual function that knows how to make
* ALCopyEngine and ALGreenleafEngine engines.
* CreateStorageObject() : Virtual function that knows how to make
* ALFile and ALMemory objects.
* AddWildCardFiles() : A static function used to create
* new ALEntry objects, and add them to an
* ALEntryList object.
* MakeEntriesFromListBox() : A second static function used to create
* new ALEntry objects and add them to an
* ALEntryList object.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALArchive : public ALArchiveBase {
/*
* Constructors, destructors, declarations
*/
public :
AL_PROTO ALArchive( const char AL_DLL_FAR *file_name );
AL_PROTO ALArchive( ALStorage AL_DLL_FAR &object );
virtual AL_PROTO ~ALArchive();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* As usual, I prohibit the copy constructor and assignment operator.
* They are declared here but they don't exist.
*/
protected :
AL_PROTO ALArchive( ALArchive AL_DLL_FAR & );
ALArchive AL_DLL_FAR & AL_PROTO operator=( ALArchive AL_DLL_FAR & );
/*
* Member Functions
*
* Note, these guys are used inside the Archive class for extraction.
* The may be better off protected.
*/
public :
virtual ALCompressionEngine AL_DLL_FAR * AL_PROTO CreateCompressionEngine( int engine_type );
virtual ALStorage AL_DLL_FAR * AL_PROTO CreateStorageObject( const char AL_DLL_FAR *name, int object_type );
public :
/*
* These two member functions are both static. They are in this class
* to take advantage of this classes knowledge of how to create
* ALFile and ALGreenleafEngine objects. They are used to create
* new ALEntry objects. It would be good in a future release to
* change their names to be more uniform.
*/
static int AL_PROTO
AddWildCardFiles( ALEntryList AL_DLL_FAR & list,
const char AL_DLL_FAR *pattern = "*.*",
int traverse_flag = 0,
short int compression_level = AL_GREENLEAF_LEVEL_2 );
#if defined( AL_WINDOWS_GUI )
static int AL_PROTO MakeEntriesFromListBox( ALEntryList AL_DLL_FAR &list, HWND hDlg, int list_box = -1 );
#endif
/*
* Data members, hey there aren't any!
*/
public :
AL_CLASS_TAG( _ALArchiveTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _ARCHIVE_H */

1456
al/archiveb.cpp Executable file

File diff suppressed because it is too large Load Diff

226
al/archiveb.h Executable file
View File

@ -0,0 +1,226 @@
/*
* ARCHIVEB.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class definition for class
* ALArchiveBase.
*
* CLASS DEFINITIONS:
*
* ALArchiveBase
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ARCHIVEB_H
#define _ARCHIVEB_H
#if defined( __cplusplus )
/*
* class ALArchiveBase
*
* DESCRIPTION
*
* This is the most important class definition in the library.
* ALArchiveBase defines the interface to archive objects, on disk,
* memory, or whatever. This class is a pure base class, so you
* won't ever create an instance of an ALArchiveBase object.
*
* The derived class for a given archive type has several very important
* virtual functions it has to provide. The most important two are
* CreateCompressionEngine() and CreateStorageObject(). These
* two functions are called when the directory is being read from
* a given archive. In the directory, the type of a storage object
* and the compression engine used to create it are defined as just
* plain integers. Somewhere, somebody has to look at these integers
* and create real objects based on their contents, and then maybe
* perform some initialization as well.
*
* At first glance it might seem like there is no reason the base class
* shouldn't just do all this work itself. However, there is a good reason
* not to do it this way. If the base class is designed to be a completely
* general purpose class, it would need to know how to create a Greenleaf
* compression engine, a Microsoft compression engine, and so on. It
* would also need to know how to create all different kinds of storage
* objects, probably including our demo storage objects. This would mean
* that the base ALArchiveBase class would basically have to link in our
* entire library. What is worse, if someone created a lean and mean
* derived class that only supported one storage type and one compression
* engine, they would still have to link in all that other code because
* it was referenced in the base class.
*
* So the compromise is the current hierarchy. We have a base class that
* has no links to any engines or storage objects. A user can derive
* a lean and mean class from the base class and not have to worry as much
* about code bloat. On the other hand, we have a relatively full
* featured derived class one level down, called ALArchive. It
* has the built in links to the "ordinary" object types. This way, you
* have a ready-built class that will do lots of ordinary jobs without a
* lot of fuss.
*
* DATA MEMBERS
*
* mpArchiveStorageObject : Pointer to the Archive's storage object.
* This is the ALFile, or whatever, that
* actually contains (or will contain) the
* archive.
*
* mszComment : The comment associated with this archive.
* This comment is stored on disk along with
* the archive directory.
*
* mlDirectoryOffset : The offset in the storage object to the
* archive's directory. All of the compressed
* objects in the archive are stored sequentially
* at the start of the file. The directory
* and other information starts after all of
* the objects. This data member tells us
* how to get there. Not filled in until
* an archive has actually been created.
*
* miVersion : The archive version. This version field
* refers to the format version of the archive,
* which won't necessarily be the save as
* the format of ArchiveLib.
*
* miDeleteStorageObject : If this flag is set, the storage object
* associated with the archive object will
* have its object destroyed in the
* archive destructor. This saves you
* from having to do the job explicitly
* in your code.
*
* mStatus : The only public data member, this is a
* standard ArchiveLib status object.
*
*
* MEMBER FUNCTIONS
*
* ALArchiveBase() : The only constructor.
* ~ALArchiveBase() : The virtual destructor.
* operator new() : Memory allocation operator used when
* the library is in a DLL
* AddJobs() : Protected function used to create
* CopyJobs() : Protected function used to create
* AddDirectoryEntries() : Protected function used to create, append
* CalculateJobSize() : Protected function to help monitor
* CalculateCompressedJobSize() : Protected function to help monitor
* ScanStatus() : Protected function to update status
* CreateCompressionEngine() : Virtual fn used when extracting
* CreateStorageObject() : Virtual fn used when extracting
* WriteArchiveData() : Protected fn to write part of directory
* ReadArchiveData() : Protected fn to read part of directory
* Create(ALEntryList&) : Create a new archive
* Create(ALArchiveBase&, : Create a new archive from another
* ALEntryList&)
* Append(ALEntryList&) : Add objects to archive
* Append(ALArchiveBase&, : Add objects to archive from another one
* ALEntryList&)
* Extract() : Extract objects from an archive
* Delete() : Delete objects from an archive
* GetComment() : Get the comment stored in the archive
* SetComment() : Set the comment that will be stored
* ReadDirectory() : Read the directory into an ALEntryList
* WriteDirectory() : Write the directory back out.
* GetVersion() : Get the archive's version
* GetStorageObject() : Get pointer to the archive's storage object
* FillListBox() : Fill a list box with the archive's entries
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALArchiveBase {
/*
* Constructors, destructors, declarations, and friends
*/
protected :
public :
AL_PROTO ALArchiveBase( ALStorage AL_DLL_FAR *, short int delete_in_dtor );
virtual AL_PROTO ~ALArchiveBase();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/* The copy constructor and assignment operator do not exist. */
protected :
AL_PROTO ALArchiveBase( const ALArchiveBase AL_DLL_FAR & );
ALArchiveBase AL_DLL_FAR & AL_PROTO operator=( ALArchiveBase AL_DLL_FAR &rhs );
/*
* Member functions
*
*
* Used internally, not for public access
*/
private :
int AL_PROTO AddJobs( ALEntryList AL_DLL_FAR & list );
int AL_PROTO CopyJobs( ALArchiveBase AL_DLL_FAR & source_archive,
ALEntryList AL_DLL_FAR & list );
int AL_PROTO AddDirectoryEntries( ALEntryList AL_DLL_FAR &list );
long AL_PROTO CalculateJobSize( ALEntryList AL_DLL_FAR &list );
long AL_PROTO CalculateCompressedJobSize( ALEntryList AL_DLL_FAR &list );
void AL_PROTO ScanStatus( ALEntryList AL_DLL_FAR &list );
/*
* This batch of functions are the ones that have to be created by a derived
* class. The first four are simple U/I functions that are normally used
* to print stuff on the screen when starting or finishing a compression
* or extraction. The final two provide the very important function of
* binding compression engines and object types to the archive.
*/
protected :
virtual ALCompressionEngine AL_DLL_FAR * AL_PROTO CreateCompressionEngine( int engine_type ) = 0;
virtual ALStorage AL_DLL_FAR * AL_PROTO CreateStorageObject( const char AL_DLL_FAR *name, int object_type ) = 0;
virtual int AL_PROTO WriteArchiveData();
virtual int AL_PROTO ReadArchiveData();
/*
* These functions provide the public API to an archive
*/
public :
int AL_PROTO Create( ALEntryList AL_DLL_FAR &list );
int AL_PROTO Create( ALArchiveBase AL_DLL_FAR &source_archive,
ALEntryList AL_DLL_FAR &source_list );
int AL_PROTO Append( ALEntryList AL_DLL_FAR &list );
int AL_PROTO Append( ALArchiveBase AL_DLL_FAR &source_archive,
ALEntryList AL_DLL_FAR &source_list );
int AL_PROTO Extract( ALEntryList AL_DLL_FAR &list );
int AL_PROTO Delete( ALEntryList AL_DLL_FAR &list,
ALArchiveBase AL_DLL_FAR & destination_archive );
const char AL_DLL_FAR * AL_PROTO GetComment(){ return mszComment; }
int AL_PROTO SetComment( char AL_DLL_FAR *comment );
int AL_PROTO ReadDirectory( ALEntryList AL_DLL_FAR &list );
int AL_PROTO WriteDirectory( ALEntryList AL_DLL_FAR &list );
short AL_PROTO GetVersion(){ return miVersion; }
ALStorage AL_DLL_FAR *GetStorageObject(){ return mpArchiveStorageObject; }
#if defined( AL_WINDOWS_GUI )
int AL_PROTO FillListBox( HWND hWnd, int list_box_id = -1 );
#endif
/*
* Data members
*/
protected :
ALStorage AL_DLL_FAR *mpArchiveStorageObject;
char AL_DLL_FAR *mszComment;
long mlDirectoryOffset;
short miVersion;
const short int miDeleteStorageObject;
public :
ALStatus mStatus;
AL_CLASS_TAG( _ALArchiveBaseTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _ARCHIVEB_H */

85
al/arclib.h Executable file
View File

@ -0,0 +1,85 @@
/*
* ARCLIB.H
*
* Master header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This is the master header file for Archive Library. It will include
* all header files that define base classes, but no derived classes. For
* people who don't want the massive flood of include files provided by
* AL.H, this is the answer. However, you will have to include some
* other headers, leading to some extra work.
*
* This file must be included by any module that is either a part of
* Archive Library, or part of a project that uses archive library.
*
* Defines that you should be creating in your program when using this
* product include:
*
* #define AL_USING_DLL Every module calling the AL DLL *must*
* have this defined
* #define NDEBUG Turns off assertions. Note that assertions
* defined in the debug version of the library
* won't go away just because you define this
* #define _DEBUG Turn this on to turn on some of the debugging
* features of the library. Doesn't do much
* at this time.
*
* We set up the rest of the definitions in ALDEFS.H, based on compiler
* settings that can be detected using your compiler's predefined
* macros.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _ARCLIB_H
#define _ARCLIB_H
/*
* Want to customize the workings of our library? Just define AL_CUSTOM,
* and then create your own personal version of ALCUSTOM.H. (No, we don't
* ship a copy of this header file with the library, it is for you to
* define. This is a really good way to use products like MEMCHECK or
* SmartHeap that want to insert an included file in every one of
* our source files.
*/
#if defined( AL_CUSTOM )
#include "alcustom.h"
#endif
#if defined( __cplusplus )
/* All these includes needed for various library features */
#include "iostream.h"
#include "string.h"
#include "aldefs.h"
#include "_debug.h"
/* Base classes */
#include "status.h"
#include "objname.h"
#include "storage.h"
#include "cmpengn.h"
#include "monitor.h"
#include "arcentry.h"
#include "cmpobj.h"
#include "archiveb.h"
#else /* #if defined( __cplusplus ) */
#include "alcxl.h" /* Included only if we are compiling C code, not C++ */
#endif /* #if defined( __cplusplus ) ... #else */
#endif /* ARCLIB_H */

107
al/bargraph.h Executable file
View File

@ -0,0 +1,107 @@
/*
* BARGRAPH.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* The class definition for ALBarGraph is found here.
*
* CLASS DEFINITIONS:
*
* class ALBarGraph
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _BARGRAPH_H
#define _BARGRAPH_H
#include "arclib.h"
#if defined( __cplusplus )
/*
* class ALBarGraph : public ALMonitor
*
* DESCRIPTION
*
* This is a utility class. The constructor opens a file for input,
* and keeps track of whether it was already open or not. The destructor
* will automatically close the file if it was closed when the
* ctor was invoked.
*
* DATA MEMBERS
*
* miCurrentOffset : The current offset of the bargraph, in screen
* units. Usually the bar itself is 20 characters
* long, in which case this value will be somewhere
* between 0 and 19.
*
* miBarLength : The length of the bar, defined when the
* constructor is called. This is a const member,
* which means we can leave it public.
*
* mrStream : Reference to an output stream. This is the
* stream where the bargraph gets drawn.
*
* MEMBER FUNCTIONS
*
* ALBarGraph() : The constructor.
* ~ALBarGraph() : Virtual destructor.
* Progress() : The progress routine, where the bargraph
* gets updated.
* ArchiveOperation() : The routine that gets called when files
* are opened, closed, etc.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALBarGraph : public ALMonitor {
/*
* Constructors, destructors, and friend classes
*/
public :
AL_PROTO ALBarGraph( ALMonitorType monitor_type,
ostream& stream = cout,
int bar_length = 25 );
virtual AL_PROTO ~ALBarGraph();
/*
* The copy constructor and assignment operator do not exist.
*/
protected :
ALBarGraph( const ALBarGraph& );
ALBarGraph& operator=( const ALBarGraph& );
/*
* Member functions
*/
protected :
virtual void AL_PROTO Progress( long object_so_far,
ALStorage& object );
virtual void AL_PROTO
ArchiveOperation( ALArchiveOperation operation,
ALArchiveBase *archive,
ALEntry *job );
/*
* Data Members
*/
protected :
int miCurrentOffset;
const int miBarLength;
ostream& mrStream;
public :
AL_CLASS_TAG( _ALBarGraphTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _BARGRAP_H */

204
al/cmpengn.cpp Executable file
View File

@ -0,0 +1,204 @@
//
// CMPENGN.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALCompressionEngine::operator new()
// ALCompressionEngine::ALCompressionEngine()
// ALCompressionEngine::WriteEngineData()
// ALCompressionEngine::ReadEngineData()
// ALCompressionEngine::~ALCompressionEngine()
//
// DESCRIPTION
//
// This file contains all the functions for the base class
// ALCompressionEngine. Since the base class doesn't do much,
// this is a pretty small file. See derived classes for
// excitement.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
//
// void * ALCompressionEngine::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALCompressionEngine
// object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALCompressionEngine::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALCompressionEngine::
// ALCompressionEngine( ALCompressionType compression_type_int,
// const char *compression_type_string )
//
// ARGUMENTS:
//
// compression_type_int : The enumerated constant for the compression
// type supported by this compression engine.
//
// compression_type_string : The string describing the compression engine.
//
// RETURNS
//
// None.
//
// DESCRIPTION
//
// This constructor can only be called by derived classes, and all they
// do with it is call it to set up the compression type and integer
// members. This class has a couple of pure virtual functions, so
// you can't instantiate a freestanding object.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO
ALCompressionEngine::ALCompressionEngine( ALCompressionType compression_type_int,
const char *compression_type_string )
: miCompressionType( compression_type_int ),
mszCompressionType( compression_type_string )
{
}
//
// int ALCompressionEngine::WriteEngineData( ALStorage *archive )
//
// ARGUMENTS:
//
// archive : The storage object where the engine specific data is
// going to be written.
//
// RETURNS
//
// AL_SUCCESS, or < AL_SUCCESS if something bad happens.
//
// DESCRIPTION
//
// Compression engines can write private data out to the archive
// directory to provide customization information. For example, the
// Greenleaf compression engine writes its compression level
// using this function. By default, there is no data, which is what
// this function writes out, a 0 length string.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO
ALCompressionEngine::WriteEngineData( ALStorage AL_DLL_FAR * archive )
{
return archive->WritePortableShort( 0 );
}
//
// int ALCompressionEngine::ReadEngineData( ALStorage * archive )
//
// ARGUMENTS:
//
// archive : The storage object where the engine specific data is
// going to be read in from.
//
// RETURNS
//
// AL_SUCCESS, or < AL_SUCCESS if something bad happened.
//
// DESCRIPTION
//
// Compression engines can write private data out to the archive
// directory to provide customization information. For example, the
// Greenleaf compression engine writes its compression level
// using this function. By default, no data is written out. This
// function expects to find a zero length string, and complains
// with a fatal error if it doesn't.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO
ALCompressionEngine::ReadEngineData( ALStorage AL_DLL_FAR * archive )
{
short temp;
int status = archive->ReadPortableShort( temp );
AL_ASSERT( temp == 0, "ReadEngineData: engine data not 0 length" );
return status;
}
//
// ALCompressionEngine::~ALCompressionEngine()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// None, destructor.
//
// DESCRIPTION
//
// This guy doesn't have anything to do. In the debug version of
// the library, it at least checks to be sure the object type is correct.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALCompressionEngine::~ALCompressionEngine()
{
AL_ASSERT( GoodTag(), "~ALCompressionEngine: attempt to delete invalid object" );
}

130
al/cmpengn.h Executable file
View File

@ -0,0 +1,130 @@
/*
* CPMENGN.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class declaration for ALCompressionEngine,
* the base class used by all ArchiveLib compression engines.
*
* CLASS DEFINITIONS:
*
* ALCompressionEngine
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _CMPENGN_H
#define _CMPENGN_H
#if defined( __cplusplus )
/*
* class ALOpenInputFile
*
* DESCRIPTION
*
* This header file defines the ALCompressionEngine class. It is a base
* class with pure virtual functions, so it cannot be instantiated.
* The two derived classes supplied with Archive Library at this time are
* ALGreenleafEngine, which implements a Greenleaf proprietary compression
* engine, and ALCopyEngine, which just performs straight copying.
*
* ALCompressionEngine has two public virtual functions, Compress()
* and Decompress(), which are pure here. It also provides two
* virtual protected functions which are used to store configuration
* in the archive directory.
*
* DATA MEMBERS
*
* miCompressionType : The compression type integer is what gets stored
* in the archive directory, and what the archive
* class looks at when extracting so it can figure
* out what type of compression engine to construct
* for a specific type of object.
*
* mszCompressionType : This string just describes the compression type
* in ASCII format suitable for printing or display.
*
* mStatus : A standard ArchiveLib status object, stored
* with the compression engine. Check this after
* completing a compression or decompression to
* see how things went.
*
* MEMBER FUNCTIONS
*
* ALCompressionEngine() : The constructor. Only called by the ctors for
* derived classes.
* ~ALCompressionEngine() : The virtual destructor.
* operator new() : Memory allocation operator, only gets used
* when the library is in a DLL.
* WriteEngineData() : Private virtual function used to store engine
* specific data.
* ReadEngineData() : Private virtual function used to read back
* engine specific data.
* Compress() : The compression routine. Derived classes
* have to provide their own versions of this
* function. Wouldn't be much good without it.
* Decompress() : The inverse, has to know how to undo the
* Compress() output.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALCompressionEngine {
/*
* Constructors, destructors, declarations, and friends
*/
friend class AL_CLASS_TYPE ALArchiveBase;
public :
AL_PROTO ALCompressionEngine( ALCompressionType compression_type_int,
const char AL_DLL_FAR *compression_type_string );
virtual AL_PROTO ~ALCompressionEngine();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* The copy constructor and assignment operator do not exist. I define
* them here to prevent the compiler from creating default versions.
*/
protected :
AL_PROTO ALCompressionEngine( ALCompressionEngine AL_DLL_FAR & );
ALCompressionEngine AL_DLL_FAR & AL_PROTO operator=( ALCompressionEngine AL_DLL_FAR & rhs );
/*
* Member functions
*/
protected :
virtual int AL_PROTO WriteEngineData( ALStorage AL_DLL_FAR * archive );
virtual int AL_PROTO ReadEngineData( ALStorage AL_DLL_FAR * archive );
public :
virtual int AL_PROTO Compress( ALStorage AL_DLL_FAR &input_object,
ALStorage AL_DLL_FAR &output_object ) = 0;
virtual int AL_PROTO Decompress( ALStorage AL_DLL_FAR &input_object,
ALStorage AL_DLL_FAR &output_object,
long compressed_length = -1 ) = 0;
/*
* Data members
*/
public :
const ALCompressionType miCompressionType;
const char AL_DLL_FAR *mszCompressionType;
ALStatus mStatus;
AL_CLASS_TAG( _ALCompressionEngineTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _CMPENGN_H */

361
al/cmpobj.cpp Executable file
View File

@ -0,0 +1,361 @@
//
// CMPOBJ.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALCompressedObject::operator new()
// ALCompressedObject::ALCompressedObject()
// ALCompressedObject::~ALCompressedObject()
// ALCompressedObject::Insert()
// ALCompressedObject::Extract()
// ALCompressedObject::WriteHeaderData()
// ALCompressedObject::ReadHeaderData()
//
// DESCRIPTION
//
// This file contains all the support code for the ALCompressedObject
// class. This class is sort of a poor-man's archive, with just one
// file, no flexibility, and super-low overhead.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "_openf.h"
//
// void * ALCompressedObject::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALCompressedObject
// object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALCompressedObject::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALCompressedObject::
// ALCompressedObject( ALStorage AL_DLL_FAR & storage_object,
// ALCompressionEngine AL_DLL_FAR & compression_engine )
//
// ARGUMENTS:
//
// storage_object : A reference to the storage object that is going
// to get the compressed data.
//
// compression_engine : A reference to the compression engine that will
// be used to insert an object or extract an object.
//
// RETURNS
//
// A constructor, you don't get a return.
//
// DESCRIPTION
//
// A compressed object is a storage object that gets a single compressed
// object packed into it. You get to call Insert() or Extract(), to
// put the object in or take it out. Compressed objects don't get all
// the fancy options that Archives do. For example, you have to know in
// advance what sort of compression engine and storage object you are
// going to use to put things in and take things out. You don't get to
// store comments or time date stamps, or anything like that.
//
// The one piece of flexibility you do get the ALCompressedObject is
// the ability to derive a new class from this base, then use the
// new class to write some custom data out to the object.
//
// This constructor stores references to the object being used to hold the
// compressed data, and the engine being used to pack and unpack it.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALCompressedObject::
ALCompressedObject( ALStorage AL_DLL_FAR & storage_object,
ALCompressionEngine AL_DLL_FAR & compression_engine )
{
mpCompressionEngine = &compression_engine;
mpStorageObject = &storage_object;
}
//
// ALCompressedObject::~ALCompressedObject()
//
// ARGUMENTS:
//
// None, destructor.
//
// RETURNS
//
// None, destructor.
//
// DESCRIPTION
//
// This destructor has nothing important to do. The debug version
// checks the object type for validity, but that's it.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
AL_PROTO ALCompressedObject::~ALCompressedObject()
{
AL_ASSERT_OBJECT( this, ALCompressedObject, "~ALCompressedObject" );
}
//
// int ALCompressedObject::Insert( ALStorage &input_object )
//
// ARGUMENTS:
//
// input_object : A storage object that is going to be inserted into
// the compressed object.
//
// RETURNS
//
// AL_SUCCESS if everything worked properly, or < AL_SUCCESS if an
// error was encountered.
//
// DESCRIPTION
//
// The compressed object has this format:
//
// long uncompressed_size
// long compressed_size
// DWORD crc_32
// Any data from derived classes
// unsigned char data[]
//
// Writing all this out is pretty straightforward, although you might
// note that it is going to require at least one seek() back to the
// start of the compressed object after the compression is done.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALCompressedObject::Insert( ALStorage AL_DLL_FAR &input_object )
{
AL_ASSERT_OBJECT( this, ALCompressedObject, "Insert" );
AL_ASSERT_OBJECT( &input_object, ALStorage, "Insert" );
if ( mStatus < AL_SUCCESS )
return mStatus;
//
// Here is where we open the input and the output.
//
ALOpenFiles files( input_object, *mpStorageObject );
//
// We first write out the uncompressed size, which we already know. We
// then save the current position, and write placeholder longs out for
// what will become the compressed size and the CRC-32.
//
mpStorageObject->WritePortableLong( input_object.GetSize() );
long saved_pos = mpStorageObject->Tell();
mpStorageObject->WritePortableLong( 0xfedcba98L ); //Temporary
mpStorageObject->WritePortableLong( 0x01234567L ); //Temporary
//
// If a derived class has any header data to write out, this is where it
// will be performed. The base class writes 0 bytes here.
//
WriteHeaderData();
long start = mpStorageObject->Tell();
//
// Next, perform the compression. Once that is done we can calculate
// the compressed size. The CRC-32 will have been calculated on the fly
// as the compression was performed.
//
mpCompressionEngine->Compress( input_object, *mpStorageObject );
long compressed_size = mpStorageObject->Tell() - start;
if ( mpCompressionEngine->mStatus < 0 )
return mStatus = mpCompressionEngine->mStatus;
//
// Go back to the spot we remembered, and write out the compressed
// size and the CRC. At that point, the compressed object is complete.
//
mpStorageObject->Seek( saved_pos );
mpStorageObject->WritePortableLong( compressed_size );
mpStorageObject->WritePortableLong( ~input_object.GetCrc32() );
if ( mpStorageObject->mStatus < 0 )
return mStatus = mpStorageObject->mStatus;
return AL_SUCCESS;
}
//
// int ALCompressedObject::Extract( ALStorage &output_object )
//
// ARGUMENTS:
//
// output_object : The storage object that is going to receive the
// extracted data from the compressed object.
//
// RETURNS
//
// AL_SUCCESS, or < AL_SUCCESS if an error occurs.
//
// DESCRIPTION
//
// Extracting the data to a new storage object is easy. We read in
// all the data so that we can do a little error checking along the
// way, but that's all.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALCompressedObject::Extract( ALStorage AL_DLL_FAR &output_object )
{
long compressed_length;
long crc32;
AL_ASSERT_OBJECT( this, ALCompressedObject, "Extract" );
AL_ASSERT_OBJECT( &output_object, ALStorage, "Extract" );
if ( mStatus < AL_SUCCESS )
return mStatus;
//
// Open the input and output files.
//
ALOpenFiles files( *mpStorageObject, output_object );
//
// Now read in all the data stored at the start of the object,
// including any header data created by derived classes. If we are
// using the base class, there won't be any additional data bytes there.
//
mpStorageObject->ReadPortableLong( output_object.mlSize );
mpStorageObject->ReadPortableLong( compressed_length );
mpStorageObject->ReadPortableLong( crc32 );
ReadHeaderData();
if ( mpStorageObject->mStatus < 0 )
return mStatus = mpStorageObject->mStatus;
//
// Extract the data and store it in the storage object specified
// as an argument.
//
if ( mpCompressionEngine->Decompress( *mpStorageObject,
output_object,
compressed_length ) < 0 )
return mStatus = mpCompressionEngine->mStatus;
//
// A little error checking leads to an error return if things didn't
// go well, or AL_SUCCESS if things did.
//
if ( mpStorageObject->mStatus < 0 )
return mStatus = mpStorageObject->mStatus;
if ( crc32 != ~output_object.GetCrc32() )
return mStatus.SetError( AL_CRC_ERROR,
"CRC32 differs between %s and %s",
mpStorageObject->mName.GetName(),
output_object.mName.GetName() );
return AL_SUCCESS;
}
//
// int ALCompressedObject::WriteHeaderData()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, always.
//
// DESCRIPTION
//
// Derived classes can override this function and use it to add
// additional data bytes to the header of a compressed object. Note
// that this data does not have to be written out in any particular
// format, we have no portability concerns here. It is up to the
// derived class to insure that the data is written in an internally
// consistent format so that ReadHeaderData() can always position the
// file pointer to the correct start of data.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALCompressedObject::WriteHeaderData()
{
return AL_SUCCESS;
}
//
// int ALCompressedObject::ReadHeaderData()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, always.
//
// DESCRIPTION
//
// Derived classes can override this function and use it to read
// additional data bytes from the header of a compressed object. Note
// that this data does not have to be written out in any particular
// format, we have no portability concerns here. It is up to the
// derived class to insure that the data is written in an internally
// consistent format so that ReadHeaderData() can always position the
// file pointer to the correct start of data.
//
// REVISION HISTORY
//
// May 23, 1994 1.0A : First release
//
int AL_PROTO ALCompressedObject::ReadHeaderData()
{
return AL_SUCCESS;
}

120
al/cmpobj.h Executable file
View File

@ -0,0 +1,120 @@
/*
* CMPOBJ.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class definition for ALCompressedObject.
*
* CLASS DEFINITIONS:
*
* ALCompressedObject
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _CMPOBJ_H
#define _CMPOBJ_H
#if defined( __cplusplus )
/*
* class ALCompressedObject
*
* DESCRIPTION
*
* This is the class definition for ALCompressedObject. A compressed
* object is a very simple artifact that contains some compressed data,
* a checksum, and a couple of length variables. No comments, no engine
* data, no archive data, nothing else. This give this type of object
* a very low overhead. It also assumes that when you create a compressed
* object using a storage object and a compression engine that you will
* know what type of storage object and compression engine to use when
* expanding it.
*
* If you decide you want to add some private data to your compressed
* object, it isn't hard. Just derive a new class, and implement the
* two virtual functions defined here to read and write your own private
* data during compression and decompression.
*
* DATA MEMBERS
*
* mpCompressionEngine : A pointer to the compression engine that will
* be used by this object. This is assigned when
* the object is created, and used to insert or
* extract objects.
*
* mpStorageObject : A pointer to the storage object where this
* object will live.
*
* mStatus : A standard ArchiveLib status object.
*
* MEMBER FUNCTIONS
*
* ALCompressedObject() : The only constructor for ALCompressedObject.
* ~ALCompressedObject() : The virtual destructor.
* operator new() : Memory allocation operator, used in DLL only.
* WriteHeaderData() : Virtual function to allow for storage of
* customized data in the object header.
* ReadHeaderData() : The virtual complement to the previous function,
* lets you read in some customized data.
* Insert() : Insert a single storage object into the Compressed
* object.
* Extract() : Extract the storage object from the Compressed
* object.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALCompressedObject {
/*
* Constructors, destructors, declarations, friends
*/
public :
AL_PROTO ALCompressedObject( ALStorage AL_DLL_FAR & storage_object,
ALCompressionEngine AL_DLL_FAR & engine );
virtual AL_PROTO ~ALCompressedObject();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Define the copy constructor and assignment operator here, that way
* the compiler won't attempt to.
*/
protected :
AL_PROTO ALCompressedObject( ALCompressedObject AL_DLL_FAR & );
ALCompressedObject AL_DLL_FAR & AL_PROTO operator = ( ALCompressedObject AL_DLL_FAR & );
/*
* Member functions
*/
protected :
virtual int AL_PROTO WriteHeaderData();
virtual int AL_PROTO ReadHeaderData();
public :
int AL_PROTO Insert( ALStorage AL_DLL_FAR &input_object );
int AL_PROTO Extract( ALStorage AL_DLL_FAR &output_object );
/*
* Data members
*/
protected :
ALCompressionEngine AL_DLL_FAR *mpCompressionEngine;
ALStorage AL_DLL_FAR *mpStorageObject;
public :
ALStatus mStatus;
AL_CLASS_TAG( _ALCompressedObjectTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _CMPOBJ_H */

241
al/copyengn.cpp Executable file
View File

@ -0,0 +1,241 @@
//
// COPYENGN.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALCopyEngine::operator new()
// ALCopyEngine::ALCopyEngine()
// ALCopyEngine::~ALCopyEngine()
// ALCopyEngine::Compress()
// ALCopyEngine::Decompress()
//
// DESCRIPTION
//
// This file contains all the source code for the class ALCopyEngine.
// The copy engine just does a straight binary copy, so it is pretty
// simple. Note that it doesn't have to overload the routines to
// read and write the engine data in the archive directory. This is
// because it has nothing to write.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "copyengn.h"
#include "_openf.h"
//
// void * ALCopyEngine::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The amount of storage that needs to be allocated for
// this object.
//
// RETURNS
//
// A pointer to the storage.
//
// DESCRIPTION
//
// When using the DLL version of ArchiveLib, it is a good idea to
// allocate the storage for objects from inside the DLL, since they
// will be freed inside the DLL. If we don't have the new operator
// for a class, its storage will be allocated from the EXE before
// the constructor code is called. Then, when it is time to free
// the storage, the delete operator will be called inside the DLL.
// Not good, right?
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 21, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALCopyEngine::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALCopyEngine::ALCopyEngine()
//
// ARGUMENTS:
//
// None, constructor.
//
// RETURNS
//
// Nothing, this is a constructor.
//
// DESCRIPTION
//
// The copy engine doesn't have to store any data, because it just
// performs a straight binary copy, without any frills. Because of
// this simplicity, it doesn't have any data members to initialize.
// The only thing it does initialize is the base class, with the
// appropriate enum value and string identifier.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALCopyEngine::ALCopyEngine()
: ALCompressionEngine( AL_COMPRESSION_COPY, "Binary copy" )
{
}
//
// ALCopyEngine::~ALCopyEngine()
//
// ARGUMENTS:
//
// None, destructor.
//
// RETURNS
//
// Nothing, destructor.
//
// DESCRIPTION
//
// The destructor has absolutely nothing to do. In the debug
// versions of the library, the dtor checks to be sure that it
// is operating on the right type of object.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALCopyEngine::~ALCopyEngine()
{
AL_ASSERT( GoodTag(), "~ALCopyEngine: Attempt to delete invalid object" );
}
//
// int ALCopyEngine::Compress( ALStorage &input, ALStorage &output )
//
// ARGUMENTS:
//
// input : A reference to the input storage object.
//
// output : A reference to the output storage object.
//
// RETURNS
//
// AL_SUCCESS, or < AL_SUCCESS if something bad happens.
//
// DESCRIPTION
//
// This is ostensibly a compression engine, but really all it does
// is copy input directly to the output. The most exciting thing it
// does during the entire process is initialize CRC checking.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALCopyEngine::Compress( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output )
{
//
// Open the input and output files, and initialize CRC 32 checking.
//
ALOpenFiles files( input, output );
input.InitCrc32();
//
// Now read all the data from the input file, and write it to the
// output file.
//
int c;
for ( ; ; ) {
c = input.ReadChar();
if ( c < 0 )
break;
output.WriteChar( c );
}
//
// Finally, check on the error status codes, then return.
//
if ( input.mStatus < AL_SUCCESS )
return mStatus = input.mStatus;
if ( output.mStatus < AL_SUCCESS )
return mStatus = output.mStatus;
return mStatus;
}
//
// int ALCopyEngine::Decompress( ALStorage &input,
// ALStorage &output,
// long length )
//
// ARGUMENTS:
//
// input : A reference to the storage object containing the
// compressed data.
//
// output : A reference to the storage object that is going to receive
// the uncompressed data.
//
// length : The number of byte in the uncompressed image.
//
// RETURNS
//
// AL_SUCCESS if things went properly, error code < AL_SUCCESS if
// a problem occurred.
//
// DESCRIPTION
//
// This is a decompression routine, but really it just performs a
// straight binary copy of input to output. This is the copy engine you
// use when you just want to copy/archive files, and aren't worried
// about saving disk space.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALCopyEngine::Decompress( ALStorage AL_DLL_FAR & input,
ALStorage AL_DLL_FAR & output,
long length )
{
ALOpenFiles files( input, output );
output.InitCrc32();
int c;
// if ( length == -1 )
// return SetError( NEED_LENGTH,
// "The copy engine requires a length parameter when "
// "decompressing" );
for ( ; length != 0 ; length-- ) {
c = input.ReadChar();
if ( c < 0 )
break;
output.WriteChar( c );
}
if ( input.mStatus < AL_SUCCESS )
return mStatus = input.mStatus;
if ( output.mStatus < AL_SUCCESS )
return mStatus = output.mStatus;
return mStatus;
}

93
al/copyengn.h Executable file
View File

@ -0,0 +1,93 @@
/*
* COPYENGN.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class definition for the derived
* class ALCopyEngine.
*
* CLASS DEFINITIONS:
*
* ALCopyEngine
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _COPYENG_H
#define _COPYENG_H
#include "arclib.h"
#if defined( __cplusplus )
#include "cmpengn.h"
#include "storage.h"
/*
* class ALOpenInputFile
*
* DESCRIPTION
*
* ALCopyEngine is a full fledged compression engine. It just
* copies files from input to output, instead of doing something
* exciting like making them smaller. Its principal virtue is that it
* is very fast. If you are packing a bunch of files into an archive,
* and don't particularly need to compress them, you can use an instance of
* ALCopyEngine and get your work done quickly.
*
* DATA MEMBERS
*
* None.
*
* MEMBER FUNCTIONS
*
* ALCopyEngine() : The one and only constructor.
* ~ALCopyEngine() : The virtual destructor.
* operator new() : Memory allocation operator, only used when the
* library is in a DLL.
* Compress() : The virtual compression function.
* Decompress() : The virtual decompression function.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALCopyEngine : public ALCompressionEngine {
/*
* Constructors, destructors, declarations, friends
*/
public :
AL_PROTO ALCopyEngine();
virtual AL_PROTO ~ALCopyEngine();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Member functions
*/
public :
virtual int AL_PROTO Compress( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output );
virtual int AL_PROTO Decompress( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output,
long compressed_length = -1 );
/*
* Data members
*/
public :
AL_CLASS_TAG( _ALCompressedObjectTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _COPYENG_H */

956
al/cxl_arch.cpp Executable file
View File

@ -0,0 +1,956 @@
//
// CXL_ARCH.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALArchiveExtract()
// ALArchiveCreate()
// ALArchiveCreateFromArchive()
// ALArchiveAppend()
// ALArchiveAppendFromArchive()
// ALArchiveReadDirectory()
// ALArchiveWriteDirectory()
// ALArchiveDelete()
// ALArchiveSetComment()
// ALArchiveGetComment()
// ALArchiveGetCommentVB()
// ALArchiveGetStorage()
// ALArchiveFillListBoxWindow()
// ALArchiveFillListBoxDialog()
// deleteALArchive()
// ALArchiveSetError()
// ALArchiveGetStatusCode()
// ALArchiveGetStatusString()
// ALArchiveGetStatusStringVB()
// ALArchiveGetStatusDetail()
// ALArchiveGetStatusDetailVB()
// ALArchiveGetVersion()
//
// DESCRIPTION
//
// This file contains all the C translation layer routines for the
// member functions in ALArchiveBase. Note that we shorten the name
// of the base class to ALArchive here.
//
// Most of the descriptions in this file of the routines are going
// to be pretty skimpy. After all, there isn't much code to look
// at here anyway. For detailed descriptions, you will want to
// look in ARCHIVEB.CPP for the C++ archive base class member functions.
//
// The one thing all these functions do have in common is that they
// perform type checking on the arguments passed from C or VB.
//
// REVISION HISTORY
//
// May 22, 1994 2.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" int ALArchiveExtract( hALArchive this_object,
// hALEntryList list )
//
// ARGUMENTS:
//
// this_object : The handle of (pointer to) an ALArchiveBase object.
//
// list : The handle of (pointer to) an ALEntryList object.
//
// RETURNS
//
// A status code, AL_SUCCESS or < AL_SUCCESS in case of an error.
//
// DESCRIPTION
//
// This is the wrapper function for ALArchiveBase::Extract(). See the
// function in ARCHIVEB.CPP for more details.
//
// REVISION HISTORY
//
// May 22, 1994 2.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveExtract( hALArchive this_object, hALEntryList list )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveExtract" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveExtract" );
return ((ALArchiveBase *) this_object )->Extract( *( (ALEntryList *) list ) );
}
//
// extern "C" int ALArchiveCreate( hALArchive this_object,
// hALEntryList list )
//
// ARGUMENTS:
//
// this_object : The handle of (pointer to) an ALArchiveBase object.
//
// list : The handle of (pointer to) an ALEntryList object.
//
// RETURNS
//
// AL_SUCCESS for successful creation, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function that supports the
// ALArchiveBase::Create(ALEntryList&) function. For details on the
// internals, see ARCHIVEB.CPP. Note that the two arguments
// are checked for correct type. The second version of
// ALArchiveBase::Create() is found below.
//
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveCreate( hALArchive this_object, hALEntryList list )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveCreate" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveCreate" );
return ((ALArchiveBase *) this_object )->Create( *( (ALEntryList *) list ) );
}
//
// extern "C" int ALArchiveCreateFromArchive( hALArchive this_object,
// hALArchive input_archive,
// hALEntryList list )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// This is the archive that is going to be created.
//
// input_archive : A handle for (pointer to) an ALArchiveBase object.
// This is the archive that contains the compressed
// objects that are going to be inserted.
//
// list : A handle for (pointer to) an ALEntryList object.
// It will contains descriptions of all the compressed
// objects in input_archive that are going to be inserted
// into this_object.
//
// RETURNS
//
// AL_SUCCESS for successful creation, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::Create(ALArchiveBase&,ALEntrylist&).
// For details on how the member function actually works, take a
// gander at ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveCreateFromArchive( hALArchive this_object, hALArchive input_archive, hALEntryList list )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveCreateFromArchive" );
AL_ASSERT_OBJECT( input_archive, ALArchiveBase, "ALArchiveCreateFromArchive" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveCreateFromArchive" );
return ((ALArchiveBase *) this_object )->Create( *(ALArchiveBase *)input_archive, *( (ALEntryList *) list ) );
}
//
// extern "C" int ALArchiveAppend( hALArchive this_object,
// hALEntryList list )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// This is the archive that is going to have new objects
// appended to it.
//
// list : A handle for (pointer to) an ALEntryList object.
// It will contains descriptions of all the standalone
// objects that are going to be inserted into this_object.
//
// RETURNS
//
// AL_SUCCESS for a successful append, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::Append(ALEntrylist&). For details on how the member
// function actually works, see ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveAppend( hALArchive this_object, hALEntryList list )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveAppend" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveAppend" );
return ((ALArchiveBase *) this_object )->Append( *( (ALEntryList *) list ) );
}
//
// extern "C" int ALArchiveAppendFromArchive( hALArchive this_object,
// hALArchive input_archive,
// hALEntryList list )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// This is the archive that is going to get new stuff
// appended to it.
//
// input_archive : A handle for (pointer to) an ALArchiveBase object.
// This is the archive that contains the compressed
// objects that are going to be added to this_object.
//
// list : A handle for (pointer to) an ALEntryList object.
// It will contains descriptions of all the compressed
// objects in input_archive that are going to be added
// to this_object.
//
// RETURNS
//
// AL_SUCCESS for a successful append, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::Append(ALArchiveBase&,ALEntrylist&).
// For details on how the member function actually works, take a
// look at ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveAppendFromArchive( hALArchive this_object, hALArchive input_archive, hALEntryList list )
{
AL_ASSERT( ((ALArchiveBase *) this_object)->GoodTag(),
"archive argument is not a valid ALArchiveBase" );
AL_ASSERT( ((ALArchiveBase *) input_archive)->GoodTag(),
"input archive argument is not a valid ALArchiveBase" );
AL_ASSERT( ((ALEntryList *) list)->GoodTag(),
"list argument is not a valid ALEntryList" );
return ((ALArchiveBase *) this_object )->Append( *(ALArchiveBase *) input_archive, *( (ALEntryList *) list ) );
}
//
// extern "C" int ALArchiveReadDirectory( hALArchive this_object,
// hALEntryList list )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// This is the archive that is going to have its directory
// read into the list.
//
// list : A handle for (pointer to) an ALEntryList object.
// The list is going to receive descriptions for all
// of the compressed objects stored in the archive.
//
// RETURNS
//
// AL_SUCCESS for a successful read, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::ReadDirectory(ALEntrylist&). For details on how
// the member function actually works, take a look at ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveReadDirectory( hALArchive this_object, hALEntryList list )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveReadDirectory" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveReadDirectory" );
return ((ALArchiveBase *) this_object )->ReadDirectory( *( (ALEntryList *) list ) );
}
//
// extern "C" int ALArchiveWriteDirectory( hALArchive this_object,
// hALEntryList list )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// This is the archive that is going to get the new copy
// of the directory written out to it.
//
// list : A handle for (pointer to) an ALEntryList object.
// The list contains descriptions for all
// of the compressed objects stored in the archive.
//
// RETURNS
//
// AL_SUCCESS for a successful write, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::WriteDirectory(ALEntrylist&). For details on how
// the member function actually works, take a look at ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveWriteDirectory( hALArchive this_object, hALEntryList list )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveWriteDirectory" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveWriteDirectory" );
return ( (ALArchiveBase *) this_object )->WriteDirectory( *( (ALEntryList *) list ) );
}
//
// extern "C" int ALArchiveDelete( hALArchive this_object,
// hALEntryList list,
// hALArchive output_archive )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// This archive will have some of its compressed
// objects copied to the output archive. It will
// then be renamed to a backup name, with its contents
// unchanged.
//
// list : A handle for (pointer to) an ALEntryList object.
// All of the marked objects in the list will be
// deleted (by not copying) from the output_archive.
//
// output_archive: This archive will get some of the files from
// this_object. It will then be renamed to have the
// original name of this_object.
//
// RETURNS
//
// AL_SUCCESS for a successful deletion, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::Delete(). For details on how the member function
// actually works, take a look at ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveDelete( hALArchive this_object,
hALEntryList list,
hALArchive output_archive )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveDelete" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveDelete" );
AL_ASSERT_OBJECT( output_archive, ALArchiveBase, "IALArchiveDelete" );
return ((ALArchiveBase *) this_object )->Delete( *( (ALEntryList *) list ), *( (ALArchiveBase *) output_archive ) );
}
//
// extern "C" int ALArchiveSetComment( hALArchive this_object,
// char *comment )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We are going to change the comment in archive, although
// the new comment won't be stored in the archive until
// we do a WriteDirectory().
//
// comment : An ASCII string that will be the new comment. Note
// that this gets passed properly from both C and VB.
// RETURNS
//
// AL_SUCCESS for a successful update, < AL_SUCCESS for a failure.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::SetComment(). For details on how the member function
// actually works, take a look at ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveSetComment( hALArchive this_object, char *comment )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveSetComment" );
if ( comment == 0 )
comment = "";
return ( (ALArchiveBase *) this_object )->SetComment( comment );
}
//
// extern "C" char * ALArchiveGetComment( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We are going to get the comment from this archive.
// Note that there won't be any comment here until
// you have performed a ReadDirectory().
// RETURNS
//
// A pointer to the new string, which is stored in the ArchiveBase
// object. You can print it, copy it, or whatever, but don't you
// dare change it.
//
// DESCRIPTION
//
// This is the C wrapper function for the C++ function
// ALArchiveBase::GetComment(). For details on how the member function
// actually works, take a look at ARCHIVEB.CPP. Very important
// to note that this is for C ONLY! VB strings take a special
// return type, see the next function.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char * AL_FUNCTION ALArchiveGetComment( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveGetComment" );
return (char *) ( (ALArchiveBase *) this_object )->GetComment();
}
//
// extern "C" long ALArchiveGetCommentVB( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We are going to get the comment from this archive.
// Note that there won't be any comment here until
// you have performed a ReadDirectory().
// RETURNS
//
// A pointer (or something, I'm not really sure) to a VB string.
// The string is created inside VB.EXE (I think), by the
// special string creation function.
//
// DESCRIPTION
//
// This is the VB wrapper function for the C++ function
// ALArchiveBase::GetComment(). For details on how the member function
// actually works, take a look at ARCHIVEB.CPP. Very important
// to note that this is for VB ONLY! We have to do something
// special to translate a C character string to a VB native string
// type, and the two are not interchangeable!!!
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting. The return result from the
// function has to get ground through the VB string maker before we
// have something good to return.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALArchiveGetCommentVB( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveGetCommentVB" );
const char _far *status = ( (ALArchiveBase *) this_object )->GetComment();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif
//
// extern "C" hALStorage ALArchiveGetStorage( hALArchive hArchive )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// we are going to get the handle for (pointer to)
// the underlying storage object that contains the
// archive.
// RETURNS
//
// A handle for (pointer to) an ALStorage object. I think in theory
// it isn't possible for this guy to return a 0.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::GetStorageObject(). For details on how the member
// function actually works, take a look at ARCHIVEB.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALStorage AL_FUNCTION ALArchiveGetStorage( hALArchive this_object )
{
AL_ASSERT( ((ALArchiveBase *) this_object)->GoodTag(),
"archive argument is not a valid ALArchiveBase" );
ALStorage *obj = ((ALArchiveBase *) this_object)->GetStorageObject();
return (hALStorage) obj;
}
//
// extern "C" int ALArchiveFillListBoxWindow( hALArchive this_object,
// HWND window )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We are going to fill a list box with the names
// of the storage objects in this archive.
//
// window : The window handle (not the ID!!!) of a list box.
//
// RETURNS
//
// AL_SUCCESS for good things, <AL_SUCCESS for bad things.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::FillListBox(). For details on how the member
// function actually works, take a look at ARCHIVEB.CPP. Note that
// even though there is only a single C++ function, we have two
// different incarnations for the wrapper function. One that uses
// a window handle by itself, and another that uses a dialog handle
// /list box id combo to identify the list box.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
extern "C" int AL_FUNCTION ALArchiveFillListBoxWindow( hALArchive this_object,
HWND window )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveFillListBoxWindow" );
return ((ALArchiveBase *) this_object)->FillListBox( window );
}
//
// extern "C" int ALArchiveFillListBoxDialog( hALArchive this_object,
// HWND dialog,
// int id );
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We are going to fill a list box with the names
// of the storage objects in this archive.
//
// window : The window handle of a dialog box that contains
// the list box that will be filled.
//
// id : The id of the list box control in the dialog.
//
// RETURNS
//
// AL_SUCCESS for good things, <AL_SUCCESS for bad things.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::FillListBox(). For details on how the member
// function actually works, take a look at ARCHIVEB.CPP. Note that
// even though there is only a single C++ function, we have two
// different incarnations for the wrapper function. One that uses
// a window handle by itself, and another that uses a dialog handle
// /list box id combo to identify the list box.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveFillListBoxDialog( hALArchive this_object,
HWND dialog,
int id )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveFillListBoxDialog" );
return ((ALArchiveBase *) this_object )->FillListBox( dialog, id );
}
#endif
//
// extern "C" void deleteALArchive( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We destroy it in this function.
//
// RETURNS
//
// No returns from destructors.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALArchiveBase::~ALArchiveBase(). For details on how the member
// function actually works, take a look at ARCHIVEB.CPP.
//
// Note that this destructor function is virtual, and should be called
// to destroy any derived classes as well.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION deleteALArchive( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "deleteALArchive()" );
delete (ALArchiveBase *) this_object;
}
//
// extern "C" int ALArchiveSetError( hALArchive this_object,
// int error,
// char *text )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We are going to set the archive's status member
// so that it is in an error state.
//
// error : The error code to apply to the object. Values from
// ALDEFS.H are good, but it really doesn't matter as
// long as you use a negative number.
//
// text : The text of the error message you want to associate with
// this error.
//
// RETURNS
//
// Returns the error code that you passed it.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ member function
// ALName::SetError(), as applied to an ALArchive object. For more
// details on how the function actually works, check out OBJNAME.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveSetError( hALArchive this_object,
int error,
char AL_DLL_FAR *text )
{
AL_ASSERT_OBJECT( this_object, ALArchive, "ALArchiveSetError" );
( (ALArchive *) this_object )->mStatus.SetError( error, text );
return error;
}
//
// extern "C" int ALArchiveGetStatusCode( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
//
// RETURNS
//
// An integer that contains the current status code for the object.
// Note that values of < 0 always indicate an error conditions.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALName::GetStatusCode() as implemented for objects of type
// ALArchiveBase. For details on how the member
// function actually works, take a look at OBJNAME.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveGetStatusCode( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase , "ALArchiveGetStatusCode" );
return ( (ALArchiveBase *) this_object )->mStatus.GetStatusCode();
}
//
// extern "C" char *ALArchiveGetStatusString( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We want to get the string translation of the error
// code for this object.
//
// RETURNS
//
// Always returns a pointer to a short string translation of the
// current error code.
//
// DESCRIPTION
//
// This is the C wrapper function for the C++ function
// ALName::GetStatusString(), as implemented for class ALArchiveBase.
// Note that we need a completely different function return strings
// to VB programmers.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALArchiveGetStatusString( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveGetStatusString" );
const char *status = ( (ALArchiveBase *) this_object )->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" long ALArchiveGetStatusStringVB( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We want to get the string translation of the error
// code for this object.
//
// RETURNS
//
// Always returns a VB handle (pointer?) to a short string translation of
// the current error code for the ALArchiveBase object.
//
// DESCRIPTION
//
// This is the VB wrapper function for the C++ function
// ALName::GetStatusString(), as implemented for class ALArchiveBase.
// Note that we need a completely different function to return strings
// to C programmers. In this case, we use a special VB translation routine
// to convert a C string to one that is nice and easy for VB to use.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALArchiveGetStatusStringVB( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveGetStatusStringVB" );
const char _far *status = ( (ALArchiveBase *) this_object )->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif
//
// extern "C" char * ALArchiveGetStatusDetail( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We want to get the detailed string describing this
// object's current status.
//
// RETURNS
//
// Always returns a pointer to a status detail message.
//
// DESCRIPTION
//
// This is the C wrapper function for the C++ function
// ALName::GetStatusDetail(), as implemented for class ALArchiveBase.
// Note that we need a completely different function to return strings
// to VB programmers.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALArchiveGetStatusDetail( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveGetStatusDetail" );
const char *status = ( (ALArchiveBase *) this_object )->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" long ALArchiveGetStatusDetailVB( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We want to get the detailed status message for
// this object.
//
// RETURNS
//
// Always returns a VB handle (pointer?) to a translation of
// the current status detail for the ALArchiveBase object.
//
// DESCRIPTION
//
// This is the VB wrapper function for the C++ function
// ALName::GetStatusDetail(), as implemented for class ALArchiveBase.
// Note that we need a completely different function to return strings
// to C programmers. In this case, we use a special VB translation routine
// to convert a C string to one that is nice and easy for VB to use.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALArchiveGetStatusDetailVB( hALArchive archive )
{
AL_ASSERT_OBJECT( archive, ALArchiveBase, "ALArchiveGetStatusDetailVB" );
const char _far *status = ( (ALArchiveBase *) archive)->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif
//
// extern "C" int ALArchiveGetVersion( hALArchive this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALArchiveBase object.
// We want to get the version of this archive.
//
// RETURNS
//
// Always returns the integer version of the object. The current version
// is 0x100. Note that this is the version of the Archive, not of the
// library.
//
// DESCRIPTION
//
// This is the VB/C wrapper function for the C++ function
// ALArchiveBase::GetVersion(). For details on this function,
// take a look at source file ARCHIVEB.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveGetVersion( hALArchive this_object )
{
AL_ASSERT_OBJECT( this_object, ALArchiveBase, "ALArchiveGetVersion" );
return ( (ALArchiveBase *) this_object )->GetVersion();
}

442
al/cxl_cmpo.cpp Executable file
View File

@ -0,0 +1,442 @@
//
// CXL_CMPO.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALCompressed()
// deleteALCompressed()
// ALCompressedInsert()
// ALCompressedExtract()
// ALCompresssedGetStatusCode()
// ALCompressedSetError()
// ALCompressedGetStatusString()
// ALCompressedGetStatusStringVB()
// ALCompressedGetStatusDetail()
// ALCompressedGetStatusDetailVB()
//
// DESCRIPTION
//
// This file contains all the C/VB translation routines to support
// operations on ALCompressedObject objects. These routines are all
// going to be short and sweet, so don't expect too much explanation.
// The meat can all be found in CMPOBJ.CPP
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" hALCompressed newALCompressed( hALStorage storage,
// hALEngine engine )
//
// ARGUMENTS:
//
// storage : A handle for (pointer to) an ALStorage object that is
// going to hold the compressed object.
//
// engine : A handle for (pointer to) an ALCompressionEngine that will
// be used to insert and extract objects from the the storage
// object.
//
// RETURNS
//
// A handle for (pointer to) a newly created ALCompressedObject, or 0 if
// the constructor failed.
//
// DESCRIPTION
//
// This is the C/VB translation function for the C++ constructor
// ALCompressedObject::ALCompressedObject(). See CMPOBJ.CPP for
// details on what happens in the member function.
//
// In the translation function, we just check the arguments for
// correct type (in the debug version) and call the function, returning
// the result to the calling function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALCompressed AL_FUNCTION
newALCompressed( hALStorage storage,
hALEngine engine )
{
AL_ASSERT_OBJECT( storage, ALStorage, "newALCompressed" );
AL_ASSERT_OBJECT( engine, ALCompressionEngine, "newALCompressed" );
return (hALCompressed) new ALCompressedObject( *(ALStorage *) storage, *(ALCompressionEngine *) engine );
}
//
// extern "C" void deleteALCompressed( hALCompressed this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject
// that is going to be destroyed.
//
// RETURNS
//
// Nothing, this is a destructor.
//
// DESCRIPTION
//
// This is the C/VB translation function for the C++ destructor
// ALCompressedObject::~ALCompressedObject(). See CMPOBJ.CPP for
// details on what happens in the member function.
//
// In the translation function, we just check the arguments for
// correct type (in the debug version) and call the function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION deleteALCompressed( hALCompressed this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "deleteALCompressed" );
delete (ALCompressedObject *) this_object;
}
//
// extern "C" int ALCompressedInsert( hALCompressed this_object,
// hALStorage input_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject
// that is going to have a storage object inserted
// int it.
//
// input_object : A handle for (pointer to) a storage object that is
// going to get compressed into this_object.
//
// RETURNS
//
// AL_SUCCESS for success, or < AL_SUCCESS for one of many failures
//
// DESCRIPTION
//
// This is the C/VB translation function for the C++ function
// ALCompressedObject::Insert(). See CMPOBJ.CPP for more details
// on what happens in the member function.
//
// In the translation function, we just check the arguments for
// correct type (in the debug version) and call the function. We
// return the integer result of the function directly to the calling
// function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALCompressedInsert( hALCompressed this_object,
hALStorage input_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedInsert" );
AL_ASSERT_OBJECT( input_object, ALStorage, "ALCompressedInsert" );
return ( (ALCompressedObject *) this_object )->Insert( * (ALStorage *) input_object );
}
//
// extern "C" int ALCompressedExtract( hALCompressed this_object,
// hALStorage output_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject
// that is going to have a storage object extracted
// from it.
//
// output_object: A handle for (pointer to) a storage object that is
// going to receive the uncompressed object.
//
// RETURNS
//
// AL_SUCCESS for success, or < AL_SUCCESS for one of many failures
//
// DESCRIPTION
//
// This is the C/VB translation function for the C++ function
// ALCompressedObject::Extract(). See CMPOBJ.CPP for more details
// on what happens in the member function.
//
// In the translation function, we just check the arguments for
// correct type (in the debug version) and call the function. We
// return the integer result of the function directly to the calling
// function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALCompressedExtract( hALCompressed this_object,
hALStorage output_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedExtract" );
AL_ASSERT_OBJECT( output_object, ALStorage, "ALCompressedExtract" );
return ( (ALCompressedObject *) this_object )->Extract( * (ALStorage *) output_object );
}
//
// extern "C" int ALCompressedGetStatusCode( hALCompressed this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject.
//
// RETURNS
//
// An integer that contains the current status code for the object.
// Note that values of < 0 always indicate an error conditions.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALName::GetStatusCode() as implemented for objects of type
// ALCompressedObject. For details on how the member
// function actually works, take a look at OBJNAME.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION
ALCompressedGetStatusCode( hALCompressed this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedGetStatusCode" );
return ( (ALCompressedObject *) this_object )->mStatus.GetStatusCode();
}
//
// extern "C" int ALCompressedSetError( hALCompressed this_object,
// int error,
// char *text )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject.
// We are going to set the object's status member
// so that it is in an error state.
//
// error : The error code to apply to the object. Values from
// ALDEFS.H are good, but it really doesn't matter as
// long as you use a negative number.
//
// text : The text of the error message you want to associate with
// this error.
//
// RETURNS
//
// Returns the error code that you passed it.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ member function
// ALName::SetError(), as applied to an ALCompressedObject. For more
// details on how the function actually works, check out OBJNAME.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALCompressedSetError( hALCompressed this_object,
int error_code,
char AL_DLL_FAR *text )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedSetError" );
( (ALCompressedObject *) this_object )->mStatus.SetError( error_code, text );
return error_code;
}
//
// extern "C" char *ALCompressedGetStatusString( hALCompressed this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject.
// We want to get the string translation of the error
// code for this object.
//
// RETURNS
//
// Always returns a pointer to a short string translation of the
// current error code.
//
// DESCRIPTION
//
// This is the C wrapper function for the C++ function
// ALName::GetStatusString(), as implemented for class ALCompressedObject.
// Note that we need a completely different function in order to
// return strings to VB programmers, this function is only good for C!
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALCompressedGetStatusString( hALCompressed this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedGetStatusString" );
const char *status = ( (ALCompressedObject *) this_object )->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" long ALCompressedGetStatusStringVB( hALCompressed this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject.
// We want to get the string translation of the error
// code for this object.
//
// RETURNS
//
// Always returns a VB handle (pointer?) to a short string translation of
// the current error code for the ALCompressedObject.
//
// DESCRIPTION
//
// This is the VB wrapper function for the C++ function
// ALName::GetStatusString(), as implemented for class ALCompressedObject.
// Note that we need a completely different function to return strings
// to C programmers. In this case, we use a special VB translation routine
// to convert a C string to one that is nice and easy for VB to use.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALCompressedGetStatusStringVB( hALCompressed this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedGetStatusStringVB" );
const char _far *status = ( (ALCompressedObject *) this_object )->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif
//
// extern "C" char *ALCompressedGetStatusDetail( hALCompressed this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedObject.
// We want to get the detailed string describing this
// object's current status.
//
// RETURNS
//
// Always returns a pointer to a status detail message.
//
// DESCRIPTION
//
// This is the C wrapper function for the C++ function
// ALName::GetStatusDetail(), as implemented for class ALCompressedObject.
// Note that we need a completely different function in order to
// return strings to VB programmers.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALCompressedGetStatusDetail( hALCompressed this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedGetStatusDetail" );
const char *status = ( (ALCompressedObject *) this_object )->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" long ALCompressedGetStatusDetailVB( hALCompressed this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressedobject.
// We want to get the detailed status message for
// this object.
//
// RETURNS
//
// Always returns a VB handle (pointer?) to a translation of
// the current status detail for the ALCompressedObject.
//
// DESCRIPTION
//
// This is the VB wrapper function for the C++ function
// ALName::GetStatusDetail(), as implemented for class ALCompressedObject.
// Note that we need a completely different function to return strings
// to C programmers. In this case, we use a special VB translation routine
// to convert a C string to one that is nice and easy for VB to use.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION
ALCompressedGetStatusDetailVB( hALCompressed this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressedObject, "ALCompressedGetStatusDetailVB" );
const char _far *status = ( (ALCompressedObject *) this_object )->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif

586
al/cxl_engn.cpp Executable file
View File

@ -0,0 +1,586 @@
//
// CXL_ENGN.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALCopyEngine()
// newALGreenleafEngine()
// ALEngineGetStatusCode()
// ALEngineSetError()
// ALEngineGetStatusString()
// ALEngineGetStatusStringVB()
// ALEngineGetStatusDetail()
// ALEngineGetStatusDetailVB()
// deleteALEngine()
// ALEngineCompress()
// ALEngineDecompress()
// ALEngineGetTypeCode()
// ALEngineGetTypeString()
// ALEngineGetTypeStringVB()
//
// DESCRIPTION
//
// This file contains all of the C/VB translation functions for all
// of the Compression enging classes: ALEngine, ALCopyEngine, and
// ALGreenleafEngine. You won't get much good information out of this
// file, since there really isn't much code in the translation layer.
// For detailed information, see CMPENGN.CPP, COPYENGN.CPP, and
// GRENENGN.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" hALEngine newALCopyEngine( void )
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A handle for (pointer to) a newly create ALCopyEngine object.
// If for some reason the constructor failed this function might
// just return a 0.
//
// DESCRIPTION
//
// This is the C/VB translation layer function for the C++ constructor
// ALCopyEngine::ALCopyEngine(). It simply calls the constructor
// and returns the resulting value. For more information on what
// actually happens inside the constructor, see COPYENGN.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALEngine AL_FUNCTION newALCopyEngine( void )
{
return (hALEngine) new ALCopyEngine();
}
//
// extern "C" hALEngine newALGreenleafEngine( void )
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A handle for (pointer to) a newly create ALGreenleafEngine object.
// If for some reason the constructor failed this function might
// just return a 0.
//
// DESCRIPTION
//
// This is the C/VB translation layer function for the C++ constructor
// ALGreenleafEngine::ALGreenleafEngine(). It simply calls the constructor
// and returns the resulting value. For more information on what
// actually happens inside the constructor, see GRENENGN.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALEngine AL_FUNCTION newALGreenleafEngine( int level )
{
return (hALEngine) new ALGreenleafEngine( (short int) level );
}
//
// extern "C" int ALEngineGetStatusCode( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressionEngine object.
//
// RETURNS
//
// An integer that contains the current status code for the object.
// Note that values of < 0 always indicate an error conditions.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ function
// ALName::GetStatusCode() as implemented for objects of type
// ALCompressionEngine. For details on how the member
// function actually works, take a look at OBJNAME.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEngineGetStatusCode( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineGetStatusCode" );
return ( (ALCompressionEngine *) this_object )->mStatus.GetStatusCode();
}
//
// extern "C" int ALEngineSetError( hALEngine this_object,
// int error,
// char *text )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressionEngine object.
// We are going to set the engine's status member
// so that it is in an error state.
//
// error : The error code to apply to the object. Values from
// ALDEFS.H are good, but it really doesn't matter as
// long as you use a negative number.
//
// text : The text of the error message you want to associate with
// this error.
//
// RETURNS
//
// Returns the error code that you passed it.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ member function
// ALName::SetError(), as applied to an ALCompressionEngine object.
// For more details on how the function actually works, check out
// OBJNAME.CPP.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEngineSetError( hALEngine this_object,
int error,
char AL_DLL_FAR *text )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineSetError" );
( (ALCompressionEngine *) this_object )->mStatus.SetError( error, text );
return error;
}
//
// extern "C" char *ALEngineGetStatusString( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressionEngine object.
// We want to get the string translation of the error
// code for this object.
//
// RETURNS
//
// Always returns a pointer to a short string translation of the
// current error code.
//
// DESCRIPTION
//
// This is the C wrapper function for the C++ function
// ALName::GetStatusString(), as implemented for class ALCompressionEngine.
// Note that we need a completely different function return strings
// to VB programmers.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALEngineGetStatusString( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineGetStatusString" );
const char *status = ( (ALCompressionEngine *) this_object )->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" long ALEngineGetStatusStringVB( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressionEngine object.
// We want to get the string translation of the error
// code for this object.
//
// RETURNS
//
// Always returns a VB handle (pointer?) to a short string translation of
// the current error code for the ALCompressionEngine object.
//
// DESCRIPTION
//
// This is the VB wrapper function for the C++ function
// ALName::GetStatusString(), as implemented for class ALCompressionEngine.
// Note that we need a completely different function to return strings
// to C programmers. In this case, we use a special VB translation routine
// to convert a C string to one that is nice and easy for VB to use.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALEngineGetStatusStringVB( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object , ALCompressionEngine, "ALEngineGetStatusStringVB" );
const char _far *status = ( (ALCompressionEngine *) this_object )->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif
//
// extern "C" char * ALEngineGetStatusDetail( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressionEngine object.
// We want to get the detailed string describing this
// object's current status.
//
// RETURNS
//
// Always returns a pointer to a status detail message.
//
// DESCRIPTION
//
// This is the C wrapper function for the C++ function
// ALName::GetStatusDetail(), as implemented for class ALCompressionEngine.
// Note that we need a completely different function to return strings
// to VB programmers.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALEngineGetStatusDetail( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineGetStatusDetail" );
const char *status = ( (ALCompressionEngine *) this_object )->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" long ALEngineGetStatusDetailVB( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressionEngine object.
// We want to get the detailed status message for
// this object.
//
// RETURNS
//
// Always returns a VB handle (pointer?) to a translation of
// the current status detail for the ALCompressionEngine object.
//
// DESCRIPTION
//
// This is the VB wrapper function for the C++ function
// ALName::GetStatusDetail(), as implemented for class ALCompressionEngine.
// Note that we need a completely different function to return strings
// to C programmers. In this case, we use a special VB translation routine
// to convert a C string to one that is nice and easy for VB to use.
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALEngineGetStatusDetailVB( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineGetStatusDetailVB" );
const char _far *status = ( (ALCompressionEngine *) this_object )->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif
//
// extern "C" void deleteALEngine( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALCompressionEngine object.
// We destroy it in this function.
//
// RETURNS
//
// No returns from destructors.
//
// DESCRIPTION
//
// This is the C/VB wrapper function for the C++ destructor
// ALCompressionEngine::~ALCompressionEngine()). For details
// on what the member function actually works, take a look at
// CMPENGN.CPP.
//
// Note that this destructor function is virtual, and should be called
// to destroy any derived classes (ALCopyEngine and ALGreenleafEngine).
//
// All that happens here is that the arguments are checked for correct
// type (when in debug mode), and a call is made to the appropriate
// member function, with lots of casting.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION deleteALEngine( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "deleteALEngine" );
delete (ALCompressionEngine *) this_object;
}
//
// extern "C" int ALEngineCompress( hALEngine this_object,
// hALStorage input,
// hALStorage output )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an object of type
// ALCompressionEngine. The engine contains
// the code that will perform the compression.
//
// input : A handle for (pointer to) an object of type
// ALStorage that contains the input data that will
// be fed to the compression engine.
//
// output : A handle for (pointer to) an object of type
// ALStorage that will receive the compressed output
// from the engine.
//
// RETURNS
//
// AL_SUCCESS if everything worked, code < AL_SUCCESS if not.
//
// DESCRIPTION
//
// This function is the C/VB translation function for the C++ member
// function ALCompressionEngine::Compress(). For details on what
// this function does, you will need to look at the source code
// in the appropriate module, such as COPYENGN.CPP or GRENENGN.CPP.
//
// All the wrapper function does is check the type of the arguments
// (if in debug mode), then call the C++ member function, returning
// the result to the calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEngineCompress( hALEngine this_object,
hALStorage input,
hALStorage output )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineCompress" );
AL_ASSERT_OBJECT( input, ALStorage, "ALEngineCompress" );
AL_ASSERT_OBJECT( output, ALStorage, "ALEngineCompress" );
return ( (ALCompressionEngine *) this_object )->Compress( *(ALStorage *) input, *(ALStorage *) output );
}
//
// extern "C" int ALEngineDecompress( hALEngine this_object,
// hALStorage input,
// hALStorage output )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an object of type
// ALCompressionEngine. The engine contains
// the code that will perform the expansion.
//
// input : A handle for (pointer to) an object of type
// ALStorage that contains a stream of compressed
// data that was previously created using Compress().
//
// output : A handle for (pointer to) an object of type
// ALStorage that will receive the plain text output
// from the compression engine.
//
// RETURNS
//
// AL_SUCCESS if everything worked, code < AL_SUCCESS if not.
//
// DESCRIPTION
//
// This function is the C/VB translation function for the C++ member
// function ALCompressionEngine::Decompress(). For details on what
// this function does, you will need to look at the source code
// in the appropriate module, such as COPYENGN.CPP or GRENENGN.CPP.
//
// All the wrapper function does is check the type of the arguments
// (if in debug mode), then call the C++ member function, returning
// the result to the calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION
ALEngineDecompress( hALEngine this_object,
hALStorage input,
hALStorage output,
long compressed_length )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineDecompress" );
AL_ASSERT_OBJECT( input, ALStorage, "ALEngineDecompress" );
AL_ASSERT_OBJECT( output, ALStorage, "ALEngineDecompress" );
return ( (ALCompressionEngine *) this_object )->Decompress( *(ALStorage *) input, *(ALStorage *) output, compressed_length );
}
//
// extern "C" int ALEngineGetTypeCode( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an object of type
// ALCompressionEngine.
//
// RETURNS
//
// The compression engine type, found in enum ALCompressionType in
// ALDEFS.H.
//
// DESCRIPTION
//
// This function is the C/VB translation function that provides access
// to the C++ data member ALCompressionEngine::miCompressionType. Since
// C and VB can't access the class object directly, they have to go through
// this function as an intermediary.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEngineGetTypeCode( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineGetTypeCode" );
return ( (ALCompressionEngine *) this_object )->miCompressionType;
}
//
// extern "C" char *ALEngineGetTypeString( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an object of type
// ALCompressionEngine.
//
// RETURNS
//
// The string describing the engine type. The description string is always
// provided by the derived class.
//
// DESCRIPTION
//
// This function is the C translation function that provides access
// to the C++ data member ALCompressionEngine::mszCompressionType. Since
// C can't access the class object directly, it has to go through
// this function as an intermediary. Note that there is a special
// function to return the compression type string to a VB program.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION ALEngineGetTypeString( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineGetTypeString" );
return (char AL_DLL_FAR *) ( (ALCompressionEngine *) this_object )->mszCompressionType;
}
//
// extern "C" char *ALEngineGetTypeStringVB( hALEngine this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an object of type
// ALCompressionEngine.
//
// RETURNS
//
// A VB string describing the engine type. The description string is
// always provided by the derived class.
//
// DESCRIPTION
//
// This function is the VB translation function that provides access
// to the C++ data member ALCompressionEngine::mszCompressionType. Since
// VB can't access the class object directly, it has to go through
// this function as an intermediary. Note that this is a special
// function that knows how to convert a standard C string to one that
// VB likes.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALEngineGetTypeStringVB( hALEngine this_object )
{
AL_ASSERT_OBJECT( this_object, ALCompressionEngine, "ALEngineGetTypeStringVB" );
const char _far *status = ( (ALCompressionEngine *) this_object )->mszCompressionType;
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif

704
al/cxl_entr.cpp Executable file
View File

@ -0,0 +1,704 @@
//
// CXL_ENTR.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALEntry()
// deleteALEntry()
// ALEntryDuplicate()
// ALEntryGetNextEntry()
// ALEntrySetMark()
// ALEntryClearMark()
// ALEntrySetMarkState()
// ALEntryGetStorage()
// ALEntrySetStorage()
// ALEntrySetComment()
// ALEntryGetCompressedSize()
// ALEntryGetCrc32()
// ALEntryGetMark()
// ALEntryCompressionRatio()
// ALEntryGetComment()
// ALEntryGetCommentVB()
// ALEntryGetEngine()
// ALEntrySetEngine()
//
// DESCRIPTION
//
// This file contains the C/VB translation layer for the ALEntry class.
// These functions all provide mapping to equivalent member functions
// or data members in class ALEntry. Since there isn't much code
// involved in the translation, it is recommended that you look in
// ARCENTRY.CPP for details on how the ALEntry class really works.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" hALEntry newALEntry( hALEntryList list,
// hALStorage storage,
// hALEngine engine )
//
// ARGUMENTS:
//
// list : A handle for (pointer to) the ALEntryList that is
// going get this ALEntry.
//
// storage : A handle for (pointer to) the storage object that is
// being described in this ALEntry object.
//
// engine : A handle for (pointer to) the compression engine that
// will be/was used to compress/expand the storage object.
//
// RETURNS
//
// A handle for (pointer to) a freshly constructed ALEntry object. In the
// case of a really horrible error, this might be a 0.
//
// DESCRIPTION
//
// This C/VB function provides a translation layer so that those two
// languages can access the C++ constructor ALEntry::ALEntry().
// For details on what exactly happens in the ALEntry ctor, check out
// the source module in ARCENTRY.CPP.
//
// Like most of the translation layer functions, this guy works by simply
// performing type checking on the arguments (in debug mode), and calling
// the function. The result is then cast properly and returned to the
// calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALEntry AL_FUNCTION newALEntry( hALEntryList list,
hALStorage storage,
hALEngine engine )
{
AL_ASSERT_OBJECT( list, ALEntryList, "newALEntry" );
AL_ASSERT_OBJECT( storage, ALStorage, "newALEntry" );
AL_ASSERT_OBJECT( engine, ALCompressionEngine, "newALEntry" );
return (hALEntry) new ALEntry( *( (ALEntryList *) list ),
(ALStorage * ) storage,
(ALCompressionEngine *) engine );
}
//
// extern "C" void deleteALEntry( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) a valid ALEntry object.
//
// RETURNS
//
// Nothing, this is a destructor.
//
// DESCRIPTION
//
// This C/VB function provides a translation layer so that those two
// languages can access the C++ destructor ALEntry::~ALEntry().
// For details on what exactly happens in the ALEntry dtor, check out
// the source module in ARCENTRY.CPP.
//
// Like most of the translation layer functions, this guy works by simply
// performing type checking on the arguments (in debug mode), and calling
// the function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION deleteALEntry( hALEntry entry )
{
AL_ASSERT_OBJECT( entry, ALEntry, "deleteALEntry" );
delete (ALEntry *) entry;
}
//
// extern "C" int ALEntryDuplicate( hALEntry this_object, hALEntryList list )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// list : A handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// 1 if the entry is duplicated somewhere in the list, 0 if not.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::Duplicate(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return
// from the member function is passed right back to the calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION
ALEntryDuplicate( hALEntry this_object, hALEntryList list )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryDuplicate" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALEntryDuplicate" );
return ( (ALEntry *) this_object )->Duplicate( * (ALEntryList *) list );
}
//
// extern "C" hALEntry ALEntryGetNextEntry( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A valid handle for (pointer to) an ALEntry if there are more
// objects in the list. If not, 0.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::GetNextEntry(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return
// from the member function is passed right back to the calling routine
// after being cast to the appropriate C/VB type.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALEntry AL_FUNCTION ALEntryGetNextEntry( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetNextEntry" );
return (hALEntry) ( ((ALEntry *) this_object )->GetNextEntry() );
}
//
// extern "C" void ALEntrySetMark( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::SetMark(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION ALEntrySetMark( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntrySetMark" );
((ALEntry *) this_object )->SetMark();
}
//
// extern "C" void ALEntryClearMark( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::ClearMark(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION ALEntryClearMark( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryClearMark" );
((ALEntry *) this_object )->ClearMark();
}
//
// extern "C" void ALEntrySetMarkState( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::SetMarkState(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION ALEntrySetMarkState( hALEntry this_object,
short int new_state )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntrySetMarkState" );
((ALEntry *) this_object )->SetMarkState( new_state );
}
//
// extern "C" hALStorage ALEntryGetStorage( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A valid handle for (pointer to) an ALStorage object. It is possible
// to get a return value of 0, since an ALEntry is not required to have
// a valid ALStorage object attached to it.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ data member ALEntry::mpStorageObject. For more information on
// what this data member actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and gets the data member. The data member
// is passed right back to the calling routine after being cast to the
// appropriate C/VB type.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALStorage AL_FUNCTION ALEntryGetStorage( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetStorage" );
return (hALStorage) ( (ALEntry *) this_object )->mpStorageObject;
}
//
// extern "C" void ALEntrySetStorage( hALEntry this_object,
// hALStorage storage )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// storage : A handle for (pointer to) an ALStorage object that
// will now be attached to the ALEntry object. Note
// that a value of 0 is acceptable.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ data member ALEntry::mpStorageObject. For more information on
// what this data member actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and accesses the data member.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION ALEntrySetStorage( hALEntry this_object,
hALStorage storage )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntrySetStorage" );
if ( storage != 0 )
AL_ASSERT_OBJECT( storage, ALStorage, "ALEntrySetStorage" );
( (ALEntry *) this_object )->mpStorageObject = (ALStorage *) storage;
}
//
// extern "C" int ALEntrySetComment( hALEntry this_object, char *comment )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// comment : A pointer to a character string that is going to be
// copied into the ALEntry object.
//
// RETURNS
//
// AL_SUCCESS if things went okay, or a code < AL_SUCCESS if not.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ data member ALEntry::mpStorageObject. For more information on
// what this data member actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and accesses the data member.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION
ALEntrySetComment( hALEntry this_object, char *comment )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntrySetComment" );
if ( comment == 0 )
comment = "";
return ( (ALEntry *) this_object )->SetComment( comment );
}
//
// extern "C" long ALEntryGetCompressedSize( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A long value, indicating the compressed size. Note that this information
// will only be available after reading a directory, or performing an
// operation that compresses the file.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member ALEntry::GetCompressedSize. For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return data
// from the member function is passed back directly to the calling module.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" long AL_FUNCTION ALEntryGetCompressedSize( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetCompressedSize" );
return ( (ALEntry *) this_object )->GetCompressedSize();
}
//
// extern "C" long ALEntryGetCrc32( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A long value, indicating the object's CRC. Note that this information
// will only be available after reading a directory, or performing an
// operation that compresses the file.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::GetCrc32(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return data
// from the member function is passed back directly to the calling module.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" long AL_FUNCTION ALEntryGetCrc32( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetCrc32" );
return ( (ALEntry *) this_object )->GetCrc32();
}
//
// extern "C" int ALEntryGetMark( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A 1 or 0, indicating the object's mark state.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::GetMark(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return data
// from the member function is passed back directly to the calling module.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEntryGetMark( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetMark" );
return ( (ALEntry *) this_object )->GetMark();
}
//
// extern "C" int ALEntryCompressionRatio( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A number usually ranging from 0 to 100. Less than 0 indicates
// an error.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ member function ALEntry::CompressionRatio(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return data
// from the member function is passed back directly to the calling module.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEntryCompressionRatio( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryCompressionRatio" );
return ( (ALEntry *) this_object )->CompressionRatio();
}
//
// extern "C" char *ALEntryGetComment( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A pointer to a C character string. The pointer is the value of the
// string pointer embedded in the class object.
//
// DESCRIPTION
//
// This function provides a translation layer for C to access the
// C++ member function ALEntry::GetComment(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return data
// from the member function is passed back directly to the calling module.
//
// C strings aren't happy in VB, so there is a special function just to
// convert strings to vB format. Don't call this function from
// Visual Basic, there is an easier way!
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char *AL_FUNCTION ALEntryGetComment( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetComment" );
return (char *) ( (ALEntry *) this_object )->GetComment();
}
//
// extern "C" long ALEntryGetCommentVB( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A Visual Basic character string. The string is a copy of the
// string pointer embedded in the class object.
//
// DESCRIPTION
//
// This function provides a translation layer for VB to access the
// C++ member function ALEntry::GetComment(). For more information on
// what this member function actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and calls the member function. The return data
// from the member function is passed back directly to the calling module.
//
// C strings aren't happy in VB, so this function converts the C
// character pointer to a super-special VB string.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION ALEntryGetCommentVB( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetComment" );
char _far *p = (char _far *) ( (ALEntry *) this_object )->GetComment();
return ALCreateVBString( p, (unsigned short int) _fstrlen( p ) );
}
#endif
//
// extern "C" hALEngine ALEntryGetEngine( hALEntry this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// RETURNS
//
// A valid handle for (pointer to) an ALCompressionEngine object. It is
// possible to get a return value of 0, since an ALEntry is not required to
// have a valid ALCompressionEngine object attached to it.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ data member ALEntry::mpCompressionEngine. For more information on
// what this data member actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and gets the data member. The data member
// is passed right back to the calling routine after being cast to the
// appropriate C/VB type.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALEngine AL_FUNCTION ALEntryGetEngine( hALEntry this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetEngine" );
return (hALEngine) ( (ALEntry *) this_object )->mpCompressionEngine;
}
//
// extern "C" void ALEntrySetEngine( hALEntry this_object, hALEngine engine )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntry object.
//
// engine : A handle for (pointer to) an ALcompressionEngine
// will now be attached to the ALEntry object. Note
// that a value of 0 is acceptable.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function provides a translation layer for C and VB to access the
// C++ data member ALEntry::mpCompressionEngine. For more information on
// what this data member actually does, see ARCENTRY.CPP.
//
// Like most of the translation functions, this routine checks the
// arguments for correct type (in debug mode), then casts this_object
// to the desired class, and accesses the data member.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION ALEntrySetEngine( hALEntry this_object, hALEngine engine )
{
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntrySetEngine" );
if ( engine != 0 )
AL_ASSERT_OBJECT( engine, ALCompressionEngine, "ALEntrySetEngine" );
( (ALEntry *) this_object )->mpCompressionEngine = (ALCompressionEngine *) engine;
}

64
al/cxl_file.cpp Executable file
View File

@ -0,0 +1,64 @@
//
// CXL_FILE.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALFile()
//
// DESCRIPTION
//
// This file contains the one and only source file to support
// the C and VB translation layer for ALFile objects. Everything
// else you might want to do with a file after constructing it is done
// via the base class.
//
// If you want to learn more about ALFile, (and who wouldn't) look in
// FILESTOR.CPP for the juicy C++ code.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" hALStorage newALFile( char *file_name )
//
// ARGUMENTS:
//
// file_name : The name of the file to construct.
//
// RETURNS
//
// A handle for (pointer to) a newly constructed ALFile object. It is
// possible to get a 0 back if the file could not be constructed for
// some reason.
//
// DESCRIPTION
//
// This is the C and VB translation function that provides access to
// ALFile::ALFile(). It calls the constructor, then casts the result
// to a type C will be happy with and returns it.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALStorage AL_FUNCTION newALFile( char AL_DLL_FAR *file_name )
{
return (hALStorage) new ALFile( file_name );
}

319
al/cxl_garc.cpp Executable file
View File

@ -0,0 +1,319 @@
//
// CXL_GARC.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALArchive()
// newALArchiveFromStorage()
// ALArchiveAddFilesToList() /* OBSOLETE!!! */
// ALEntryListAddFromDialog()
// ALEntryListAddFromWindow()
// ALEntryListAddWildCardFiles() /* Replacement for the obsolete fn */
//
// DESCRIPTION
//
// This file contains the source code for the C and VB translation
// layer modules to support class ALArchive. The source file
// has "GARC" because once upon a time class ALArchive was called
// ALGreenleafArchive.
//
// There isn't too much to learn by looking at the translation layers, so
// if you really want to see some exciting C++ code, check out ARCHIVE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" hALArchive newALArchive( char *name )
//
// ARGUMENTS:
//
// name : This constructor automatically creates an ALFile object
// for the archive. This is the name of the ALFile object.
//
// RETURNS
//
// A handle for (pointer to) a newly created ALArchive, or 0 if
// the constructor failed for some reason.
//
// DESCRIPTION
//
// This is the C/VB translation function for the C++ constructor
// ALArchive::ALArchive(char *). See ARCHIVE.CPP for details on what
// happens in the constructor.
//
// Unlike most translation functions, this constructor doesn't have to check
// or cast any arguments before calling its C++ code. It does however have
// to cast the result to the correct type before giving it back to the
// C or VB calling module.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALArchive AL_FUNCTION newALArchive( char *name )
{
ALArchive *archive;
archive = new ALArchive( name );
return (hALArchive) archive;
}
//
// extern "C" hALArchive newALArchiveFromStorage( hALStorage storage )
//
// ARGUMENTS:
//
// storage : A handle for (pointer to) a preconstructed storage object.
// This storage object will be where the archive keeps all of
// its stuff. Note that you have to create and destroy this
// storage object yourself, unlike the previous constructor.
//
// RETURNS
//
// A handle for (pointer to) a newly created ALArchive, or 0 if
// the constructor failed for some reason.
//
// DESCRIPTION
//
// This is the C/VB translation function for the C++ constructor
// ALArchive::ALArchive(ALStorage&). See ARCHIVE.CPP for details on what
// happens in the constructor.
//
// Like most translation functions, this one checks the type off its single
// argument (in debug mode), before casting and calling the C++ function.
// It takes the result from the C++ constructor and casts it back to
// correct type before giving it back to the C or VB calling module.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALArchive AL_FUNCTION newALArchiveFromStorage( hALStorage storage )
{
AL_ASSERT( ( (ALStorage *) storage)->GoodTag(),
"storage argument is not a valid ALStorageObject" );
ALArchive *archive;
archive = new ALArchive( *(ALStorage *) storage );
return (hALArchive) archive;
}
// OBSOLETE FUNCTION
//
// extern "C" int ALArchiveAddFilesToList( hALArchive this_object,
// hALEntryList list,
// char *pattern,
// int traverse )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) a valid ALArchive object.
// It isn't used since we are calling a static function.
//
// list : A handle for (pointer to) an ALEntryList. This list
// is going to get a bunch of new entries, like it or not.
//
// pattern : A list of wild-card file specs, separated by spaces,
// commas, or semicolons.
//
// traverse : A flag to indicate whether the search engine should
// traverse subdirectories when expanding file specs.
//
// RETURNS
//
// An integer indicating how many entries were added to the list.
//
// DESCRIPTION
//
// This function has been replaced by the more appropriately named
// ALEntryListAddWildCardFiles().
//
// This function is the C/VB translation function to access the C++
// member function ALArchive::AddWildCardFiles(). For details on how
// the AddWildCardFiles() function actually works, please check out
// ARCHIVE.CPP, cuz that is where the real code is.
//
// Like all the other translation routines, this guy just has to
// check the arguments to see if they are the correct type (in debug
// mode only), then cast and call the C++ member function. The
// return value from the function is shot directly back to the C or
// VB calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALArchiveAddFilesToList( hALArchive, hALEntryList list, char *pattern, int traverse )
{
AL_ASSERT_OBJECT( list, ALEntryList, "ALArchiveAddFilesToList" );
return ALArchive::AddWildCardFiles( *( (ALEntryList *) list), pattern, traverse );
}
//
// extern "C" int ALEntryListAddFromDialog( hALEntryList this_object,
// HWND hDlg,
// int id )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// hDlg : Windows handle for a dialog box containing the
// target list box.
//
// id : The id of the list box found in the dialog box.
//
// RETURNS
//
// The number of entries added to the list box.
//
// DESCRIPTION
//
// This is C translation function that provides access to the C++
// member function ALArchive::MakeEntriesFromListBox(). Like most of the
// translation functions, you don't get to see much here. For detailed
// information on what happens in the constructor, check ARCHIVE.CPP.
//
// You might think that this function looks like a member of ALEntryList,
// not ALArchive. Yes, it looks like it, but in fact it is a static
// member of ALArchive.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// You might think that this function looks like a member of ALEntryList,
// not ALArchive. Yes, it looks like it, but in fact it is a static
// member of ALArchive. The fact that it is static explains why there
// is no ALArchive object in the argument list.
//
// You can't use this dude with VB because VB doesn't use Dialog boxes,
// at least I don't think so.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
extern "C" int AL_FUNCTION ALEntryListAddFromDialog( hALEntryList this_object,
HWND hDlg,
int id )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListAddFromDialog" );
return ALArchive::MakeEntriesFromListBox( *(ALEntryList *) this_object, hDlg, id );
}
#endif
//
// extern "C" int ALEntryListAddFromWindow( hALEntryList this_object,
// HWND hwnd )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// hwnd : Windows handle for a the list box control.
//
// RETURNS
//
// The number of entries added to the list box.
//
// DESCRIPTION
//
// This is C translation function that provides access to the C++
// member function ALArchive::MakeEntriesFromListBox(). Like most of the
// translation functions, you don't get to see much here. For detailed
// information on what happens in the constructor, check ARCHIVE.CPP.
//
// You might think that this function looks like a member of ALEntryList,
// not ALArchive. Yes, it looks like it, but in fact it is a static
// member of ALArchive. The fact that it is static explains why there
// is no ALArchive argument in the picture.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
extern "C" int AL_FUNCTION ALEntryListAddFromWindow( hALEntryList this_object,
HWND hwnd )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListAddFromWindow" );
return ALArchive::MakeEntriesFromListBox( *(ALEntryList *) this_object, hwnd );
}
#endif
//
// extern "C" int ALEntryListAddWildCardFiles( hALEntryList this_object,
// char *pattern,
// int traverse )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntryList. This list
// is going to get a bunch of new entries, like it or not.
//
// pattern : A list of wild-card file specs, separated by spaces,
// commas, or semicolons.
//
// traverse : A flag to indicate whether the search engine should
// traverse subdirectories when expanding file specs.
//
// RETURNS
//
// An integer indicating how many entries were added to the list.
//
// DESCRIPTION
//
// This function is the C/VB translation function to access the C++
// member function ALArchive::AddWildCardFiles(). For details on how
// the AddWildCardFiles() function actually works, please check out
// ARCHIVE.CPP, cuz that is where the real code is. You might notice
// that there is no ALArchive object passed to this function. That
// is because this function is a static member function of ALArchive,
// we just need its ability to create ALFile objects.
//
// Like all the other translation routines, this guy just has to
// check the arguments to see if they are the correct type (in debug
// mode only), then cast and call the C++ member function. The
// return value from the function is shot directly back to the C or
// VB calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION
ALEntryListAddWildCardFiles( hALEntryList this_object,
char AL_DLL_FAR *pattern,
int traverse )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListAddWildCardFiles" );
return ALArchive::AddWildCardFiles( *( (ALEntryList *) this_object), pattern, traverse );
}

786
al/cxl_list.cpp Executable file
View File

@ -0,0 +1,786 @@
//
// CXL_LIST.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALEntryList()
// ALEntryListGetFirstEntry()
// ALEntryListUnmarkDuplicates()
// ALEntryListSetMarksFromDialog()
// ALEntryListSetMarksFromWindow()
// ALEntryListFillListBoxWindow()
// ALEntryListFillListBoxDialog()
// deleteALEntryList()
// ALEntryListSetMarks()
// ALEntryListClearMarks()
// ALEntryListDeleteUnmarked()
// ALEntryListToggleMarks()
// ALEntryListGetStatusCode()
// ALEntryListGetStatusString()
// ALEntryListGetStatusDetail()
// ALEntryListGetStatusStringVB()
// ALEntryListGetStatusDetailVB()
//
// DESCRIPTION
//
// This file contains the translation layer for C and VB to the
// ALEntryList class. The translation routines are all real short
// functions that mostly cast things. If you want to see what is
// going on in ALEntryList, take a look at ARCENTRY.CPP for the
// details.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" hALEntryList newALEntryList( hALMonitor monitor )
//
// ARGUMENTS:
//
// monitor : A handle for (pointer to) an ALMonitor object.
// The monitor will stay attached to the list, and will
// be used to provide feedback during all archiving operations.
//
// RETURNS
//
// A handle for (pointer to) an ALEntryList object. It is possible to get
// back a 0 if the constructor fails for lack of memory. Not likely
// though.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// constructor ALEntryList::ALEntryList(). Like most of the translation
// functions, you don't get to see much here. For detailed information
// on what happens in the constructor, check ARCENTRY.CPP.
//
// This routine first performs type checking on all the passed object
// handles (in debug mode), then calls the constructor. The returned
// object pointer is then cast to a C/VB compatible type and returned
// to the calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALEntryList AL_FUNCTION newALEntryList( hALMonitor monitor )
{
if ( monitor != 0 )
AL_ASSERT( ((ALMonitor *) monitor)->GoodTag(),
"monitor argument is not a valid ALMonitor" );
ALEntryList *list = new ALEntryList( (ALMonitor *) monitor );
return (hALEntryList) list;
}
//
// extern "C" hALEntry ALEntryListGetFirstEntry( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// A handle for (pointer to) an ALEntry object. If there are no
// entries in the list you will get back a 0.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::GetFirstEntry(). This routine is
// the first one called when iterating through an entire list.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. The returned
// object pointer is then cast to a C/VB compatible type and returned
// to the calling routine.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" hALEntry AL_FUNCTION
ALEntryListGetFirstEntry( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListGetFirstEntry" );
return (hALEntry) ( ((ALEntryList *) this_object )->GetFirstEntry() );
}
//
// extern "C" void ALEntryListUnmarkDuplicates( hALEntryList this_object,
// hALEntryList list,
// char *error_message )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// list : Handle for (pointer to) another ALEntryList object.
// (can be the same one, no problem).
//
// error_message : A character string giving an error message that
// will be attached to each entry that turns out
// to be a duplicate and gets unmarked.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::UnmarkDuplicates(). This routine is
// used to remove the marks from any ALEntry objects in the list that
// are duplicated in another list.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handles (in debug mode), then calls the member function.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION
ALEntryListUnmarkDuplicates( hALEntryList this_object,
hALEntryList list,
char *error_message )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListUnmarkDuplicates" );
AL_ASSERT_OBJECT( list, ALEntryList, "ALEntryListUnmarkDuplicates" );
( (ALEntryList *) this_object )->UnmarkDuplicates( * (ALEntryList *) list, error_message );
}
//
// extern "C" int ALEntryListSetMarksFromDialog( hALEntryList this_object,
// HWND hDlg,
// int id )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// HDlg : Windows handle for a dialog box containing a list box
// control.
//
// id : The id of the list box in the dialog. The routine
// will set marks in the ALEntryList based on the
// names are set in the list box.
//
// RETURNS
//
// The number of entries marked in the list box.
//
// DESCRIPTION
//
// This is C translation function that provides access to the C++
// member function ALEntryList::SetMarksFromListBox(). This function is
// used to set marks in an ALEntryList based on selections made
// in a list box.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// Note that since this routine looks to a dialog for its input,
// it isn't useful to VB.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
extern "C" int AL_FUNCTION
ALEntryListSetMarksFromDialog( hALEntryList this_object, HWND hDlg, int id )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListSetMarksFromDialog" );
return ( (ALEntryList *) this_object)->SetMarksFromListBox( hDlg, id );
}
#endif
//
// extern "C" int ALEntryListSetMarksFromWindow( hALEntryList this_object,
// HWND hWnd )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// hWnd : Windows handle for a list box that contains names
// that are marked.
// RETURNS
//
// The number of entries marked in the list box.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::SetMarksFromListBox(). This function is
// called to transfer the marks a user makes in a list box into
// the ALEntryList.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
extern "C" int AL_FUNCTION
ALEntryListSetMarksFromWindow( hALEntryList this_object, HWND hWnd )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListSetMarksFromWindow" );
return ( (ALEntryList *) this_object )->SetMarksFromListBox( hWnd );
}
#endif
//
// extern "C" int ALEntryListFillListBoxWindow( hALEntryList this_object,
// HWND hWnd )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// hWnd : Windows handle for a list box that is going to get
// filled up.
// RETURNS
//
// The number of entries placed in the list box.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::SetMarksFromListBox(). This function
// is used to transfer the selections a user made in a list box into
// marks in the list.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
extern "C" int AL_FUNCTION
ALEntryListFillListBoxWindow( hALEntryList this_object,
HWND hWnd )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListFillListBoxWindow" );
return ( (ALEntryList *) this_object )->FillListBox( hWnd );
}
#endif
//
// extern "C" int ALEntryListFillListBoxDialog( hALEntryList this_object,
// HWND hDlg,
// int list_box_id )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// HDlg : Windows handle for a dialog box containing a list box
// control.
//
// id : The id of the list box in the dialog. The routine
// will fill up this list box with the names of all
// the marked files in this_object.
//
// RETURNS
//
// The number of entries added to the list box.
//
// DESCRIPTION
//
// This is C translation function that provides access to the C++
// member function ALEntryList::FillListBox(). This routine is called
// to fill a list box with the names of storage objects in the list.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// Note that since this routine wants to use a list box that is
// embedded in a dialog box, it isn't much use to VB.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_GUI )
extern "C" int AL_FUNCTION
ALEntryListFillListBoxDialog( hALEntryList this_object,
HWND hDlg,
int list_box_id )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListFillListBoxDialog" );
return ( (ALEntryList *) this_object )->FillListBox( hDlg, list_box_id );
}
#endif
//
// extern "C" void deleteALEntryList( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// None, a destructor.
//
// DESCRIPTION
//
// This is the C/VB translation routine for the ALEntryList destructor.
// You don't see much exciting code in this routine, so if you want to
// see exactly what is going on in the destructor, take a look at
// ARCENTRY.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION deleteALEntryList( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "deleteALEntryList" );
delete (ALEntryList *) this_object;
}
//
// extern "C" int ALEntryListSetMarks( hALEntryList this_object,
// char *pattern )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// pattern : A regular expression (wildcard) that will be used as
// a pattern to set marks in the list.
//
// RETURNS
//
// The number of entries marked in the list.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::SetMarks(). This function is used
// to set marks for ALEntry objects in the list that match the wild
// card pattern.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEntryListSetMarks( hALEntryList this_object,
char AL_DLL_FAR *pattern )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListSetMarks" );
return ( (ALEntryList *) this_object )->SetMarks( pattern );
}
//
// extern "C" int ALEntryListClearMarks( hALEntryList this_object,
// char *pattern )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// pattern : A regular expression (wildcard) that will be used as
// a pattern to clear marks in the list.
//
// RETURNS
//
// The number of entries cleared in the list.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::ClearMarks(). It is used to clear
// the marks of entries in the list that match the wildcard pattern.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEntryListClearMarks( hALEntryList this_object,
char AL_DLL_FAR *pattern )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListClearMarks" );
return ( (ALEntryList *) this_object )->ClearMarks( pattern );
}
//
// extern "C" int ALEntryListDeleteUnmarked( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
//
// RETURNS
//
// The number of entries deleted from the list.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::DeleteUnmarked(). This function is used
// to delete ALEntry objects from the list.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION
ALEntryListDeleteUnmarked( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListDeleteUnmarked" );
return ( (ALEntryList *) this_object )->DeleteUnmarked();
}
//
// extern "C" int ALEntryListToggleMarks( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// The number of entries whose marks were toggled.
//
// DESCRIPTION
//
// This is C/VB translation function that provides access to the C++
// member function ALEntryList::ToggleMarks(). This function is used
// toggle the marks of *every* entry in the list.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALEntryListToggleMarks( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListToggleMarks" );
return ( (ALEntryList *) this_object )->ToggleMarks();
}
//
// extern "C" int ALEntryListGetStatusCode( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// The current status integer for the ALEntryList object.
//
// DESCRIPTION
//
// This is a C/VB translation function that provides access to the C++
// member function ALStatus::GetStatusCode(), for the mStatus data
// member for the ALEntryList object.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// returns the status integer unchanged to the calling procedure.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION
ALEntryListGetStatusCode( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListGetStatusCode" );
return ( (ALEntryList *) this_object )->mStatus.GetStatusCode();
}
//
// extern "C" char * ALEntryListGetStatusString( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// The current status string translation for the ALEntryList object.
//
// Note that this return type is just not very good for VB people.
// They should use the VB specific function to get a real VB string
// back.
//
// DESCRIPTION
//
// This is C translation function that provides access to the C++
// member function ALStatus::GetStatusString(), for the mStatus data
// member for the ALEntryList object. This is the short string
// translation, not the status detail.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// then casts and returns the status string.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALEntryListGetStatusString( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListGetStatusString" );
const char *status = ( (ALEntryList *) this_object)->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" char * ALEntryListGetStatusDetail( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// The current status string detail for the ALEntryList object.
//
// Note that this return type is just not very good for VB people.
// They should use the VB specific function to get a real VB string
// back.
//
// DESCRIPTION
//
// This is C translation function that provides access to the C++
// member function ALStatus::GetStatusDetail(), for the mStatus data
// member for the ALEntryList object. This is the detailed message,
// not to be confused with the short translation.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// then casts and returns the status string.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
ALEntryListGetStatusDetail( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListGetStatusString" );
const char *status = ( (ALEntryList *) this_object )->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return (char AL_DLL_FAR *) status;
}
//
// extern "C" long ALEntryListGetStatusStringVB( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// The current status string translation for the ALEntryList object.
//
// Note that this function performs a translation of the string type to
// a VB string. It won't do you much good to call this from a C program.
//
// DESCRIPTION
//
// This is VB translation function that provides access to the C++
// member function ALStatus::GetStatusString(), for the mStatus data
// member for the ALEntryList object. This is the short string
// translation, not the status detail.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// then converts and returns the status string.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION
ALEntryListGetStatusStringVB( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryLisGetStatusStringVB" );
const char _far *status = ( (ALEntryList *) this_object )->mStatus.GetStatusString();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif
//
// extern "C" long ALEntryListGetStatusDetailVB( hALEntryList this_object )
//
// ARGUMENTS:
//
// this_object : Handle for (pointer to) an ALEntryList object.
//
// RETURNS
//
// The current status detail string for the ALEntryList object.
//
// Note that this function performs a translation of the string type to
// a VB string. It won't do you much good to call this from a C program.
//
// DESCRIPTION
//
// This is VB translation function that provides access to the C++
// member function ALStatus::GetStatusDetail(), for the mStatus data
// member for the ALEntryList object. This is the detailed status
// string, not the short status translation.
//
// Like most of the translation functions, you don't get to see much here.
// For detailed information on what happens in the member function, check
// ARCENTRY.CPP.
//
// This routine first performs type checking on the passed object
// handle (in debug mode), then calls the member function. It
// then converts and returns the status string.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
extern "C" long AL_FUNCTION
ALEntryListGetStatusDetailVB( hALEntryList this_object )
{
AL_ASSERT_OBJECT( this_object, ALEntryList, "ALEntryListGetStatusDetailVB" );
const char _far *status = ( (ALEntryList *) this_object )->mStatus.GetStatusDetail();
if ( status == 0 )
status = "";
return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) );
}
#endif

348
al/cxl_mem.cpp Executable file
View File

@ -0,0 +1,348 @@
//
// CXL_MEM.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALMemory()
// ALMemoryGetBufferOwner()
// ALMemorySetBufferOwner()
// ALMemoryGetHandle()
// ALMemoryGetBufferSize()
// ALMemoryGetBuffer()
//
//
// DESCRIPTION
//
// This file contains the C and VB translation routines to access
// class ALMemory. Most of the ALStorage routines need to be called
// via the base class, so most of the functions to use ALMemory
// from C or VB will be found in CXL_STOR.CPP.
//
// As always, these translation routines are extremely uninformative.
// To get the real lowdown on what is happening, look first at the C++
// member functions in MEMSTORE.CPP, then STORAGE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
// Windows:
//
// extern "C" hALStorage newALMemory( char *buffer_name,
// char AL_HUGE *user_buffer,
// DWORD user_buffer_size )
//
// MS-DOS:
//
// extern "C" hALStorage newALMemory( char *buffer_name,
// char *user_buffer,
// int user_buffer_size )
// ARGUMENTS:
//
// name : A character string containing an arbitrary name
// name for the memory buffer.
//
// user_buffer : If you want to supply a buffer of your own, pass it
// here. Otherwise, set it to 0, and the ALMemory
// class will allocate storage as needed.
//
// user_buffer_size : If you are supplying a buffer, you have to say how
// long it is.
//
// RETURNS
//
// A handle for (pointer to) a newly created ALMemory object.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the ALMemory
// constructor. Note that the constructor has the same name under
// MS-DOS and Windows, but it does have slightly different capabilities.
// Because of this, the Windows version also has different argument types.
//
// This function passes all of its arguments to the C++ constructor
// in unchanged form. It then takes the return from the function, casts
// it to a C/VB acceptable type, and returns it otherwise unchanged.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real information about what
// is happening in the constructor, take a look at the source for the
// C++ functions in MEMSTORE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_MEMORY )
extern "C" hALStorage AL_FUNCTION
newALMemory( char AL_DLL_FAR *buffer_name,
char AL_HUGE *user_buffer,
DWORD user_buffer_size )
{
if ( user_buffer_size == 0 )
return (hALStorage) new ALMemory( buffer_name );
else
return (hALStorage) new ALMemory( buffer_name, user_buffer, user_buffer_size );
}
#else
extern "C" hALStorage AL_FUNCTION newALMemory( char AL_DLL_FAR *buffer_name,
char AL_DLL_FAR *user_buffer,
int user_buffer_size )
{
if ( user_buffer_size == 0 )
return (hALStorage) new ALMemory( buffer_name );
else
return (hALStorage) new ALMemory( buffer_name, user_buffer, user_buffer_size );
}
#endif
//
// extern "C" int ALMemoryGetBufferOwner( hALStorage this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALMemory object.
//
// RETURNS
//
// An integer flag indicating whether the user owns the buffer.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMemory::mfUserOwnsBuffer.
//
// This function first tests its only argument for correct type (when in
// debug mode), then casts and accesses the data member. The value of
// the data member is then returned unchanged to the calling C or VB
// procedure.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real information about what
// is happening in the constructor, take a look at the source for the
// C++ functions in MEMSTORE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" int AL_FUNCTION ALMemoryGetBufferOwner( hALStorage this_object )
{
AL_ASSERT_OBJECT( this_object, ALMemory, "ALMemoryGetBufferOwner" );
return ( (ALMemory *) this_object )->mfUserOwnsBuffer;
}
//
// extern "C" void ALMemorySetBufferOwner( hALStorage this_object,
// int user_owns_buffer )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALMemory object.
//
// user_owns_buffer : The new setting of the flag.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMemory::mfUserOwnsBuffer. Why would you want to change this
// data member? Well, if the ALMemory object is currently the buffer
// owner, the buffer will be deleted when the ALMemory object is destroyed.
// You can set the owner of the buffer to be you, the user, and copy
// the pointer to it. Then you get to keep it long after the ALMemory
// object is done with it.
//
// This function first tests its only argument for correct type (when in
// debug mode), then casts and modifies the data member.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real information about what
// is happening in the constructor, take a look at the source for the
// C++ functions in MEMSTORE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION ALMemorySetBufferOwner( hALStorage this_object,
int user_owns_buffer )
{
AL_ASSERT_OBJECT( this_object, ALMemory, "ALMemorySetBufferOwner" );
( (ALMemory *) this_object )->mfUserOwnsBuffer = user_owns_buffer;
}
// WINDOWS ONLY PROCEDURE
//
// extern "C" UINT ALMemoryGetHandle( hALStorage this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALMemory object.
//
// RETURNS
//
// A UINT windows memory handle.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMemory::mhUserMemoryHandle. Under C++, this is a public data
// member that the programmer is free to access or modify.
//
// This function first tests its only argument for correct type (when in
// debug mode), then casts and accesses the data member. The value of
// the data member is then returned unchanged to the calling C or VB
// procedure.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real information about what
// is happening in the constructor, take a look at the source for the
// C++ functions in MEMSTORE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_MEMORY )
extern "C" UINT AL_FUNCTION ALMemoryGetHandle( hALStorage this_object )
{
AL_ASSERT_OBJECT( this_object, ALMemory, "ALMemorySetBufferOwner" );
return (UINT) ( (ALMemory *) this_object )->mhUserMemoryHandle;
}
#endif
// WINDOWS Version
//
// extern "C" long ALMemoryGetBufferSize( hALStorage this_object )
//
// MS-DOS Real Mode version
//
// extern "C" size_t ALMemoryGetBufferSize( hALStorage this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALMemory object.
//
// RETURNS
//
// The size of the memory buffer being uses as a storage object. The
// type of the the size differs between Windows and Real mode DOS, simply
// because Windows can access a lot more memory, especially when
// using Win32s.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMemory::muUserBufferSize. Under C++, this is a public data
// member that the programmer is free to access or modify.
//
// This function first tests its only argument for correct type (when in
// debug mode), then casts and accesses the data member. The value of
// the data member is then returned unchanged to the calling C or VB
// procedure.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real information about what
// is happening in the constructor, take a look at the source for the
// C++ functions in MEMSTORE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_MEMORY )
extern "C" long AL_FUNCTION ALMemoryGetBufferSize( hALStorage this_object )
{
AL_ASSERT_OBJECT( this_object, ALMemory, "ALMemoryGetBufferSize" );
return ( (ALMemory *) this_object )->muUserBufferSize;
}
#else
extern "C" size_t AL_FUNCTION ALMemoryGetBufferSize( hALStorage this_object )
{
AL_ASSERT_OBJECT( this_object, ALMemory, "ALMemoryGetBufferSize" );
return ( (ALMemory *) this_object )->muUserBufferSize;
}
#endif
// WINDOWS Version
//
// extern "C" char AL_HUGE * ALMemoryGetBuffer( hALStorage this_object )
//
// MS-DOS Real Mode version
//
// extern "C" char *ALMemoryGetBuffer( hALStorage this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALMemory object.
//
// RETURNS
//
// A pointer to the memory buffer being uses as a storage object. The
// type of the the pointer differs between the various modes of our
// library. Under Real Dos, it is just a normal pointer. Under Win16
// it is a _huge pointer. Under Win32s, it is a flat model pointer.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMemory::mpcUserBuffer. Under C++, this is a public data
// member that the programmer is free to access or modify.
//
// This function first tests its only argument for correct type (when in
// debug mode), then casts and accesses the data member. The value of
// the data member is then returned unchanged to the calling C or VB
// procedure.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real information about what
// is happening in the constructor, take a look at the source for the
// C++ functions in MEMSTORE.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_MEMORY )
extern "C" char AL_HUGE * AL_FUNCTION ALMemoryGetBuffer( hALStorage this_object )
{
AL_ASSERT_OBJECT( this_object, ALMemory, "ALMemoryGetBuffer" );
return ( (ALMemory *) this_object )->mpcUserBuffer;
}
#else
extern "C" char AL_DLL_FAR *AL_FUNCTION ALMemoryGetBuffer( hALStorage this_object )
{
AL_ASSERT_OBJECT( this_object, ALMemory, "ALMemoryGetBuffer" );
return ( (ALMemory *) this_object )->mpcUserBuffer;
}
#endif

246
al/cxl_mon.cpp Executable file
View File

@ -0,0 +1,246 @@
//
// CXL_MON.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALMonitorSetObjectSize()
// ALMonitorSetObjectStart()
// ALMonitorSetJobSize()
// ALMonitorSetJobSoFar()
// deleteALMonitor()
//
// DESCRIPTION
//
// This file contains a few access routines
// We don't really do anything exciting in the WEP, it is just
// here for decoration. LibMain() has to set up memory allocation
// for Borland.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" long ALMonitorSetObjectSize( hALMonitor this_object,
// long size )
//
// ARGUMENTS:
//
// this_object : The monitor whose object size member needs to be set.
//
// size : The new value to be assigned to mlObjectSize.
//
// RETURNS
//
// The long size value.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMonitor::mlObjectSize. Why would you want to change this
// data member? Normally this data member is set up by the member functions
// of ALArchiveBase before performing an operation. If you are trying
// to use a monitor to provide feedback on an operation of your own,
// such as a file copy, you would have to set the data member up
// using this function.
//
// This function first tests its handle argument for correct type (when in
// debug mode), then casts and modifies the data member.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real scoop on monitor objects,
// look at MONITOR.CPP and ARCHIVEB.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" long AL_FUNCTION ALMonitorSetObjectSize( hALMonitor this_object,
long size )
{
AL_ASSERT_OBJECT( this_object, ALMonitor, "ALMonitorSetObjectSize" );
return ( (ALMonitor *) this_object )->mlObjectSize = size;
}
//
// extern "C" long ALMonitorSetObjectStart( hALMonitor this_object,
// long offset )
//
// ARGUMENTS:
//
// this_object : The monitor whose object start member needs to be set.
//
// offset : The new value to be assigned to mlObjectStart.
//
// RETURNS
//
// The long offset value.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMonitor::mlObjectStart. Why would you want to change this
// data member? Normally this data member is set up by the member functions
// of ALArchiveBase before performing an operation. If you are trying
// to use a monitor to provide feedback on an operation of your own,
// such as a file copy, you would have to set the data member up
// using this function.
//
// This function first tests its handle argument for correct type (when in
// debug mode), then casts and modifies the data member.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real scoop on monitor objects,
// look at MONITOR.CPP and ARCHIVEB.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" long AL_FUNCTION ALMonitorSetObjectStart( hALMonitor this_object,
long offset )
{
AL_ASSERT_OBJECT( this_object, ALMonitor, "ALMonitorSetObjectStart" );
return ( (ALMonitor *) this_object )->mlObjectStart = offset;
}
//
// extern "C" long ALMonitorSetJobSize( hALMonitor this_object,
// long size )
//
// ARGUMENTS:
//
// this_object : The monitor whose job size member needs to be set.
//
// size : The new value to be assigned to mlJobSize.
//
// RETURNS
//
// The long size value.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMonitor::mlJobSize. Why would you want to change this
// data member? Normally this data member is set up by the member functions
// of ALArchiveBase before performing an operation. If you are trying
// to use a monitor to provide feedback on an operation of your own,
// such as a batch file copy, you would have to set the data member up
// using this function.
//
// This function first tests its handle argument for correct type (when in
// debug mode), then casts and modifies the data member.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real scoop on monitor objects,
// look at MONITOR.CPP and ARCHIVEB.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" long AL_FUNCTION ALMonitorSetJobSize( hALMonitor this_object,
long size )
{
AL_ASSERT_OBJECT( this_object, ALMonitor, "ALMonitorSetJobSize" );
return ( (ALMonitor *) this_object )->mlJobSize = size;
}
//
// extern "C" long ALMonitorSetJobSoFar( hALMonitor this_object,
// long job_so_far )
//
// ARGUMENTS:
//
// this_object : The monitor whose "job so far" member needs to be set.
//
// job_so_far : The new value to be assigned to mlJobSoFar.
//
// RETURNS
//
// The new value of mlJobSoFar.
//
// DESCRIPTION
//
// This C/VB translation function provides access to the C++ data member
// ALMonitor::mlJobSoFar. Why would you want to change this
// data member? Normally this data member is set up by the member functions
// of ALArchiveBase before performing an operation. If you are trying
// to use a monitor to provide feedback on an operation of your own,
// such as a batch file copy, you would have to set the data member up
// using this function.
//
// This function first tests its handle argument for correct type (when in
// debug mode), then casts and modifies the data member.
//
// This function is like all of the other translation routines in that
// it is fairly uninformative. To get the real scoop on monitor objects,
// look at MONITOR.CPP and ARCHIVEB.CPP.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
extern "C" long AL_FUNCTION ALMonitorSetJobSoFar( hALMonitor this_object,
long job_so_far )
{
AL_ASSERT_OBJECT( this_object, ALMonitor, "ALMonitorSetJobSoFar" );
return ( (ALMonitor *) this_object )->mlJobSoFar = job_so_far;
}
//
// extern "C" void deleteALMonitor( hALMonitor this_object )
//
// ARGUMENTS:
//
// this_object : The monitor object to be destroyed. This will usually
// be an object from a derived class, not the base class.
// The dtor is virtual, so we always call the base
// class destructor using this function.
//
// RETURNS
//
// No returns, this is a destructor.
//
// DESCRIPTION
//
// This is the C/VB wrapper function that calls the destructor for an
// ALMonitor object. This is a virtual destructor, so you won't find
// equivalent functions defined for the base classes used with
// ArchiveLib.
//
// This function just checks its single argument for correct type, then
// casts it and calls the destructor.
//
// Like most of these wrapper functions, this is fairly unenlightening.
// For more real dirt, try looking at the base class dtor in MONITOR.CPP,
// or derived class dtors in BARGRAPH.CPP and WINMON.CPP.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION deleteALMonitor( hALMonitor this_object )
{
AL_ASSERT_OBJECT( this_object, ALMonitor, "deleteALMonitor" );
delete (ALMonitor *) this_object;
}

2432
al/cxl_sobj.cpp Executable file

File diff suppressed because it is too large Load Diff

153
al/cxl_util.cpp Executable file
View File

@ -0,0 +1,153 @@
//
// CXL_UTIL.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// StripFileName()
// StripFileNameVB()
// StripPath()
// StripPathVB()
//
// DESCRIPTION
//
// This file contains a couple of C/VB functions that are used to
// mangle file names. They defied ordinary categorization, so they
// ended up here. The deal is that they operate on objects of class
// ALName, but there is no C/VB translation for ALName. Because of
// this, we provide these versions that return native string types.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
// C TRANSLATION FUNCTION
//
// extern "C" char * StripFileName( char *filename )
//
// VB TRANSLATION FUNCTION
//
// extern "C" long StripFileNameVB( char *filename )
//
// ARGUMENTS:
//
// filename : An ordinary VB or C string that contains a file name.
//
// RETURNS
//
// Either a C or VB string type, containing just the path. Note that
// the C version of the function copies over your existing string,
// whereas the VB version creates a new VB string.
//
// DESCRIPTION
//
// This function takes a file name, and strips off any filename and
// extension, leaving the drive and path name. These functions are
// very handy when it comes to wild card expansion, which is why
// they are in ArchiveLib.
//
// If you want to see how the C++ member functions perform these
// amazing feats, see OBJNAME.CPP.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
// The C translation function.
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
StripFileName( char AL_DLL_FAR *filename )
{
ALName temp = filename;
temp.StripFileName();
strcpy( filename, temp );
return filename;
}
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
//
// The VB translation function.
//
extern "C" long AL_FUNCTION StripFileNameVB( char AL_DLL_FAR *filename )
{
ALName temp = filename;
char _far *p = temp.StripFileName();
return ALCreateVBString( p, (unsigned short int) _fstrlen( p ) );
}
#endif
// C TRANSLATION FUNCTION
//
// extern "C" char * StripPath( char *filename )
//
// VB TRANSLATION FUNCTION
//
// extern "C" long StripPathVB( char *filename )
//
// ARGUMENTS:
//
// filename : An ordinary VB or C string that contains a file name.
//
// RETURNS
//
// Either a C or VB string type, with the drive and path stripped,
// leaving just a filename and extension. Note that
// the C version of the function copies over your existing string,
// whereas the VB version creates a new VB string.
//
// DESCRIPTION
//
// This function takes a file name, and strips off any path and drive
// information, leaving the file and extension. These functions are
// very handy when it comes to wild card expansion, which is why
// they are in ArchiveLib.
//
// If you want to see how the C++ member functions perform these
// amazing feats, see OBJNAME.CPP.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
// The C translation function.
//
extern "C" char AL_DLL_FAR * AL_FUNCTION
StripPath( char AL_DLL_FAR *filename )
{
ALName temp = filename;
temp.StripPath();
strcpy( filename, temp );
return filename;
}
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
//
// The VB translation function
//
extern "C" long AL_FUNCTION StripPathVB( char AL_DLL_FAR *filename )
{
ALName temp = filename;
char _far *p = temp.StripPath();
return ALCreateVBString( p, (unsigned short int) _fstrlen( p ) );
}
#endif

184
al/cxl_wild.cpp Executable file
View File

@ -0,0 +1,184 @@
//
// CXL_UTIL.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// newALExpander()
// ALExpanderGetNextFile()
// ALExpanderGetNextFileVB()
// deleteALExpander()
//
// DESCRIPTION
//
// This file contains the C and VB interface functions for using
// the ALWildCardExpander class. This consists of only a
// constructor, destructor, and a Get Next File function.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "al.h"
#include "alcxl.h"
//
// extern "C" hALExpander newALExpander( char *wild_spec,
// int traverse_flag,
// ALCase name_case )
//
// ARGUMENTS:
//
// wild_spec : A sequence of wild card file specifications separated
// by spaces or semicolons.
//
// traverse_flag : set this guy if you want the wild card expansion
// to traverse all subdirectories.
//
// name_case : How the names will be returned, AL_UPPER, AL_MIXED,
// or AL_LOWER.
//
//
// RETURNS
//
// Returns a handle for (pointer to) a newly constructed
// ALWildCardExpander object.
//
// DESCRIPTION
//
// This ctor is used to create a new ALWildCardExpander object from
// C or VB. It operates identically to the wild card expander
// constructors defined in WILDCARD.CPP.
//
// You don't get to see much of the wild card expander code in this
// module, since this is just a translation layer. Look at WILDCARD.CPP
// for lots of neat stuff.
//
// This function passes the arguments it receives to the constructor
// with no changes. It then casts the return value to the appropriate
// handle type, and returns it to the calling procedure.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
extern "C" hALExpander AL_FUNCTION newALExpander( char *wild_spec,
int recurse_flag,
ALCase name_case )
{
ALWildCardExpander *expander;
expander = new ALWildCardExpander( wild_spec, recurse_flag, name_case );
return (hALExpander) expander;
}
// C TRANSLATION FUNCTION
//
// extern "C" char * ALExpanderGetNextFile( hALExpander this_object )
//
// VB TRANSLATION FUNCTION
//
// extern "C" long ALExpanderGetNextFileVB( hALExpander this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALWildCardExpander
// object.
//
// RETURNS
//
// A string containing the next expanded wild card generated by
// the wild card engine. Note that under C, you will get a pointer
// to a string that is residing inside the ALWildCardExpander
// object, which you are free to copy or duplicate. The VB translation
// function actually creates a new string using the ALCreateVBString
// function.
//
// DESCRIPTION
//
// This function provides a C or VB translation layer that allows you to
// access the ALWildCardExpander::GetNextFile() function. The function
// operators by first checking the single handle argument for correct
// type (in debug mode). It then casts the handle to an object pointer,
// and uses that to invoke the member function. Under C, the return from
// the member function is passed directly back to the calling routine.
// Under VB, the return is first converted to a Visual Basic string, then
// returned.
//
// To see the details of ALWildCardExpander::GetNextFile(), look at
// WILDCARD.CPP.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
//
// The C translation layer.
//
extern "C" char * AL_FUNCTION
ALExpanderGetNextFile( hALExpander this_object )
{
AL_ASSERT_OBJECT( this_object, ALWildCardExpander, "ALExpanderGetNextFile" );
return ( (ALWildCardExpander *) this_object )->GetNextFile();
}
#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL )
//
// VB translation layer.
//
extern "C" long AL_FUNCTION
ALExpanderGetNextFileVB( hALExpander this_object )
{
AL_ASSERT_OBJECT( this_object, ALWildCardExpander, "ALExpanderGetNextFileVB" );
char _far *ret_guy = ( (ALWildCardExpander *) this_object )->GetNextFile();
if ( ret_guy == 0 )
ret_guy = "";
return ALCreateVBString( ret_guy, (unsigned short int) _fstrlen( ret_guy ) );
}
#endif
//
// extern "C" void deleteALExpander( hALExpander this_object )
//
// ARGUMENTS:
//
// this_object : A handle for (pointer to) an ALWildCardExpander
// object.
//
// RETURNS
//
// Nothing, this is a destructor.
//
// DESCRIPTION
//
// This function provides a C or VB translation layer that allows you to
// access the ALWildCardExpander destructor. The function works
// by first checking the single handle argument for correct
// type (in debug mode). It then casts the handle to an object pointer,
// and uses that to invoke the destructor.
//
// To see the details of the ALWildCardExpander destructor, look at
// WILDCARD.CPP.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
extern "C" void AL_FUNCTION deleteALExpander( hALExpander this_object )
{
AL_ASSERT_OBJECT( this_object, ALWildCardExpander, "deleteALExpander" );
delete (ALWildCardExpander *) this_object;
}

363
al/fileattr.cpp Executable file
View File

@ -0,0 +1,363 @@
//
// FILEATTR.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALFileAttributes::operator new()
// ALFileAttributes::ALFileAttributes()
// ALFileAttributes::~ALFileAttributes()
// ALFileAttributes::SetFromPackedAttributes()
// ALFileAttributes::SetFromWin32Attributes()
// ALFileAttributes::SetFromDosAttributes()
// ALFileAttributes::PackedAttributes()
// ALFileAttributes::GetDosAttributes()
//
// DESCRIPTION
//
// This file contains all of the source to support the ALFileAttributes
// class. Even though this is in theory a standalone, independent class,
// it really has not life of its own. It always exists as a data
// member embedded in ALStorage. The only reason these functions aren't
// member functions of ALStorage was simply to modularize things a bit.
// As it is, it makes pretty good sense as a class of its own.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
#include "arclib.h"
#pragma hdrstop
#include <dos.h>
#include "fileattr.h"
//
// void * ALFileAttributes::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The amount of storage that needs to be allocated for
// this object.
//
// RETURNS
//
// A pointer to the storage.
//
// DESCRIPTION
//
// When using the DLL version of ArchiveLib, it is a good idea to
// allocate the storage for objects from inside the DLL, since they
// will be freed inside the DLL. If we don't have the new operator
// for a class, its storage will be allocated from the EXE before
// the constructor code is called. Then, when it is time to free
// the storage, the delete operator will be called inside the DLL.
// Not good, right?
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALFileAttributes::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALFileAttributes::ALFileAttributes()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Constructor, no return.
//
// DESCRIPTION
//
// This is the only constructor for class ALFileAttributes. It does
// nothing more than set all of the bits to 0. I was thinking that
// it might be a good idea to set them to -1 instead, indicating that
// they are presently in an unknown state. I would want to set them
// to 0 when I called Create(), and read them in when I call Open().
// Just thinking out loud.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
AL_PROTO ALFileAttributes::ALFileAttributes()
{
miReadOnly = 0;
miSystem = 0;
miHidden = 0;
miArchive = 0;
}
//
// ALFileAttributes::~ALFileAttributes()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Destructor, no returns.
//
// DESCRIPTION
//
// The destructor doesn't have to worry about freeing any dynamic
// storage or anything like that, so it gets to do a great big nothing.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
AL_PROTO ALFileAttributes::~ALFileAttributes()
{
}
//
// void ALFileAttributes::SetFromPackedAttributes( short int attributes )
//
// ARGUMENTS:
//
// attributes : A set of attributes that have been packed into a
// short int using our internal bit ordering:
//
// X | X | X | X | A | H | S | R
//
// RETURNS
//
// Nothing, a void function.
//
// DESCRIPTION
//
// The packed format is how we actually store file attributes in an
// archive. When we read in the directory from an archive, we can
// use this function to apply the packed attribute bits to a storage
// object. All it has to do is set the four bits internal to the
// class.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
void AL_PROTO ALFileAttributes::
SetFromPackedAttributes( short int attributes )
{
miReadOnly = ( attributes & 1 ) != 0;
miSystem = ( attributes & 2 ) != 0;
miHidden = ( attributes & 4 ) != 0;
miArchive = ( attributes & 8 ) != 0;
}
//
// void ALFileAttributes::SetFromWin32Attributes( DWORD win32_attributes )
//
// ARGUMENTS:
//
// attributes : The set of file attributes as defined for Win32s.
// These are the attributes you get back from the
// GetFileAttributes() function call.
//
// RETURNS
//
// Nothing, a void function.
//
// DESCRIPTION
//
// When the ALFile class opens a file under Win32s, it reads in
// the file attributes with a call to GetFileAttributes. It can then store
// those file attributes in the ALFileAttributes member of ALStorage
// by calling this function.
//
// Converting the data to our internal format is simply a matter of picking
// bits out of a DWORD.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
#if defined( AL_WIN32S )
void AL_PROTO ALFileAttributes::
SetFromWin32Attributes( DWORD win32_attributes )
{
miReadOnly = ( win32_attributes & FILE_ATTRIBUTE_READONLY ) != 0;
miSystem = ( win32_attributes & FILE_ATTRIBUTE_SYSTEM ) != 0;
miHidden = ( win32_attributes & FILE_ATTRIBUTE_HIDDEN ) != 0;
miArchive = ( win32_attributes & FILE_ATTRIBUTE_ARCHIVE ) != 0;
}
#endif
//
// void ALFileAttributes::SetFromDosAttributes( unsigned dos_attributes )
//
// ARGUMENTS:
//
// attributes : The set of file attributes as defined for MS-DOS.
// These are the attributes you get back from the
// _dos_getfileattr() function call.
//
// RETURNS
//
// Nothing, a void function.
//
// DESCRIPTION
//
// When the ALFile class opens a file under MS-DOS or Windows, it reads in
// the file attributes with a call to _dos_getfileattr(). It can then store
// those file attributes in the ALFileAttributes member of ALStorage
// by calling this function.
//
// Converting the data to our internal format is simply a matter of picking
// bits out of an unsigned int
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
#if !defined( AL_WIN32S )
void AL_PROTO ALFileAttributes::SetFromDosAttributes( unsigned dos_attributes )
{
miReadOnly = ( dos_attributes & _A_RDONLY ) != 0;
miSystem = ( dos_attributes & _A_SYSTEM ) != 0;
miHidden = ( dos_attributes & _A_HIDDEN ) != 0;
miArchive = ( dos_attributes & _A_ARCH ) != 0;
}
#endif
//
// unsigned short int ALFileAttributes::PackedAttributes()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// An unsigned short int containing the four file attribute bits, packed
// into the format we use to store file attributes in an archive:
//
//
// X | X | X | X | A | H | S | R
//
// DESCRIPTION
//
// When it comes time to write an archive directory out to disk, we need
// to store the file attributes in a consistent format. This format
// is our internal packed attribute format. You can get the file attributes
// in this packed attribute format with a call to this function.
//
// REVISION HISTORY
//
// May 25, 1994 1.0A : First release
//
unsigned short int AL_PROTO ALFileAttributes::PackedAttributes()
{
int result = 0;
result |= miReadOnly ? 1 : 0;
result |= miSystem ? 2 : 0;
result |= miHidden ? 4 : 0;
result |= miArchive ? 8 : 0;
return (unsigned short int ) result;
}
//
// unsigned short int ALFileAttributes::GetDosAttributes()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// The set of file attributes, packed into the order that MS-DOS
// expects them for the _dos_setfileattr() function call.
//
// DESCRIPTION
//
// When we are closing a file that we have to set the time stamp and
// attributes for, this function is used to get the attributes.
// Under MS-DOS at least. All it needs to do is repack some bits
// into the order that MS-DOS expects.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if !defined( AL_WIN32S )
unsigned short int AL_PROTO ALFileAttributes::GetDosAttributes()
{
int result = 0;
result |= miReadOnly ? _A_RDONLY : 0;
result |= miSystem ? _A_SYSTEM : 0;
result |= miHidden ? _A_HIDDEN : 0;
result |= miArchive ? _A_ARCH : 0;
return (unsigned short int) result;
}
#endif //#if !defined( AL_WIN32S )
//
// DWORD ALFileAttributes::GetWin32Attributes()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// The set of file attributes, packed into the order that Win32s
// expects them for the SetFileAttributes() function call.
//
// DESCRIPTION
//
// When we are closing a file that we have to set the time stamp and
// attributes for, this function is used to get the attributes.
// Under Win32s at least. All it needs to do is repack some bits
// into the order that Win32s expects.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_WIN32S )
DWORD AL_PROTO ALFileAttributes::GetWin32Attributes()
{
DWORD result = 0;
result |= miReadOnly ? FILE_ATTRIBUTE_READONLY : 0;
result |= miSystem ? FILE_ATTRIBUTE_SYSTEM : 0;
result |= miHidden ? FILE_ATTRIBUTE_HIDDEN : 0;
result |= miArchive ? FILE_ATTRIBUTE_ARCHIVE : 0;
return result;
}
#endif //#if !defined( AL_WIN32S )

111
al/fileattr.h Executable file
View File

@ -0,0 +1,111 @@
/*
* FIELATTR.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file contains the class definition for ALFileAttributes.
*
* CLASS DEFINITIONS:
*
* ALFileAttributes
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _FILEATTR_H
#define _FILEATTR_H
/*
* class ALFileAttributes
*
* DESCRIPTION
*
* This class is used to carry around file attributes. Its only
* real job at this time is to sit in the ALStorage class
* and then produce packed attributes for inclusion in an archive,
* and vice versa. We will need to add some additional members
* here for searching archives based on certain attribute criteria.
*
* Note that most of the classes in Archive library deliberately
* withhold the copy constructor and assignment operator. In this case,
* however, the compiler is able to generate an adequate version of
* these functions, so they aren't disabled.
*
* DATA MEMBERS
*
* miReadOnly : The read only file attribute bit, set when the file
* is opened or when the directory is read from the archive.
*
* miSystem : The system file attribute bit.
*
* miHidden : The hidden file attribute bit.
*
* miArchive : The archive (backup) file attribute bit.
*
* MEMBER FUNCTIONS
*
* ALFileAttributes() : The constructor, doesn't have to do much.
* ~ALFileAttributes() : The destructor, doesn't have to do anything.
* operator new( size_t size ) : Memory allocation operator, only used if
* the library is inside a DLL.
* PackedAttributes() : Returns the bits packed into an integer
* in ArchiveLib proprietary format.
* SetFromWin32Attributes() : Sets the four member bits using as input
* the attributes as returned in a Win32 call.
* GetWin32Attributes() : Returns the four member bits packed into
* Win 32 format.
* SetFromDosAttributes() : Sets the four using as input the settings
* returned from a DOS function call.
* GetDosAttributes() : Returns the member bits formatted into
* the short int used by a Dos function call.
* SetFromPackedAttributes() : Sets the member bits using as input a
* short int in proprietary ArchiveLib format.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALFileAttributes {
/*
* Constructors, destructors, declarations, and friends
*/
public :
AL_PROTO ALFileAttributes();
AL_PROTO ~ALFileAttributes();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Member functions
*/
public :
short unsigned int AL_PROTO PackedAttributes();
#if defined( AL_WIN32S )
void AL_PROTO SetFromWin32Attributes( DWORD win32_attributes );
DWORD AL_PROTO GetWin32Attributes();
#else
void AL_PROTO SetFromDosAttributes( unsigned dos_attributes );
unsigned short int AL_PROTO GetDosAttributes();
#endif
void AL_PROTO SetFromPackedAttributes( short int attributes );
/*
* Data members
*/
protected :
int miReadOnly:1;
int miSystem:1;
int miHidden:1;
int miArchive:1;
};
#endif /* #ifndef _FILEATTR_H */

837
al/filestor.cpp Executable file
View File

@ -0,0 +1,837 @@
//
// FILESTOR.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALFile::operator new()
// ALFile::ALFile()
// ALFile::~ALFile()
// ALFile::LoadBuffer()
// ALFile::FlushBuffer()
// ALFile::Seek()
// ALFile::Open()
// ALFile::MakeTempName()
// ALFile::Create()
// ALFile::Close()
// ALFile::RenameToBackup()
// ALFile::Rename()
// ALFile::UnRename()
// ALFile::Delete()
//
// DESCRIPTION
//
// This file contains the C++ member functions to support class
// ALFile. This class works very closely with the parent class,
// ALStorage, found in STORAGE.CPP. You will find in many cases
// the virtual functions found here in the derived class call
// the same function in the parent class to help out with some
// of the work.
// We don't really do anything exciting in the WEP, it is just
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
//#include <dos.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "filestor.h"
//
// void * ALFile::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALFile object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALFile::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALFile::ALFile( const char *file_name = "",
// int buffer_size = 4096,
// ALCase name_case = AL_LOWER)
//
// ARGUMENTS:
//
// file_name : The initial file name of the ALFile object you are
// creating. By default, this is a blank string, which
// will get converted to a temporary name before opening
// the actual disk file.
//
// buffer_size : The size of the object's I/O buffer. The default of 4096
// should give very good performance.
//
// name_case : This parameter determines whether the file names will
// always be converted to upper case, lower case, or left
// in mixed case. Under MS-DOS, you shouldn't use mixed
// case, because the O/S file naming convention is case
// insensitive. ArchiveLib will think "TEMP.BAK" and
// "temp.bak" are different, when they really aren't.
//
// RETURNS
//
// Nothing, this is a constructor.
//
// DESCRIPTION
//
// This constructor is used to create a new ALFile object, which will
// usually be treated as an ALStorage object by ArchiveLib functions.
// It is important to note that not much happens during construction of
// this object, the real activity happens after you call the Open()
// function. Just creating this object *does not* create a file on disk!
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALFile::ALFile( const char AL_DLL_FAR *file_name /* = "" */,
int buffer_size /* = 4096 */,
ALCase name_case /* = AL_LOWER */)
// Note: if non-msdos, change case parameter to AL_MIXED
: ALStorage( file_name, buffer_size, AL_FILE_OBJECT, name_case ) {
miHandle = -1;
}
//
// ALFile::~ALFile()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// The destructor for an ALFile object doesn't have to do much work.
// The base class destructor will take care of freeing the I/O buffer,
// and any other loose ends. All we have to do here is make sure
// the file gets closed, and that its buffers get flushed to the disk
// file.
//
// Note that in debug mode, the destructor also checks this for the
// correct class type. This helps flag erroneous or duplicated
// destructor calls.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALFile::~ALFile()
{
AL_ASSERT( GoodTag(), "~ALFile: attempting to delete invalid object" );
if ( miHandle != -1 )
Close();
}
//
// int ALFile::LoadBuffer( long address )
//
// ARGUMENTS:
//
// address : The long offset into the physical storage object. A
// seek/read combination will be executed at this location,
// so that subsequent calls to read data will start at
// the given address.
//
// RETURNS
//
// AL_SUCCESS, AL_SEEK_ERROR, AL_END_OF_FILE, or possibly another
// error code < AL_SUCCESS.
//
// DESCRIPTION
//
// This function is used in the library whenever a byte needs to be read
// that isn't present in the current I/O buffer. It has to use
// the C RTL function lseek() to go to the correct position in the library.
// If that works, it uses the C RTL function read() to read in an I/O
// buffer full of data.
//
// After that operation is performed, muReadIndex is set to 0, indicating
// that the next read from the I/O buffer will take place at location 0.
// mlFilePointer is set to address plus the number of bytes read, so
// we know where the next read from the file will take place. And
// muBufferValidData is set to the count of bytes read in from this
// location. That lets us know how far we can read in the I/O buffer
// before we run out of space.
//
// Note that if CRC checking has been turned on, we will update the
// current working CRC value with the new data that has been read
// in from the buffer.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::LoadBuffer( long address )
{
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mlFilePointer != address ) {
long result = lseek( miHandle, address, SEEK_SET );
if ( result == -1L )
return mStatus.SetError( AL_SEEK_ERROR,
"Seek failure on %s. errno = %d",
mName.GetName(),
errno );
}
int result = read( miHandle, mpcBuffer, muBufferSize );
if ( result == 0 )
return AL_END_OF_FILE;
if ( result < 0 )
return mStatus.SetError( AL_READ_ERROR,
"Read failure on %s. errno = %d",
mName.GetName(),
errno );
if ( miUpdateCrcFlag )
UpdateCrc( result );
muReadIndex = 0; //Reading can resume at this location in the I/O buffer
mlFilePointer += result;
muBufferValidData = result;
YieldTime();
return result;
}
//
// int ALFile::FlushBuffer()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// An integer status value, AL_SUCCESS, AL_WRITE_ERROR, or possibly some
// status code < AL_SUCCESS.
//
// DESCRIPTION
//
// This function is the counterpart to LoadBuffer(). It gets called
// when a write operation is poised to overflow the I/O buffer. This
// means we need to flush the buffer out to disk, then reset some
// data members.
//
// Unlike LoadBuffer(), this function doesn't have an address argument,
// so we don't have to perform a seek(). Instead, the data will be
// written out to the current position of the file pointer. If the
// write is successful, muWriteIndex is set to 0, indicating that the
// next write to the I/O buffer can go to position 0. mlFilePointer is
// incremented by the length of the write, so we know where the next read
// or write will occur. Finally, muBufferValidData is set to 0, indicating
// that there is no data in the I/O buffer that has been written, and
// there is no data that can be read.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::FlushBuffer()
{
if ( mStatus < 0 )
return mStatus;
if ( muWriteIndex != 0 ) {
if ( miUpdateCrcFlag )
UpdateCrc( muWriteIndex );
int result = write( miHandle, mpcBuffer, muWriteIndex );
muWriteIndex = 0;
if ( result == -1L )
return mStatus.SetError( AL_WRITE_ERROR,
"Write failure on %s. errno = %d",
mName.GetName(),
errno );
mlFilePointer += result;
}
muReadIndex = 0;
muBufferValidData = 0;
YieldTime();
return AL_SUCCESS;
}
//
// int ALFile::Seek( long address )
//
// ARGUMENTS:
//
// address : The address in the physical disk to seek to.
//
// RETURNS
//
// AL_SUCCESS, AL_SEEK_ERROR, or possibly some other status code < AL_SUCCESS.
//
// DESCRIPTION
//
// This is a function the user can call to position the read/write pointer
// to a new location in the disk file. If there is any data that has been
// written to the I/O buffer, it gets flushed first. After that, we do
// a seek, and update mlFilePointer to reflect the new reality. Note that
// the other important data members will have been updated by FlushBuffer().
//
// And no, this guy doesn't do a LoadBuffer(). Which is fine if you are
// going to do a bunch of writes afterwards. If you are going to read data
// immediately after Seek(), you would have been better of calling
// LoadBuffer().
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::Seek( long address )
{
FlushBuffer();
if ( mStatus < 0 )
return mStatus;
if ( mlFilePointer != address ) {
long result = lseek( miHandle, address, SEEK_SET );
if ( result == -1L )
return mStatus.SetError( AL_SEEK_ERROR,
"Seek failure on %s. errno = %d",
mName.GetName(),
errno );
}
mlFilePointer = address;
return AL_SUCCESS;
}
//
// int ALFile::Open()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_CANT_OPEN_FILE, AL_SUCCESS, or possibly some other error code
// < AL_SUCCESS.
//
// DESCRIPTION
//
// This is an important function, because it converts the ALFile
// object from a dinky little unimportant object, to a big massive
// thing that is ready to do serious work.
//
// The first thing we do here is see if we can open the file. We try
// to open it with READ/WRITE privileges, but we give up and drop back
// to READ only if that doesn't work out.
//
// We then call the base class ALStorage::Open() who takes care of
// allocating buffers and initializing data members.
//
// Finally, we have to get the protection attributes and time date
// stamps for the file. After those are stored off, the file is ready
// for abuse.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::Open()
{
if ( mStatus < AL_SUCCESS )
return mStatus;
miHandle = open( mName, O_BINARY | O_RDWR );
if ( miHandle == -1 && errno == EACCES )
miHandle = open( mName, O_BINARY | O_RDONLY );
if ( miHandle == -1 )
return mStatus.SetError( AL_CANT_OPEN_FILE,
"File open failure. Open of %s returned "
"errno = %d",
mName.GetName(),
errno );
ALStorage::Open();
struct stat buf;
struct tm *tblock;
if ( stat( mName, &buf ) == -1 )
return mStatus.SetError( AL_CANT_OPEN_FILE,
"Couldn't get time, date, and size "
"information for %s. errno = %d.",
mName.GetName(),
errno );
mlSize = buf.st_size;
tblock = localtime( &buf.st_mtime );
mTimeDate.SetTimeDate( tblock );
#if defined( AL_WIN32S )
DWORD attributes = GetFileAttributes( mName );
if ( attributes == 0xFFFFFFFF )
return mStatus.SetError( AL_CANT_OPEN_FILE,
"Couldn't get Win32 file attribute "
"information for %s. GetLastError = %d.",
mName.GetName(),
GetLastError() );
mAttributes.SetFromWin32Attributes( attributes );
#else
unsigned attributes;
if ( _dos_getfileattr( mName, &attributes ) != 0 )
return mStatus.SetError( AL_CANT_OPEN_FILE,
"Couldn't get DOS attribute "
"information for %s. errno = %d.",
mName.GetName(),
errno );
mAttributes.SetFromDosAttributes( attributes );
#endif
return AL_SUCCESS;
}
//
// void ALFile::MakeTempName( int i )
//
// ARGUMENTS:
//
// i : A numeric argument that can somehow be incorporated into
// the temporary file name. Create() will call this function
// while incrementing this number in an attempt to find a unique
// name.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function is called by Create() and other functions when they
// decide they need to cook up a temporary file name. The single parameter
// i is incremented by the calling program so that repeated calls should
// eventually produce a unique name.
//
// All this function does to create that unique name is perform a sprintf()
// into a buffer using a simple template. The result is copied into the
// mName member, and is ready to be tried out.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALFile::MakeTempName( int i )
{
char name[ 21 ];
sprintf( name, "~al~%03d.tmp", i );
mName = name;
}
//
// int ALFile::Create()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, AL_CANT_OPEN_FILE, or possibly some other error code
// < AL_SUCCESS.
//
// DESCRIPTION
//
// This function is used to create a new file storage object. Since
// we are creating a new object, we must be able to open it with read
// access. We will also rudely obliterate any existing file.
//
// The first thing we do here is call the base class Create() function.
// It takes care of setting up the I/O buffer and initializing the
// data members used to support the class.
//
// Next, function checks to see if we have a valid filename. If
// not, a search is made for a valid temporary file name. In either
// case, the file is then opened with R/W access, in O_CREAT
// mode, obliterating any existing file with the same name.
//
// Once the file is open, everything is ready to go, and you can write
// to the file at will. Don't expect much to happen if you try to
// read, however.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::Create()
{
ALStorage::Create();
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( (char *) mName == 0 || strlen( mName ) == 0 ) {
for ( int i = 0 ; i < 999 ; i++ ) {
MakeTempName( i );
miHandle = open( mName,
O_CREAT | O_RDWR | O_BINARY | O_EXCL,
S_IREAD | S_IWRITE );
if ( miHandle != -1 )
break;
else if ( errno != EEXIST && errno != EACCES ) {
mStatus.SetError( AL_CANT_OPEN_FILE,
"Temporary file creation failure. "
"Open of %s returned errno = %d",
mName.GetName(),
errno );
mName = "";
return AL_CANT_OPEN_FILE;
}
}
if ( i == 1000 ) {
mStatus.SetError( AL_CANT_OPEN_FILE,
"Temporary file creation failure. "
"Tried 1000 times to open %s "
"(or a name something like that).",
mName.GetName() );
mName = "";
return AL_CANT_OPEN_FILE;
}
} else {
miHandle = open( mName,
O_CREAT | O_RDWR | O_BINARY | O_TRUNC,
S_IREAD | S_IWRITE );
}
if ( miHandle == -1 )
return mStatus.SetError( AL_CANT_OPEN_FILE,
"File creation failure. "
"Open of %s returned errno = %d",
mName.GetName(),
errno );
return AL_SUCCESS;
}
//
// int ALFile::Close()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Any status code, hopefully AL_SUCCESS.
//
// DESCRIPTION
//
// This function is called when you are done accessing a file, and want
// to free up its resources. The first thing it does is check to see
// if the file was ever actually opened. If it was, we flush the output
// buffer, then calculate and store the file length. Finally, we close
// the disk file, then call the base class Close() function to clean up
// the buffers and deal with other miscellaneous dirty work.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::Close()
{
if ( miHandle == -1 )
return mStatus;
FlushBuffer();
mlSize = filelength( miHandle );
if ( miCreated && mTimeDate.Valid() ) {
#if defined( AL_WIN32S )
// Can you do this under NT? I don't know how.
#else
_dos_setftime( miHandle, mTimeDate.GetDosDate(), mTimeDate.GetDosTime() );
#endif
}
close( miHandle );
miHandle = -1;
ALStorage::Close();
if ( miCreated && mTimeDate.Valid() ) {
#if defined( AL_WIN32S )
SetFileAttributes( mName, mAttributes.GetWin32Attributes() );
#else
_dos_setfileattr( mName, mAttributes.GetDosAttributes() );
#endif
}
return mStatus;
}
//
// int ALFile::RenameToBackup( int delete_on_clash = 1 )
//
// ARGUMENTS:
//
// delete_on_clash : If this flag is set, it means that we will overwrite
// an existing file with this file if the names clash.
// For example, if I am renaming TEMP.DAT to TEMP.BAK,
// and a TEMP.BAK already exists, I will delete it
// before renaming if this arg is set.
//
// RETURNS
//
// AL_SUCCESS or AL_RENAME_ERROR.
//
// DESCRIPTION
//
// This function is a quick way to rename a storage object. The new
// name created is the default name, which usually means changing the
// file extension to ".BAK", from whatever it was.
//
// You don't see it here, but both the mName member and the physical file
// name are both updated. That all happens in the Rename() function.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::RenameToBackup( int delete_on_clash /* = 1 */ )
{
mName.ChangeExtension();
return Rename( 0, delete_on_clash );
}
//
// int ALFile::Rename( const char *new_name /* = 0 */,
// int delete_on_clash /* = 1 */ )
//
// ARGUMENTS:
//
// new_name : A character pointer to a new file name. If a name is
// defined here, the file is renamed to this new value.
// If this value is 0, it means that we expect that
// the mName member has already been updated with a
// new name. In this case, the old name of the
// file is renamed to the new name.
//
// delete_on_clash : If this flag is set, it means that we will overwrite
// an existing file with this file if the names clash.
// For example, if I am renaming TEMP.DAT to TEMP.BAK,
// and a TEMP.BAK already exists, I will delete it
// before renaming if this arg is set.
//
// RETURNS
//
// AL_SUCCESS or AL_RENAME_ERROR.
//
// DESCRIPTION
//
// This virtual function provides a way to rename a storage object's
// physical implementation. It first updates the mName member if a
// new_name argument is provided. After that, we unlink the clash file
// if one exists, then do a simple rename of mName.mszOldName to
// new_name.
//
// Note that this function does a lot of error checking in debug mode.
// It also does a little error checking in release mode.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::Rename( const char AL_DLL_FAR *new_name /* = 0 */,
int delete_on_clash /* = 1 */ )
{
AL_ASSERT( miHandle == -1, "Rename: attempting to rename open file" );
AL_ASSERT( mName.GetName() != 0, "Rename: attempting to rename file with null name" );
AL_ASSERT( strlen( mName ) > 0, "Rename: attempting to rename file with 0 length name" );
int status;
const char *real_old_name;
const char *real_new_name;
if ( new_name ) {
real_old_name = mName.GetSafeName();
real_new_name = new_name;
} else {
real_old_name = mName.GetSafeOldName();
real_new_name = mName.GetSafeName();
}
#if !defined( AL_WIN32S )
const char *p = strchr( real_new_name, '.' );
if ( p && strlen( p ) > 4 )
return mStatus.SetError( AL_RENAME_ERROR,
"Error trying to rename %s. It has a long "
"extension, which could lead to inadvertent "
"deletion of a file when trying to rename.",
real_old_name );
#endif
if ( delete_on_clash ) {
if ( mName.mCase == AL_MIXED )
status = strcmp( real_new_name, real_old_name );
else
status = stricmp( real_new_name, real_old_name );
if ( status == 0 )
return mStatus.SetError( AL_RENAME_ERROR,
"Error attempting to rename %s to %s. "
"Can't rename to the same name!",
real_new_name,
real_old_name );
status = unlink( real_new_name );
if ( status != 0 && errno != ENOENT )
return mStatus.SetError( AL_RENAME_ERROR,
"Error deleting %s before renaming %s. "
"errno = %d",
real_new_name,
real_old_name,
errno );
}
status = rename( real_old_name, real_new_name );
if ( status != 0 )
return mStatus.SetError( AL_RENAME_ERROR,
"Error renaming %s to %s. errno = %d",
real_old_name,
real_new_name,
errno );
if ( new_name != 0 )
mName = new_name;
return AL_SUCCESS;
}
//
// int ALFile::UnRename( int delete_on_clash /* = 1 */ )
//
// ARGUMENTS:
//
// delete_on_clash : If this flag is set, it means that we will overwrite
// an existing file with this file if the names clash.
// For example, if I am renaming TEMP.BAK to TEMP.DAT,
// and a TEMP.DAT already exists, I will delete it
// before renaming if this arg is set.
//
// RETURNS
//
// AL_SUCCESS or AL_RENAME_ERROR.
//
// DESCRIPTION
//
// This virtual function provides a way to undo a previous renaming of
// a storage object's physical name. We can do this because the mName
// member of ALStorage keeps track both of the current name of the file,
// and the old name. In this case, we just rename the current name to
// the old name. Then we update the mName member so it is accurate.
//
// Note that this function does a lot of error checking in debug mode.
// It also does a little error checking in release mode.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::UnRename( int delete_on_clash /* = 1 */ )
{
AL_ASSERT( miHandle == -1, "UnRename: attempting to rename open file" );
AL_ASSERT( mName.GetName() != 0, "UnRename: attempting to rename file with null name" );
AL_ASSERT( mName.GetOldName() != 0, "UnRename: attempting to rename file with null old name" );
AL_ASSERT( strlen( mName ) > 0, "UnRename: attempting to rename file with 0 length name" );
AL_ASSERT( strlen( mName.GetOldName() ) > 0, "UnRename: attempting to rename file with 0 length old name" );
int status;
if ( delete_on_clash ) {
status = unlink( mName.GetOldName() );
if ( status != 0 && errno != ENOENT )
return mStatus.SetError( AL_RENAME_ERROR,
"Error deleting %s before renaming %s. "
"errno = %d",
mName.GetOldName(),
mName.GetName(),
errno );
}
status = rename( mName, mName.GetOldName() );
if ( status != 0 && errno != ENOENT )
return mStatus.SetError( AL_RENAME_ERROR,
"Error renaming %s to %s. errno = %d",
mName.GetName(),
mName.GetOldName(),
errno );
ALStorage::mName = mName.GetOldName();
return AL_SUCCESS;
}
//
// int ALFile::Delete()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_DELETE_ERROR or AL_SUCCESS.
//
// DESCRIPTION
//
// This function is called to delete the physical object associated with
// a file. This simply means calling the unlink() function for the
// given name.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALFile::Delete()
{
AL_ASSERT( miHandle == -1, "Delete: attempting to delete open file" );
AL_ASSERT( mName.GetName() != 0, "Delete: attempting to delete file with null name" );
AL_ASSERT( strlen( mName ) > 0, "Delete: attempting to delete file with 0 length name" );
int status = unlink( mName );
if ( status != 0 )
return mStatus.SetError( AL_DELETE_ERROR,
"Error deleting file %s, errno = %d ",
mName.GetName(),
errno );
return AL_SUCCESS;
}

133
al/filestor.h Executable file
View File

@ -0,0 +1,133 @@
/*
* FILESTOR.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file contains the class definition for the frequently used
* ALFile class.
*
* CLASS DEFINITIONS:
*
* ALFile
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _FILESTOR_H
#define _FILESTOR_H
#include "arclib.h"
#if defined( __cplusplus )
#include "storage.h"
/*
* class ALFile : public ALStorage
*
* DESCRIPTION
*
* This is the class declaration for ALFile. This is the fundamental disk
* storage class used in Archive Library. It is derived directly from
* ALStorage, so it has to implement versions of the five or six
* critical virtual functions, mostly relating to opening files, closing
* them, loading and flushing buffers.
*
* DATA MEMBERS
*
* miHandle : The handle of the file when opened. This is the value
* returned by the function call to open().
*
* MEMBER FUNCTIONS
*
* ALFile() : The constructor.
* ~ALFile() : The virtual destructor.
* operator new() : The memory allocation operator, only used when the
* library is inside a DLL.
* MakeTempName() : Private function used to generate temporary names.
* Open() : Virtual function to open the file.
* Create() : Virtual function to create the file.
* Close() : Virtual fn to close the file.
* LoadBuffer() : Virtual fn to load the I/O buffer from a specific address.
* FlushBuffer() : Virtual fn to flush the I/O buffer.
* Seek() : Virtual fn to seek to seek to a new position in the file.
* Rename() : Rename the underlying file.
* UnRename() : Undo the rename process.
* Delete() : Delete the disk file (not destroy!)
* RenameToBackup(): Rename the current file to a backup name.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALFile : public ALStorage {
/*
* Constructors, destructors, assignment operator, friends, declarations
*/
public :
AL_PROTO ALFile( const char AL_DLL_FAR *file_name = "",
int buffer_size = 4096,
ALCase name_case = AL_LOWER );
virtual AL_PROTO ~ALFile();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* As usual, I don't want the compiler to generate a default copy constructor,
* or an assignment operator here. I force it to back off by declaring them
* here. They do not exist!
*/
protected :
AL_PROTO ALFile( ALFile AL_DLL_FAR & );
ALFile AL_DLL_FAR & AL_PROTO operator=( const ALFile AL_DLL_FAR & );
/*
* Member functions, grouped by category.
*
*
* Protected member manipulation, used inside library, not for public use.
*/
protected :
virtual void AL_PROTO MakeTempName( int i );
/*
* The file I/O access public interface
*/
public :
virtual int AL_PROTO Open();
virtual int AL_PROTO Create();
virtual int AL_PROTO Close();
virtual int AL_PROTO LoadBuffer( long address );
virtual int AL_PROTO FlushBuffer();
virtual int AL_PROTO Seek( long address );
/*
* File name and underlying object manipulation public interface
*/
public :
virtual int AL_PROTO Rename( const char AL_DLL_FAR *new_name = 0,
int delete_on_clash = 1 );
virtual int AL_PROTO UnRename( int delete_on_clash = 1 );
virtual int AL_PROTO Delete();
virtual int AL_PROTO RenameToBackup( int delete_on_clash = 1 );
/*
* Data members
*/
protected :
int miHandle;
public :
AL_CLASS_TAG( _ALFileTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _FILESTOR_H */

361
al/grenengn.cpp Executable file
View File

@ -0,0 +1,361 @@
//
// GRENENGN.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALGreenleafEngine::operator new()
// ALGreenleafEngine::ALGreenleafEngine()
// ALGreenleafEngine::~ALGreenleafEngine()
// ALGreenleafEngine::Compress()
// ALGreenleafEngine::Decompress()
// ALGreenleafEngine::WriteEngineData()
// ALGreenleafEngine::ReadEngineData()
//
// DESCRIPTION
//
// This file contains the front end to the Greenleaf compression engine.
// This contains everything but the actual low level compression
// and expansion code, which can be found in _RE.CPP and _RC.CPP. Those
// two source files are shrouded though, so you won't get a tremendous
// amount of detail!
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "grenengn.h"
#include "_openf.h"
#include "_r.h"
//
// void * ALGreenleafEngine::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALGreenleafEngine::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALGreenleafEngine::
// ALGreenleafEngine( short int compression_level = AL_GREENLEAF_LEVEL_2,
// short int fail_uncompressible = 0 )
//
// ARGUMENTS:
//
// compression_level : This is one of the enumerated types found in ALDEFS.H,
// namely AL_GREENLEAF_LEVEL_0 through
// AL_GREENLEAF_LEVEL_4. Level 4 gives the most
// compression, but takes up the most memory as well.
//
// fail_uncompressible : This flag is used to indicate the disposition
// of an uncompressible file. If this flag is set,
// the compression of an incompressible file will
// be interrupted, and the file will be recompressed
// using a straight copy. Note that this requires
// a Seek() operation! Note also that this feature
// is NOT YET IMPLEMENTED!!!
//
// RETURNS
//
// Nothing, a constructor.
//
// DESCRIPTION
//
// The constructor for the Greenleaf engine has a pretty simple life. All
// it has to do is call the base class constructor, then define a couple of
// data members. This is a lightweight object until the compression
// or expansion routines are invoked, at which time the memory requirements
// go through the roof.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALGreenleafEngine::
ALGreenleafEngine( short int compression_level /* = AL_GREENLEAF_LEVEL_2 */,
short int fail_uncompressible /* = 0 */ )
: ALCompressionEngine( AL_COMPRESSION_GREENLEAF, "Greenleaf" )
{
miCompressionLevel = compression_level;
miFailUncompressible = fail_uncompressible;
}
//
// ALGreenleafEngine::~ALGreenleafEngine()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// The destructor for objects of this class doesn't have to do
// anything. In debug mode, we at least check for the validity
// of the object.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALGreenleafEngine::~ALGreenleafEngine()
{
AL_ASSERT( GoodTag(), "~ALGreenleafEngine: attempt to delete invalid object" );
}
//
// int ALGreenleafEngine::Compress( ALStorage &input,
// ALStorage &output )
//
// ARGUMENTS:
//
// input : A reference to the storage object that will be compressed.
//
// output : A reference to the storage object that will receive the
// compressed data.
//
// RETURNS
//
//
// AL_SUCCESS in the event of a success, an error code < AL_SUCCESS
// if a failure occurred.
//
// DESCRIPTION
//
// This is the virtual function that is called to compress data. The
// This section of code is really just a front end to the real engine,
// which is found in _RC.CPP. The first thing we do here
// is create an RCompress object, which allocates all of the
// storage we need to perform the compression. In a tight memory
// situation, that may well fail, so we check its status before moving
// on. If it succeeded, we can call the low level compression function
// to do the real work.
//
// After the compress function returns, we have to check for errors on
// any of the other objects involved in the compression, and return the
// cumulative result.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALGreenleafEngine::Compress( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output )
{
ALOpenFiles files( input, output );
input.InitCrc32();
RCompress rc( input,
output,
miCompressionLevel + 10,
miFailUncompressible );
if ( rc.mStatus < 0 )
return mStatus = rc.mStatus;
else
rc.Compress();
if ( rc.mStatus < 0 )
return mStatus = rc.mStatus;
else if ( input.mStatus < 0 )
return mStatus = input.mStatus;
else if ( output.mStatus < 0 )
return mStatus = output.mStatus;
return mStatus;
}
//
// int ALGreenleafEngine::Decompress( ALStorage &input,
// ALStorage &output,
// long compressed_length )
//
// ARGUMENTS:
//
// input : A reference to the storage object that will be
// expanded.
//
// output : A reference to the storage object that will receive
// the expanded data.
//
// compressed_length : A long value indicating how long the compressed
// object is. This helps to tell the decompressor
// when to quit.
// RETURNS
//
//
// AL_SUCCESS in the event of a success, an error code < AL_SUCCESS
// if a failure occurred.
//
// DESCRIPTION
//
// This is the virtual function that is called to expand a compressed
// object. This section of code is really just a front end to the real
// engine, which is found in _RE.CPP. The first thing we do here
// is create an RExpand object, which allocates all of the
// storage we need to perform the decompression. In a tight memory
// situation, that may well fail, so we check its status before moving
// on. If it succeeded, we can call the low level expansion function
// to do the real work.
//
// After the expand function returns, we have to check for errors on
// any of the other objects involved in the expansion, and return the
// cumulative result.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALGreenleafEngine::Decompress( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output,
long compressed_length )
{
ALOpenFiles files( input, output );
output.InitCrc32();
RExpand re( input, output, compressed_length, miCompressionLevel + 10 );
if ( re.mStatus < 0 )
return mStatus = re.mStatus;
else
re.Expand();
if ( re.mStatus < 0 )
return mStatus = re.mStatus;
else if ( input.mStatus < 0 )
return mStatus = input.mStatus;
else if ( output.mStatus < 0 )
return mStatus = output.mStatus;
return mStatus;
}
//
// int ALGreenleafEngine::WriteEngineData( ALStorage * archive )
//
// ARGUMENTS:
//
// A pointer to the storage area where the data is to be written.
//
// RETURNS
//
// AL_SUCCESS if the data was written properly, else an error code
// less than AL_SUCCESS.
//
// DESCRIPTION
//
// Every compression engine used in ArchiveLib gets the opportunity
// to store data it needs to save in order to characterize its compression
// process. The Greenleaf compression engine only needs to save a single
// integer, which contains the compression level used. This is the
// function that does so.
//
// Data like this is stored in string format, which consists of a single
// short integer describing the number of bytes in the string, followed
// by the string. We store in this portable format so that even a program
// that doesn't know about compression engines would be able to read in
// archive directory data.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALGreenleafEngine::
WriteEngineData( ALStorage AL_DLL_FAR * archive )
{
archive->WritePortableShort( 2 );
return archive->WritePortableShort( miCompressionLevel );
}
//
// int ALGreenleafEngine::ReadEngineData( ALStorage * archive )
//
// ARGUMENTS:
//
// A pointer to the storage area where the data is to be read.
//
// RETURNS
//
// AL_SUCCESS if the data was read properly, else an error code
// less than AL_SUCCESS.
//
// DESCRIPTION
//
// Every compression engine used in ArchiveLib gets the opportunity
// to store data it needs to save in order to characterize its compression
// process. The Greenleaf compression engine only needs to save a single
// integer, which contains the compression level used.
//
// During the creation of the compression engine, this function gets called
// in order to load the engine's private data. All we do is read in
// the compression level, along with a little error checking.
//
// Data like this is stored in string format, which consists of a single
// short integer describing the number of bytes in the string, followed
// by the string. We store in this portable format so that even a program
// that doesn't know about compression engines would be able to read in
// archive directory data.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALGreenleafEngine::ReadEngineData( ALStorage AL_DLL_FAR * archive )
{
short temp;
archive->ReadPortableShort( temp );
AL_ASSERT( temp == 2, "ReadEngineData: engine data size is not 2, it should be" );
return archive->ReadPortableShort( miCompressionLevel );
}

125
al/grenengn.h Executable file
View File

@ -0,0 +1,125 @@
/*
* GRENENGH.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file contains the class declaration for ALGreenleafEngine.
*
* CLASS DEFINITIONS:
*
* ALGreenleafEngine
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _GRENENGN_H
#define _GRENENGN_H
#include "arclib.h"
#if defined( __cplusplus )
#include "cmpengn.h"
/*
* class ALGreenleafEngine : public ALCompressionEngine
*
* DESCRIPTION
*
* ALGreenleaf Engine is the Greenleaf proprietary compression
* engine. Compression engines are simple, so there aren't
* too many functions. This class has two data members that
* are initialized in the constructor. One of them, the compression level,
* has to be saved with the data in order for decompression to work
* properly. It is saved and read with the virtual functions
* ReadEngineData() and WriteEngineData(), using a single short
* in the archive directory.
*
* DATA MEMBERS
*
* miCompressionLevel : This is the compression level that the
* compressor will attempt to use, selected
* from one of the five settings found in
* the enumerated type in ALDEFS.H. If the
* file is incompressible and the engine
* performs a straight binary copy this value
* changes to AL_GREENLEAF_COPY.
*
* miFailUncompressible : This data member is used to flag the
* action the compressor takes if a file
* turns out to be incompressible. If this
* member is set, the engine will stop compressing,
* seek back to the start of the file, and
* just copy the data. If this member is clear,
* we don't ever check to see if the file is
* compressing properly.
*
* MEMBER FUNCTIONS
*
* ALGreenleafEngine() : The constructor.
* ~ALGreenleafEngine() : The virtual destructor.
* operator new() : The memory allocation operator, which is
* only used when the library is in a DLL.
* WriteEngineData() : The virtual function that writes private
* configuration data. For this class, this
* function writes out a single short int
* containing the compression level.
* ReadEngineData() : The complement for the above function, used
* during extraction.
* Compress() : The routine that actually performs the
* compression.
* Decompress() : The routine that actually performs the
* decompression.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALGreenleafEngine : public ALCompressionEngine {
/*
* Declarations, friends, constructors, destructors
*/
public :
AL_PROTO ALGreenleafEngine( short int compression_level = AL_GREENLEAF_LEVEL_2,
short int fail_uncompressible = 0 );
virtual AL_PROTO ~ALGreenleafEngine();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Member functions
*/
protected :
virtual int AL_PROTO WriteEngineData( ALStorage AL_DLL_FAR * archive );
virtual int AL_PROTO ReadEngineData( ALStorage AL_DLL_FAR * archive );
public :
virtual int AL_PROTO Compress( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output );
virtual int AL_PROTO Decompress( ALStorage AL_DLL_FAR &input,
ALStorage AL_DLL_FAR &output,
long compressed_length = -1 );
/*
* Data members
*/
protected :
short int miCompressionLevel;
short int miFailUncompressible;
public :
AL_CLASS_TAG( _ALGreenleafEngineTag );
};
#endif /* #ifdef __cplusplus */
#endif /* #ifdef _GRENENGN_H */

851
al/memstore.cpp Executable file
View File

@ -0,0 +1,851 @@
//
// MEMSTORE.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALMemory::operator new()
// ALMemory::ALMemory()
// ALMemory::~ALMemory()
// ALMemory::LoadBuffer()
// ALMemory::Delete()
// ALMemory::Rename()
// ALMemory::RenameToBackup()
// ALMemory::UnRename()
// ALMemory::Seek()
// ALMemory::GrowUserBuffer()
// ALMemory::FlushBuffer()
// ALMemory::Close()
// ALMemory::Create()
// ALMemory::Open()
//
// DESCRIPTION
//
// This file contains all the C++ member functions to support the
// ALMemory class. ALMemory is conceptually pretty simple, but it suffers
// from a little bit of #ifdef'itis. The reason for this is that
// things change just a little bit when we are using Windows memory
// management. Not enough to create a new class, but enough to have
// to make a lot of code conditional.
//
// The big difference between the Windows and DOS code shows up in two
// areas. First, under Windows we have huge buffers that can support
// up to either 16Mbytes or 4GBytes, depending. Under MS-DOS real mode,
// out biggest buffer is 64Kb. Second, under MS-DOS we get new memory
// with malloc/realloc/free. Under Windows we use LocalAlloc etc.
//
// Other than that, the whole class is pretty straightforward. Try not to
// let the issue of naming the buffers throw you, it is basically
// irrelevant.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include "memstore.h"
#include <stdlib.h> // might be using malloc()!
//
// void * ALMemory::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The amount of storage that needs to be allocated for
// this object.
//
// RETURNS
//
// A pointer to the storage.
//
// DESCRIPTION
//
// When using the DLL version of ArchiveLib, it is a good idea to
// allocate the storage for objects from inside the DLL, since they
// will be freed inside the DLL. If we don't have the new operator
// for a class, its storage will be allocated from the EXE before
// the constructor code is called. Then, when it is time to free
// the storage, the delete operator will be called inside the DLL.
// Not good, right?
//
//
// Very important: this new operator is called to allocate the
// storage for the ALMemory object itself. This has nothing to do
// with the storage buffer that the memory object will be using
// later on. In other words, this new operator is responsible for
// no more than a couple of dozen bytes, not potentially hundreds
// of Kbytes.
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALMemory::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
// WINDOWS version:
//
// ALMemory::ALMemory( const char *buffer_name = "",
// char AL_HUGE *user_buffer = 0,
// DWORD user_buffer_size = 0,
// ALCase name_case = AL_MIXED )
//
// MS-DOS real mode version :
//
// ALMemory::ALMemory( const char *buffer_name = "",
// char *user_buffer = 0,
// int user_buffer_size = 0,
// ALCase name_case = AL_MIXED )
//
// ARGUMENTS:
//
// buffer_name : An arbitrary name assigned to the buffer. Buffer
// names don't have to be unique, because buffers aren't
// named at the operating system level. But if you are
// going to insert the storage object into an archive, the
// name needs to be unique so that you will be able to
// extract it properly.
//
// user_buffer : If you want the ALMemory class to automatically allocate
// a buffer for you, and grow it as necessary, just leave
// this pointer set to 0. If you want to use your own buffer,
// which won't have the ability to grow, pass a pointer to
// it in this parameter. Note that under Windows 16 this
// is a huge pointer, meaning it can span segments, and
// access potentially 16 Mbytes of memory.
//
// user_buffer_size : If you are passing a pointer to your own buffer,
// you need to indicate how large it is here. Under
// Windows this is a DWORD instead of a size_t.
//
// name_case : This decides whether you want the file name to be
// case sensitive when making comparisons. MS-DOS
// file names are case-insensitive. You can make memory
// buffers either mixed case, forced upper, or forced
// lower. The default of mixed case means that comparisons
// will be case sensitive, which is fine.
// RETURNS
//
// Nothing, it is a constructor.
//
// DESCRIPTION
//
// This constructor calls the base class constructor in an initializer
// list, which takes care of most of the dirty work right away. After that
// is done, all the constructor has to do is initialize a few data members.
// That should be self-explanatory. Remember that if the user doesn't
// supply a buffer, we are going to allocate it for her, but not until
// there is actually a demand for memory.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_MEMORY )
//
// The Windows and MS-DOS constructors are nearly identical.
//
AL_PROTO ALMemory::ALMemory( const char AL_DLL_FAR *buffer_name /* = "" */,
char AL_HUGE *user_buffer /* = 0 */,
DWORD user_buffer_size /* = 0 */,
ALCase name_case /* = AL_MIXED */)
: ALStorage( buffer_name, 4096, AL_MEMORY_OBJECT, name_case )
{
if ( user_buffer != 0 ) {
mpcUserBuffer = user_buffer;
mfUserOwnsBuffer = 1;
muUserBufferSize = user_buffer_size;
} else {
mfUserOwnsBuffer = 0;
mpcUserBuffer = 0;
muUserBufferSize = 0;
}
mhUserMemoryHandle = 0;
}
#else // #if defined( AL_WINDOWS_MEMORY )
AL_PROTO ALMemory::ALMemory( const char AL_DLL_FAR *buffer_name /* = "" */,
char AL_DLL_FAR *user_buffer /* = 0 */ ,
int user_buffer_size /* = 0 */,
ALCase name_case /* = AL_MIXED */ )
: ALStorage( buffer_name, 4096, AL_MEMORY_OBJECT, name_case )
{
if ( user_buffer != 0 ) {
mpcUserBuffer = user_buffer;
mfUserOwnsBuffer = 1;
muUserBufferSize = user_buffer_size;
} else {
mfUserOwnsBuffer = 0;
mpcUserBuffer = 0;
muUserBufferSize = 0;
}
}
#endif
//
// ALMemory::~ALMemory()
//
// ARGUMENTS:
//
// None, you don't get any for a destructor.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// The destructor has just one thing it has to do before this object
// goes away. If the buffer that it has been using all along doesn't
// belong to the user, then it is the class's responsibility to get
// rid of it. We do so here, using one of two methods, depending on
// whether we are under MS-DOS or Windows.
//
// Note also that we check the GoodTag() function when in Debug mode.
// That will help catch really bad mistakes, such as trying to delete
// an object that is not even an ALMemory object, maybe a beer can.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
AL_PROTO ALMemory::~ALMemory()
{
AL_ASSERT( GoodTag(), "~ALMemory: attempting to delete invalid object" );
if ( !mfUserOwnsBuffer ) {
if ( mpcUserBuffer ) {
#if defined( AL_WINDOWS_MEMORY )
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
GlobalFree( (HGLOBAL) mhUserMemoryHandle );
mhUserMemoryHandle= 0;
#else
free( mpcUserBuffer );
#endif
mpcUserBuffer = 0;
}
}
AL_ASSERT( GoodTag(), "~ALMemory: attempting to delete invalid object" );
}
//
// int ALMemory::LoadBuffer( long address )
//
// ARGUMENTS:
//
// address : An offset that we need to load data from.
//
// RETURNS
//
// AL_SEEK_ERROR if we try to read past the end of file. AL_END_OF_FILE
// if we just run out of data. Otherwise an int indicating how many bytes
// are now in the buffer.
//
// DESCRIPTION
//
// This is a virtual function the ALStorage functions rely on when reading
// data. Anytime someone tries to do a ReadChar() or ReadBuffer(), and
// it turns out that the I/O buffer has been exhausted, this function
// is called.
//
// The simple job of this function is to read as many bytes as possible out
// of the giant memory block allocated for the ALMemory object, and stick
// it into the I/O buffer, which caches it for calls to ReadChar()
// and friends.
//
// This works fine unless you try to go past the end of the buffer,
// since there is nothing there we flag that as an error.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::LoadBuffer( long address )
{
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mlFilePointer != address ) {
if ( mlFilePointer > (long) muUserBufferSize )
return mStatus.SetError( AL_SEEK_ERROR,
"Attempt to read past end of the "
"buffer in ALMemory %s",
mName.GetName() );
}
long load = muUserBufferSize - address;
if ( load > (long) muBufferSize )
muBufferValidData = muBufferSize;
else
muBufferValidData = (size_t) load;
if ( muBufferValidData <= 0 )
return AL_END_OF_FILE;
#if defined( AL_WINDOWS_MEMORY )
//
// Some problems passing huge arrays to memcpy, got to do it inline instead
// I think Microsoft says memcpy() will work with huge pointers as long
// as you don't try to use the inline optimizations, but I say why take
// chances...
//
// Another note: AL_HUGE is _huge for win16, but blank for win32.
//
char AL_HUGE *temp = mpcUserBuffer + address;
for ( unsigned i = 0 ; i < muBufferValidData ; i++ )
mpcBuffer[ i ] = *temp++;
// memcpy( mpcBuffer, mpcUserBuffer + address, muBufferValidData );
#else
memcpy( mpcBuffer, mpcUserBuffer + (size_t) address, muBufferValidData );
#endif
if ( miUpdateCrcFlag )
UpdateCrc( muBufferValidData );
muReadIndex = 0; //Reading can resume at this location
mlFilePointer += muBufferValidData;
YieldTime();
return muBufferValidData;
}
//
// int ALMemory::Delete()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Always returns AL_SUCCESS.
//
// DESCRIPTION
//
// This function is supposed to delete the underlying physical object.
// This makes a lot of sense with files, because you are essentially
// emulating the MS-DOS command line DEL function. With memory
// objects things aren't quite as clear. So we destroy the buffer,
// and that's that.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::Delete()
{
if ( !mfUserOwnsBuffer ) {
#if defined( AL_WINDOWS_MEMORY )
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
GlobalFree( (HGLOBAL) mhUserMemoryHandle );
mhUserMemoryHandle= 0;
#else
free( mpcUserBuffer );
#endif
mpcUserBuffer = 0;
}
return AL_SUCCESS;
}
//
// int ALMemory::Rename( const char *new_name /* = 0 */,
// int /* delete_on_clash = 1 */ )
//
// ARGUMENTS:
//
// new_name : The new name of the buffer.
//
// delete_on_clash : This argument makes sense with files. What it says
// is that if you try to rename BOB.DAT to BOB.BAK,
// and it turns out that there is another BOB.BAK, should
// you delete the other one? With memory buffers,
// there is no clash, cause the OS doesn't care about
// unique names. So we ignore this parm.
//
// RETURNS
//
// Always returns AL_SUCCESS.
//
// DESCRIPTION
//
// This function is supposed to rename the underlying physical object.
// But in the case of memory buffers, the underlying physical object
// doesn't actually have a name, so this is really just a local rename.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::Rename( const char AL_DLL_FAR *new_name /* = 0 */,
int /* delete_on_clash = 1 */ )
{
if ( new_name )
mName = new_name;
return AL_SUCCESS;
}
//
// int ALMemory::RenameToBackup( int delete_on_clash /* = 1 */ )
//
// ARGUMENTS:
//
// delete_on_clash : This argument makes sense with files. What it says
// is that if you try to rename BOB.DAT to BOB.BAK,
// and it turns out that there is another BOB.BAK, should
// you delete the other one? With memory buffers,
// there is no clash, cause the OS doesn't care about
// unique names. So it doesn't matter what value you
// pass to the Rename() function, it is going to be
// ignored.
//
// RETURNS
//
// Always returns AL_SUCCESS.
//
// DESCRIPTION
//
// This function renames an object. But instead of making you sweat in
// order to come up with a new name, it just uses the default name
// that we use to assign a backup name.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::RenameToBackup( int delete_on_clash /* = 1 */ )
{
mName.ChangeExtension();
return Rename( 0, delete_on_clash );
}
//
// int ALMemory::UnRename( int /* delete_on_clash = 1 */)
//
// ARGUMENTS:
//
// delete_on_clash : This argument makes sense with files. What it says
// is that if you try to rename BOB.DAT to BOB.BAK,
// and it turns out that there is another BOB.BAK, should
// you delete the other one? With memory buffers,
// there is no clash, cause the OS doesn't care about
// unique names. So we just ignore it here.
//
// RETURNS
//
// Always returns AL_SUCCESS.
//
// DESCRIPTION
//
// If you decide you didn't really want to rename an object after all, you
// can call this function to get the old name back!
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::UnRename( int /* delete_on_clash = 1 */)
{
AL_ASSERT( mName.GetName() != 0, "UnRename: trying to rename with a null name" );
AL_ASSERT( mName.GetOldName() != 0, "UnRename: trying to rename with a null old name" );
AL_ASSERT( strlen( mName ) > 0, "UnRename: trying to rename with a zero length name" );
AL_ASSERT( strlen( mName.GetOldName() ) > 0, "UnRename: trying to rename with a zero length old name" );
ALStorage::mName = mName.GetOldName();
return AL_SUCCESS;
}
//
// int ALMemory::Seek( long address )
//
// ARGUMENTS:
//
// address : The address in the memory object to go to. The read and
// write pointers will now be repositioned to this point.
//
// RETURNS
//
// AL_SEEK_ERROR if we can't get to that point in the buffer. Otherwise
// AL_SUCCESS.
//
// DESCRIPTION
//
// This function acts just like the seek() function in the C runtime
// library. It flushes the current I/O buffers, and then moves the file
// read and write pointers to a new spot, specified by the address. if
// there is no memory there, you will get an error. Note that this
// makes it not quite like the C run time library, since it can create
// new space with a seek(). But I don't think we need that ability yet.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::Seek( long address )
{
FlushBuffer();
if ( mStatus < 0 )
return mStatus;
if ( mlFilePointer != address ) {
if ( mlFilePointer > (long) muUserBufferSize )
return mStatus.SetError( AL_SEEK_ERROR,
"Attempt to read past end of the "
"buffer in ALMemory %s",
mName.GetName() );
}
mlFilePointer = address;
return AL_SUCCESS;
}
//
// int ALMemory::GrowUserBuffer( long minimum_new_size )
//
// ARGUMENTS:
//
// minimum_new_size : The absolute minimum new size you need the buffer
// to grow to. This amount is usually determined by
// a pending I/O request. For example, if the current
// size of the buffer is 1000, and you have a 1 byte
// data block to write at 1000, the minimum new size
// will be 1001.
//
// RETURNS
//
// AL_CANT_ALLOCATE_MEMORY, if we just can't get it. AL_SUCCESS if we can.
//
// DESCRIPTION
//
// When you are trying to write to the memory object, and you have hit
// the end of the currently allocated area, it would seem like a good
// time to allocate more. When that situation occurs, this function is
// called. If the user owns the buffer, we don't have the option of asking
// the O/S or RTL for more memory, because we don't even know if the user
// memory is on the heap or what. But if we own the memory we know how
// to ask for more.
//
// The strategy for asking for more memory is pretty simple. Normally,
// we ask for another 16K. If that fails, we fall back to asking for
// just enough memory to cover our current I/O request. Asking for
// this memory is sufficiently different under real mode dos and protected
// mode windows that we have two completely different routines, separated
// only by #ifdefs.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
#if defined( AL_WINDOWS_MEMORY )
int AL_PROTO ALMemory::GrowUserBuffer( long minimum_new_size )
{
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mfUserOwnsBuffer )
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Attempt to write past the end of a "
"user owned buffer for ALMemory "
"%s",
mName.GetSafeName() );
long trial_size = muUserBufferSize + 16384;
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
HGLOBAL new_handle = GlobalReAlloc( (HGLOBAL) mhUserMemoryHandle, trial_size, GMEM_MOVEABLE );
if ( new_handle == 0 ) {
trial_size = minimum_new_size;
new_handle = GlobalReAlloc( (HGLOBAL) mhUserMemoryHandle, trial_size, GMEM_MOVEABLE );
}
if ( new_handle == 0 ) {
mpcUserBuffer = (char AL_HUGE *) GlobalLock( (HGLOBAL) mhUserMemoryHandle );
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Allocation failure when attempting to "
"allocate a buffer "
"of %ld bytes for ALMemory "
"%s",
minimum_new_size,
mName.GetSafeName() );
}
mpcUserBuffer = (char AL_HUGE *) GlobalLock( new_handle );
mhUserMemoryHandle = new_handle;
muUserBufferSize = trial_size;
return AL_SUCCESS;
}
#else // #ifdef AL_WINDOWS_MEMORY
int AL_PROTO ALMemory::GrowUserBuffer( long minimum_new_size )
{
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mfUserOwnsBuffer )
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Attempt to write past the end of a "
"user owned buffer for ALMemory "
"%s",
mName.GetSafeName() );
if ( minimum_new_size >= 65535L )
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Attempt to allocate a huge buffer "
"of %ld bytes for ALMemory "
"%s",
minimum_new_size,
mName.GetSafeName() );
long trial_size = muUserBufferSize + 16384;
if ( trial_size >= 65000U )
trial_size = 65000U;
if ( trial_size >= minimum_new_size ) {
char *new_buf = (char *) realloc( mpcUserBuffer, (size_t) trial_size );
if ( new_buf ) {
mpcUserBuffer = new_buf;
muUserBufferSize = (size_t) trial_size;
return AL_SUCCESS;
}
}
char *new_buf = (char *) realloc( mpcUserBuffer, (size_t) minimum_new_size );
if ( new_buf ) {
mpcUserBuffer = new_buf;
muUserBufferSize = (size_t) trial_size;
return AL_SUCCESS;
}
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Allocation failure when attempting to "
"allocate a buffer "
"of %ld bytes for ALMemory "
"%s",
minimum_new_size,
mName.GetSafeName() );
}
#endif
//
// int ALMemory::FlushBuffer()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_CANT_ALLOCATE_MEMORY, if we run out. Otherwise, AL_SUCCESS.
//
// DESCRIPTION
//
// This routine is called when the I/O buffer is filled up. It means
// you have filled up the cache with what is usually 4K bytes of data.
// This routine is also called if you have hot data in the I/O buffer
// and you decide to do a seek(), or a read().
//
// All we have to do here is take the hot data in the I/O buffer and
// write it out to our massive memory object. The big complication is
// that sometimes the memory object isn't big enough, so while we are
// all busy trying to do this, we have to ask for more data at the
// same time.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::FlushBuffer()
{
if ( mStatus < 0 )
return mStatus;
//
// If the write index is 0, we can skip all this stuff, because there
// is nothing in the buffer to flush out.
//
if ( muWriteIndex != 0 ) {
if ( miUpdateCrcFlag )
UpdateCrc( muWriteIndex );
if ( ( muWriteIndex + mlFilePointer ) > (long)muUserBufferSize )
if ( GrowUserBuffer( muWriteIndex + mlFilePointer ) < 0 )
return mStatus;
#if defined( AL_WINDOWS_MEMORY )
//
// Can't use memcpy with huge pointers, at least not with the optimized
// versions.
//
char AL_HUGE *temp = mpcUserBuffer + mlFilePointer;
for ( unsigned int i = 0 ; i < muWriteIndex ; i++ )
*temp++ = mpcBuffer[ i ];
// memcpy( mpcUserBuffer + mlFilePointer, mpcBuffer, muWriteIndex );
#else
memcpy( mpcUserBuffer + (size_t) mlFilePointer, mpcBuffer, muWriteIndex );
#endif
mlFilePointer += muWriteIndex;
muWriteIndex = 0;
if ( mlSize < mlFilePointer )
mlSize = mlFilePointer;
}
muReadIndex = 0;
muBufferValidData = 0;
YieldTime();
return AL_SUCCESS;
}
//
// int ALMemory::Close()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, or various error codes that filter on down from other
// routines.
//
// DESCRIPTION
//
// Close() is supposed to do the same thing as fclose() in the run
// time library. The most important thing we are concerned about is
// that the I/O buffer gets freed up by the base class, so this suddenly
// might not be a giant heavyweight object any more.
//
// After freeing things up in the base class, we check to see if
// we have allocated more space than we really need. If so, we do
// a realloc() of some sort to give space back to the O/S.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::Close()
{
if ( mpcBuffer == 0 )
return mStatus;
FlushBuffer();
ALStorage::Close();
//
// If we aren't using all our space, give back the extra.
//
if ( mlSize < (long) muUserBufferSize ) {
#if defined( AL_WINDOWS_MEMORY )
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
HGLOBAL new_handle = GlobalReAlloc( (HGLOBAL) mhUserMemoryHandle, mlSize, GMEM_MOVEABLE );
if ( new_handle != 0 )
mhUserMemoryHandle = new_handle;
mpcUserBuffer = (char AL_HUGE *) GlobalLock( (HGLOBAL) mhUserMemoryHandle );
muUserBufferSize = mlSize;
#else
char *new_buf = (char *) realloc( mpcUserBuffer, (size_t) mlSize );
if ( new_buf )
mpcUserBuffer = new_buf;
muUserBufferSize = (size_t) mlSize;
#endif
}
return mStatus;
}
//
// int ALMemory::Create()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, AL_CANT_ALLOCATE_MEMORY, or various error codes that
// filter on down from other routines.
//
// DESCRIPTION
//
// This is like creating a new file. If there isn't a memory buffer
// already assigned to this object, we create one, with an initial
// allocation of 16Kbytes.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::Create()
{
ALStorage::Create();
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( (char *) mName == 0 || strlen( mName ) == 0 )
mName = "AL.TMP";
if ( mfUserOwnsBuffer )
return AL_SUCCESS; //If the user supplied the buffer, we take what's available
#if defined( AL_WINDOWS_MEMORY )
mhUserMemoryHandle = GlobalAlloc( GMEM_MOVEABLE, 16384 );
if ( mhUserMemoryHandle ) {
mpcUserBuffer = (char AL_HUGE *) GlobalLock( (HGLOBAL) mhUserMemoryHandle );
muUserBufferSize = 16384;
} else {
mpcUserBuffer = 0;
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Allocation failure when attempting to "
"create a buffer "
"of %ld bytes for ALMemory "
"%s in Create()",
16384,
mName.GetSafeName() );
}
#else
mpcUserBuffer = (char *) malloc( 16384 );
muUserBufferSize = 16384;
if ( mpcUserBuffer == 0 )
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Allocation failure when attempting to "
"create a buffer "
"of %ld bytes for ALMemory "
"%s in Create()",
16384,
mName.GetSafeName() );
#endif
return AL_SUCCESS;
}
//
// int ALMemory::Open()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, AL_CANT_OPEN_FILE, or various error codes that
// filter on down from other routines.
//
// DESCRIPTION
//
// This is like opening an existing file. Since there is supposed to be
// an existing memory buffer already, we gripe if we can't find one.
//
// REVISION HISTORY
//
// May 22, 1994 1.0A : First release
//
int AL_PROTO ALMemory::Open()
{
ALStorage::Open();
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mpcUserBuffer == 0 )
return mStatus.SetError( AL_CANT_OPEN_FILE,
"Attempt to open ALMemory %s "
"with no buffer allocated",
mName.GetSafeName() );
else
mlSize = (long) muUserBufferSize;
return AL_SUCCESS;
}

182
al/memstore.h Executable file
View File

@ -0,0 +1,182 @@
/*
* MEMSTORE.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class declaration for ALMemory.
*
* CLASS DEFINITIONS:
*
* ALMemory
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _MEMSTORE_H
#define _MEMSTORE_H
#include "arclib.h"
#if defined( __cplusplus )
/*
* class ALMemory : public ALStorage
*
* DESCRIPTION
*
* Class ALMemory is an ALStorage class that stores its data in memory
* buffers. Under real mode MS-DOS, buffers are limited to 64Kbytes.
* Under Windows, they can get a lot bigger. There are slight
* differences in operations between the the Windows and MS-DOS
* versions, so you will see some #ifdefs here and there.
*
* You can use ALMemory to work with a buffer of your own, or you
* can ask the class to allocate the memory for you. You can
* also change the ownership of the buffer in midstream, allowing
* you to take control of a buffer that the class has generated.
*
* DATA MEMBERS
*
* mfUserOwnsBuffer : If this flag is set, it indicates that the user
* owns the buffer, not the class. This means
* the class can't grow the buffer if it runs out
* of space, and it can't delete it in the
* ALMemory destructor.
*
* mhUserMemoryHandle : Under Windows, this member contains the handle
* of the Windows memory block that has been
* allocated
*
* muUserBufferSize : The actual size of the buffer, whether it is
* owned by the user or not. This is a size_t
* member under real mode DOS, and a long under
* Windows.
*
* mpcUserBuffer : A pointer to the buffer the class is presently
* using. The name User Buffer was probably a bad
* choice, because this is the pointer we use
* regardless of whether or not the user owns the
* buffer.
*
* MEMBER FUNCTIONS
*
* ALMemory() : The constructor, slightly different between DOS
* and Windows.
* ~ALMemory() : The virtual destructor.
* operator new() : Memory allocation operator, only used when the
* library is in a DLL. Note that this isn't the
* operator used to allocate the buffer, just the
* one to allocate a class object.
* Open() : Open the storage object for reading and writing.
* Create() : Create a new buffer to write to.
* Close() : Close the existing memory object.
* LoadBuffer() : Load a new block from the memory object into
* the I/O buffer.
* FlushBuffer() : Flush the contents of the I/O buffer, sending
* the contents into the memory object.
* Seek() : Seek to a new location in the memory object.
* Rename() : Give the object a new name. Names are pretty
* irrelevant for memory objects, feel free to use
* whatever you want here.
* UnRename() : Restore the old name.
* Delete() : Delete the memory object. It is gone forever.
* RenameToBackup() : Give the memory object an arbitrary new name.
* GrowUserBuffer() : A private function used to give us more space
* when the memory object is owner of the buffer.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALMemory : public ALStorage {
/*
* Constructors, destructors, assignment operator, friends, declarations
*/
public :
#ifdef AL_WINDOWS_MEMORY
AL_PROTO ALMemory( const char AL_DLL_FAR *buffer_name = "",
char AL_HUGE *user_buffer = 0,
DWORD user_buffer_size = 0,
ALCase name_case = AL_MIXED );
#else
AL_PROTO ALMemory( const char AL_DLL_FAR *buffer_name = "",
char AL_DLL_FAR *user_buffer = 0,
int user_buffer_size = 0,
ALCase name_case = AL_MIXED );
#endif
virtual AL_PROTO ~ALMemory();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* As usual, I don't want the compiler to generate a default copy constructor,
* or an assignment operator here. I force it to back off by declaring them
* here. They do not exist!
*/
protected :
AL_PROTO ALMemory( ALMemory AL_DLL_FAR & );
ALMemory AL_DLL_FAR & AL_PROTO operator=( const ALMemory AL_DLL_FAR & );
/*
* Member functions, grouped by category.
*
*
* Protected member manipulation, used inside library, not for public use.
*/
protected :
/*
* The file I/O access public interface
*/
public :
virtual int AL_PROTO Open();
virtual int AL_PROTO Create();
virtual int AL_PROTO Close();
virtual int AL_PROTO LoadBuffer( long address );
virtual int AL_PROTO FlushBuffer();
virtual int AL_PROTO Seek( long address );
/*
* File name and underlying object manipulation public interface
*/
public :
virtual int AL_PROTO Rename( const char AL_DLL_FAR *new_name = 0,
int delete_on_clash = 1 );
virtual int AL_PROTO UnRename( int delete_on_clash = 1 );
virtual int AL_PROTO Delete();
virtual int AL_PROTO RenameToBackup( int delete_on_clash = 1 );
/*
* Unique to this class
*/
protected :
int AL_PROTO GrowUserBuffer( long minimum_new_size );
/*
* Data members
*/
protected :
public : /* Should some of these might be better off private */
int mfUserOwnsBuffer;
#ifdef AL_WINDOWS_MEMORY
HGLOBAL mhUserMemoryHandle;
long muUserBufferSize;
char AL_HUGE *mpcUserBuffer;
#else
size_t muUserBufferSize;
char AL_DLL_FAR *mpcUserBuffer;
#endif
AL_CLASS_TAG( _ALMemoryTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _MEMSTORE_H */

244
al/monitor.cpp Executable file
View File

@ -0,0 +1,244 @@
//
// MONITOR.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALMonitor::operator new()
// ALMonitor::ALMonitor()
// ALMonitor::~ALMonitor()
// ALMonitor::Progress()
// ALMonitor::ArchiveOperation()
//
// DESCRIPTION
//
// This file contains the four functions defined for ALMonitor. This is
// a base class, and you generally won't use an implementation of it.
// It doesn't have any pure functions, so if you want a do-nothing
// monitor, use this guy. Other than that, the Progress() function actually
// does a useful calculation for derived classes, so they might call it.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
//
// void * ALMonitor::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALMonitor object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALMonitor::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALMonitor::ALMonitor( ALMonitorType monitor_type )
//
// ARGUMENTS:
//
// monitor_type : One of the enumerated types from ALDEFS.H. The only
// two types supported are AL_MONITOR_OBJECTS and
// AL_MONITOR_JOB.
// RETURNS
//
// Nothing, this is a constructor.
//
// DESCRIPTION
//
// This function is called when one of the derived classes is creating
// a new monitor. (It could be called directly, but you aren't likely
// to instantiate an ALMonitor.) It has only one thing to do, which
// is to initialize the miMonitorType data member. This data member
// is a const member, so it has to be initialized in an initializer list.
// It's nice to make it const, because then you can leave it public and
// nobody gets to jack with it.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALMonitor::ALMonitor( ALMonitorType monitor_type )
: miMonitorType( monitor_type )
{
}
//
// ALMonitor::~ALMonitor()
//
// ARGUMENTS:
//
// None, destructor.
//
// RETURNS
//
// Likewise, none for a destructor.
//
// DESCRIPTION
//
// The ALMonitor destructor doesn't have to clean up any dynamic
// storage or anything like that. As a consequence, all we do is
// check the validity of this in debug mode.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALMonitor::~ALMonitor()
{
AL_ASSERT( GoodTag(), "~ALMonitor: attempt to delete invalid object" );
}
//
// void ALMonitor::Progress( long object_tell,
// ALStorage & object )
//
// ARGUMENTS:
//
// object_tell : The current offset withing the object being compressed,
// expanded, copied, or processed.
//
// object : A reference to the storage object being processed.
//
// RETURNS
//
// None.
//
// DESCRIPTION
//
// This is a virtual function. ALMonitor::Progress() gets called from
// YieldTime() inside a storage object, which happens pretty
// frequently. Normally the derived class will have its own version
// of Progress(), so this guy won't get called directly.
//
// However, most of the derived versions of Progress() will go ahead and
// call this version anyway. Why? Because this guy calculates the values
// of miRatio and mlByteCount for you.
//
// The calculated values of miRatio and mlByteCount will differ depending
// on whether the monitor is of type AL_MONITOR_JOB or AL_MONITOR_OBJECTS.
//
// In AL_MONITOR_OBJECTS mode, the byte count is going be calculated by
// taking the current offset of the object and subtracting the starting
// position of the object. We have to subtract out the starting position,
// because sometimes we are going to be monitoring an object that resides
// in an archive, and its starting position will not be at location 0.
//
// If we are in AL_MONITOR_JOB mode, the byte count is going to be the
// same as referred to above, plus the value of mlJobSoFar. That data
// member contains the total number of bytes processed in previous objects
// in this job. That figure is updated after each object is processed,
// but not by this class. ALArchiveBase does this for ordinary archiving
// operations, you can look at that code for hints on how to do this
// yourself.
//
// Calculating the ratio is pretty easy. If you are in AL_MONITOR_OBJECTS
// mode, you just divide the byte count by the object size. If you are
// in AL_MONITOR_JOB mode, you divide the byte count by the job size. Once
// again, the job size will have been calculated in advance by whatever
// process is performing the compression/expansion operation.
//
// Note that there is one tricky bit here. If the object size was set to
// -1 by the calling program, it means this routine has to go out and
// get the size. This convenience cuts down on code in the high level
// routine.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALMonitor::Progress( long object_tell,
ALStorage AL_DLL_FAR & object )
{
mlByteCount = object_tell - mlObjectStart;
if ( mlObjectSize == -1 )
mlObjectSize = object.GetSize();
if ( miMonitorType == AL_MONITOR_JOB ) {
mlByteCount += mlJobSoFar;
if ( mlJobSize == 0 )
miRatio = -1;
else
miRatio = (int)( 100 * mlByteCount / mlJobSize );
} else {
if ( mlObjectSize == 0 )
miRatio = -1;
else
miRatio = (int)(100 * mlByteCount / mlObjectSize );
}
}
//
// void ALMonitor::ArchiveOperation( ALArchiveOperation,
// ALArchiveBase *,
// ALEntry * )
//
// ARGUMENTS:
//
// None. There are actually three arguments passed to this function,
// but we ignore them here. Derived classes may do something.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// Derived classes override this function to print informative information
// about various archiving operations. The base class does absolutely
// nothing with this information, it is a do-nothing function.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALMonitor::ArchiveOperation( ALArchiveOperation,
ALArchiveBase AL_DLL_FAR *,
ALEntry AL_DLL_FAR * )
{
}

194
al/monitor.h Executable file
View File

@ -0,0 +1,194 @@
/*
* MONITOR.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file contains the class declaration for the base class ALMonitor.
* You can instantiate objects of this class, but they don't do
* anything. The derived classes are much more interesting.
*
* CLASS DEFINITIONS:
*
* ALMonitor
*
* ENUMERATED TYPES:
*
* ALArchiveOperation
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _MONITOR_H
#define _MONITOR_H
#if defined( __cplusplus )
/*
* Most of our enumerated types are defined in ALDEFS.H so C programs
* have easy access to them. But C and VB have no use for these
* values, because they are only used by members of ALMonitor,
* they can't be passed to C or VB procedures.
*
* This type defines the various messages that are passed to
* ALMonitor::ArchiveOperation() during progress of an
* archiving operation.
*/
enum ALArchiveOperation {
AL_ARCHIVE_OPEN,
AL_ARCHIVE_CLOSE,
AL_EXTRACTION_OPEN,
AL_EXTRACTION_CLOSE,
AL_INSERTION_OPEN,
AL_INSERTION_CLOSE,
AL_COPY_OPEN,
AL_COPY_CLOSE,
AL_START_DIRECTORY_WRITE,
AL_END_DIRECTORY_WRITE,
AL_START_DIRECTORY_READ,
AL_END_DIRECTORY_READ
};
/*
* A forward declaration.
*
*/
class AL_CLASS_TYPE ALEntry;
/*
* class ALMonitor
*
* DESCRIPTION
*
* The ALMonitor class is used primarily for providing user interface
* information during archiving or other operations. Each ALEntryList
* object has an ALMonitor attached to it. When the archive operations
* are performed, the ALMonitor object is called using its two functions,
* Progress() and ArchiveOperation(). Progress() is used to update
* progress information, such as byte count or percent complete. The
* archive operation is functioned at various times, such as when files
* are opened, archives are opened, files are closed, etc.
*
* Good examples of how derived classes do all this stuff can be found in
* BARGRAPH.CPP and WINMON.CPP.
*
* DATA MEMBERS
*
* mlJobSize : The total size of the job being monitored. If the
* monitor is in AL_MONITOR_JOBS mode, we care about
* this. The archive base class has to set up this
* member before the archiving procedure starts.
*
* mlJobSoFar : The total number of bytes that have already been
* processed so far in this job. This number is
* updated after each file is completely processed. It
* does not reflect work done on the current file.
*
* mlObjectSize : The size of the current object being processed. This
* is usually set up by the archive function at the start
* of processing for the current file. If this number is
* set to -1, it means we have to check on it, since
* the archiving program was to lazy to open the file and
* check on.
*
* mlObjectStart : The starting offset of the current object in the
* file being processed. Sometimes the object we are
* working on might be in an archive, in which case
* we need to know where it starts.
*
* mlByteCount : This private member contains the byte count for all
* the data processed so far. Derived classes can
* call Progress() for the base class, and it will
* calculate this number. The number will be for
* the entire job when we are in AL_MONITOR_JOB mode,
* but just for the current object when we are in
* AL_MONITOR_OBJECTS mode.
*
* miRatio : The percentage of processing we have completed, an
* integer that hopefully ranges from 0 to 100. This
* number can also be calculated by calling Progress()
* in the base class. It will differ depending on whether
* we are in AL_MONITOR_JOB mode or AL_MONITOR_OBJECTS.
*
* miMonitorType : Either AL_MONITOR_OBJECT or AL_MONITOR_JOBS, depending
* on what was specified in the constructor.
*
* MEMBER FUNCTIONS
*
* ALMonitor() : The constructor.
* ~ALMonitor() : The virtual destructor.
* operator new() : The memory allocation operator used when the
* library resides in a DLL.
* Progress() : The routine called periodically to update progress
* indicators. The base class version just makes
* calculations.
* ArchiveOperation() : The routine called at various points during an
* archive operation. Does nothing worthwhile in the
* base class.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALMonitor
{
/*
* Constructors, destructors, friends, declarations
*/
friend class AL_CLASS_TYPE ALArchiveBase;
friend class AL_CLASS_TYPE ALStorage;
public :
AL_PROTO ALMonitor( ALMonitorType monitor_type );
virtual AL_PROTO ~ALMonitor();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* The copy constructor and assignment operator do not exist.
*/
protected :
AL_PROTO ALMonitor( ALMonitor AL_DLL_FAR &);
ALMonitor AL_DLL_FAR & AL_PROTO operator=( ALMonitor AL_DLL_FAR & );
/*
* Member functions
*/
protected :
virtual void AL_PROTO Progress( long mlObjectTell,
ALStorage AL_DLL_FAR & object );
virtual void AL_PROTO
ArchiveOperation( enum ALArchiveOperation operation,
ALArchiveBase AL_DLL_FAR *archive,
ALEntry AL_DLL_FAR *job );
/*
* Data members, not sure if we should keep these public or not
*/
public :
long mlJobSize;
long mlJobSoFar;
long mlObjectSize;
long mlObjectStart;
/*
* Calculated by ALMonitor::Progress()
*/
long mlByteCount;
int miRatio;
public :
const ALMonitorType miMonitorType;
AL_CLASS_TAG( _ALMonitorTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _MONITOR_H */

754
al/objname.cpp Executable file
View File

@ -0,0 +1,754 @@
//
// OBJNAME.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALName::operator new()
// ALName::operator+()
// ALName::ALName( const char *, ALCase )
// ALName::ALName( const ALName & )
// ALName::operator=( const char * )
// ALName::operator = ( const ALName & )
// ALName::~ALName()
// ALName::ChangeExtension()
// ALName::ChangeTrailingChar()
// ALName::GetSafeName()
// ALName::GetSafeOldName()
// ALName::operator char *()
// ALName::StripFileName()
// ALName::StripPath()
// ALName::WildCardMatch()
// ALName::Strcpy()
//
// DESCRIPTION
//
// This file contains all the source code to support class ALName.
// Class ALName doesn't really do much outside of ALStorage, where
// it shows up as the mName data member. It does make cameo appearances
// elsewhere, such as in the wild card expansion code, but those
// are pretty limited.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <string.h>
#include <ctype.h>
#include "_match.h"
//
// void * ALName::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALName object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALName::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALName ALName::operator+( const char *rhs )
//
// ARGUMENTS:
//
// rhs : The character pointer that is going to be added to the
// ALName object. This will often be the string component
// of another ALName object, cast to type const char *.
//
// RETURNS
//
// A newly created ALName object. This disappears quickly, but can
// be copied into a result object using either the assignment operator
// or the copy constructor.
//
// DESCRIPTION
//
// This is one of those C++ functions that makes converts out of C
// programmers. It allows me to add two strings together to create
// a third. I really like that.
//
// The implementation is pretty easy. I allocate a new character buffer of
// the correct length, the copy the two strings into it. I use this
// result as the initializer for a new ALName object, and return that.
//
// Note that the new string will have the same case sensitivity as this.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
ALName ALName::operator+( const char AL_DLL_FAR *rhs )
{
int l1 = ( rhs ) ? strlen( rhs ) : 0;
int l2 = ( mszName ) ? strlen( mszName ) : 0;
char *p = new char[ l1 + l2 + 1 ];
if ( p ) {
strcpy( p, mszName );
if ( rhs )
strcat( p, rhs );
}
ALName result( p, mCase );
if ( p )
delete p;
return result;
}
//
// ALName::ALName( const char *s = "", ALCase name_case = AL_MIXED )
//
// ARGUMENTS:
//
// s : The initial string value of the new object. Note that
// you can pass a null pointer here and all will still be okay.
//
// name_case: The case sensitivity of the new ALName object. Will its
// contents be mixed, or will it always be forced to upper
// or lower.
//
// RETURNS
//
// Nothing, a constructor.
//
// DESCRIPTION
//
// This constructor first initializes the mCase member in an initializer.
// mCase is a const member, which is nice, because you can make it public.
// But, it means you can't initialize it *in* the constructor, you have
// to do it before the body.
//
// Things are pretty easy after that. We allocate enough space to hold
// the initializer string and copy it in. The old name gets set to 0, since
// this name hasn't been around long enough to have been renamed.
// And that's it.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALName::ALName( const char AL_DLL_FAR *s /* = "" */,
ALCase name_case /* = AL_MIXED */ )
: mCase( name_case )
{
mszName = new AL_DLL_FAR char[ strlen( s ) + 1 ];
if ( mszName )
Strcpy( s );
mszOldName = 0;
}
//
// ALName::ALName( const ALName &rhs )
//
// ARGUMENTS:
//
// rhs : A reference to another ALName object. This is the ALName
// we are going to copy.
//
// RETURNS
//
// Nothing, a constructor.
//
// DESCRIPTION
//
// This is the copy constructor. It is very nearly the same as the
// other constructor.
//
// This constructor first initializes the mCase member in an initializer.
// mCase is a const member, which is nice, because you can make it public.
// But, it means you can't initialize it *in* the constructor, you have
// to do it before the body.
//
// Things are pretty easy after that. We allocate enough space to hold
// a copy of the string in the rhs, and then copy it. The old name gets
// set to 0, since this name hasn't been around long enough to have been
// renamed. We could have copied the old name from the rhs, but I think
// this way makes more sense.
// And that's it.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALName::ALName( const ALName AL_DLL_FAR &rhs )
: mCase( rhs.mCase )
{
const char *s = rhs.GetSafeName();
mszName = new AL_DLL_FAR char[ strlen( s ) + 1 ];
if ( mszName )
Strcpy( s );
mszOldName = 0;
}
//
// ALName & ALName::operator = ( const char * rhs )
//
// ARGUMENTS:
//
// rhs : This is the character string that we are going to assign to this.
//
// RETURNS
//
// A reference to this. We need to do it that way so we can do:
//
// a = b = c = "test";
//
// DESCRIPTION
//
// This function performs roughly the same function as the first
// constructor, but there is a twist. When we assign a new name to
// an ALName object, we also make a copy of fit and place it in
// the old name data member.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
ALName AL_DLL_FAR & AL_PROTO ALName::
operator = ( const char AL_DLL_FAR * rhs )
{
if ( rhs == 0 )
rhs = "";
if ( rhs == mszName ) // Pathological?
return *this;
char AL_DLL_FAR *new_name = new AL_DLL_FAR char[ strlen( rhs ) + 1 ];
if ( new_name ) {
if ( mszOldName )
delete[] mszOldName;
mszOldName = mszName;
mszName = new_name;
Strcpy( rhs );
} else {
if ( mszOldName )
delete[] mszOldName;
mszOldName = mszName;
mszName = 0;
}
return *this;
}
//
// ALName & ALName::operator = ( const ALName & rhs )
//
// ARGUMENTS:
//
// rhs : The right hand side of the assignment operator.
//
// RETURNS
//
// A reference to this. Like in the above function, we do this so
// that you can stack assignments:
//
// a = b = c = "Dummy";
//
// DESCRIPTION
//
//
// This function is very similar to the copy constructor, but it has
// one additional twist. When we copy the rhs string value into our
// string, we move our old name into the backup copy member,
// mszOldName. That way, if we change our mind, we can easily
// switch back to the old name.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
ALName AL_DLL_FAR & AL_PROTO ALName::
operator = ( const ALName AL_DLL_FAR & rhs )
{
return *this = rhs.GetName();
}
//
// ALName::~ALName()
//
// ARGUMENTS:
//
// None, this is a destructor.
//
// RETURNS
//
// None, destructor.
//
// DESCRIPTION
//
// All this function has to do is free up the two pieces of
// dynamic memory. I just can't get out of that old C habit of
// checking a pointer for NULL before deleting it.
//
// In debug mode, I check the state of this before and after freeing
// the dynamically allocated memory, in hopes of catching any
// heap errors near their source.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALName::~ALName()
{
AL_ASSERT( GoodTag(), "~ALName: attempt to delete invalid object" );
if ( mszName )
delete[] mszName;
if ( mszOldName )
delete[] mszOldName;
AL_ASSERT( GoodTag(), "~ALName: attempt to delete invalid object" );
}
//
// ALName & ALName::ChangeExtension( const char *new_extension = ".bak" )
//
// ARGUMENTS:
//
// new_extension : The new extension you want to apply to the name.
//
// RETURNS
//
// A reference to this. This is nice, because it lets you do things
// like this:
//
// fopen( name.ChangeExtension( ".OBJ" ), "rb" );
//
// DESCRIPTION
//
// This function is used to change the extension of a filename stored
// in an ALName object. A lot of times you will want to do this
// in order to create a backup. For example, you could change
// TEMP.DAT to TEMP.BAK.
//
// This function makes a copy of the current name in mszOldName, so we
// can keep track of it later. It then searches for the '.' character
// in the new file name, and sticks the new extension there.
//
// If you apply this function to a filename, you can then rename the file
// by calling ALStorage::Rename() with no argument. When you do this,
// the rename function uses the saved OldName and current name as its
// arguments for the rename() function.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
// I need to fix this code up to handle extensions with and without a
// leading '.' character. Maybe you can use a leading character
// other than '.' to indicate a different type of extension?
//
ALName AL_DLL_FAR & AL_PROTO ALName::
ChangeExtension( const char AL_DLL_FAR *new_extension /* = ".bak" */ )
{
AL_ASSERT( new_extension != 0, "ChangeExtension: new extension is null" );
AL_ASSERT( mszName, "ChangeExtension: current name is null" );
char *file_name = new char[ strlen( mszName ) + strlen( new_extension ) + 1 ];
if ( mszOldName )
delete[] mszOldName;
mszOldName = mszName;
mszName = file_name;
if ( !file_name )
return *this;
strcpy( mszName, mszOldName );
char *p = strrchr( file_name, '.' );
if ( p )
strcpy( p, new_extension );
else
strcat( mszName, new_extension );
switch ( mCase ) {
case AL_UPPER : strupr( mszName ); break;
case AL_LOWER : strlwr( mszName ); break;
}
return *this;
}
//
// ALName & ALName::ChangeTrailingChar( char new_char = '@' )
//
// ARGUMENTS:
//
// new_char : The new character to use as the last name of the file
// name.
//
// RETURNS
//
// A reference to this. This is nice, because it lets you do things
// like this:
//
// fopen( name.ChangeTrailingChar(), "rb" );
//
// DESCRIPTION
//
// This function is used to change the the last character of the extension
// in filename stored in an ALName object. A lot of times you will want to
// do this in order to create a backup. For example, you could change
// TEMP.DAT to TEMP.DA@.
//
// This function makes a copy of the current name in mszOldName, so we
// can keep track of it later. It then searches for the end of the
// current file name, and changes it.
//
// Note that if the filename doesn't have an extension, we do something
// funny. Instead of just changing the last character, we create a
// new extension, and append that instead. So if the filename is
// "TEST", the new name will be "TEST.@".
//
// If you apply this function to a filename, you can then rename the file
// by calling ALStorage::Rename() with no argument. When you do this,
// the rename function uses the saved OldName and current name as its
// arguments for the rename() function.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
ALName AL_DLL_FAR & AL_PROTO ALName::
ChangeTrailingChar( char new_char /* = '@' */ )
{
AL_ASSERT( mszName != 0, "ChangeTrailingChar: current name is null" );
char *file_name = new char[ strlen( mszName ) + 2 ];
if ( mszOldName )
delete[] mszOldName;
mszOldName = mszName;
mszName = file_name;
switch ( mCase ) {
case AL_UPPER : new_char = (char) toupper( new_char ); break;
case AL_LOWER : new_char = (char) tolower( new_char ); break;
}
if ( !file_name )
return *this;
strcpy( mszName, mszOldName );
char *p;
if ( ( p = strrchr( mszName, '.' ) ) != 0 ) {
if ( p[ 1 ] == '0' ) {
p[ 1 ] = new_char;
p[ 2 ] = '\0';
} else
mszName[ strlen( mszName ) - 1 ] = new_char;
} else {
char new_extension[ 3 ];
new_extension[ 0 ] ='.';
new_extension[ 1 ] = new_char;
new_extension[ 2 ] = 0;
strcat( mszName, new_extension );
}
return *this;
}
//
// const char * ALName::GetSafeName() const
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// This function normally returns the value of mszName. However, if
// mszName is currently a null pointer, we return a pointer to an
// empty string instead. This means you can use the return value from
// this function anywhere you want without checking for its NULLity.
//
// DESCRIPTION
//
// See above.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
const char AL_DLL_FAR * AL_PROTO ALName::GetSafeName() const
{
if ( mszName )
return mszName;
else
return "";
}
//
// const char * ALName::GetSafeOldName() const
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// This function normally returns the value of mszOldName. However, if
// mszOldName is currently a null pointer, we return a pointer to an
// empty string instead. This means you can use the return value from
// this function anywhere you want without checking for its NULLity.
//
// DESCRIPTION
//
// See above.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
const char AL_DLL_FAR * AL_PROTO ALName::GetSafeOldName() const
{
if ( mszOldName )
return mszOldName;
else
return "";
}
//
// ALName::operator const char *() const
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A pointer to the string inside the object. If the string is
// presently a null pointer, we return a pointer to an empty string
// instead. See ALName::GetSafeName() for an explanation of why
// this is.
//
// DESCRIPTION
//
// This is the casting operator that pretty much lets me use
// an ALName object anywhere I use a char *. There are some strange
// Microsoft compiler problems that make me use this goofy STRINGF
// typedef instead of char *, but it all adds up the same in
// the wash.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_MICROSOFT ) && ( AL_MICROSOFT < 800 ) && defined( AL_BUILDING_DLL ) //??????
AL_PROTO ALName::operator char *() const
#else
AL_PROTO ALName::operator const STRINGF() const
#endif
{
if ( mszName )
return mszName;
else
return "";
}
//
// ALName & ALName::StripFileName()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A reference to this. This is nice, because you can strip the
// file name from an object and use it in the same operation.
//
// DESCRIPTION
//
// In the wildcard parsing code, sometimes I need to get the path
// of a file, which means stripping off the filename and extension.
// This is pretty easy to do, I just find the right spot and stick
// a string termination character in that position.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
ALName AL_DLL_FAR & AL_PROTO ALName::StripFileName()
{
if ( mszName ) {
char *p = strrchr( mszName, '\\' );
if ( p == 0 )
p = strrchr( mszName, ':' );
if ( p )
p[ 1 ] = '\0';
else
mszName[ 0 ] = '\0';
}
return *this;
}
//
// ALName & ALName::StripPath()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A reference to this. This is nice, because you can strip the
// file name from an object and use it in the same operation.
//
// DESCRIPTION
//
// In the wildcard parsing code, sometimes I need to get just the
// filename and extension of a file, which means stripping off the
// drive and path information. This is pretty easy to do, I just find
// the start of the filename, and move it up to the start of the string.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
ALName AL_DLL_FAR & AL_PROTO ALName::StripPath()
{
if ( mszName ) {
char *p = strrchr( mszName, '\\' );
if ( p == 0 )
p = strrchr( mszName, ':' );
if ( p ) {
p++;
char *s = mszName;
while( ( *s++ = *p++ ) != 0 )
;
*s = '\0';
} //If not p, path is already stripped
}
return *this;
}
//
// int ALName::WildCardMatch( const char *pattern )
//
// ARGUMENTS:
//
// pattern : A pointer to a regular expression, including wildcards
// and sets. It can get pretty complicated.
//
// RETURNS
//
// 0 if the pattern doesn't match the object name, 1 if it does.
//
// DESCRIPTION
//
// This is a super-duper powerful function. It is used to compare
// a regular expression to the contents of an ALName. The real meat
// here is in the public domain string matching code found in _MATCH.CPP.
//
// The tricky bit here is that we have to make a comparison based
// on the case sensitivity of this. Rather than trying to modify
// the code in _MATCH.CPP, I just make a new copy of the pattern, and
// mangle the case according to what this expects.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALName::WildCardMatch( const char AL_DLL_FAR *pattern )
{
int error;
int result;
char *p = new char[ strlen( pattern ) + 1 ];
if ( !p )
return 0;
strcpy( p, pattern );
switch ( mCase ) {
case AL_UPPER : strupr( p ); break;
case AL_LOWER : strlwr( p ); break;
}
if ( !is_valid_pattern( p, &error ) )
result = 0;
else if ( matche( p, mszName ) == MATCH_VALID )
result = 1;
else
result = 0;
delete p;
return result;
}
// PROTECTED MEMBER FUNCTION.
//
// void ALName::Strcpy( const char *s )
//
// ARGUMENTS:
//
// s : A character string to be copied into mszName.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// Whenever I am going to copy a string into mszName, I need to convert
// it to the case that this object expects. If it is AL_UPPER or
// AL_LOWER, that means copying and then converting to either all upper
// case or all lower case. I do that here.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALName::Strcpy( const char *s )
{
strcpy( mszName, s );
switch ( mCase ) {
case AL_UPPER : strupr( mszName ); break;
case AL_LOWER : strlwr( mszName ); break;
}
}

215
al/objname.h Executable file
View File

@ -0,0 +1,215 @@
/*
* OBJNAME.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file contains the class definition for ALName. Most of the time
* this class is used to contain file names.
*
* CLASS DEFINITIONS:
*
* ALName
*
* FUNCTIONS:
*
* ostream& operator << ( ostream& stream, const ALName &object )
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _OBJNAME_H
#define _OBJNAME_H
#if defined( __cplusplus )
#include <string.h>
#include <iostream.h>
/*
* class ALName
*
* DESCRIPTION
*
* Object names are mostly used for names of storage objects.
* There are enough things that I do with these guys to justify
* a class of their own. Having all the object name functions in their
* own class also cuts back on the number of functions in ALStorage,
* which is already cluttered.
*
* Besides serving as the mName member in ALStorage, this class is
* also pressed into service in ALWildCardExpander, where it is very
* handy.
*
* DATA MEMBERS
*
* mszName : A pointer to the name associated with this object.
* This pointer can be a null pointer. The object is
* responsible for deleting this guy in the ALName
* destructor, along with the next member, mszOldName.
*
* mszOldName : A pointer to the last name associated with this
* object. When you assign a new name to one of these
* objects, the old name gets stored here. This makes
* it easy to revert to the old name in case of trouble.
*
* mCase : One of AL_UPPER, AL_LOWER, or AL_MIXED. If the value
* is AL_UPPER or AL_LOWER, the name is forced to all
* upper or lower case whenever it is assigned to the
* object.
*
* MEMBER FUNCTIONS
*
* ALName(const ALName &) : The copy constructor.
* ALName(const char *) : Constructor that initializes with a char *.
* operator=(const ALName&) : Assignment operator.
* operator=(const char *) : Assignment operator for char *.
* ~ALName() : Destructor, has to clean up dynamic storage.
* operator new() : Memory allocation operatory, only used
* when the library is inside the DLL. Be
* aware that this operator allocates space for
* the object itself, not the strings that it
* will contain.
* Strcpy() : A protected member function, copies and
* converts to the appropriate case if necessary.
* GetName() : Returns a pointer to the name string, might
* be 0.
* GetOldName() : Returns a pointer to the previous name
* string, might be 0.
* GetSafeName() : Returns a pointer to the name string, but
* is guaranteed not to return 0.
* GetSafeOldName() : Returns a pointer to the old name string, but
* is guaranteed not to return 0.
* ChangeExtension() : Change a filename extension to a new one.
* ChangeTrailingChar() : Change the trailing character in the filename.
* StripFileName() : Remove the filename, leaving the path and drive.
* StripPath() : Remove path and drive, leaving the filename.
* WildCardMatch() : Test for a match against a regular expression.
* operator const char *() : Return a char *.
* operator+() : Append a string to this string.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
/*
* Microsoft won't let me create a cast operator for char _far *.
* But they will let me cast to this typedef. Ugly, but it works.
*/
typedef char AL_DLL_FAR * STRINGF;
class AL_CLASS_TYPE ALName {
/*
* Constructors, destructors, assignment operator, and friends
*/
public :
AL_PROTO ALName( const ALName AL_DLL_FAR & );
AL_PROTO ALName( const char AL_DLL_FAR *s = "",
ALCase name_case = AL_MIXED );
ALName AL_DLL_FAR & AL_PROTO operator = ( const ALName AL_DLL_FAR & rhs );
ALName AL_DLL_FAR & AL_PROTO operator = ( const char AL_DLL_FAR * rhs );
AL_PROTO ~ALName();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Note that I don't have the normal prohibition against a copy constructor
* or an assignment operator in this class, because I support them here.
*/
/*
* Member Functions
*/
protected :
void AL_PROTO Strcpy( const char AL_DLL_FAR *s );
public :
const char AL_DLL_FAR * AL_PROTO GetName() const { return mszName; }
const char AL_DLL_FAR * AL_PROTO GetOldName() const { return mszOldName; }
const char AL_DLL_FAR * AL_PROTO GetSafeName() const;
const char AL_DLL_FAR * AL_PROTO GetSafeOldName() const;
ALName AL_DLL_FAR & AL_PROTO
ChangeExtension( const char AL_DLL_FAR *new_extension = ".bak" );
ALName AL_DLL_FAR & AL_PROTO ChangeTrailingChar( char new_char = '@' );
ALName AL_DLL_FAR & AL_PROTO StripFileName();
ALName AL_DLL_FAR & AL_PROTO StripPath();
int AL_PROTO WildCardMatch( const char AL_DLL_FAR *pattern );
/*
* Operators
*/
public :
#if defined( AL_MICROSOFT ) && ( AL_MICROSOFT < 800 ) && ( defined( AL_BUILDING_DLL ) || defined( AL_USING_DLL ) ) /*??? DON'T ASK ME WHY */
AL_PROTO operator STRINGF() const;
#else
AL_PROTO operator const STRINGF() const;
#endif
ALName AL_PROTO operator + ( const char AL_DLL_FAR *rhs );
/*
* Data members
*/
protected :
char AL_DLL_FAR * mszName;
char AL_DLL_FAR * mszOldName;
public :
const ALCase mCase;
AL_CLASS_TAG( _ALNameTag );
};
/*
* ostream& operator << ( ostream& stream, const ALName &object )
*
* ARGUMENTS:
*
* stream : An I/O stream.
*
* object : A reference to an ALName object.
*
* RETURNS
*
* A reference to the stream provided as an operator.
*
* DESCRIPTION
*
* This stream operator makes it easy to send ALName objects
* to an output stream. I need to define this function as inline,
* because it is tough to use far references to ostreams from a DLL.
* There are other problems associated with using this function
* in a DLL, and I don't understand them all.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
inline ostream& operator << ( ostream& stream, const ALName AL_DLL_FAR &object )
{
#if defined( AL_USING_DLL ) && !defined( AL_LARGE_MODEL ) && !defined( AL_FLAT_MODEL )
const char _far *p = (STRINGF) object;
char *near_string = new char[ _fstrlen( p ) + 1 ];
if ( near_string ) {
_fstrcpy( near_string, p );
stream << near_string;
delete near_string;
} else
stream << "Memory allocation failure!";
#else
stream << (STRINGF) object;
#endif
return stream;
}
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _OBJNAME_H */

100
al/spinner.h Executable file
View File

@ -0,0 +1,100 @@
/*
* SPINNER.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class definition for the ALMonitor
* derived object ALSpinner.
*
* CLASS DEFINITIONS:
*
* ALSpinner
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _SPINNER_H
#define _SPINNER_H
#include "arclib.h"
#if defined( __cplusplus )
/*
* class ALSpinner : public ALMonitor
*
* DESCRIPTION
*
* ALSpinner is a very simple monitor class, and is only useful under
* DOS, not Windows. All ALSpinner does is spin a little propellor
* around while the file is being processed. This lets you know
* that something is happening in an otherwise boring process.
*
* DATA MEMBERS
*
* miSpinIndex : A Static variable that keeps track of which
* position the propellor should be in. The
* propellor travels through one of four different
* positions.
*
* mrStream : A reference to the stream that the propellor is
* going to be written on.
*
* MEMBER FUNCTIONS
*
* ALSpinner() : The one and only constructor.
* ~ALSpinner() : The virtual destructor.
* Progress() : The routine that gets called to make the
* propellor twitch.
* ArchiveOperation() : The routine that gets called when archiving
* starts, stops, etc.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALSpinner : public ALMonitor {
/*
* Constructors, destructors, and friend classes
*/
public :
AL_PROTO ALSpinner( ALMonitorType monitor_type,
ostream& stream = cout );
virtual AL_PROTO ~ALSpinner();
/*
* The copy constructor and assignment operator do not exist.
*/
protected :
ALSpinner( const ALSpinner& );
ALSpinner& operator=( const ALSpinner& );
/*
* Member functions
*/
protected :
virtual void AL_PROTO Progress( long mlObjectSoFar, ALStorage& object );
virtual void AL_PROTO ArchiveOperation( ALArchiveOperation operation,
ALArchiveBase *archive,
ALEntry *job );
/*
* Data Members
*/
protected :
static int miSpinIndex;
ostream& mrStream;
public :
AL_CLASS_TAG( _ALSpinnerTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef SPINNER_H */

335
al/status.cpp Executable file
View File

@ -0,0 +1,335 @@
//
// STATUS.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) 1994 Greenleaf Software, Inc.
// All Rights Reserved
//
// CONTENTS
//
// ALStatus::operator new()
// ALStatus::ALStatus()
// ALStatus::~ALStatus()
// ALStatus::SetError()
// ALStatus::GetStatusString()
// ALStatus::GetStatusDetail()
// ALStatus::operator = ()
//
//
// DESCRIPTION
//
// This file contains LibMain() and the WEP() for ArchiveLib DLLs.
// We don't really do anything exciting in the WEP, it is just
// here for decoration. LibMain() has to set up memory allocation
// for Borland.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <stdio.h>
#include <stdarg.h>
//
// void * ALStatus::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALStatus object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALStatus::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALStatus::ALStatus()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Nothing, this is a constructor.
//
// DESCRIPTION
//
// This is the only constructor for objects of class ALStatus. It
// initializes the detail length member to 129, which is a const and
// won't change. The initial status is AL_SUCCESS, and there is no
// detail string to start with.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALStatus::ALStatus() : miStatusDetailLength( 129 )
{
miStatus = AL_SUCCESS;
mszStatusDetail = 0;
}
//
// ALStatus::~ALStatus()
//
// ARGUMENTS:
//
// None, destructor.
//
// RETURNS
//
// None, destructor.
//
// DESCRIPTION
//
// The destructor has to free up any space allocated for the detailed
// error status string. That's all.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALStatus::~ALStatus()
{
if ( mszStatusDetail )
delete[] mszStatusDetail;
}
//
// int ALStatus::SetError( int error, const char AL_DLL_FAR *fmt, ... )
//
// ARGUMENTS:
//
// error : The new error code to set the miStatus member to. A value
// less than 0 (AL_SUCCESS) will always be interpreted as
// an error.
//
// fmt : A sprintf style formatting string. This is for the
// message that is going to go into the status detail message.
//
// ... : Any additional arguments needed by the formatting string.
//
//
// RETURNS
//
// error, the error code that just got passed in.
//
// DESCRIPTION
//
// I don't know why I did the status detail allocation the way it is
// done here, it is really stupid. I should just allocate whatever space
// is necessary after formatting the string. This will probably be
// fixed in 1.x.
//
// This function is used to set the status of an object to an error state.
// Normally this is done by sending an error code, along with a detailed
// message explaining what went wrong and why. Note that to clear
// and error state, you can pass AL_SUCCESS for the error code and
// 0 for the format. The object will look like it is healthy and happy
// after that.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStatus::SetError( int error, const char AL_DLL_FAR *fmt, ... )
{
char detail[ 256 ];
va_list argptr;
miStatus = error;
if ( fmt == 0 ) {
if ( mszStatusDetail )
delete[] mszStatusDetail;
mszStatusDetail = 0;
} else {
va_start( argptr, fmt );
vsprintf( detail, fmt, argptr );
va_end( argptr );
if ( mszStatusDetail == 0 )
mszStatusDetail = new char[ miStatusDetailLength ];
if ( mszStatusDetail ) {
strncpy( mszStatusDetail, detail, miStatusDetailLength - 1 );
mszStatusDetail[ miStatusDetailLength - 1 ] = '\0';
}
}
return error;
}
//
// const char * ALStatus::GetStatusString()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A short ASCII translation of the current error code.
//
// DESCRIPTION
//
// Rather than just printing an error code number, it is usually more
// helpful to translate that number into ASCII text, so a user or
// programmer can read the description. This function is used to
// do just that. It translates the current error code into a short
// ASCII text string. Note that this is not the same as the detail
// string, which is tailored for each specific occurrence of an error code.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
const char AL_DLL_FAR * AL_PROTO ALStatus::GetStatusString()
{
switch ( miStatus ) {
case AL_SUCCESS : return "Success";
case AL_END_OF_FILE : return "End of file";
case AL_CANT_OPEN_BUFFER : return "Can't allocate buffer";
case AL_CANT_CREATE_ENGINE : return "Can't create compression engine";
case AL_CANT_CREATE_STORAGE_OBJECT: return "Can't create storage object";
case AL_CANT_ALLOCATE_MEMORY : return "Memory allocation failure";
case AL_RENAME_ERROR : return "Error renaming file";
case AL_CANT_OPEN_FILE : return "Can't open file";
case AL_SEEK_ERROR : return "Seek error";
case AL_READ_ERROR : return "Read error";
case AL_WRITE_ERROR : return "Write error";
case AL_DELETE_ERROR : return "File deletion error";
case AL_ILLEGAL_PARAMETER : return "Illegal parameter";
case AL_INTERNAL_ERROR : return "Internal error";
case AL_USER_ABORT : return "User abort";
case AL_SERVER_NOT_PRESENT : return "Server not present";
case AL_COMPRESSION_TYPE_MISMATCH : return "Mismatch in compression type";
case AL_NEED_LENGTH : return "Missing length parameter";
case AL_CRC_ERROR : return "CRC Error";
case AL_COMPARE_ERROR : return "Comparison error";
case AL_UNKNOWN_COMPRESSION_TYPE : return "Unknown compression type";
case AL_UNKNOWN_STORAGE_OBJECT : return "Unknown type of storage object";
case AL_INVALID_ARCHIVE : return "Invalid archive";
case AL_LOGIC_ERROR : return "Logic error";
case AL_BACKUP_FAILURE : return "Could not create backup";
case AL_GETSEL_ERROR : return "Error getting selections from list box";
case AL_DUPLICATE_ENTRY : return "Duplicate entry";
default : return "Unknown error";
}
}
//
// const char * ALStatus::GetStatusDetail() const
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Guaranteed to return a valid character string.
//
// DESCRIPTION
//
// Whenever we set the error code for an object in ArchiveLib, we
// call ALStatus::SetError(). At the same time that we set the
// error code of the object to a non-zero value, we supply a formatted
// string providing some detail about when and where the error
// took place, maybe even including some other information provided by the
// O/S. That information is stored in the detail string, which is a
// private data member. This function provides the ability to get at
// that detail string.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
const char AL_DLL_FAR * AL_PROTO ALStatus::GetStatusDetail() const
{
if ( mszStatusDetail )
return mszStatusDetail;
else if ( miStatus == AL_SUCCESS )
return "No errors";
else
return "Unable to allocate memory for error detail message";
}
//
// ALStatus & ALStatus::operator = ( ALStatus &rhs )
//
// ARGUMENTS:
//
// rhs : Another ALStatus object that I want to copy into this object.
//
// RETURNS
//
// A reference to this.
//
// DESCRIPTION
//
// Somewhere in ArchiveLib I want to be able to copy one status
// into another. This function does just that. It has to allocate
// new space to make a copy of the detail string, and be sure to
// free up any old space, and all that.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
ALStatus AL_DLL_FAR & AL_PROTO ALStatus::operator = ( ALStatus AL_DLL_FAR &rhs )
{
if ( rhs.mszStatusDetail == 0 ) {
if ( mszStatusDetail ) {
delete[] mszStatusDetail;
mszStatusDetail = 0;
}
} else {
if ( mszStatusDetail == 0 )
mszStatusDetail = new char[ miStatusDetailLength ];
if ( mszStatusDetail )
strcpy( mszStatusDetail, rhs.mszStatusDetail );
}
miStatus = rhs.miStatus;
return *this;
}

158
al/status.h Executable file
View File

@ -0,0 +1,158 @@
/*
* STATUS.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class declaration for ALStatus.
* This is a utility class that is used as a data member in many
* different types of objects. It holds the current error status
* of an object.
*
* CLASS DEFINITIONS:
*
* ALStatus
*
* MACROS
*
* ostream& operator << ( ostream& stream, const ALStatus &status )
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _STATUS_H
#define _STATUS_H
#if defined( __cplusplus )
/*
* class ALStatus
*
* DESCRIPTION
*
* ALStatus is a utility class that is used as a data member of several
* other classes. It provides an integer member that keeps track
* of the current status of the object, with AL_SUCCESS meaning
* everything is okay, and a code < 0 meaning the object has
* experienced an error.
*
* The object also contains a character pointer to a detailed error
* message. Usually when an error occurs in ArchiveLib, the
* routine that detects the error generates a detailed message that
* can be stored to provide additional information.
*
* Error states in ArchiveLib are "sticky". Once an object is flagged
* as being in error, it will stay that way until the programmer
* resets it, which means it will fail most ordinary operations.
* When you want to clear the error statue of an object, call
* SetError() with AL_SUCCESS as the error code.
*
* DATA MEMBERS
*
* miStatus : The current status of the object, with AL_SUCCESS
* being a good value. You can get at this easily
* by casting ALStatus to type int.
*
* miStatusDetailLength : This member keeps track of the length of the
* status detail. The status detail buffer
* is dynamically allocated when it is needed.
* Keeping this member is really kind of dumb, I
* need to just allocate as much space as necessary
* when the error detail is created. Look for this
* data member to go away in an upcoming release.
*
* mszStatusDetail : The detailed error message. It will be set to
* 0 until a message is generated, when it
* is dynamically allocated. Cleaned up if necessary
* in the destructor.
*
* MEMBER FUNCTIONS
*
* ALStatus() : The default and only constructor.
* ~ALStatus() : The destructor, has to clean up detail string.
* operator new() : Memory allocation operator, allocates space
* for the class object when the library is in
* the DLL.
* SetError() : Sets the error code to a value, and writes
* new data into the detail string.
* GetStatusCode() : Returns the current integer status code,
* just like operator int().
* GetStatusString() : Returns the short string translation.
* GetStatusDetail() : Returns the detailed status message, created
* at the point the error took place.
* operator int() : The casting operator, used all over ArchiveLib
* when testing a status for a value < AL_SUCCESS.
* operator=() : Assignment operator, easy here.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALStatus {
/*
* Constructors, destructors, assignment operators, and declarations
*/
public :
AL_PROTO ALStatus();
AL_PROTO ~ALStatus();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* I don't want to allow the copy constructor, although I probably could
* support it without too much trouble.
*/
protected :
AL_PROTO ALStatus( ALStatus AL_DLL_FAR & );
/*
* Member functions
*/
public :
int AL_PROTO SetError( int error, const char AL_DLL_FAR *fmt, ... );
AL_PROTO GetStatusCode(){ return miStatus; }
const char AL_DLL_FAR * AL_PROTO GetStatusString();
const char AL_DLL_FAR * AL_PROTO GetStatusDetail() const;
AL_PROTO operator int(){ return miStatus; }
ALStatus AL_DLL_FAR & AL_PROTO operator = ( ALStatus AL_DLL_FAR & );
/*
* Data members
*/
protected :
int miStatus;
const int miStatusDetailLength;
char AL_DLL_FAR *mszStatusDetail;
};
inline ostream& operator << ( ostream& stream, const ALStatus AL_DLL_FAR &status )
{
#if defined( AL_USING_DLL ) && !defined( AL_LARGE_MODEL ) && !defined( AL_FLAT_MODEL )
const char _far *p = status.GetStatusDetail();
char *near_string = new char[ _fstrlen( p ) + 1 ];
if ( near_string ) {
_fstrcpy( near_string, p );
stream << near_string;
delete near_string;
} else
stream << "Memory allocation failure!";
return stream;
#else
return stream << status.GetStatusDetail();
#endif
}
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _STATUS_H */

979
al/storage.cpp Executable file
View File

@ -0,0 +1,979 @@
//
// STORAGE.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALStorage::operator new()
// ALStorage::ALStorage()
// ALStorage::~ALStorage()
// ALStorage::UpdateCrc()
// ALStorage::Open()
// ALStorage::Create()
// ALStorage::Close()
// ALStorage::GetCrc32()
// ALStorage::InitCrc32()
// ALStorage::ReadBuffer()
// ALStorage::WriteBuffer()
// ALStorage::WritePortableShort()
// ALStorage::WritePortableLong()
// ALStorage::ReadPortableShort()
// ALStorage::ReadPortableLong()
// ALStorage::WriteString()
// ALStorage::ReadString()
// ALStorage::Tell()
// ALStorage::YieldTime()
// ALStorage::WriteStorageObjectData()
// ALStorage::ReadStorageObjectData()
//
// DESCRIPTION
//
// This file contains all of the source code for the member functions
// of ALStorage. AlStorage has pure virtual functions, so you can't
// ever instantiate one of these guys.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <string.h>
//
// void * ALStorage::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALStorage object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALStorage::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALStorage::ALStorage( const char *file_name,
// size_t size,
// const enum ALStorageType object_type,
// ALCase name_case )
//
// ARGUMENTS:
//
// file_name : The name to assign to the mName data member of the
// newly created storage object.
//
// size : The size of the I/O buffer that is going to be used
// for the storage object. ALFile uses 4096 as a default.
//
// object_type : The type of object, as defined in ALDEFS.H. Good
// values include AL_FILE_OBJECT and AL_MEMORY_OBJECT.
//
// name_case : The case sensitivity of the object name. For objects
// such as ALFile, AL_MIXED is a no-no. Those objects
// need to be forced to convert names to all upper
// or all lower, because the operating system considers
// file names to be case insensitive.
//
// RETURNS
//
// Nothing, it is a constructor.
//
// DESCRIPTION
//
// The constructor for ALStorage gets called from the constructor of
// derived classes. It has to initialize all sorts of data members.
// First, in the initializer list, it sets up the mName data member,
// as well as muBufferSize and miStorageObjectType. The latter two
// data members are set to be const so I can make them public, which
// means we have to initialize them in the initializer list.
//
// In the body of the constructor, we initialize a bunch of data members,
// none of which mean anything at this point.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALStorage::ALStorage( const char AL_DLL_FAR *file_name,
size_t size,
const enum ALStorageType object_type,
ALCase name_case )
: mName( file_name, name_case ),
miStorageObjectType( object_type ),
muBufferSize( size )
{
mpcBuffer = 0;
muBufferValidData = 0;
muWriteIndex = 0;
muReadIndex = 0;
mlFilePointer = 0;
miUpdateCrcFlag = 0;
mlCrc32 = 0xffffffffL;
mlSize = -1L;
mpMonitor = 0;
miCreated = 0;
if ( mName.GetName() == 0 )
mStatus.SetError( AL_CANT_OPEN_BUFFER,
"Allocation of buffer failed in "
"ALStorage constructor" );
}
//
// ALStorage::~ALStorage()
//
// ARGUMENTS:
//
// No arguments for destructors.
//
// RETURNS
//
// No returns from destructors.
//
// DESCRIPTION
//
// In debug mode, we first check to make sure we are destroying the
// right type of object.
//
// The only thing left to do is free up the I/O buffer if it is still
// allocated. This piece of work probably isn't necessary. Since this
// is a virtual destructor, we will be called after the destructors
// for the derived class. Any derived class that is doing its job
// will make sure that it calls Close() before destroying itself. If
// it doesn't, it will probably be leaving unfinished business behind
// that we aren't going to be able to deal with here. Even so, we will
// be diligent in our attention to detail.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALStorage::~ALStorage()
{
AL_ASSERT( GoodTag(), "~ALStorage: attempting to delete invalid object" );
if ( mpcBuffer )
Close();
}
//
// This giant table is used by the CRC routines. These are the coefficients
// for calculating the CCITT 32 bit CRC. I typed these in from memory, so
// I hope they are correct.
//
static unsigned long ccitt_32[ 256 ] =
{
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
};
//
// void ALStorage::UpdateCrc( size_t count )
//
// ARGUMENTS:
//
// count : The number of characters to process in the I/O buffer.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// If CRC checking has been turned on for the storage object, this
// routine will be called every time LoadBuffer() or FlushBuffer()
// are called. It does CRC checking on a buffer full of data at
// a time. Hopefully this means the compiler can optimize the
// heck out of this code.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALStorage::UpdateCrc( size_t count )
{
unsigned char *p = (unsigned char *) mpcBuffer;
while ( count-- != 0 )
mlCrc32 = ( ( mlCrc32 >> 8 ) & 0x00FFFFFFL ) ^
( ccitt_32[ ( (int) mlCrc32 ^ *p++ ) & 0xff ] );
}
//
// int ALStorage::Open()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, or AL_CANT_OPEN_BUFFER on memory allocation failure.
// If the object was already in an error state, it is very possible to
// get some other error code < 0.
//
// DESCRIPTION
//
// Any derived class needs to have its own Open() function. However,
// the derived class can also call this Open() function in the base
// class to do some odds and ends for it. The most important thing it
// does is allocate the I/O buffer, which is what makes ALStorage a
// relatively fast way to read and write data. Although the buffer
// is in place, there is no data in it, so this guy also sets up the
// indices and pointers to reflect that.
//
// Upon exit, all you need to to is start reading or writing, and the
// whole thing should be ready to go.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::Open()
{
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( muBufferSize != 0 )
mpcBuffer = new unsigned char[ muBufferSize ];
muBufferValidData = 0;
muWriteIndex = 0;
muReadIndex = 0;
mlFilePointer = 0;
miUpdateCrcFlag = 0;
mlCrc32 = 0xffffffffL;
if ( mpcBuffer == 0 )
return mStatus.SetError( AL_CANT_OPEN_BUFFER,
"Allocation of buffer failed in Open()" );
return AL_SUCCESS;
}
//
// int ALStorage::Create()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// AL_SUCCESS, or AL_CANT_OPEN_BUFFER on memory allocation failure.
// If the object was already in an error state, it is very possible to
// get some other error code < 0.
//
// DESCRIPTION
//
// This function is nearly identical to ALStorage::Open().
//
// Any derived class needs to have its own Create() function. However,
// the derived class can also call this Create() function in the base
// class to do some odds and ends for it. The most important thing it
// does is allocate the I/O buffer, which is what makes ALStorage a
// relatively fast way to read and write data. Although the buffer
// is in place, there is no data in it, so this guy also sets up the
// indices and pointers to reflect that.
//
// Upon exit, all you need to to is start writing, and the
// whole thing should be ready to go.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::Create()
{
if ( mStatus < AL_SUCCESS )
return mStatus;
mpcBuffer = new unsigned char[ muBufferSize ];
muBufferValidData = 0;
muWriteIndex = 0;
muReadIndex = 0;
mlFilePointer = 0;
miUpdateCrcFlag = 0;
mlCrc32 = 0xffffffffL;
miCreated = 1;
if ( mpcBuffer == 0 )
return mStatus.SetError( AL_CANT_OPEN_BUFFER,
"Allocation of buffer failed in Open()" );
return AL_SUCCESS;
}
//
// int ALStorage::Close()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// The current integer status of the object. Hopefully this will be
// AL_SUCCESS, but it could well be a value < AL_SUCCESS.
//
// DESCRIPTION
//
// Just like with Open(), must derived classes will have their own
// versions of Close(). They can call this version to delete the I/O
// buffer if they feel like it is too hard to do themselves.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::Close()
{
if ( mpcBuffer ) {
delete[] mpcBuffer;
mpcBuffer = 0;
}
return mStatus;
}
//
// long ALStorage::GetCrc32()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// The current value of the CRC-32.
//
// DESCRIPTION
//
// This function is used to get the CRC-32 of a storage object. But it
// does a little bit more than just give you the CRC. First, it makes
// sure the buffers have been flushed, so that the CRC is accurate. If
// we didn't do this we might try to get the CRC on an incompletely
// written file.
//
// Once we get the CRC,the miUpdateCrcFlag is set to 0, which means
// that from here on out the value will not be updated. So retrieving
// the CRC means you are no longer interested in further calculation.
// It also means you can trust the value you just read, because it
// will never be modified again.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
long AL_PROTO ALStorage::GetCrc32()
{
if ( IsOpen() && miUpdateCrcFlag )
FlushBuffer();
miUpdateCrcFlag = 0;
return mlCrc32;
}
//
// void ALStorage::InitCrc32( unsigned long seed = 0xffffffffL )
//
// ARGUMENTS:
//
// seed : The long value to start the CRC off at. There is probably
// no reason to change this from the default value, although
// I won't be surprised if someone comes up with one.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// Calling this function kicks off the CRC calculation for a given
// storage object should be done immediately after the object is
// opened. Once the miUpdateCrcFlag is set, the CRC will be updated
// every time a LoadBuffer() or FlushBuffer() is called.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALStorage::InitCrc32( unsigned long seed /* = 0xffffffffL */ )
{
miUpdateCrcFlag = 1;
mlCrc32 = seed;
}
//
// size_t ALStorage::ReadBuffer( unsigned char *buf, size_t length )
//
// ARGUMENTS:
//
// buf : The buffer that is going to receive input characters.
//
// length : The number of bytes you want to read.
//
// RETURNS
//
// The number of bytes read in, always. If this function generates an
// error, it will be found in the mStatus member.
//
// DESCRIPTION
//
// We could write a simple version of this function by just calling
// ReadChar() over and over, but it would be nice to do things
// a little more efficiently. Since we have this nice big buffer
// full of data ready to read, it makes sense to copy big chunks of
// it in one fell swoop. That is what this guy does. It sits in a loop
// doing a memcpy() followed by LoadBuffer() until all of the data
// that has been asked for got moved. As data is read in, we have to
// update the data member muReadIndex. Other data members will get
// updated by LoadBuffer().
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
size_t AL_PROTO ALStorage::ReadBuffer( unsigned char *buf,
size_t length )
{
size_t bytes_left_to_read = length;
size_t buffer_bytes_available;
while ( bytes_left_to_read ) {
buffer_bytes_available = muBufferValidData - muReadIndex;
if ( buffer_bytes_available == 0 ) {
if ( LoadBuffer( mlFilePointer ) < 0 )
return length - bytes_left_to_read;
buffer_bytes_available = muBufferValidData;
}
if ( bytes_left_to_read <= buffer_bytes_available ) {
memcpy( buf, mpcBuffer + muReadIndex, bytes_left_to_read );
muReadIndex += bytes_left_to_read;
return length;
} else {
memcpy( buf, mpcBuffer + muReadIndex, buffer_bytes_available );
buf += buffer_bytes_available;
bytes_left_to_read -= buffer_bytes_available;
muReadIndex += buffer_bytes_available;
if ( LoadBuffer( mlFilePointer ) < 0 )
return length - bytes_left_to_read;
}
}
return length;
}
//
// size_t ALStorage::WriteBuffer( const unsigned char *buf,
// size_t length )
//
// ARGUMENTS:
//
// buf : The buffer that is contains the output data.
//
// length : The number of bytes you want to write.
//
// RETURNS
//
// The number of bytes written, always. If this function generates an
// error, it will be found in the mStatus member.
//
// DESCRIPTION
//
// We could write a simple version of this function by just calling
// WriteChar() over and over, but it would be nice to do things
// a little more efficiently. Since we have this nice big buffer
// just waiting for data, it makes sense to copy big chunks to
// it in one fell swoop. That is what this guy does. It sits in a loop
// doing a memcpy() followed by FlushBuffer() until all of the data
// that was ready to go has been sent. As data is written, we have to
// update the data member muWriteIndex. Other data members will get
// updated by FlushBuffer().
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
size_t AL_PROTO ALStorage::WriteBuffer( const unsigned char *buf,
size_t length )
{
size_t buffer_bytes_free;
size_t write_bytes_left = length;
if ( mStatus < 0 )
return 0;
while ( write_bytes_left > 0 ) {
buffer_bytes_free = muBufferSize - muWriteIndex;
if ( buffer_bytes_free == 0 ) {
if ( FlushBuffer() < 0 )
return length - write_bytes_left;
buffer_bytes_free = muBufferSize;
}
if ( write_bytes_left <= buffer_bytes_free ) {
memcpy( mpcBuffer + muWriteIndex, buf, write_bytes_left );
muWriteIndex += write_bytes_left;
return length;
} else {
memcpy( mpcBuffer + muWriteIndex, buf, buffer_bytes_free );
muWriteIndex += buffer_bytes_free;
buf += buffer_bytes_free;
write_bytes_left -= buffer_bytes_free;
if ( FlushBuffer() < 0 )
return length - write_bytes_left;
}
}
return length;
}
//
// int ALStorage::WritePortableShort( short int short_data )
//
// ARGUMENTS:
//
// short_data : A 16 bit int that is going to be written out in
// little endian format.
//
// RETURNS
//
// AL_SUCCESS if all goes well. Otherwise, some error code < AL_STATUS.
//
// DESCRIPTION
//
// In order to make sure our archives can be read and written on all sorts
// of systems, we have a few functions that are used to write numerical
// data in a portable fashion. This function writes short integers in
// little endian format (which is not native Intel format). The complementary
// function, ReadPortableShort(), reads short integers back using the
// same format.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::WritePortableShort( short int short_data )
{
WriteChar( short_data >> 8 );
WriteChar( short_data );
return mStatus;
}
//
// int ALStorage::WritePortableLong( long int long_data )
//
// ARGUMENTS:
//
// long_data : A 32 bit long int that is going to be written out in
// little endian format.
//
// RETURNS
//
// AL_SUCCESS if all goes well. Otherwise, some error code < AL_STATUS.
//
// DESCRIPTION
//
// In order to make sure our archives can be read and written on all sorts
// of systems, we have a few functions that are used to write numerical
// data in a portable fashion. This function writes long integers in
// little endian format (which is not native Intel format). The
// complementary function, ReadPortableLong(), reads long integers back
// using the same format.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::WritePortableLong( long long_data )
{
WriteChar( (int) ( long_data >> 24 ) );
WriteChar( (int) ( long_data >> 16 ) );
WriteChar( (int) ( long_data >> 8 ) );
WriteChar( (int) long_data );
return mStatus;
}
//
// int ALStorage::ReadPortableShort( short int &short_data )
//
// ARGUMENTS:
//
// short_data : A reference to a 16 bit integer that is going to
// have data read in from this storage object.
//
// RETURNS
//
// AL_SUCCESS if all goes well. Otherwise, some error code < AL_STATUS.
//
// DESCRIPTION
//
// In order to make sure our archives can be read and written on all sorts
// of systems, we have a few functions that are used to read numerical
// data in a portable fashion. This function reads short integers in
// little endian format (which is not native Intel format). The
// complementary function, WritePortableShort(), writes short integers out
// using the same format.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::ReadPortableShort( short int & short_data )
{
short_data = (short int) ( ReadChar() << 8 );
short_data |= (short int) ReadChar();
return mStatus;
}
//
// int ALStorage::ReadPortableLong( long int &short_data )
//
// ARGUMENTS:
//
// long_data : A reference to a 32 bit integer that is going to
// have data read in from this storage object.
//
// RETURNS
//
// AL_SUCCESS if all goes well. Otherwise, some error code < AL_STATUS.
//
// DESCRIPTION
//
// In order to make sure our archives can be read and written on all sorts
// of systems, we have a few functions that are used to read numerical
// data in a portable fashion. This function reads long integers in
// little endian format (which is not native Intel format). The
// complementary function, WritePortableLong(), writes long integers out
// using the same format.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::ReadPortableLong( long & long_data )
{
long_data = (long) ReadChar() << 24;
long_data |= (long) ReadChar() << 16;
long_data |= (long) ReadChar() << 8;
long_data |= ReadChar();
return mStatus;
}
//
// int ALStorage::WriteString( const char *string_data )
//
// ARGUMENTS:
//
// string_data : A string to be written out in our portable format.
//
// RETURNS
//
// AL_SUCCESS if things work, or an error code < AL_SUCCESS if an error
// occurs writing the data out.
//
// DESCRIPTION
//
// We write random length data to archive directories using this special
// format, which is a 16 bit int describing the length of the data,
// followed by the data itself. All of the storage objects and compression
// engines write their own private data out using this format. This
// means that even if another class doesn't understand the content of data
// stored in this format, at least it knows how to read it in so as to
// move past it.
//
// This function won't write just any random data, it is specifically
// oriented towards C strings. This means it is mostly used to write
// file names and comments. Their are a few places where classes
// write private data that isn't kept in C strings, they just manually
// write the length with WritePortableShort(), followed by the data.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::WriteString( const char *string_data )
{
short unsigned int len;
if ( string_data != 0 )
len = (short unsigned int) strlen( string_data );
else
len = 0;
WritePortableShort( len );
if ( len )
WriteBuffer( (unsigned char *) string_data, len );
return mStatus;
}
// PROTECTED MEMBER FUNCTION
//
// char * ALStorage::ReadString()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A pointer to a string. This string has been allocated by the library,
// which can cause a problem if you are using a DLL. If an EXE tried
// to free a string pointer allocated by the DLL, havoc would result.
// Because of this hassle, this is a protected function.
//
// The solution to this is to write a new version of this that returns
// an ALName object. I thought of that, but too late.
//
// DESCRIPTION
//
// This function is used internally by ArchiveLib. It is used to read
// random length blocks of data out of archives (or other storage objects).
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
char AL_DLL_FAR * AL_PROTO ALStorage::ReadString()
{
short int len;
if ( ReadPortableShort( len ) < 0 )
return 0;
char *new_string = new char[ len + 1 ];
if ( new_string ) {
ReadBuffer( (unsigned char *) new_string, len );
new_string[ len ] = '\0';
return new_string;
} else {
mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Error allocating buffer space in call "
"to ReadString() for object %s",
mName.GetSafeName() );
return 0;
}
}
//
// long ALStorage::Tell()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A long integer indicating the current position of the read/write
// pointer for the file.
//
// DESCRIPTION
//
// Because we are using buffered I/O here, figuring out the current
// position of the read write pointer is just a tiny bit more complicated
// than just checking a pointer. We have to find the physical location of
// the file pointer, then add in any offset created by the presence of
// data in the I/O buffer.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
long AL_PROTO ALStorage::Tell()
{
if ( muWriteIndex )
return mlFilePointer + muWriteIndex;
else
return mlFilePointer - muBufferValidData + muReadIndex;
}
//
// void ALStorage::YieldTime()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function has two important things to do. It gets called
// at a few different points in the process of reading or writing data
// from storage objects. During normal reading and writing, it
// will get called every time the buffer is loaded or flushed.
//
// If we are in Windows mode, we execute a PeekMessage() loop. This
// makes sure that we aren't hogging the CPU. By doing it this way,
// the programmer can be ensure that he/she is being a good citizen
// without any significant effort.
//
// The second important function is that of calling the monitor function.
// The user interface elements need to be updated regularly, and this
// is done via this call.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALStorage::YieldTime()
{
if ( mpMonitor )
mpMonitor->Progress( Tell(), *this );
/*
* For right now I am going to put the PeekMessage loop in the load
* buffer routine by default. Most Windows applications are going
* to want to use this, right?
*/
#if defined( AL_WINDOWS_GUI )
MSG msg;
while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
TranslateMessage( &msg );
DispatchMessage(&msg);
}
#endif
}
//
// int ALStorage::WriteStorageObjectData( ALStorage * archive )
//
// ARGUMENTS:
//
// archive : A pointer to the storage object where we are going to
// write the private data.
//
// RETURNS
//
// AL_SUCCESS if things went okay, otherwise an error code < AL_SUCCESS.
//
// DESCRIPTION
//
// All storage objects have the ability to create a private data block
// that will be stored along with the directory when creating an archive.
// None of the classes predefined in ArchiveLib use this data block, which
// means they use this function instead of providing their own virtual
// substitute. This function writes a private data block of exactly 0
// bytes in length. Our internal storage format means that a block
// of 0 bytes length takes 2 bytes to store.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::WriteStorageObjectData( ALStorage * archive )
{
return archive->WritePortableShort( 0 );
}
//
// int ALStorage::ReadStorageObjectData( ALStorage * archive )
//
// ARGUMENTS:
//
// archive : A pointer to the storage object where we are going to
// read in the private data..
//
// RETURNS
//
// AL_SUCCESS if things went okay, otherwise an error code < AL_SUCCESS.
//
// DESCRIPTION
//
// All storage objects have the ability to create a private data block
// that will be stored along with the directory when creating an archive.
// None of the classes predefined in ArchiveLib use this data block, which
// means they use this function instead of providing their own virtual
// substitute. This function reads a private data block of exactly 0
// bytes in length. Our internal storage format means that a block
// of 0 bytes length takes 2 bytes to store.
//
// In debug mode, we get really bent out of shape if this data block
// doesn't look exactly like we expect it to.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::ReadStorageObjectData( ALStorage * archive )
{
short int temp;
int status = archive->ReadPortableShort( temp );
AL_ASSERT( temp == 0, "ReadStorageObjectData: stored data is not null" );
return status;
}

424
al/storage.h Executable file
View File

@ -0,0 +1,424 @@
/*
* STORAGE.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file contains the class declaration for the very important
* base class ALStorage.
*
* CLASS DEFINITIONS:
*
* ALStorage
*
* FUNCTIONS:
*
* ALStorage::ReadChar()
* ALStorage::WriteChar()
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _STORAGE_H
#define _STORAGE_H
#if defined( __cplusplus )
#include <stddef.h> /* need for size_t */
#include "timedate.h"
#include "fileattr.h"
/*
* class ALStorage
*
* DESCRIPTION
*
* ALStorage is a base class that defines the different types
* of storage objects used by Archive Library. The two most
* commonly used storage object types are file objects and memory
* objects, defined by the derived classes ALFile and
* ALMemory.
*
* ALStorage objects are used to store and retrieve objects from archives.
* They are also used to store and retrieve the archives themselves,
* allowing archives to be stored in files or directly in memory.
*
* The ALStorage adds buffering to the storage object, allowing for
* fast access to data presently cached in memory. This is very similar to
* the buffering provided for FILE types in stdio.h. Note that this
* buffering is generally only efficient/useful if lots of sequential
* reads or writes are being done, as opposed to random accessess.
*
* ALStorage objects give up a lot of flexibility in order to provide
* quick and efficient access to data. The primary way this affects
* use of the class is that the I/O buffer can only be used for reading
* or writing, but not both simultaneously. The class doesn't check
* for this at run time, so programmers need to enforce it themselves.
*
* When a read is initiated for the first time, the buffer is loaded up,
* and subsequent reads are performed out of the I/O buffer. To switch
* to writing mode, a call to FlushBuffer needs to be performed, which
* will reset the input and output indices. Likewise, when, done writing,
* a call to FlushBuffer() can be performed to clear the indices. A
* read can be done subsequently.
*
* DATA MEMBERS
*
* mpcBuffer : This is the I/O buffer. I read big blocks of
* data into this buffer, then I can perform
* character reads from an inline functin that
* doesn't have to access any virtual fns. Speeds
* things up tremendously. Likewise, I write
* to this buffer using inline functions until it
* it is full. Only then do I call a virtual
* to flush it to disk, memory, or whatever.
*
* muBufferValidData : This keeps track of the end of valid data,
* both when reading and writing. When re
* read in a block of data, this index is set
* to the end of the data. When writing, this
* index is continually updated to reflect the
* end of the user written data.
*
* muWriteIndex : The index in the I/O buffer where the next byte
* is going to be written.
*
* muReadIndex : The index in the I/O buffer where the next read
* will come from.
*
* mlFilePointer : The current location of the read/write pointer
* in the underlying object, e.g. a file. This
* is the location where the data will be written
* out of the I/O buffer when a FlushBuffer() call
* is made. Or, if reading, it is where the next
* LoadBuffer() will read data from.
*
* mlSize : The size of the file/object. This will ordinarily
* be set to -1 when we create an object, because
* we don't know the size yet. When you call Open()
* for an existing object, the value will usually
* be loaded using some sort of system call. We
* also can figure out what the size is when we do
* a ReadDirectory call on an archive.
*
* mlCrc32 : The CRC-32 for the object. This value normally
* won't be known until an object has been placed
* in an archive, or when the information has
* been read out using in ReadDirectory().
*
* miUpdateCrcFlag : This flag is set to indicate that we are in the
* process of calculating the CRC while the file
* is being compressed.
*
* miCreated : This flag will be set if the file was opened
* using Create(), clear if it was opened using
* Open(). When miCreated is set, we will try
* to set the file time, date and attributes when
* we close the file. This is so we can set these
* attributes when we are recreating a file that
* was stored in an archive.
*
* miStorageObjectType : An integer that is assigned when the object was
* constructed. Usually one of the enumerated
* constants found in ALDEFS.H. This is the number
* that gets stored in the Archive directory with
* the object, so we can figure out what type of
* object to create when extracting.
*
* muBufferSize : The size of the I/O buffer.
*
* mpMonitor : A pointer to the monitor attached to this object.
* During the archiving process, this pointer gets
* set by the archive routine for each storage object
* as it is being processes. A value of 0 just
* means no monitor is watching this object at the
* moment.
*
* mTimeDate : The time and date stamp for the file, this usually
* gets set when the object is opened using Open(),
* it is also set when we read in a storage object's
* information using ReadDirectory().
*
* mAttributes : The attributes associated with the file. R/H/S/A.
*
* mName : The name of the storage object.
*
* mStatus : The current status of the object.
*
* MEMBER FUNCTIONS
*
* ALStorage() : The constructor, creates the object, but doesn't
* necessarily create the file/whatever.
* operator=() : Assignment operator.
* operator new() : The memory allocation operator. This is only
* used if the library is in a DLL.
* ~ALStorage() : Virtual destructor.
* UpdateCrc() : Protected function used internally when the
* crc is being calculated
* ReadString() : Read a string in ArchiveLib's proprietary format.
* WriteStorageObjectData() : Protected function to write custom data needed
* for a particular derived classe.
* ReadStorageObjectData() : Protected function read that data back in.
* ReadChar() : Superfast inline function to read a bytee
* WriteChar() : Fast inline function to write a byte.
* ReadBuffer() : Function to read blocks of data.
* WriteBuffer() : Function to write blocks of data.
* Open() : Open() used to prepare an existing object for I/O.
* Create() : Create a new underlying object for I/O.
* Close() : Called when I/O is complete.
* LoadBuffer() : Called to reload the I/O buffer, used internally
* when ReadChar() runs out of stuff to read.
* FlushBuffer() : Called to flush the I/O buffer to the underlying
* object. Called when WriteChar() has gone too far.
* Seek() : Called to reposition the I/O pointer of the
* underlying object.
* YieldTime() : Called whenever a FlushBuffer() or LoadBuffer()
* takes place. Used to update the Monitor attached
* to the file, and to yield time to the O/S.
* Compare() : Compare two storage objects.
* InitCrc32() : Called to start calculating the CRC for an object.
* WritePortableShort() : Write 16 bit integer in little endian format.
* WritePortableLong() : Write 32 bit integer in little endian format.
* ReadPortableShort() : Read 16 bit integer in little endian format.
* ReadPortableLong() : Read 32 bit integer in little endian format.
* WriteString() : Write string in ArchiveLib format.
* Rename() : Rename the underlying object.
* UnRename() : Undo a rename operation.
* RenameToBackup() : Rename to a special backup name.
* Delete() : Delete an underlying storage object.
* GetCrc32() : Return value of the CRC member.
* GetSize() : Reeturn value of the size member.
* IsOpen() : Indicate if the file is open.
* Tell() : Indicate where the next read or write will
* take place.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
/*
* Forward declaration
*/
class AL_CLASS_TYPE ALMonitor;
class AL_CLASS_TYPE ALStorage {
public :
/*
* Classes I trust
*/
friend class AL_CLASS_TYPE ALArchiveBase;
friend class AL_CLASS_TYPE ALCompressedObject;
/*
* Constructors, destructors, assignment operator
*/
protected :
AL_PROTO ALStorage( const char AL_DLL_FAR *file_name,
size_t buffer_size,
const ALStorageType storage_type,
ALCase name_case = AL_MIXED );
ALStorage AL_DLL_FAR & AL_PROTO operator=( const ALStorage AL_DLL_FAR & );
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
public :
virtual AL_PROTO ~ALStorage();
/*
* I don't want to allow the copy constructor to exist.
*/
protected :
AL_PROTO ALStorage( const ALStorage AL_DLL_FAR & );
/*
* Member functions, grouped somewhat
*
*
* Private member manipulation
*/
protected :
void AL_PROTO UpdateCrc( size_t count );
/*
* This is private, because it allocates memory in the DLL, so it
* must be deleted in the DLL as well.
*/
private :
char AL_DLL_FAR * AL_PROTO ReadString();
virtual int AL_PROTO
WriteStorageObjectData( ALStorage AL_DLL_FAR * archive );
virtual int AL_PROTO
ReadStorageObjectData( ALStorage AL_DLL_FAR * archive );
/*
* The file I/O access public interface
*/
public :
int AL_PROTO ReadChar();
int AL_PROTO WriteChar( int c );
size_t AL_PROTO ReadBuffer( unsigned char AL_DLL_FAR *buffer,
size_t length );
/* Please keep this arg const, breaks WriteString o/w */
size_t AL_PROTO WriteBuffer( const unsigned char AL_DLL_FAR *buffer,
size_t length );
virtual int AL_PROTO Open();
virtual int AL_PROTO Create();
virtual int AL_PROTO Close();
virtual int AL_PROTO LoadBuffer( long address ) = 0;
virtual int AL_PROTO FlushBuffer() = 0;
virtual int AL_PROTO Seek( long address ) = 0;
virtual void AL_PROTO YieldTime();
int AL_PROTO Compare( ALStorage AL_DLL_FAR &test_object );
void AL_PROTO InitCrc32( unsigned long seed = 0xffffffffl );
int AL_PROTO WritePortableShort( short int short_data );
int AL_PROTO WritePortableLong( long long_data );
int AL_PROTO ReadPortableShort( short int AL_DLL_FAR &short_data );
int AL_PROTO ReadPortableLong( long AL_DLL_FAR &long_data );
int AL_PROTO WriteString( const char AL_DLL_FAR *string_data );
/*
* File manipulation public interface
*/
public :
virtual int AL_PROTO Rename( const char AL_DLL_FAR *new_name = 0,
int delete_on_clash = 1 ) = 0;
virtual int AL_PROTO UnRename( int delete_on_clash = 1 ) = 0;
virtual int AL_PROTO RenameToBackup( int delete_on_clash = 1 ) = 0;
virtual int AL_PROTO Delete() = 0;
/*
* Access functions
*/
public :
long AL_PROTO GetCrc32();
long AL_PROTO GetSize() const { return mlSize; }
int AL_PROTO IsOpen(){ return mpcBuffer != 0; }
long AL_PROTO Tell();
/*
* Data members
*/
protected :
unsigned char AL_DLL_FAR *mpcBuffer;
size_t muBufferValidData;
size_t muWriteIndex;
size_t muReadIndex;
long mlFilePointer;
long mlSize;
long mlCrc32;
short int miUpdateCrcFlag;
short int miCreated;
/*
* Public members
*/
public :
const ALStorageType miStorageObjectType;
const size_t muBufferSize;
ALMonitor AL_DLL_FAR *mpMonitor;
ALTimeDate mTimeDate;
ALFileAttributes mAttributes;
ALName mName;
ALStatus mStatus;
AL_CLASS_TAG( _ALStorageTag );
};
/*
* It is really important to keep these guys inline.
*/
/*
* inline int ALStorage::ReadChar()
*
* ARGUMENTS:
*
* None.
*
* RETURNS
*
* Either the next character available from the I/O buffer, or
* AL_END_OF_FILE.
*
* DESCRIPTION
*
* This is an inline function that is able to quickly do buffered I/O.
* By utilizing an I/O buffer we can make this routine very fast, since
* it doesn't have to call a virtual function. The virtual function
* only has to be called when LoadBuffer() gets called.
*
* Different compilers have different abilities to make this code inline,
* so sometimes it needs to be tinkered with. If you see anything in here
* that looks funny, that probably explains why.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
inline int AL_PROTO ALStorage::ReadChar()
{
int result;
AL_ASSERT( muWriteIndex == 0, "ReadChar(): Attempt to read while in write mode" ); /*Can't read if I've done a write!*/
result = muBufferValidData - muReadIndex;
if ( result <= 0 )
result = LoadBuffer( mlFilePointer );
AL_ASSERT( mpcBuffer != 0, "ReadChar(): Attempt to read from closed file" ); /*Potential disaster*/
if ( result < 0 )
return result;
else
return mpcBuffer[ muReadIndex++ ] & 0xff;
}
/*
* inline int ALStorage::WriteChar( int c )
*
* ARGUMENTS:
*
* c : The character that is going to be written.
*
* RETURNS
*
* Either the character that we just wrote out, or an error < AL_SUCCESS.
*
* DESCRIPTION
*
* This is an inline function that is able to quickly do buffered I/O.
* By utilizing an I/O buffer we can make this routine very fast, since
* it doesn't have to call a virtual function. The virtual function
* only has to be called when FlushBuffer() gets called.
*
* Different compilers have different abilities to make this code inline,
* so sometimes it needs to be tinkered with. If you see anything in here
* that looks funny, that probably explains why.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
inline int AL_PROTO ALStorage::WriteChar( int c )
{
int result;
/* assert( muReadIndex == 0 ); */ /* Can't write if I've done a read */
AL_ASSERT( mpcBuffer != 0, "WriteChar(): Attempt to write to closed file" ); /* Disaster! */
result = muBufferSize - muWriteIndex;
if ( result <= 0 )
result = FlushBuffer();
if ( result < 0 )
return mStatus;
else
return mpcBuffer[ muWriteIndex++ ] = (char) c;
}
#endif /* #if defined( __cplusplus ) */
#endif /* #ifndef _STORAGE_H */

85
al/storcmp.cpp Executable file
View File

@ -0,0 +1,85 @@
//
// STORCMP.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALStorage::Compare()
//
// DESCRIPTION
//
// This file contains a single function from ALStorage. I'm not
// sure why it is in a separate file.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <string.h>
#include "storage.h"
#include "_openf.h"
//
// int ALStorage::Compare( ALStorage & test )
//
// ARGUMENTS:
//
// test : The storage object that will be compared to this.
//
// RETURNS
//
// AL_SUCCESS if the two files match. AL_COMPARE_ERROR if the files
// don't match. An error code < AL_SUCCESS is possible if some other
// error takes place during the process.
//
// DESCRIPTION
//
// This function provides a convenient way to test this object
// against another. Note that if the comparison fails, the status
// code of this object will be set to an error state. You will need
// to clear that error if you intend to use this object again.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALStorage::Compare( ALStorage AL_DLL_FAR & test )
{
ALOpenInputFile in1( test );
ALOpenInputFile in2( *this );
if ( test.mStatus < 0 )
return mStatus = test.mStatus;
if ( GetSize() != test.GetSize() )
return mStatus.SetError( AL_COMPARE_ERROR,
"Comparison failed. "
"File %s and %s are two different sizes.",
mName.GetSafeName(),
test.mName.GetSafeName() );
long position = 0;
for ( ; ; ) {
int c = ReadChar();
if ( c < 0 )
break;
if ( c != test.ReadChar() )
return mStatus.SetError( AL_COMPARE_ERROR,
"File %s and %s differed at position %ld",
mName.GetSafeName(),
test.mName.GetSafeName(),
position );
position++;
}
return mStatus;
}

457
al/timedate.cpp Executable file
View File

@ -0,0 +1,457 @@
//
// TIMEDATE.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALTimeDate::operator new()
// ALTimeDate::ALTimeDate()
// ALTimeDate::~ALTimeDate()
// ALTimeDate::ToJulian()
// ALTimeDate::FromJulian()
// ALTimeDate::GetUnixTime()
// ALTimeDate::SetTimeDate(long)
// ALTimeDate::SetTimeDate(struct tm *)
// ALTimeDate::GetTimeDate()
//
// DESCRIPTION
//
// This file contains all of the member functions of class ALTimeDate.
// This class is used only by ALStorage, but it seemed like a good
// idea to break it out in a separate class. A lot of the code in here
// came straight out of CommLib.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <time.h>
#include "timedate.h"
//
// void * ALTimeDate::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALTimeDate object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALTimeDate::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALTimeDate::ALTimeDate()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// None.
//
// DESCRIPTION
//
// All the constructor does is initialize the data members. By
// setting the year to an invalid value of 0, we can always see
// that the time date stamp for a file hasn't been initialized.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALTimeDate::ALTimeDate()
{
miYear = 0; //This is an illegal year, means it is uninitialized
miMonth = 0;
miDate = 0;
miHour = 0;
miMinute = 0;
miSecond = 0;
}
//
// ALTimeDate::~ALTimeDate()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// None.
//
// DESCRIPTION
//
// The destructor has nothing to do.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALTimeDate::~ALTimeDate()
{
}
//
// long ALTimeDate::ToJulian()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A Julian day.
//
// DESCRIPTION
//
// This function is used to make a Julian day number from a normal
// month/day/year thing. We need a Julian day in order to make a
// UNIX style time stamp. The UNIX time stamp is used to store
// time stamps in Archive directories.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
long AL_PROTO ALTimeDate::ToJulian()
{
return (long)( miDate - 32076)
+ 1461L * ( miYear + 4800L + ( miMonth - 14) / 12) / 4
+ 367 * ( miMonth - 2 - ( miMonth - 14) / 12 * 12) / 12
- 3 * (( miYear + 4900L + ( miMonth - 14) / 12) / 100) / 4
+ 1;
}
//
// void ALTimeDate::FromJulian( long jdn )
//
// ARGUMENTS:
//
// jdn : A julian date number, ideally one produced by ToJulian().
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function is used to convert a julian date to a normal
// year/month/day. Time/date stamps are stored in Archives in
// UNIX format. This function is needed to convert a UNIX
// time stamp to a normal mm/dd/yy.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALTimeDate::FromJulian( long jdn )
{
long x;
long z;
long m;
long d;
long y;
const long daysPer400Years = 146097L;
const long fudgedDaysPer4000Years = 1460970L + 31;
x = jdn + 68569L;
z = 4 * x / daysPer400Years;
x = x - (daysPer400Years * z + 3) / 4;
y = 4000 * (x + 1) / fudgedDaysPer4000Years;
x = x - 1461 * y / 4 + 31;
m = 80 * x / 2447;
d = x - 2447 * m / 80;
x = m / 11;
m = m + 2 - 12 * x;
y = 100 * (z - 49) + y + x;
//
// I don't know whether or not we could eliminate these temporary longs
//
miYear = (short int) y;
miMonth = (short int) m;
miDate = (short int) d;
}
//
// long ALTimeDate::GetUnixTime()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// A UNIX time, converted from the internal m/d/y h:m:s data.
//
// DESCRIPTION
//
// This function is used to convert the m/d/y h:m:s time stamp for a file
// into a UNIX time stamp. The UNIX time stamp is a 32 bit long that
// is used to store time stamps in an Archive.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
long AL_PROTO ALTimeDate::GetUnixTime()
{
const long UnixFirstDay = 2440588L;
long result;
result = ToJulian();
result -= UnixFirstDay;
if ( result >= 0L ) {
result *= 3600L * 24;
result += 3600L * miHour;
result += 60L * miMinute;
result += miSecond;
} else
result = 0L;
return result;
}
//
// void ALTimeDate::SetTimeDate( long unix_time )
//
// ARGUMENTS:
//
// unix_time : A long integer in UNIX timestamp format.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function is called when we are reading a directory in from
// an archive. It is used to set the internal data members of an
// ALTimeDate object, after converting from unix time.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALTimeDate::SetTimeDate( long unix_time )
{
const long UnixFirstDay = 2440588L;
long jd = unix_time / ( 3600L * 24 );
long hms = unix_time % ( 3600L * 24 );
FromJulian( jd + UnixFirstDay );
miHour = (short int) ( hms / 3600 );
hms -= 3600L * miHour;
miMinute = (short int) ( hms / 60 );
miSecond = (short int) ( hms - ( miMinute * 60 ) );
}
//
// void ALTimeDate::SetTimeDate( struct tm *tblock )
//
// ARGUMENTS:
//
// tblock : A time date stamp as used by the C run time library.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// When working with DOS files, time stamps are read in to a structure
// in the struct tm format. This function provides an easy way to convert
// the structure into our internal format. When a DOS file is opened
// using Open(), this function is called.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALTimeDate::SetTimeDate( struct tm AL_DLL_FAR *tblock )
{
AL_ASSERT( tblock != 0, "SetTimeDate: passing illegal null parameter" );
miYear = (short int) ( tblock->tm_year + 1900 );
miMonth = (short int) ( tblock->tm_mon + 1 );
miDate = (short int) tblock->tm_mday;
miHour = (short int) tblock->tm_hour;
miMinute = (short int) tblock->tm_min;
miSecond = (short int) tblock->tm_sec;
}
//
// void ALTimeDate::GetTimeDate( struct tm *tblock )
//
// ARGUMENTS:
//
// tblock : A structure in the format used by the C runtime library for
// storing time and date stamps.
//
// RETURNS
//
// Nothing.
//
// DESCRIPTION
//
// This function provides the reverse of SetTimeDate(). You would think
// that we could just set the appropriate members of struct tm, but
// there is a problem with that. struct tm has one element that is
// supposed to be the day of the week, and another that is supposed
// to be the number of the day within the year. We could try to
// figure those out using the julian day function, but since gmtime()
// will figure them out for us, we'll use that instead.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
void AL_PROTO ALTimeDate::GetTimeDate( struct tm AL_DLL_FAR *tblock )
{
AL_ASSERT( tblock != 0, "GetTimeDate: passing illegal null parameter" );
long unix_time = GetUnixTime();
struct tm *result = gmtime( (const time_t *) &unix_time );
if ( result ) {
*tblock = *result;
tblock->tm_isdst = 0;
} else { //This should never happen!
tblock->tm_year = miYear - 1900;
tblock->tm_mon = miMonth - 1;
tblock->tm_mday = miDate;
tblock->tm_hour = miHour;
tblock->tm_min = miMinute;
tblock->tm_sec = miSecond;
tblock->tm_wday = 0;
tblock->tm_yday = 0;
tblock->tm_isdst = 0;
}
}
//
// unsigned short int ALTimeDate::GetDosTime()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// This function returns the time stored in this. The bits of the
// time are packed into the form that is needed by the _dos_setftime()
// format.
//
// DESCRIPTION
//
// When we close a file that needs to have its time and date stamp
// set, we normally use the _dos_setftime() function to do the
// work. It expects to see the time packed into a particular
// sequence of bits in an unsigned short. That is what this
// function does. It packs the bits just the way you want them.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if !defined( AL_WIN32S )
unsigned short int AL_PROTO ALTimeDate::GetDosTime()
{
int result;
result = miSecond / 2;
result |= miMinute << 5;
result |= miHour << 11;
return (unsigned short int) result;
}
#endif //#if !defined( AL_WIN32S )
//
// unsigned short int ALTimeDate::GetDosDate()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// This function returns the date stored in this object. The bits of the
// date are packed into the form that is needed by the _dos_setftime()
// format.
//
// DESCRIPTION
//
// When we close a file that needs to have its time and date stamp
// set, we normally use the _dos_setftime() function to do the
// work. It expects to see the date packed into a particular
// sequence of bits in an unsigned short. That is what this
// function does. It packs the bits just the way you want them.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if !defined( AL_WIN32S )
unsigned short int AL_PROTO ALTimeDate::GetDosDate()
{
int result;
result = miDate;
result |= miMonth << 5;
result |= (miYear-1980) << 9;
return (unsigned short int ) result;
}
#endif //#if !defined( AL_WIN32S )

125
al/timedate.h Executable file
View File

@ -0,0 +1,125 @@
/*
* TIMEDATE.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the class declaration for ALTimeDate.
*
* CLASS DEFINITIONS:
*
* ALTimeDate
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _TIMEDATE_H
#define _TIMEDATE_H
#include <time.h>
/*
* class ALOpenInputFile
*
* DESCRIPTION
*
* class ALTimeDate is used strictly to keep track of the time/date
* stamp of an ALStorage object. The only place this class appears is
* as the mTimeDate member of ALStorage. It has a number of conversion
* utilities for loading and exporting its values in various formats.
* Since most of the ways we have to set time stamps for objects
* are not ANSI standard, we end up with quite a few conversion utilities.
*
* DATA MEMBERS
*
* miYear : The year just like you would expect, e.g 1994. A value of
* 0 in this field indicates an invalid time.
*
* miMonth : The month, 1-12.
*
* miDate : The date, 1-31.
*
* miHour : In 2400 format, 0 - 23.
*
* miMinute : 0 - 59
*
* miSecond : 0 -59,
*
* MEMBER FUNCTIONS
*
* ALTimeDate() : The constructor, sets all members to 0.
* ~ALTimeDate() : The destructor, has no work to do.
* operator new() : The memory allocation operator, only used
* when the library is inside a DLL.
* ToJulian() : Convert the internal m/d/y members to
* a julian day number.
* FromJulian() : Convert a julian day number to internal
* data members m/d/y.
* GetUnixTime() : Convert all members to a long in unix format,
* total seconds since 1/1/1970.
* GetDosTime() : Convert h:m:s data members to the unsigned int
* used in certain DOS commands.
* GetDosDate() : Convert m/d/y data members to the unsigned int
* used in certain DOS commands.
* SetTimeDate(long) : Set internal data members from a UNIX long.
* SetTimeDate(struct tm*) : Set internal data members from a DOS
* struct tm *.
* GetTimeDate() : Convert internal data members to a DOS struct tm *.
* Valid() : Indicate if a valid time has been set.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALTimeDate {
/*
* Constructors, destructors, declarations, assignment operator
*/
public :
AL_PROTO ALTimeDate();
AL_PROTO ~ALTimeDate();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* I usually hide the copy constructor and assignment operators,
* but in this case they are OK
*
*
* Member functions
*/
public :
long AL_PROTO ToJulian();
void AL_PROTO FromJulian( long jdn );
long AL_PROTO GetUnixTime();
#if !defined( AL_WIN32S )
unsigned short int AL_PROTO GetDosTime();
unsigned short int AL_PROTO GetDosDate();
#endif /* #if !defined( AL_WIN32S ) */
void AL_PROTO SetTimeDate( long unix_time );
void AL_PROTO SetTimeDate( struct tm AL_DLL_FAR *tblock );
void AL_PROTO GetTimeDate( struct tm AL_DLL_FAR *tblock );
int AL_PROTO Valid(){ return miYear != 0; }
/*
* Data members
*/
protected :
short int miYear; /* What you expect, e.g. 1995 */
short int miMonth; /* 1-12 */
short int miDate; /* 1-31 */
short int miHour; /* 0-23 */
short int miMinute; /* 0-59 */
short int miSecond; /* 0-59 */
};
#endif

594
al/wildcard.cpp Executable file
View File

@ -0,0 +1,594 @@
//
// WILDCARD.CPP
//
// Source file for ArchiveLib 1.0
//
// Copyright (c) Greenleaf Software, Inc. 1994
// All Rights Reserved
//
// CONTENTS
//
// ALWildCardExpander::operator new()
// ALWildCardExpander::ALWildCardExpander()
// ALWildCardExpander::~ALWildCardExpander()
// ALWildCardExpander::GetNextWildName()
// ALWildCardExpander::GetNextFile()
//
// DESCRIPTION
//
// This file contains all the source code for the nifty class
// ALWildCardExpander. The wild card expansion code is a state
// drive routine, which keeps track of its entire state between
// calls. So you can call it once to get a new file name, then
// do some processing. When you call it again later, you will
// get the next file name in the sequence.
//
// There is a little difference between the NT version and the DOS
// version, because the function calls for get first/get next
// are different. A minor difference is created by the fact
// that under NT you can't specify attributes in a search, so when
// you want to look for subdirectories, you have to search all files
// and see if any of your matches turn out to be directories.
//
// The way the wild card class handles searching through subdirectories
// is by keeping a link pointer to a subdirectory search. When it
// is time to open up a subdirectory search, we create a new file
// expander, and assign its pointer to our link pointer. As long as
// the link is active, we keep searching there. When the link runs
// out of files to return, we continue searching in our own directory.
//
// A lot of this code is easier to deal with because we use the
// ALName class. That makes it easy to strip file names and
// paths apart, and even easier to put them back together again.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
//
#include "arclib.h"
#pragma hdrstop
#include <stdlib.h>
#ifdef __BORLANDC__
#include <dir.h>
#endif
#include "wildcard.h"
//
// void * ALWildCardExpander::operator new( size_t size )
//
// ARGUMENTS:
//
// size : The number of bytes needed to create a new ALWildCardExpander
// object.
//
// RETURNS
//
// A pointer to the newly allocated storage area, or 0 if no storage
// was available.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO ALWildCardExpander::operator new( size_t size )
{
return ::new char[ size ];
}
#endif
//
// ALWildCardExpander::ALWildCardExpander( const char *file_list,
// int traverse_flag = 0,
// ALCase name_case = AL_LOWER )
//
// ARGUMENTS:
//
// file_list : A list of wild card file specifications, separated
// by commas, semicolons, or spaces, maybe looking
// something like this: "*.CPP, BOB.DAT, *.*"
//
// traverse_flag : A flag that indicates whether you want to traverse
// all subdirectories under the current path.
//
// name_case : An indicator of whether you want all the returned
// file names forced to a certain case.
//
// RETURNS
//
// No returns.
//
// DESCRIPTION
//
// The constructor for the expander has to set up a bunch of data members
// that will all be used during the expansion process. The mCase
// member is easy to understand. All of the objname objects that
// we create are going to be force to a certain case by this
// using this data member. miTraverseFlag is just our copy of the
// input parameter. And the mState variable keeps track of what we
// are doing in between function calls. We set it to GET_NEXT_WILD_NAME,
// which means we will be doing that the first time we get called.
//
// mInputLine is where we keep a copy of the list of wild card file
// specifications passed by the calling program. Each time we take
// a new file name out of mInputLine, we remove it from the ALName
// object, making mInputLine just a little shorter.
//
// The mResultFileName member is the storage area where we keep a copy
// of the file name created by the expander. This is our local copy,
// when it gets returned to the calling program they need to make
// their own copy of it and leave ours alone.
//
// Every time we get asked to get a new file, the very first thing
// we do is check to see if the mpNextExpander member is pointing
// to a new expander object. If it is, we ask him to provide
// the next file name, instead of giving it ourselves. When he
// doesn't have any file names left to give, we destroy him and
// set that pointer back to 0. Here in the constructor, the smart
// thing to do is set him to 0 for starters.
//
// The final data member differs between NT and DOS. The structure
// NT uses to expand directories is store in mFindFileHandle. The
// DOS version is stored in mpFfblk. Both of these are presently
// in an invalid state, but will get initialized when the user
// calls the member function.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALWildCardExpander::ALWildCardExpander(
const char AL_DLL_FAR *file_list,
int traverse_flag /* = 0 */,
ALCase name_case /* = AL_LOWER */ )
: mCase( name_case ),
mResultFileName( "", name_case )
{
mInputLine = file_list;
mState = GET_NEXT_WILD_NAME;
mpNextExpander = 0;
miTraverseFlag = traverse_flag;
#if defined( AL_WIN32S )
mFindFileHandle = INVALID_HANDLE_VALUE;
#else
mpFfblk = new find_t;
#endif
}
//
// ALWildCardExpander::~ALWildCardExpander()
//
// ARGUMENTS:
//
// None, destructors don't get any.
//
// RETURNS
//
// None, destructor.
//
// DESCRIPTION
//
// There are a couple of big deals we need to worry about in the
// destructor an ALWildCardExpander. First, we have to worry about
// any additional handlers we created to search subdirectories. If
// this destructor is being called before our search is done, we
// may have some of those expander objects just hanging around out
// there. We take care of the by checking the mpNextExpander member.
// If it isn't set to 0, we delete the dynamically created expander.
//
// Under NT we also have to worry about our mpFindFileHandle. Under
// NT, the file expansion algorithm isn't just a get first/get next
// deal. Instead, it is get first/get next/terminate. The termination
// is done using the FindClose() call. If we still had a search in progress
// we call that function.
//
// Under DOS, we just have to delete the dynamically created
// mpFfblk structure. I wanted to make that a data member of this
// class, instead of a pointer, but one of our compilers wasn't happy
// about putting this C struct in a class, it complained about something.
// So, to expedite, we made it a pointer.
//
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
AL_PROTO ALWildCardExpander::~ALWildCardExpander()
{
if ( mpNextExpander )
delete mpNextExpander;
#if defined( AL_WIN32S )
if ( mFindFileHandle != INVALID_HANDLE_VALUE )
FindClose( mFindFileHandle );
#else
if ( mpFfblk )
delete mpFfblk;
#endif
}
// PROTECTED MEMBER FUNCTION
//
// int ALWildCardExpander::GetNextWildName()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// 1 if it got a new file spec, 0 if it didn't.
//
// DESCRIPTION
//
// This function is called internally to get the next file spec out of
// the input line. This is simply a matter of parsing past all the
// delimiter characters. The resulting file spec is stored in
// data member mFullWildName. That member will be the one used to
// kick off the next wild card search.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
int AL_PROTO ALWildCardExpander::GetNextWildName()
{
char wild_spec[ _MAX_PATH ];
int i = 0;
char *p = mInputLine;
for ( ; ; p++ ) {
int c = *p;
if ( c != ' ' && c != ',' && c != '\t' )
break;
}
for ( ; ; p++ ) {
int c = *p;
if ( c == ' ' || c == ',' || c == '\t' || c == '\0' )
break;
wild_spec[ i++ ] = (char) c;
if ( i >= ( _MAX_PATH - 2 ) )
return 0;
}
wild_spec[ i++ ] = '\0';
if ( i <= 1 )
return 0;
mFullWildName = wild_spec;
mInputLine = p;
return 1;
}
//
// char * ALWildCardExpander::GetNextFile()
//
// ARGUMENTS:
//
// None.
//
// RETURNS
//
// In the event that this routine is able to come up with a new
// file name, it returns a character pointer to the name, which
// is kept in member variable mResultFileName. If no new file
// name could be cooked up, we return a 0, which means you are
// done.
//
// DESCRIPTION
//
// There are two wild card expander routines. One for NT, and one
// for DOS. They are both very similar in structure, but they weren't
// quite close enough to combine into a single routine. However, the
// both share a common structure, which is being described here.
//
// The ALWildCardExpander has what amounts to six different internal
// states. They are:
//
// Searching subdirectories, using another object
//
// Extracting the next wild spec from the input line
//
// Expanding the wild card to get the first matching file
//
// Expanding the wild card to get the next matching file
//
// Looking for the first subdirectory
//
// Looking for the next subdirectory
//
// For the most part, we keep track of the state using the mState
// variable. However, we keep track of whether we are searching
// subdirectories by examining the pointer to the next expander. If
// it is non-null, it means we are in that state.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
#if defined( AL_WIN32S )
//
// This is the NT version. It has to use FindFirstFile() and
// FindNextFile() to get file names. Note that this is implemented
// as a giant loop. This means we may go through several states
// inside this routine until we finally come up with a filename.
//
char AL_DLL_FAR * AL_PROTO ALWildCardExpander::GetNextFile()
{
for ( ; ; ) {
//
// If the pointer to the next expander is set, it means we are working
// on a subdirectory, so I have to let him do the work. If the subdirectory
// search fails, I continue right back where I was when interrupted.
//
if ( mpNextExpander ) {
char *p = mpNextExpander->GetNextFile();
if ( p )
return p; // Return the name if he found one
delete mpNextExpander; // If not, he is toast
mpNextExpander = 0;
}
switch ( mState ) {
//
// This is where I get the next wild spec from the input line. If
// there aren't any more, I return 0, because we are done. If there
// is one, I set up the member variable that will be used in the
// rest of the search, and set up the state so that next I will get
// get the first file name.
//
case GET_NEXT_WILD_NAME :
if ( GetNextWildName() == 0 )
return 0;
mWildPathOnly = mFullWildName;
mWildPathOnly.StripFileName();
mWildNameOnly = mFullWildName;
mWildNameOnly.StripPath();
mState = GET_FIRST_FILE_NAME;
break;
//
// Once I have a wild spec, time to start getting file names.
// FindFirstFile() does it for me. if there aren't any files, I
// either go on to search directories, or go the the next wild
// name in the input line. If there is a name, I return it to
// the calling procedure.
//
case GET_FIRST_FILE_NAME :
mFindFileHandle = FindFirstFile( mFullWildName, &mFindFileData );
if ( mFindFileHandle == INVALID_HANDLE_VALUE ) {
if ( miTraverseFlag )
mState = GET_FIRST_DIRECTORY;
else
mState = GET_NEXT_WILD_NAME;
break;
}
mState = GET_NEXT_FILE_NAME;
if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
break;
mResultFileName = ALName( mWildPathOnly + mFindFileData.cFileName );
return mResultFileName;
//
// Time to get another file name with FindNextFile(). If there aren't
// any more, I clean up, and either get the next name for the input
// line or start searching subdirectories. If there was a name, I return
// it to the calling procedure.
//
case GET_NEXT_FILE_NAME :
if ( !FindNextFile( mFindFileHandle, &mFindFileData ) ) {
FindClose( mFindFileHandle );
mFindFileHandle = INVALID_HANDLE_VALUE;
if ( miTraverseFlag )
mState = GET_FIRST_DIRECTORY;
else
mState = GET_NEXT_WILD_NAME;
break;
}
if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
break;
mResultFileName = ALName( mWildPathOnly + mFindFileData.cFileName );
return mResultFileName;
//
// The procedure to get the first subdirectory is an awful lot like that
// we use to get the first file. If we find a valid subdirectory, we create
// a new expander to deal with its wildcards. If we find a file, but
// it isn't a subdirectory, we keep on searching. If we don't find
// anything, we are going to go back and check out the next file spec
// from the input line.
//
case GET_FIRST_DIRECTORY :
mFindFileHandle = FindFirstFile( mWildPathOnly + "*.*", &mFindFileData );
if ( mFindFileHandle == INVALID_HANDLE_VALUE ) {
mState = GET_NEXT_WILD_NAME;
break;
}
mState = GET_NEXT_DIRECTORY;
if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
if ( strcmp( mFindFileData.cFileName, ".." ) == 0 )
break;
if ( strcmp( mFindFileData.cFileName, "." ) == 0 )
break;
mpNextExpander = new ALWildCardExpander( mWildPathOnly + mFindFileData.cFileName + "\\" + (char *) mWildNameOnly, 1, mCase );
}
break;
//
// This works the same as the state where I get the first directory.
// The only difference here is that if I run out of file names in the
// directory, I have to call FindClose() to clean up after myself.
//
case GET_NEXT_DIRECTORY :
if ( !FindNextFile( mFindFileHandle, &mFindFileData ) ) {
FindClose( mFindFileHandle );
mFindFileHandle = INVALID_HANDLE_VALUE;
mState = GET_NEXT_WILD_NAME;
break;
}
if ( mFindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
if ( strcmp( mFindFileData.cFileName, ".." ) == 0 )
break;
if ( strcmp( mFindFileData.cFileName, "." ) == 0 )
break;
mpNextExpander = new ALWildCardExpander( mWildPathOnly + mFindFileData.cFileName + "\\" + (char *) mWildNameOnly, 1 );
}
break;
default :
return 0;
}
}
}
#else
//
// This is the MS-DOS version of the file expander. In structure,
// it is almost identical to the NT version.
//
char AL_DLL_FAR * AL_PROTO ALWildCardExpander::GetNextFile()
{
//
// mpFfblk is the pointer to my structure used by _dos_findfirst()
// and _dos_findnext(). If for some reason this is a null pointer,
// I need to quit. The only reason this should be null is a memory
// allocation failure.
//
if ( mpFfblk == 0 )
return 0;
for ( ; ; ) {
//
// If the pointer to the next expander is non-zero, it means I am in
// the middle of a subdirectory search. If that is the case, I call
// the next expander to see if it can come up with a file name. if
// it does, we return it. If it doesn't, it means it is done, and
// I can delete it and try my luck with the next subdirectory.
//
if ( mpNextExpander ) {
char *p = mpNextExpander->GetNextFile();
if ( p )
return p;
delete mpNextExpander;
mpNextExpander = 0;
}
switch ( mState ) {
//
// This is where I start, and this is where I end up after completely
// processing one of the input wild specs. I get the next name from
// the input line here. If there aren't any more names, I can return
// 0, meaning the whole thing is done.
//
case GET_NEXT_WILD_NAME :
if ( GetNextWildName() == 0 )
return 0;
mWildPathOnly = mFullWildName;
mWildPathOnly.StripFileName();
mWildNameOnly = mFullWildName;
mWildNameOnly.StripPath();
mState = GET_FIRST_FILE_NAME;
break;
//
// Once I have a file name, I start parsing using _dos_findfirst().
// If that doesn't return a name, I have struck out on my first swing.
// if that is the case, I either move on to start searching subdirectories,
// or go back and look for another name from the input line. On the
// other hand, if I get a name, I return it to the caller.
//
case GET_FIRST_FILE_NAME :
if ( _dos_findfirst( mFullWildName, 0, mpFfblk ) ) {
if ( miTraverseFlag )
mState = GET_FIRST_DIRECTORY;
else
mState = GET_NEXT_WILD_NAME;
break;
}
mState = GET_NEXT_FILE_NAME;
mResultFileName = ALName( mWildPathOnly + mpFfblk->name );
return mResultFileName;
//
// This state is identical to GET_FIRST_FILE_NAME, except it has to
// use _dos_findnext() instead of _dos_findfirst()
//
case GET_NEXT_FILE_NAME :
if ( _dos_findnext( mpFfblk ) ) {
if ( miTraverseFlag )
mState = GET_FIRST_DIRECTORY;
else
mState = GET_NEXT_WILD_NAME;
break;
}
mResultFileName = mWildPathOnly + mpFfblk->name;
return mResultFileName;
//
// After getting all of the file names that a wildspec expands into,
// we can start searching subdirectories, if needed. Unlike with NT,
// we can set our search up to look for directories only. that means
// we don't have to check the status of the file returned from _dos_findxxxx().
// However, we always do have to check to make sure it isn't one of the
// two bogus directory entries, "." or "..".
//
// If we score here, we create a new ALWildCardExpander, and put him to
// work. If we strike out, time to go back and get our next input
// file name.
//
case GET_FIRST_DIRECTORY :
if ( _dos_findfirst( mWildPathOnly + "*.*", _A_SUBDIR, mpFfblk ) ) {
mState = GET_NEXT_WILD_NAME;
break;
}
mState = GET_NEXT_DIRECTORY;
if ( mpFfblk->attrib & _A_SUBDIR ) {
if ( strcmp( mpFfblk->name, ".." ) == 0 )
break;
if ( strcmp( mpFfblk->name, "." ) == 0 )
break;
mpNextExpander = new ALWildCardExpander( mWildPathOnly + mpFfblk->name + "\\" + (char *) mWildNameOnly, 1, mCase );
}
break;
//
// This is just like GET_FIRST_DIRECTORY, except it gets to call
// _dos_findnext() instead of _dos_findfirst().
//
case GET_NEXT_DIRECTORY :
if ( _dos_findnext( mpFfblk ) ) {
mState = GET_NEXT_WILD_NAME;
break;
}
if ( mpFfblk->attrib & _A_SUBDIR ) {
if ( strcmp( mpFfblk->name, ".." ) == 0 )
break;
if ( strcmp( mpFfblk->name, "." ) == 0 )
break;
mpNextExpander = new ALWildCardExpander( mWildPathOnly + mpFfblk->name + "\\" + (char *) mWildNameOnly, 1 );
}
break;
default :
return 0;
}
}
#if defined( AL_MICROSOFT ) && ( AL_MICROSOFT < 800 )
return 0; //MSC 7.0 thinks I need this return path. No way to get here!
#endif
}
#endif // #if defined( AL_WIN32S )... #else

169
al/wildcard.h Executable file
View File

@ -0,0 +1,169 @@
/*
* WILDCARD.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This file contains the class declaration for ALWildCardExpander,
* the class used to expand wildcard file specifications under
* DOS and Win32s.
*
* CLASS DEFINITIONS:
*
* ALWildCardExpander
*
* ENUMERATED TYPES:
*
* ALExpanderState (embedded in ALWildCardExpander)
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _WILDCARD_H
#define _WILDCARD_H
// #include <dos.h>
#include "arclib.h"
#if defined( __cplusplus )
/*
* class ALOpenInputFile
*
* DESCRIPTION
*
* This class is used to expand wild card specifications on a DOS
* or NT file system. Note that you can do exciting things with this, like
* traversing through subdirectories, and separate various specs using
* commas or white space.
*
* DATA MEMBERS
*
* mState : The current state of the expander. This is a value
* from ALExpander state that lets use keep track
* of where we are between calls to the expander.
*
* mpNextExpander : If we are traversing subdirectories, we will
* open a new expander for each subdirectory. This
* is a pointer to any subdirectory we might already
* have open for a search in progress.
*
* mInputLine : The list of wildcard filespecs passed in as an
* argument. This gets whittled away, and will be
* smaller and smaller as all the names are parsed out.
*
* mFullWildName : The current wild card file spec that is being
* expanded.
*
* mWildNameOnly : The current wild name that is being expanded,
* stripped of its drive and path information.
*
* mWildPathOnly : The current drive and path being expanded, stripped
* of its filename and extension.
*
* mResultFileName : The file name that is returned to the calling
* program.
*
* mFindFileData : Under Win32s, this holds data about the file we
* found.
*
* mFindFileHandle : Under Win32s, this is a handle used during the
* wildcard expansion.
*
* mpFfblk : Under MS-DOS, this structure holds the state of
* the wildcard expansion in progress.
*
* miTraverseFlag : This flag indicates whether the search should traverse
* traverse through subdirectories or just search
* in the current directory.
*
* mCase : Indicates whether file names should always be forced
* to upper case, forced to lower case, or left mixed.
*
* MEMBER FUNCTIONS
*
* ALWildCardExpander() : Constructor, everything we need to know to
* perform the search is defined here.
* ~ALWildCardExpander() : Destructor.
* operator new() : Memory allocation function, used when the
* library is in a DLL.
* GetNextWildName() : Protected routine to get the next wild name
* from the input line.
* GetNextFile() : The function to get the next expanded file
* name. It keeps chunking out names until
* the search is complete.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALWildCardExpander {
/*
* Constructors, destructors, assignment operators, declarations
*/
protected :
enum ALExpanderState {
GET_NEXT_WILD_NAME,
GET_FIRST_FILE_NAME,
GET_NEXT_FILE_NAME,
GET_FIRST_DIRECTORY,
GET_NEXT_DIRECTORY,
};
public :
AL_PROTO ALWildCardExpander( const char AL_DLL_FAR *file_list,
int traverse_flag = 0,
ALCase name_case = AL_LOWER );
AL_PROTO ~ALWildCardExpander();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
/*
* Disable copy constructor and assignment operator
*/
protected :
ALWildCardExpander AL_DLL_FAR & AL_PROTO operator=( ALWildCardExpander AL_DLL_FAR & );
AL_PROTO ALWildCardExpander( ALWildCardExpander AL_DLL_FAR & );
/*
* Member functions
*/
protected :
int AL_PROTO GetNextWildName();
public :
char AL_DLL_FAR * AL_PROTO GetNextFile();
/*
* Data members
*/
protected :
ALExpanderState mState;
ALWildCardExpander AL_DLL_FAR *mpNextExpander;
ALName mInputLine;
ALName mFullWildName;
ALName mWildNameOnly;
ALName mWildPathOnly;
ALName mResultFileName;
#if defined( AL_WIN32S )
WIN32_FIND_DATA mFindFileData;
HANDLE mFindFileHandle;
#else
struct find_t AL_DLL_FAR *mpFfblk;
#endif
int miTraverseFlag;
public :
const ALCase mCase;
AL_CLASS_TAG( _ALWildCardExpanderTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _WINMON_H */

113
al/winmon.h Executable file
View File

@ -0,0 +1,113 @@
/*
* WINMON.H
*
* Header file for ArchiveLib 1.0
*
* Copyright (c) 1994 Greenleaf Software, Inc.
* All Rights Reserved
*
* DESCRIPTION
*
* This header file contains the declaration for ALWindowsMessage,
* a monitor class used under Windows.
*
* CLASS DEFINITIONS:
*
* ALWindowsMessage
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
#ifndef _WINMON_H
#define _WINMON_H
#include "arclib.h"
#if defined( __cplusplus )
/*
* class ALWindowsMessage
*
* DESCRIPTION
*
* This class is used to provide user feedback when operating under
* windows. It can be constructed to send messages to windows from
* YieldTime(), allowing you to easily update progress bars, text
* boxes, or whatever.
*
* DATA MEMBERS
*
* mhMessageWindowHandle : The handle of the window that is going to
* get the text messages generated by the
* ArchiveOperation() procedure. If this
* member is set to 0, no messages are sent.
*
* mhNumberWindowHandle : The handle of the window that is going to
* get either the byte count or the percent
* complete figure. If miMessage is 0, it
* is formatted as ASCII and sent using a
* SetWindowText() call. O/W, it is sent
* using SendMessage(), in Lparam and Wparam.
*
* mMessageType : AL_SEND_BYTE_COUNT or AL_SEND_RATIO.
*
* miMessage : The message that gets sent with with the
* byte count or ratio.
*
* MEMBER FUNCTIONS
*
* ALWindowsMessage() : The one and only constructor.
* ~ALWindowsMessage() : The destructor.
* operator new() : The memory allocation operator, only used
* when the library is in a DLL.
* Progress() : The virtual function that gets called to
* update progress through the file/job.
* ArchiveOperation() : The virtual function that gets called
* at key points in the archiving process.
*
* REVISION HISTORY
*
* May 26, 1994 1.0A : First release
*
*/
class AL_CLASS_TYPE ALWindowsMessage : public ALMonitor {
/*
* Constructors, destructors, and friends
*/
public :
AL_PROTO ALWindowsMessage( ALMonitorType monitor_type,
HWND progress_text_window,
ALWindowsMessageType message_type,
HWND progress_number_window,
UINT windows_message = 0 );
virtual AL_PROTO ~ALWindowsMessage();
#if defined( AL_USING_DLL ) || defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO operator new( size_t size );
#endif
protected :
virtual void AL_PROTO Progress( long mlObjectSoFar,
ALStorage AL_DLL_FAR & object );
virtual void AL_PROTO
ArchiveOperation( ALArchiveOperation operation,
ALArchiveBase AL_DLL_FAR *archive,
ALEntry AL_DLL_FAR *job );
/*
* Data members
*/
protected :
HWND mhMessageWindowHandle;
HWND mhNumberWindowHandle;
ALWindowsMessageType mMessageType;
int miMessage;
public :
AL_CLASS_TAG( _ALWindowsMessageTag );
};
#endif /* #if defined( __cplusplus ) */
#endif /* #ifdef _WINMON_H */