From 8316a950de46ad3d5db8cd6e4405d61f1ae979cf Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 9 Oct 1997 15:45:10 +0000 Subject: [PATCH] Archive Lib versione 1.0 git-svn-id: svn://10.65.10.50/trunk@5346 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- al/_debug.cpp | 136 +++ al/_debug.h | 193 ++++ al/_match.cpp | 623 ++++++++++++ al/_match.h | 158 +++ al/_new.cpp | 367 +++++++ al/_openf.cpp | 314 ++++++ al/_openf.h | 196 ++++ al/_r.h | 93 ++ al/_rc.cpp | 190 ++++ al/_re.cpp | 113 +++ al/al.h | 55 ++ al/alcxl.h | 489 ++++++++++ al/aldefs.h | 427 +++++++++ al/algauge.h | 91 ++ al/alstream.h | 193 ++++ al/arcentry.cpp | 913 ++++++++++++++++++ al/arcentry.h | 352 +++++++ al/archive.cpp | 433 +++++++++ al/archive.h | 135 +++ al/archiveb.cpp | 1456 ++++++++++++++++++++++++++++ al/archiveb.h | 226 +++++ al/arclib.h | 85 ++ al/bargraph.h | 107 +++ al/cmpengn.cpp | 204 ++++ al/cmpengn.h | 130 +++ al/cmpobj.cpp | 361 +++++++ al/cmpobj.h | 120 +++ al/copyengn.cpp | 241 +++++ al/copyengn.h | 93 ++ al/cxl_arch.cpp | 956 +++++++++++++++++++ al/cxl_cmpo.cpp | 442 +++++++++ al/cxl_engn.cpp | 586 ++++++++++++ al/cxl_entr.cpp | 704 ++++++++++++++ al/cxl_file.cpp | 64 ++ al/cxl_garc.cpp | 319 +++++++ al/cxl_list.cpp | 786 +++++++++++++++ al/cxl_mem.cpp | 348 +++++++ al/cxl_mon.cpp | 246 +++++ al/cxl_sobj.cpp | 2432 +++++++++++++++++++++++++++++++++++++++++++++++ al/cxl_util.cpp | 153 +++ al/cxl_wild.cpp | 184 ++++ al/fileattr.cpp | 363 +++++++ al/fileattr.h | 111 +++ al/filestor.cpp | 837 ++++++++++++++++ al/filestor.h | 133 +++ al/grenengn.cpp | 361 +++++++ al/grenengn.h | 125 +++ al/memstore.cpp | 851 +++++++++++++++++ al/memstore.h | 182 ++++ al/monitor.cpp | 244 +++++ al/monitor.h | 194 ++++ al/objname.cpp | 754 +++++++++++++++ al/objname.h | 215 +++++ al/spinner.h | 100 ++ al/status.cpp | 335 +++++++ al/status.h | 158 +++ al/storage.cpp | 979 +++++++++++++++++++ al/storage.h | 424 +++++++++ al/storcmp.cpp | 85 ++ al/timedate.cpp | 457 +++++++++ al/timedate.h | 125 +++ al/wildcard.cpp | 594 ++++++++++++ al/wildcard.h | 169 ++++ al/winmon.h | 113 +++ 64 files changed, 23623 insertions(+) create mode 100755 al/_debug.cpp create mode 100755 al/_debug.h create mode 100755 al/_match.cpp create mode 100755 al/_match.h create mode 100755 al/_new.cpp create mode 100755 al/_openf.cpp create mode 100755 al/_openf.h create mode 100755 al/_r.h create mode 100755 al/_rc.cpp create mode 100755 al/_re.cpp create mode 100755 al/al.h create mode 100755 al/alcxl.h create mode 100755 al/aldefs.h create mode 100755 al/algauge.h create mode 100755 al/alstream.h create mode 100755 al/arcentry.cpp create mode 100755 al/arcentry.h create mode 100755 al/archive.cpp create mode 100755 al/archive.h create mode 100755 al/archiveb.cpp create mode 100755 al/archiveb.h create mode 100755 al/arclib.h create mode 100755 al/bargraph.h create mode 100755 al/cmpengn.cpp create mode 100755 al/cmpengn.h create mode 100755 al/cmpobj.cpp create mode 100755 al/cmpobj.h create mode 100755 al/copyengn.cpp create mode 100755 al/copyengn.h create mode 100755 al/cxl_arch.cpp create mode 100755 al/cxl_cmpo.cpp create mode 100755 al/cxl_engn.cpp create mode 100755 al/cxl_entr.cpp create mode 100755 al/cxl_file.cpp create mode 100755 al/cxl_garc.cpp create mode 100755 al/cxl_list.cpp create mode 100755 al/cxl_mem.cpp create mode 100755 al/cxl_mon.cpp create mode 100755 al/cxl_sobj.cpp create mode 100755 al/cxl_util.cpp create mode 100755 al/cxl_wild.cpp create mode 100755 al/fileattr.cpp create mode 100755 al/fileattr.h create mode 100755 al/filestor.cpp create mode 100755 al/filestor.h create mode 100755 al/grenengn.cpp create mode 100755 al/grenengn.h create mode 100755 al/memstore.cpp create mode 100755 al/memstore.h create mode 100755 al/monitor.cpp create mode 100755 al/monitor.h create mode 100755 al/objname.cpp create mode 100755 al/objname.h create mode 100755 al/spinner.h create mode 100755 al/status.cpp create mode 100755 al/status.h create mode 100755 al/storage.cpp create mode 100755 al/storage.h create mode 100755 al/storcmp.cpp create mode 100755 al/timedate.cpp create mode 100755 al/timedate.h create mode 100755 al/wildcard.cpp create mode 100755 al/wildcard.h create mode 100755 al/winmon.h diff --git a/al/_debug.cpp b/al/_debug.cpp new file mode 100755 index 000000000..678114e4c --- /dev/null +++ b/al/_debug.cpp @@ -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 +#include +#include + +// +// 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 +} + diff --git a/al/_debug.h b/al/_debug.h new file mode 100755 index 000000000..f40963d9b --- /dev/null +++ b/al/_debug.h @@ -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 */ diff --git a/al/_match.cpp b/al/_match.cpp new file mode 100755 index 000000000..b973c1761 --- /dev/null +++ b/al/_match.cpp @@ -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 + +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 diff --git a/al/_match.h b/al/_match.h new file mode 100755 index 000000000..114440f7b --- /dev/null +++ b/al/_match.h @@ -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 ); diff --git a/al/_new.cpp b/al/_new.cpp new file mode 100755 index 000000000..e9c74e9eb --- /dev/null +++ b/al/_new.cpp @@ -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 +#include +// +// 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 +#elif defined( AL_MICROSOFT ) +#include +#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 +#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 + diff --git a/al/_openf.cpp b/al/_openf.cpp new file mode 100755 index 000000000..25d59fd14 --- /dev/null +++ b/al/_openf.cpp @@ -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() +{ +} + diff --git a/al/_openf.h b/al/_openf.h new file mode 100755 index 000000000..1f82f9d7b --- /dev/null +++ b/al/_openf.h @@ -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 */ diff --git a/al/_r.h b/al/_r.h new file mode 100755 index 000000000..9026cb216 --- /dev/null +++ b/al/_r.h @@ -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 +#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 diff --git a/al/_rc.cpp b/al/_rc.cpp new file mode 100755 index 000000000..959a60e64 --- /dev/null +++ b/al/_rc.cpp @@ -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 +#else +#include +#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); _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<>_172); +if((_172+=(short)_209)>=8){ if(_171>=_156) _210(); +_179[_171++]=(uchar)(_182>>CHAR_BIT); +if((_172=(ushort)(_172-CHAR_BIT))=_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--; } } diff --git a/al/_re.cpp b/al/_re.cpp new file mode 100755 index 000000000..b8a6ad87e --- /dev/null +++ b/al/_re.cpp @@ -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; } } diff --git a/al/al.h b/al/al.h new file mode 100755 index 000000000..c6c29391b --- /dev/null +++ b/al/al.h @@ -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 */ diff --git a/al/alcxl.h b/al/alcxl.h new file mode 100755 index 000000000..a261f8751 --- /dev/null +++ b/al/alcxl.h @@ -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 +#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 + * 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 */ diff --git a/al/aldefs.h b/al/aldefs.h new file mode 100755 index 000000000..4ff0e440b --- /dev/null +++ b/al/aldefs.h @@ -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 + #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 diff --git a/al/algauge.h b/al/algauge.h new file mode 100755 index 000000000..b57e41dfe --- /dev/null +++ b/al/algauge.h @@ -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 */ + diff --git a/al/alstream.h b/al/alstream.h new file mode 100755 index 000000000..ab24453a7 --- /dev/null +++ b/al/alstream.h @@ -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 +#include "arclib.h" + +#if defined( __cplusplus ) + +/* Won't work in a DLL! */ + +#if !defined( AL_BUILDING_DLL ) + +#include + +/* + * 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 */ diff --git a/al/arcentry.cpp b/al/arcentry.cpp new file mode 100755 index 000000000..436d26082 --- /dev/null +++ b/al/arcentry.cpp @@ -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) "" ) ); + 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 diff --git a/al/arcentry.h b/al/arcentry.h new file mode 100755 index 000000000..5cc8e37de --- /dev/null +++ b/al/arcentry.h @@ -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 */ + diff --git a/al/archive.cpp b/al/archive.cpp new file mode 100755 index 000000000..c72a1caec --- /dev/null +++ b/al/archive.cpp @@ -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 diff --git a/al/archive.h b/al/archive.h new file mode 100755 index 000000000..02591d30b --- /dev/null +++ b/al/archive.h @@ -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 */ diff --git a/al/archiveb.cpp b/al/archiveb.cpp new file mode 100755 index 000000000..7057febd8 --- /dev/null +++ b/al/archiveb.cpp @@ -0,0 +1,1456 @@ +// +// ARCHIVEB.CPP +// +// Source file for ArchiveLib 1.0 +// +// Copyright (c) Greenleaf Software, Inc. 1994 +// All Rights Reserved +// +// CONTENTS +// +// ALArchiveBase::operator new() +// ALArchiveBase::ALArchiveBase() +// ALArchiveBase::~ALArchiveBase() +// ALArchiveBase::SetComment() +// ALArchiveBase::WriteDirectory() +// ALArchiveBase::ScanStatus() +// ALArchiveBase::Extract() +// ALArchiveBase::AddJobs() +// ALArchiveBase::AddDirectoryEntries() +// ALArchiveBase::CalculateJobSize() +// ALArchiveBase::CalculateCompressedJobSize() +// ALArchiveBase::Create(ALEntryList&) +// ALArchiveBase::CopyJobs() +// ALArchiveBase::Create( ALArchiveBase&,ALEntryList&) +// ALArchiveBase::Append(ALEntryList&) +// ALArchiveBase::Append(ALArchiveBase&,ALEntryList&) +// ALArchiveBase::ReadDirectory() +// ALArchiveBase::WriteArchiveData() +// ALArchiveBase::ReadArchiveData() +// ALArchiveBase::Delete(ALEntryList&,ALArchiveBase&) +// ALArchiveBase::FillListBox() +// +// +// DESCRIPTION +// +// This file contains all of the source code for the base class, +// ALArchiveBase. Classes derived from ALArchiveBase don't actually +// do much work, they just bind different sorts of storage objects and +// compression engines to an application, so this is where all the action +// is. The details on how things get inserted and extracted from an +// archive will all be found here. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// +// + +#include "arclib.h" +#pragma hdrstop + +#include "_openf.h" + +// +// void * ALArchiveBase::operator new( size_t size ) +// +// ARGUMENTS: +// +// size : The number of bytes needed to create a new ALArchiveBase 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 enter 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 ALArchiveBase::operator new( size_t size ) +{ + return ::new char[ size ]; +} +#endif + +// +// ALArchiveBase::ALArchiveBase( ALStorage *storage_object, +// short int delete_in_dtor ) +// +// ARGUMENTS: +// +// storage_object : A pointer to the storage object that will/does +// hold the archive. +// +// delete_in_dtor : This flags whether the ALArchiveBase object should call +// the destructor for the storage object when the +// ALArchiveBase object is created. +// +// RETURNS +// +// Nothing, it is a constructor. +// +// DESCRIPTION +// +// This is the ALArchiveBase constructor. It is a public member function, +// but in practice it should only be called by the constructors for +// class derived from ALArchiveBase. Since there are pure functions +// in this class, you can't construct an object of this type anyway, +// no matter how hard you try. +// +// Despite the complexity of this class, and the vast array of member +// functions it contains, the constructor doesn't have much to do. It +// just sets up the contents of a few data members, and that's that. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +AL_PROTO ALArchiveBase::ALArchiveBase( ALStorage AL_DLL_FAR *storage_object, + short int delete_in_dtor ) + : miDeleteStorageObject( delete_in_dtor ) +{ + mpArchiveStorageObject = storage_object; + mszComment = 0; + mlDirectoryOffset = -1L; + miVersion = -1; +} + +// +// ALArchiveBase::~ALArchiveBase() +// +// ARGUMENTS: +// +// None. +// +// RETURNS +// +// None, destructors don't get any. +// +// DESCRIPTION +// +// The destructor for ALArchiveBase has a few pieces of busy work to +// complete. First, it might have a comment to delete. Second, it +// might have to delete its storage object, but only if it was told +// to in the constructor. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +AL_PROTO ALArchiveBase::~ALArchiveBase() +{ + AL_ASSERT( GoodTag(), "~Archive(): Attempting to delete invalid ALArchiveBase" ); + if ( mszComment ) + delete[] mszComment; + if ( mpArchiveStorageObject && miDeleteStorageObject ) + delete mpArchiveStorageObject; + AL_ASSERT( GoodTag(), "~Archive::Attempting to delete invalid ALArchiveBase" ); +} + +// +// int ALArchiveBase::SetComment( char * comment ) +// +// ARGUMENTS: +// +// comment : The new comment that is going to be attached to the archive. +// +// RETURNS +// +// AL_SUCCESS, if things went well, AL_CANT_ALLOCATE_MEMORY if allocation +// of the character array failed. +// +// DESCRIPTION +// +// The archive object has a comment member, that is blank when first +// constructed. It can be set to something interesting either by +// reading in a new comment along with the archive directory, or by +// setting it using this function. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::SetComment( char AL_DLL_FAR * comment ) +{ + if ( mszComment ) + delete[] mszComment; + if ( comment == 0 ) + mszComment = 0; + else { + mszComment = new char[ strlen( comment ) + 1 ]; + if ( mszComment ) + strcpy( mszComment, comment ); + else + return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY, + "Failed to allocate memory for " + "comment in archive %s", + mpArchiveStorageObject->mName.GetName() ); + } + return mStatus; +} + +// +// int ALArchiveBase::WriteDirectory( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : The ALEntryList object that contains the Archive's +// up to date directory. +// +// RETURNS +// +// The integer stored in mStatus, which ought to be AL_SUCCESS if everything +// went okay, or some int < AL_SUCCESS on error. +// +// DESCRIPTION +// +// This is the public function the user can call to rewrite the directory +// for an archive. It is also called internally be several of the functions +// the update archive contents. Probably the main reason to call this under +// normal circumstances would be after modifying the comment field of an +// archive. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +// +// Don't call ArchiveOperation() here, because this might +// just be a component of a directory write (during an append, eg.) +// +int AL_PROTO ALArchiveBase::WriteDirectory( ALEntryList AL_DLL_FAR &list ) +{ + ALOpenInputFile archive( *mpArchiveStorageObject ); + + mpArchiveStorageObject->Seek( mlDirectoryOffset ); + mpArchiveStorageObject->WritePortableShort( miVersion ); + WriteArchiveData(); + mpArchiveStorageObject->WriteString( mszComment ); + + AddDirectoryEntries( list ); + return mStatus; +} + +// PRIVATE MEMBER FUNCTION +// +// void ALArchiveBase::ScanStatus( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : The list of entries that have just been processed. +// +// RETURNS +// +// None. This function sort of has a return, it will update +// the member mStatus with an error code if one is found. +// +// DESCRIPTION +// +// +// After an archive operation, I use this function to update the +// status member of the archive. If the archive doesn't already +// have an error, I check through all the storage objects and +// compression engines to see if any of them hosed up. Any error +// of any sort by any of them is copied into the archive status. +// The whole point of this is to ensure that if +// ALArchiveBase.mStatus == AL_SUCCESS, it means everything worked. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +void AL_PROTO ALArchiveBase::ScanStatus( ALEntryList AL_DLL_FAR &list ) +{ + if ( mStatus < AL_SUCCESS ) + return; + ALEntry *job = list.GetFirstEntry(); + while ( job ) { + if ( job->mpStorageObject->mStatus < AL_SUCCESS ) { + mStatus.SetError( job->mpStorageObject->mStatus, + "%s: %s", + job->mpStorageObject->mName.GetSafeName(), + job->mpStorageObject->mStatus.GetStatusDetail() ); + return; + } + job = job->GetNextEntry(); + } +} + +// +// int ALArchiveBase::Extract( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : A list of storage objects to be extracted (if marked.) +// +// RETURNS +// +// AL_SUCCESS if all went well, or < AL_SUCCESS if the process +// went sour at any point. +// +// DESCRIPTION +// +// This function is one of the high level functions that can be called +// from a user program. It has several important things it needs to do +// in order to extract the appropriate objects from an archive: +// +// o Flag any duplicates. We don't extract anything twice, that will +// be considered an error. +// +// o Open the Archive storage object. +// +// o Calculate the total number of bytes to be processed in the entire +// job, and give this information to the monitor, who might care if +// he is in AL_MONITOR_JOB mode. +// +// o Iterate through the list, performing the following actions for +// each object marked for extraction: +// +// o Update the monitor with information about the object destined +// for immediate extraction. +// +// o Locate the compressed object in the archive. +// +// o Decompress the object, and check for CRC errors. +// +// o Update the monitor. +// +// o After all objects have been extracted, update the monitor again. +// +// o Scan for extraction errors, then return the result. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::Extract( ALEntryList AL_DLL_FAR &list ) +{ +// +// Open the input storage object, if not already open. Let the monitor +// know about it. +// + ALOpenInputFile archive( *mpArchiveStorageObject ); + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 ); +// +// Get rid of any duplicate entries, and set up the monitor sizes. +// + list.UnmarkDuplicates( list, "Duplicate entry in list passed to Extract()" ); + list.mrMonitor.mlJobSoFar = 0L; + if ( list.mrMonitor.miMonitorType == AL_MONITOR_JOB ) + list.mrMonitor.mlJobSize = CalculateCompressedJobSize( list ); +// +// This loop iterates through the entire ALEntryList. We only care about +// ALEntry objects that have their mark set. +// + ALEntry *job = list.GetFirstEntry(); + while ( job ) { + if ( job->miMark ) { +// +// Go to the correct input position in this, and set up the monitor for +// this particular object. +// + list.mrMonitor.ArchiveOperation( AL_EXTRACTION_OPEN, this, job ); + mpArchiveStorageObject->Seek( job->mlCompressedObjectPosition ); + list.mrMonitor.mlObjectStart = job->mlCompressedObjectPosition; + list.mrMonitor.mlObjectSize = job->mlCompressedSize; + mpArchiveStorageObject->mpMonitor = &list.mrMonitor; +// +// Extract it, then check the CRC. +// + job->mpCompressionEngine->Decompress( *mpArchiveStorageObject, + *job->mpStorageObject, + job->mlCompressedSize ); + if ( job->mpStorageObject->GetCrc32() != job->GetCrc32() ) + job->mpStorageObject->mStatus.SetError( + AL_CRC_ERROR, + "CRC32 was supposed to be %08lx, was %08lx", + job->GetCrc32(), + job->mpStorageObject->GetCrc32() ); +// +// Update the monitor data, and yield some time. Note that I turn off +// the monitor at this point so it doesn't jump around while I seek to the +// next position in the archive. +// + list.mrMonitor.mlJobSoFar += job->mlCompressedSize; + mpArchiveStorageObject->YieldTime(); + mpArchiveStorageObject->mpMonitor = 0; + list.mrMonitor.ArchiveOperation( AL_EXTRACTION_CLOSE, this, job ); + job->mpStorageObject->mpMonitor = 0; + } + job = job->GetNextEntry(); + } +// +// Update the monitor, then scan the list for status errors. +// + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + ScanStatus( list ); + return mStatus; +} + +// PRIVATE MEMBER FUNCTION +// +// int ALArchiveBase::AddJobs( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : A list of marked objects to be added to the archive. +// +// RETURNS +// +// AL_SUCCESS if things are going well, < AL_SUCCESS in case of error. +// +// DESCRIPTION +// +// This is a helper function that is called by both Create() and +// Append(). There is enough code here to justify breaking this +// out into a separate module. +// +// All this guy does is sit in a loop, look for marked entries in the +// list, and compress each one into the archive. Before it adds each object +// to the archive, it has to set up the monitor so that progress on the +// selected object will be monitored properly. It has to dink with the +// monitor once again when the object has been compressed. It relies on +// the calling function to have set up the total job size and other info +// that the monitor might need. It also has to set up some of the +// data in the ALEntry object for each job, as not all of this information +// is available until *after* the job has been compressed. For example, +// the storage object's CRC32 gets calculated as a byproduct of the +// compression process. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::AddJobs( ALEntryList AL_DLL_FAR &list ) +{ + list.mrMonitor.mlObjectStart = 0L; // This will be true for all input jobs + // + // This loop iterates through all of the entries in the list, picking off + // only the marked entries. + // + ALEntry *job = list.GetFirstEntry(); + while ( job ) { + if ( job->miMark ) { +// +// We need to keep track of the position in the archive where the compressed +// data is going to go. +// + job->mlCompressedObjectPosition = mpArchiveStorageObject->Tell(); +// +// Attach the monitor to the storage object that is going to be inserted +// in the archive. +// + list.mrMonitor.ArchiveOperation( AL_INSERTION_OPEN, this, job ); + list.mrMonitor.mlObjectSize = -1L; // This means we ask for it in ALMonitor, after the object is opened + job->mpStorageObject->mpMonitor = &list.mrMonitor; +// +// Compress the object into the archive. Then store the resulting CRC +// the compressed size in the ALEntry object. +// + job->mpCompressionEngine->Compress( *job->mpStorageObject, + *mpArchiveStorageObject ); + job->mlCrc32 = job->mpStorageObject->GetCrc32(); + job->mpStorageObject->mpMonitor = 0; + if ( job->mpCompressionEngine->mStatus < 0 ) + return mStatus = job->mpCompressionEngine->mStatus; + job->mlCompressedSize = mpArchiveStorageObject->Tell() - + job->mlCompressedObjectPosition; +// +// Update the monitor +// + list.mrMonitor.mlJobSoFar += job->mpStorageObject->GetSize(); + list.mrMonitor.ArchiveOperation( AL_INSERTION_CLOSE, this, job ); + } + job = job->GetNextEntry(); + if ( mStatus < 0 ) + break; + } + return mStatus; +} + +// PRIVATE MEMBER FUNCTION +// + // int ALArchiveBase::AddDirectoryEntries( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : The list of ALEntry objects to be written to the directory. +// +// RETURNS +// +// AL_SUCCESS if everything goes well, < AL_SUCCESS otherwise. +// +// DESCRIPTION +// +// This function writes all the entries in the list to the Archive +// directory. It doesn't do a seek() to the start of the directory, +// so the calling routine needs to be absolutely sure that it is in +// the write spot when it invokes this. +// +// This routine leaves the output pointer of the storage object pointing +// at just the right spot to write some more entries. That means you can +// call this function repeatedly as new entries are added to the list. +// The function also terminates the directory properly, so that if you +// don't add any more directory entries, the archive is still ready +// for primetime. +// +// This function is called by WriteDirectory(), and both versions of +// Append(). +// +// Writing directory entries is a real simple linear task. The source +// code here should explain it all. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +// +// No call to ArchiveOperation here, either. The setup and everything +// else has to be done by the calling routine. +// +int AL_PROTO ALArchiveBase::AddDirectoryEntries( ALEntryList AL_DLL_FAR &list ) +{ + ALEntry *job = list.GetFirstEntry(); + while ( job ) { + if ( job->miMark ) { + mpArchiveStorageObject->WriteString( job->mpStorageObject->mName.GetSafeName() ); + mpArchiveStorageObject->WriteChar( job->mpCompressionEngine->miCompressionType ); + job->mpCompressionEngine->WriteEngineData( mpArchiveStorageObject ); + mpArchiveStorageObject->WriteChar( job->mpStorageObject->miStorageObjectType ); + job->mpStorageObject->WriteStorageObjectData( mpArchiveStorageObject ); + + mpArchiveStorageObject->WritePortableLong( job->mpStorageObject->GetSize() ); + mpArchiveStorageObject->WritePortableLong( job->GetCompressedSize() ); + mpArchiveStorageObject->WritePortableLong( job->GetCrc32() ); + mpArchiveStorageObject->WritePortableLong( job->mlCompressedObjectPosition ); + mpArchiveStorageObject->WriteString( job->GetComment() ); + mpArchiveStorageObject->WritePortableLong( job->mpStorageObject->mTimeDate.GetUnixTime() ); + mpArchiveStorageObject->WritePortableShort( job->mpStorageObject->mAttributes.PackedAttributes() ); + if ( mpArchiveStorageObject->mStatus < 0 ) + return mStatus = mpArchiveStorageObject->mStatus; + } + job = job->GetNextEntry(); + } +// +// I write out the end of directory string here. But then I back up the +// file pointer so new entries can be appended without causing any trouble +// The end of the directory is denoted by an entry with an empty name. +// + mpArchiveStorageObject->WriteString( "" ); + mpArchiveStorageObject->Seek( mpArchiveStorageObject->Tell() - 2 ); + + return AL_SUCCESS; +} + +// PRIVATE MEMBER FUNCTION +// +// long ALArchiveBase::CalculateJobSize( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : The list of entries in the job. +// +// RETURNS +// +// This function is used to calculate the total number of bytes that +// are going to have to be moved when performing a Create() or Append() +// operation. We need that info in order to set up a monitor properly +// when its mode is AL_MONITOR_JOB. Naturally, we don't really care +// about the total size when the monitor is in AL_MONITOR_OBJECTS mode. +// Anyway, it returns the total size of all the objects. +// +// DESCRIPTION +// +// If a monitor is running in AL_MONITOR_JOB mode, we need to add up +// the sizes of all the storage objects we are going to process, so +// that we can accurately track our progress from 0 to 100%. In many +// cases, the sizes of all the files will not yet be known, which means +// this routine will have to open the files up and check the values. +// That is why we only call this routine when we have to. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +long AL_PROTO ALArchiveBase::CalculateJobSize( ALEntryList AL_DLL_FAR &list ) +{ + long total = 0; + ALEntry *job = list.GetFirstEntry(); + while ( job ) { + if ( job->miMark ) { + long obj_size; + if ( ( obj_size = job->mpStorageObject->GetSize() ) == -1 ) { + job->mpStorageObject->Open(); + obj_size = job->mpStorageObject->GetSize(); + job->mpStorageObject->Close(); + if ( obj_size == -1 ) + return -1; + } + total += obj_size; + } + job = job->GetNextEntry(); + } + return total; +} + +// PRIVATE MEMBER FUNCTION +// +// long ALArchiveBase::CalculateCompressedJobSize( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : The list of compressed jobs to be processed. +// +// RETURNS +// +// The total size of a bunch of compressed objects, not the uncompressed +// size. +// +// DESCRIPTION +// +// When we are monitoring an Extract() command, the monitor object +// gets attached to the Archive, not to the objects that are getting +// sucked out of it. This means that progress is being measured +// against the compressed objects, not the true size objects. So +// before I start the extract, I call this function to see just how +// much compressed space is taken up by the compressed objects in +// the archive. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +long AL_PROTO ALArchiveBase::CalculateCompressedJobSize( ALEntryList AL_DLL_FAR &list ) +{ + long total = 0; + ALEntry *job = list.GetFirstEntry(); + while ( job ) { + if ( job->miMark ) { + if ( job->mlCompressedSize == -1 ) + return -1; + else + total += job->mlCompressedSize; + } + job = job->GetNextEntry(); + } + return total; +} + +// +// int ALArchiveBase::Create( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : A list of ALEntry objects describing what is going to +// be stuffed into the archive. +// +// RETURNS +// +// AL_SUCCESS if things went well, mStatus < 0 ) + return mStatus = mpArchiveStorageObject->mStatus; +// +// We don't want to create an archive with duplicate entries, so we check here. +// + list.UnmarkDuplicates( list, + "Duplicate entry in list passed to Create()" ); +// +// The first four bytes in the archive are a long that points to the +// first byte of the directory. I don't know where the directory is +// going to be, so I just reserve space at this time with a dummy value. +// + mpArchiveStorageObject->WritePortableLong( 0x12345678L ); +// +// Set up the monitor. +// + list.mrMonitor.mlJobSoFar = 0L; + if ( list.mrMonitor.miMonitorType == AL_MONITOR_JOB ) + list.mrMonitor.mlJobSize = CalculateJobSize( list ); +// +// AddJobs() takes care of actually adding the jobs to the archive. +// + AddJobs( list ); +// +// All the jobs are written, now I can figure out where the +// directory is in the storage object. I copy it, then write +// it out to the storage object at position 0. +// + mlDirectoryOffset = mpArchiveStorageObject->Tell(); + mpArchiveStorageObject->Seek( 0L ); + mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset ); +// +// Return without writing the directory if there is an error in the +// archive storage object. +// + if ( mpArchiveStorageObject->mStatus < 0 ) { + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + return mStatus = mpArchiveStorageObject->mStatus; + } +// +// Finally, write out the directory to the storage object. +// + list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE, this, 0 ); + WriteDirectory( list ); +// +// Update the monitor, check for errors, and blow. +// + list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 ); + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + ScanStatus( list ); + return mStatus; +} + +// PRIVATE MEMBER FUNCTIONS +// +// int ALArchiveBase::CopyJobs( ALArchiveBase & source_archive, +// ALEntryList & source_list ) +// +// ARGUMENTS: +// +// source_archive : The source for all the ALEntry objects that are +// going to get copied to this. +// +// source_list : The list of ALEntry objects that are going to be copied. +// +// RETURNS +// +// An mStatus value, either AL_SUCCESS or < AL_SUCCESS. +// +// DESCRIPTION +// +// This private member function is used by the Create() and Append() member +// functions. Each of these two public functions has two versions, one +// which compresses freestanding storage objects into an archive, and +// another which copies jobs out of one archive and into this. The +// second versions of the two functions use CopyJobs() to get the +// compressed objects out of one archive and put it into this. +// +// The actual operation of this guy is pretty simple. It would be almost +// trivial without having to take the monitor into account. Basically, +// it just has to work its way through the list of entries. For each +// marked entry, we just seek to the correct position in the input file, +// the copy the correct number of bytes to this. +// +// One thing kind of funny here is that the ALEntryList starts off with +// offsets for the objects within the source archive. But after copying them +// over, we change the offset field in the ALEntry object to reflect the new +// position in this. This means that after this function has completed, +// you ALEntryList object is no longer associated with source_archive, it +// is instead associated with this. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::CopyJobs( ALArchiveBase AL_DLL_FAR &source_archive, + ALEntryList AL_DLL_FAR &source_list ) +{ +// +// Open the storage object attached to the input archive. The storage object +// attached to this is already open. +// + ALOpenInputFile input( *(source_archive.mpArchiveStorageObject) ); +// +// Iterate through the list of entries in the list, selecting only the +// marked entries. +// + ALEntry *job = source_list.GetFirstEntry(); + while ( job ) { + if ( job->miMark ) { +// +// Seek the compressed object in the source archive, then update the monitor +// to work properly during the copy operation. +// + source_archive.mpArchiveStorageObject->Seek( job->mlCompressedObjectPosition ); + source_list.mrMonitor.mlObjectStart = job->mlCompressedObjectPosition; + source_list.mrMonitor.mlObjectSize = job->mlCompressedSize; + source_list.mrMonitor.ArchiveOperation( AL_COPY_OPEN, this, job ); + source_archive.mpArchiveStorageObject->mpMonitor = &source_list.mrMonitor; +// +// Save the new position in the destination archive, then copy the +// whole thing across. +// + job->mlCompressedObjectPosition = mpArchiveStorageObject->Tell(); + for ( long i = 0 ; i < job->mlCompressedSize ; i++ ) { + int c = source_archive.mpArchiveStorageObject->ReadChar(); + mpArchiveStorageObject->WriteChar( c ); + } +// +// Update the monitor now that the copy is complete. +// + source_list.mrMonitor.ArchiveOperation( AL_COPY_CLOSE, this, job ); + source_archive.mpArchiveStorageObject->YieldTime(); + source_list.mrMonitor.mlJobSoFar += job->mlCompressedSize; + source_archive.mpArchiveStorageObject->mpMonitor = 0; + if ( source_archive.mpArchiveStorageObject->mStatus < 0 ) + return mStatus = source_archive.mpArchiveStorageObject->mStatus; + if ( mpArchiveStorageObject->mStatus < 0 ) + return mStatus = mpArchiveStorageObject->mStatus; + } + job = job->GetNextEntry(); + if ( mStatus < 0 ) + break; + } + return mStatus; +} + +// +// int ALArchiveBase::Create( ALArchiveBase &source_archive, +// ALEntryList &source_list ) +// +// ARGUMENTS: +// +// source_archive : The archive that contains the compressed objects +// we are using to create this. +// +// source_list : The ALEntryList that contains the marked ALEntry +// objects that are going to be inserted in this. +// +// RETURNS +// +// AL_SUCCESS if things went well, < AL_SUCCESS to flag an error. +// +// DESCRIPTION +// +// This is the second version of Create(). Instead of creating a new +// archive by using a bunch of freestanding objects, this guy just +// sucks existing compressed objects out of one archive and copies +// them directly into another. The actual copying gets done in +// CopyJobs(). +// +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::Create( ALArchiveBase AL_DLL_FAR &source_archive, + ALEntryList AL_DLL_FAR &source_list ) +{ +// +// Open the source archive, set the version, and blow if for some reason +// the storage object I am writing to isn't working right. +// + ALOpenOutputFile archive( *mpArchiveStorageObject ); + miVersion = 0x100; + if ( mpArchiveStorageObject->mStatus < 0 ) + return mStatus = mpArchiveStorageObject->mStatus; +// +// I don't want to create an archive with duplicates, that would be bad. +// + source_list.UnmarkDuplicates( source_list, "Duplicate entry in list passed to Create()" ); +// +// At this point, just for fun, I am going to calculate the total +// compressed size of the jobs I am copying. Hey, it looks like I +// could substitute a call to CalculateCompressedSize() here! +// + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 ); + source_list.mrMonitor.mlJobSoFar = 0L; + source_list.mrMonitor.mlJobSize = 0L; + for ( ALEntry *job = source_list.GetFirstEntry(); + job != 0; + job = job->GetNextEntry() ) { + if ( job->GetMark() ) + source_list.mrMonitor.mlJobSize += job->mlCompressedSize; + } +// +// Since I am creating a new archive, I write a long out as a place +// holder for the directory pointer. When I am done copying jobs, +// I'll come back here and write a pointer to the directory. +// + mpArchiveStorageObject->WritePortableLong( 0x12345678L ); +// +// Now copy the data. +// + CopyJobs( source_archive, source_list ); +// +// Write out the directory offset, then the directory itself. +// + mlDirectoryOffset = mpArchiveStorageObject->Tell(); + mpArchiveStorageObject->Seek( 0L ); + mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset ); + if ( mpArchiveStorageObject->mStatus < 0 ) { + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + return mStatus = mpArchiveStorageObject->mStatus; + } + source_list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE,this, 0 ); + WriteDirectory( source_list ); + source_list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 ); + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); +// +// Update the error status, and then we are done. +// + ScanStatus( source_list ); + return mStatus; +} + +// +// int ALArchiveBase::Append( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : A list of objects to append to this. +// +// RETURNS +// +// AL_SUCCESS if things go okay, < AL_SUCCESS if they didn't. +// +// DESCRIPTION +// +// This routine is one of the public functions. It is called to add +// a list of standalone objects to an existing archive, this. +// To accomplish this, we have to read in the existing directory, then +// add the new batch of objects to the archive. Finally, I write out +// the old directory, then the directory for the new batch of objects. +// +// There is another version of Append() that takes as input a list of +// entries that are in another archive. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::Append( ALEntryList AL_DLL_FAR &list ) +{ + ALEntryList old_list; +// +// Open the storage object for this. +// + ALOpenInputFile archive( *mpArchiveStorageObject ); +// +// I read in the current directory for this archive. I am going to +// write over the directory with new stuff, so I will have to write it +// back out later. +// + ReadDirectory( old_list ); + if ( mStatus < 0 ) + return mStatus; +// +// The list of new objects I am going to add needs to be scanned for +// duplicates. First I clear duplicate entries from the list itself. +// Then I clear any duplicates between the current list and the +// stuff already in the archive. +// + list.UnmarkDuplicates( list, "Duplicate entry in list passed to Append()" ); + list.UnmarkDuplicates( old_list, "Duplicate entry in list passed to Append()" ); +// +// I get the monitor set up, for the batch of entries I am about to do. +// + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 ); + list.mrMonitor.mlJobSoFar = 0L; + if ( list.mrMonitor.miMonitorType == AL_MONITOR_JOB ) + list.mrMonitor.mlJobSize = CalculateJobSize( list ); +// +// The new entries start at the position currently occupied by the +// directory. I seek to that point, then call AddJobs() to do the +// dirty work. +// + mpArchiveStorageObject->Seek( mlDirectoryOffset ); + AddJobs( list ); + if ( mStatus < 0 ) { + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + return mStatus; + } +// +// Now that all the new stuff is in the archive, I can figure +// out where the directory belongs, and write it out to position +// 0 in the archive. +// + mlDirectoryOffset = mpArchiveStorageObject->Tell(); + mpArchiveStorageObject->Seek( 0L ); + mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset ); + if ( mpArchiveStorageObject->mStatus < 0 ) { + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + return mStatus = mpArchiveStorageObject->mStatus; + } +// +// Now I write the old directory out, and then add in the new +// directory entries. +// + list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE, this, 0 ); + WriteDirectory( old_list ); + AddDirectoryEntries( list ); +// +// Update the monitor, check for errors, then leave. +// + list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 ); + list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + ScanStatus( list ); + return mStatus; +} + +// +// int ALArchiveBase::Append( ALArchiveBase &source_archive, +// ALEntryList &source_list ) +// +// ARGUMENTS: +// +// source_archive : The archive where the objects that we are going +// use can be found. +// +// source_list : The ALEntryList that has a batch of marked entries. +// +// RETURNS +// +// AL_SUCCESS if things work, < AL_SUCCESS if they don't. +// +// DESCRIPTION +// +// This append function works just like the previous one, except it +// is appending jobs that have already been compressed and can be found +// in a different archive. It has to go through exactly the same process, +// which consists of reading the current directory in from this, appending +// the new compressed objects to this, then writing out the old directory +// and the new list. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::Append( ALArchiveBase AL_DLL_FAR &source_archive, + ALEntryList AL_DLL_FAR &source_list ) +{ + ALEntryList old_list; +// +// Open the storage object associated with this. +// + ALOpenInputFile archive( *mpArchiveStorageObject ); + + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_OPEN, this, 0 ); +// +// I have to read the current directory into memory, because as soon as +// I start to write objects out to this, I am going to obliterate +// the directory. +// + ReadDirectory( old_list ); + if ( mStatus < 0 ) { + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + return mStatus; + } +// +// We don't want to create an archive that has duplicate entries, that would +// be a bad thing. So I first comb all the duplicate entries out of the list +// of objects to append. I then compare that list for duplicates against +// the list of objects already in the library, and comb out any matches +// there as well. +// + source_list.UnmarkDuplicates( source_list, "Duplicate entry in list passed to Append()" ); + source_list.UnmarkDuplicates( old_list, "Duplicate entry in list passed to Append()" ); +// +// I am going to start writing new stuff at the location where the +// the directory starts right now. +// + mpArchiveStorageObject->Seek( mlDirectoryOffset ); +// +// Before starting to copy jobs, I have to set up the monitor. +// This includes calculating the total number of compressed bytes +// in all the marked jobs. I could do this a lot easier by calling +// the CalculateCompressedBytes() function, but it's too late to change now. +// + source_list.mrMonitor.mlJobSoFar = 0L; + source_list.mrMonitor.mlJobSize = 0L; + for ( ALEntry *job = source_list.GetFirstEntry(); + job != 0; + job = job->GetNextEntry() ) { + if ( job->GetMark() ) + source_list.mrMonitor.mlJobSize += job->mlCompressedSize; + } +// +// CopyJobs() does the hard work for me. +// + CopyJobs( source_archive, source_list ); + if ( mStatus < 0 ) { + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + return mStatus; + } +// +// The jobs are now in, I just have to update the directory with +// the old files and the new files. +// + mlDirectoryOffset = mpArchiveStorageObject->Tell(); + mpArchiveStorageObject->Seek( 0L ); + mpArchiveStorageObject->WritePortableLong( mlDirectoryOffset ); + if ( mpArchiveStorageObject->mStatus < 0 ) { + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + return mStatus = mpArchiveStorageObject->mStatus; + } + source_list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_WRITE, this, 0 ); + WriteDirectory( old_list ); + AddDirectoryEntries( source_list ); +// +// Wrap it up. +// + source_list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_WRITE, this, 0 ); + source_list.mrMonitor.ArchiveOperation( AL_ARCHIVE_CLOSE, this, 0 ); + ScanStatus( source_list ); + return mStatus; +} + +// +// int ALArchiveBase::ReadDirectory( ALEntryList &list ) +// +// ARGUMENTS: +// +// list : The target for the directory listing. +// +// RETURNS +// +// AL_SUCCESS or < AL_SUCCESS if things don't work. +// +// DESCRIPTION +// +// This function reads the directory from archive this and places the +// results in the list parameter. I have to apologize for the fact +// that it is so long. The only thing I can say in my defense is that +// even though it is really long, it is also really simple, not tricky +// bits here. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::ReadDirectory( ALEntryList AL_DLL_FAR &list ) +{ + list.mrMonitor.ArchiveOperation( AL_START_DIRECTORY_READ, this, 0 ); + ALOpenInputFile archive( *mpArchiveStorageObject ); + if ( mpArchiveStorageObject->mStatus < 0 ) + return mStatus = mpArchiveStorageObject->mStatus; +// +// First I seek to the start of the directory (offset found at 0), and +// read in the version. This function only supports the directory +// structure defined in version 0x100. +// + mpArchiveStorageObject->Seek( 0 ); + mpArchiveStorageObject->ReadPortableLong( mlDirectoryOffset ); + mpArchiveStorageObject->Seek( mlDirectoryOffset ); + mpArchiveStorageObject->ReadPortableShort( miVersion ); + if ( miVersion != 0x100 ) + return mStatus.SetError( AL_INVALID_ARCHIVE, + "%s is not a valid archive file", + mpArchiveStorageObject->mName.GetSafeName() ); +// +// Read in any customized archive data defined by a derived class. +// + ReadArchiveData(); +// +// Read in the comment, deleting the old one if necessary. +// + if ( mszComment ) + delete[] mszComment; + mszComment = mpArchiveStorageObject->ReadString(); +// +// Now, the big loop. I have to read in each entry, one at a time, and +// add it to the list. If I broke this out into a separate routine it +// would make the whole thing a lot more manageable. +// + for ( ; ; ) { + if ( mpArchiveStorageObject->mStatus < 0 ) + return mStatus = mpArchiveStorageObject->mStatus; + char *name = mpArchiveStorageObject->ReadString(); + if ( name == 0 ) + break; +// +// The directory ends with a blank name. +// + if ( strlen( name ) == 0 ) { + delete[] name; + break; + } +// +// Derived classes are responsible for providing a version of +// CreateCompressionEngine() that will convert the engine_type +// integer into a created compression engine. The derived class is +// then also responsible for reading in the engine data from the archive. +// + int engine_type = mpArchiveStorageObject->ReadChar(); + ALCompressionEngine *engine = CreateCompressionEngine( engine_type ); + if ( engine ) + engine->ReadEngineData( mpArchiveStorageObject ); + else { + char *temp = mpArchiveStorageObject->ReadString(); + if ( temp ) + delete[] temp; + return mStatus.SetError( AL_CANT_CREATE_ENGINE, + "Failure creating compression engine for object %s", + name ); + } +// +// Now we go through a nearly identical process to create the storage object. +// The derived class is responsible for writing a CreateStorageObject() +// function that converts an object_type integer to a created storage +// object. The derived class also has to read in the storage object +// data. +// + int object_type = mpArchiveStorageObject->ReadChar(); + ALStorage *storage_object = CreateStorageObject( name, object_type ); + delete[] name; // Don't need it any more + name = 0; + if ( storage_object ) + storage_object->ReadStorageObjectData( mpArchiveStorageObject ); + else { + char *temp = mpArchiveStorageObject->ReadString(); + if ( temp ) + delete[] temp; + return mStatus.SetError( AL_CANT_CREATE_STORAGE_OBJECT, + "Failure creating storage object for object %s", + name ); + } +// +// The rest of the stuff in the entry is pretty straightforward. +// + mpArchiveStorageObject->ReadPortableLong( storage_object->mlSize ); + ALEntry *job = new ALEntry( list, storage_object, engine ); + mpArchiveStorageObject->ReadPortableLong( job->mlCompressedSize ); + mpArchiveStorageObject->ReadPortableLong( job->mlCrc32 ); + mpArchiveStorageObject->ReadPortableLong( job->mlCompressedObjectPosition ); + char *comment = mpArchiveStorageObject->ReadString(); + job->SetComment( comment ); + if ( comment ) + delete[] comment; + long unix_time; + mpArchiveStorageObject->ReadPortableLong( unix_time ); + storage_object->mTimeDate.SetTimeDate( unix_time ); + short int packed_attributes; + mpArchiveStorageObject->ReadPortableShort( packed_attributes ); + storage_object->mAttributes.SetFromPackedAttributes( packed_attributes ); + } + list.mrMonitor.ArchiveOperation( AL_END_DIRECTORY_READ, this, 0 ); + return mStatus; +} + +// +// int ALArchiveBase::WriteArchiveData() +// +// ARGUMENTS: +// +// None. +// +// RETURNS +// +// AL_SUCCESS if everything writes out okay, or < AL_SUCCESS for trouble. +// +// DESCRIPTION +// +// Derived classes can write out customized archive data, for whatever +// reasons they deem necessary. Our base class has nothing that it +// needs to save, so it just writes out a zero length string, which takes +// two bytes to save. Instead of using WriteString like I ought to, for +// some reason I write the 0 out directly. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::WriteArchiveData() +{ + return mpArchiveStorageObject->WritePortableShort( 0 ); +} + +// +// int ALArchiveBase::ReadArchiveData() +// +// ARGUMENTS: +// +// None. +// +// RETURNS +// +// AL_SUCCESS if things went well, < AL_SUCCESS it things go sour. +// +// DESCRIPTION +// +// The base class doesn't store anything in the archive specific +// data area. That means that when I am reading the archive specific +// data in, I should see a zero length string, which is the same thing +// as a single short of value 0. I read it in and verify it here. +// +// Note that derived classes are free to override this function, but +// nothing we ship with ArchiveLib does so. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::ReadArchiveData() +{ + short temp; + mpArchiveStorageObject->ReadPortableShort( temp ); + AL_ASSERT( temp == 0, "ReadArchiveData(): archive data != 0" ); + return mpArchiveStorageObject->mStatus; +} + +// +// int ALArchiveBase::Delete( ALEntryList &list, +// ALArchiveBase &destination ) +// +// ARGUMENTS: +// +// list : A list of the objects to delete from the archive. +// +// destination : The destination archive, which is the result after +// deleting all the objects from this. +// +// RETURNS +// +// AL_SUCCESS if things went well, < AL_SUCCESS otherwise. +// +// DESCRIPTION +// +// Delete is really more like copy. It doesn't actually delete objects +// out of an existing archive. Instead it deletes by excluding the +// specified objects from a copy command, copying only those objects +// that aren't in the delete list. The resulting archive looks as if +// it is one that has had objects deleted from it. +// +// After deleting, we do some renaming to make it look like the delete +// operation did what you really expected. As a result, the original +// archive (this) has been renamed to a backup, and the new archive +// now has the original name of this. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +int AL_PROTO ALArchiveBase::Delete( ALEntryList AL_DLL_FAR &list, + ALArchiveBase AL_DLL_FAR &destination ) +{ + destination.SetComment( mszComment ); + list.ToggleMarks(); + destination.Create( *this, list ); + list.ToggleMarks(); + ALName temp = mpArchiveStorageObject->mName; + mpArchiveStorageObject->RenameToBackup(); + destination.mpArchiveStorageObject->Rename( temp ); + if ( destination.mStatus < 0 ) + return mStatus = destination.mStatus; + return mStatus; +} + +// +// int ALArchiveBase::FillListBox( HWND hDlg, int list_box = -1 ) +// +// ARGUMENTS: +// +// hDlg : The handle of the dialog box that has a list box in it. +// If the value of list_box is set to -1, it means that +// hDlg doesn't refer to a dialog box, instead it refers +// to the actual list box itself. +// +// list_box : This is set to the id of the list box control found in +// the hDlg dialog box. If this value is set to -1, it +// means the hDlg parameter is the handle of the list box. +// +// RETURNS +// +// The count of marked items stuffed into the list box. +// +// DESCRIPTION +// +// This is a quicky useful function to read the names of all the +// storage objects out of this, then stuffing them all into a list +// box. +// +// REVISION HISTORY +// +// May 23, 1994 1.0A : First release +// + +#if defined( AL_WINDOWS_GUI ) +int AL_PROTO ALArchiveBase::FillListBox( HWND hDlg, int list_box /* = -1 */ ) +{ + ALEntryList list; + HWND window; + ReadDirectory( list ); + if ( list_box != -1 ) + window = GetDlgItem( hDlg, (short int) list_box ); + else + window = hDlg; + int count; + if ( ( count = list.FillListBox( window ) ) == 0 ) { + if ( mStatus < 0 ) { + SendMessage( window, LB_RESETCONTENT, 0, 0 ); + SendMessage( window, + LB_ADDSTRING, + 0, + (LPARAM)( (LPSTR) "Error!" ) ); + } + } + return count; +} +#endif diff --git a/al/archiveb.h b/al/archiveb.h new file mode 100755 index 000000000..435802751 --- /dev/null +++ b/al/archiveb.h @@ -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 */ diff --git a/al/arclib.h b/al/arclib.h new file mode 100755 index 000000000..ab153534f --- /dev/null +++ b/al/arclib.h @@ -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 */ diff --git a/al/bargraph.h b/al/bargraph.h new file mode 100755 index 000000000..ff91e6ebb --- /dev/null +++ b/al/bargraph.h @@ -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 */ diff --git a/al/cmpengn.cpp b/al/cmpengn.cpp new file mode 100755 index 000000000..230cf50b7 --- /dev/null +++ b/al/cmpengn.cpp @@ -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" ); +} + diff --git a/al/cmpengn.h b/al/cmpengn.h new file mode 100755 index 000000000..9252947e3 --- /dev/null +++ b/al/cmpengn.h @@ -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 */ diff --git a/al/cmpobj.cpp b/al/cmpobj.cpp new file mode 100755 index 000000000..4c194b07e --- /dev/null +++ b/al/cmpobj.cpp @@ -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; +} diff --git a/al/cmpobj.h b/al/cmpobj.h new file mode 100755 index 000000000..18cbcdb4d --- /dev/null +++ b/al/cmpobj.h @@ -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 */ diff --git a/al/copyengn.cpp b/al/copyengn.cpp new file mode 100755 index 000000000..271d5aff3 --- /dev/null +++ b/al/copyengn.cpp @@ -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; +} + + diff --git a/al/copyengn.h b/al/copyengn.h new file mode 100755 index 000000000..c730f20ec --- /dev/null +++ b/al/copyengn.h @@ -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 */ diff --git a/al/cxl_arch.cpp b/al/cxl_arch.cpp new file mode 100755 index 000000000..c34465c57 --- /dev/null +++ b/al/cxl_arch.cpp @@ -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, 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, 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(); +} diff --git a/al/cxl_cmpo.cpp b/al/cxl_cmpo.cpp new file mode 100755 index 000000000..79e0df87b --- /dev/null +++ b/al/cxl_cmpo.cpp @@ -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 + diff --git a/al/cxl_engn.cpp b/al/cxl_engn.cpp new file mode 100755 index 000000000..bdd0230ab --- /dev/null +++ b/al/cxl_engn.cpp @@ -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 diff --git a/al/cxl_entr.cpp b/al/cxl_entr.cpp new file mode 100755 index 000000000..3ee00b3d9 --- /dev/null +++ b/al/cxl_entr.cpp @@ -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; +} diff --git a/al/cxl_file.cpp b/al/cxl_file.cpp new file mode 100755 index 000000000..79d92d8f4 --- /dev/null +++ b/al/cxl_file.cpp @@ -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 ); +} + + diff --git a/al/cxl_garc.cpp b/al/cxl_garc.cpp new file mode 100755 index 000000000..d0bb32691 --- /dev/null +++ b/al/cxl_garc.cpp @@ -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 ); +} + diff --git a/al/cxl_list.cpp b/al/cxl_list.cpp new file mode 100755 index 000000000..4774426ed --- /dev/null +++ b/al/cxl_list.cpp @@ -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 diff --git a/al/cxl_mem.cpp b/al/cxl_mem.cpp new file mode 100755 index 000000000..a6eefa3e4 --- /dev/null +++ b/al/cxl_mem.cpp @@ -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 diff --git a/al/cxl_mon.cpp b/al/cxl_mon.cpp new file mode 100755 index 000000000..aff0ad0a7 --- /dev/null +++ b/al/cxl_mon.cpp @@ -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; +} + diff --git a/al/cxl_sobj.cpp b/al/cxl_sobj.cpp new file mode 100755 index 000000000..f2125d951 --- /dev/null +++ b/al/cxl_sobj.cpp @@ -0,0 +1,2432 @@ +// +// CXL_SOBJ.CPP +// +// Source file for ArchiveLib 1.0 +// +// Copyright (c) Greenleaf Software, Inc. 1994 +// All Rights Reserved +// +// CONTENTS +// +// deleteALStorage() +// ALStorageSetMonitor() +// ALStorageDelete() +// ALStorageSetName() +// ALStorageCompare() +// ALStorageGetSize() +// ALStoragePackedAttributes() +// ALStorageSetFromDosAttributes() +// ALStorageSetFromPackedAtts() +// ALStorageWildCardMatch() +// ALStorageChangeExtension() +// ALStorageChangeExtensionVB() +// ALStorageChangeTrailingChar() +// ALStorageChangeTrailingCharVB() +// ALStorageGetName() +// ALStorageGetNameVB() +// ALStorageGetOldName() +// ALStorageGetOldNameVB() +// ALStorageGetStatusCode() +// ALStorageSetError() +// ALStorageGetStatusString() +// ALStorageGetStatusStringVB() +// ALStorageGetStatusDetail() +// ALStorageGetStatusDetailVB() +// ALStorageGetUnixTime() +// ALStorageToJulian() +// ALStorageFromJulian() +// ALStorageSetTimeDateFromStruc() +// ALStorageGetStrucFromTimeDate() +// ALStorageSetTimeDateFromUnix() +// ALStorageIsOpen() +// ALStorageReadChar() +// ALStorageReadShort() +// ALStorageReadLong() +// ALStorageWriteLong() +// ALStorageWriteShort() +// ALStorageWriteString() +// ALStorageInitCrc32() +// ALStorageTell() +// ALStorageReadBuffer() +// ALStorageWriteBuffer() +// ALStorageGetCrc32() +// ALStorageClose() +// ALStorageCreate() +// ALStorageFlushBuffer() +// ALStorageLoadBuffer() +// ALStorageOpen() +// ALStorageRename() +// ALStorageRenameToBackup() +// ALStorageSeek() +// ALStorageUnRename() +// ALStorageWriteChar() +// ALStorageGetType() +// +// DESCRIPTION +// +// This file contains all of the C/VB translation routines to support +// class ALStorage. There are very few functions that you will need +// to call for classes derived from ALStorage (other than constructors) +// so this file should contain most of the stuff you need. +// +// All of these translation/wrapper functions are markedly unenlightening. +// The real details for most of the code can be found in STORAGE.CPP. +// When you want to know what a derived class is doing, try looking in +// in MEMSTORE.CPP or FILESTOR.CPP. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// +// + +#include "arclib.h" +#pragma hdrstop + +#include "al.h" +#include "alcxl.h" + +// +// extern "C" void deleteALStorage( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// is going to be destroyed. +// +// RETURNS +// +// Nothing, this is a destructor. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ destructor ALStorage::~ALStorage(). This function checks its +// single handle argument for correct type (in debug mode), then casts +// and calls the dtor. +// +// Note that since the destructor is virtual, you will actually be +// going to the destructor for your derive class. +// +// The ALStorage destructor does a fair amount of work, so you might +// want to check it out in STORAGE.CPP. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION deleteALStorage( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "deleteALStorage" ); + delete (ALStorage *) this_object; +} + +// +// extern "C" void ALStorageSetMonitor( hALStorage this_object, +// hALMonitor monitor ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// is have a new monitor assigned to it. +// +// monitor : A handle for (pointer to) an ALMonitor object. This +// object is going to be assigned to the storage object. +// +// RETURNS +// +// Nothing. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ data member ALStorage::mpMonitor. This function checks its +// two handle arguments for correct type (in debug mode), then casts +// and assigns. +// +// Normally, assignment of monitor objects to storage objects is done +// inside the member functions of ALArchiveBase. However, if you want +// to use a monitor for some operation you are performing on your own, +// such as a batch file copy, you will have to use this function (along +// with a couple of others) to get things to work properly. +// +// Note that 0 is a valid value for a monitor. +// +// To see how the monitor actually works, check out ARCHIVEB.CPP, +// and BARGRAPH.CPP or WINMON.CPP. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION ALStorageSetMonitor( hALStorage this_object, + hALMonitor monitor ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSetMonitor" ); + if ( monitor ) + AL_ASSERT_OBJECT( monitor, ALMonitor, "ALStorageSetMonitor" ); + ( (ALStorage *) this_object )->mpMonitor = (ALMonitor *) monitor; +} + +// +// extern "C" int ALStorageDelete( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// is going to have its underlying physical object deleted. +// +// RETURNS +// +// AL_SUCCESS, or some other error code. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALStorage::Delete(). This function checks its +// handle argument for correct type (in debug mode), then casts +// and calls Delete(). +// +// Delete() is used to delete the underlying physical object associated +// with a storage object, for example, a disk file. The implementation +// of this function will vary widely across derived classes. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALStorage::Delete(). See FILESTOR.CPP and MEMSTORE.CPP for an +// in-depth look at the whole deal. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageDelete( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageDelete" ); + return ( (ALStorage *) this_object)->Delete(); +} + +// +// extern "C" void ALStorageSetName( hALStorage this_object, +// char *object_name ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// is going to have its name changed. +// +// object_name : The new name. +// +// RETURNS +// +// Nothing. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALName::operator =(char*), for the mName member +// of objects of class ALStorage. This function checks its single +// handle argument for correct type (in debug mode), then casts +// and assigns. +// +// This function changes the name in the ALStorage object, but it doesn't +// change the underlying name of the physical object (if there is one.) +// To do that, you need to call ALStorageRename(). +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALName. See OBJNAME.CPP for the details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION ALStorageSetName( hALStorage this_object, + char *object_name ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSetName" ); + ( (ALStorage *) this_object )->mName = object_name; +} + +// +// extern "C" int ALStorageCompare( hALStorage this_object, +// hALStorage test_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// is going to be half of the comparison. +// +// test_object : A handle for (pointer to) the storage object that +// is going to be the other half of the comparison. +// +// RETURNS +// +// AL_SUCCESS if they match, AL_COMPARE_ERROR if they don't, some other +// code < AL_SUCCESS if a bad thing happened. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALStorage::Compare(). This function checks its two +// handle arguments for correct type (in debug mode), then casts +// and calls ALStorage::Compare(). +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALStorage::Compare(). See STORCMP.CPP for the details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageCompare( hALStorage this_object, + hALStorage test_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageCompare" ); + AL_ASSERT_OBJECT( test_object, ALStorage, "ALStorageCompare" ); + return ( (ALStorage *) this_object )->Compare( *(ALStorage *) test_object ); +} + +// +// extern "C" long ALStorageGetSize( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// you want to get this size of. +// +// RETURNS +// +// The long size of the storage object if it is known. -1 if it +// isn't known. Some other error code < 0 if things went haywire. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALStorage::GetSize(). This function checks its +// handle argument for correct type (in debug mode), then casts +// and calls ALStorage::GetSize(). It returns the long integer +// result back to the calling procedure unchanged. +// +// GetSize() is not a virtual function, it simply provides access to +// the mlSize member of ALStorage. However, mlSize will be updated +// many of the member functions of ALStorage and derived classes. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALStorage::GetSize(). See STORAGE.H for the details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" long AL_FUNCTION ALStorageGetSize( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetSize" ); + return ( (ALStorage *) this_object)->GetSize(); +} + +// +// extern "C" unsigned short int ALStoragePackedAttributes( +// hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// has the packed attributes you are interested int. +// +// RETURNS +// +// An unsigned short containing the packed attributes of the storage +// object. The attributes are packed in our own internal format +// (which is documented). +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALFileAttributes::PackedAttributes() for the +// mAttributes data member of class ALStorage. This function checks its +// handle argument for correct type (in debug mode), then casts +// and calls the C++ function. It returns the unsigned short +// result back to the calling procedure unchanged. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALFileAttributes::PackedAttributes. See FILEATTR.H for the details +// on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" unsigned short int AL_FUNCTION +ALStoragePackedAttributes( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStoragePackedAttributes" ); + return ( (ALStorage *) this_object)->mAttributes.PackedAttributes(); +} + +// +// extern "C" void +// ALStorageSetFromDosAttributes( hALStorage this_object, +// unsigned short int dos_attributes ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// attributes you want to set. +// +// dos_attributes : A set of file attributes in the format you normally +// get from MS-DOS functions such as _dos_getfileattr(). +// RETURNS +// +// Nothing, a void guy. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to set the +// value of the ALStorage data member mAttributes by way of the +// ALFileAttributes::SetFromDosAttributes() member function. This function +// checks the handle argument for correct type (in debug mode), then casts +// and calls the C++ function. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALFileAttributes::SetFromDosAttributes(). See FILEATTR.CPP for the +// details on that. +// +// Doesn't compile in AL_FLAT_MODEL, because file attributes are handled +// completely differently in Win32s/NT. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +#if !defined( AL_WIN32S ) +extern "C" void AL_FUNCTION ALStorageSetFromDosAttributes( hALStorage this_object, unsigned short int dos_attributes ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSetFromDosAttributes" ); + ( (ALStorage *) this_object)->mAttributes.SetFromDosAttributes( dos_attributes ); +} +#endif + +// +// extern "C" void +// ALStorageSetFromPackedAtts( hALStorage this_object, +// unsigned short int packed_attributes ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// attributes you want to set. +// +// packed_attributes : A set of file attributes in the format used +// internally by ArchiveLib. +// RETURNS +// +// Nothing, a void guy. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to set the +// value of the ALStorage data member mAttributes by way of the +// ALFileAttributes::SetFromPackedAttributes() member function. This +// function checks the handle argument for correct type (in debug mode), +// then casts and calls the C++ function. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALFileAttributes::SetFromPackedAttributes(). See FILEATTR.CPP for the +// details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION ALStorageSetFromPackedAtts( hALStorage this_object, unsigned short int packed_attributes ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSetFromPackedAtts" ); + ( (ALStorage *) this_object )->mAttributes.SetFromPackedAttributes( packed_attributes ); +} + +// +// extern "C" int ALStorageWildCardMatch( hALStorage this_object, +// char *pattern ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// name you want to test. +// +// pattern : A regular expression that will be tested for a match. +// +// RETURNS +// +// 1 for a match, 0 for not. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALName::WildCardMatch() C++ member function for the mName data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALName::WildCardMatch(). See OBJNAME.CPP for more information. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageWildCardMatch( hALStorage this_object, char AL_DLL_FAR *pattern ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWildCardMatch" ); + return ( (ALStorage *) this_object )->mName.WildCardMatch( pattern ); +} + +// C TRANSLATION FUNCTION +// +// extern "C" char * ALStorageChangeExtension( hALStorage this_object, +// char *new_extension ) +// VB TRANSLATION FUNCTION +// +// extern "C" long ALStorageChangeExtensionVB( hALStorage this_object, +// char *new_extension ) +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// name you want to test. +// +// new_extension : A new three letter (maybe) extension you want +// to apply to the object name. +// +// RETURNS +// +// A string pointer (or VB string) containing the file name after the +// new extension has been applied to it. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALName::ChangeExtension() C++ member function for the mName data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// Note that the VB version of this function is almost identical. However, +// instead of returning a pointer to a character string, this routine calls +// ALVBCreateString() to build a VB string, which it returns to the +// calling module. Don't use the VB function from C, it will blow up. +// Don't use the C function from VB, because it returns a string pointer, +// which VB doesn't know how to deal with. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALName::ChangeExtension(). See OBJNAME.CPP for more information. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" char AL_DLL_FAR * AL_FUNCTION +ALStorageChangeExtension( hALStorage this_object, + char AL_DLL_FAR *new_extension ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageChangeExtension" ); + return ( (ALStorage *) this_object )->mName.ChangeExtension( new_extension ); +} + +#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL ) + +extern "C" long AL_FUNCTION +ALStorageChangeExtensionVB( hALStorage this_object, + char AL_DLL_FAR *new_extension ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageChangeExtensionVB" ); + char _far * p = ( (ALStorage *) this_object )->mName.ChangeExtension( new_extension ); + return ALCreateVBString( p, (unsigned short int) _fstrlen( p ) ); +} + +#endif + +// C TRANSLATION FUNCTION +// +// extern "C" char * ALStorageChangeTrailingChar( hALStorage this_object, +// char new_char ) +// +// VB TRANSLATION FUNCTION +// +// extern "C" long ALStorageChangeTrailingCharVB( hALStorage this_object, +// char new_char ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// name you want to test. +// +// new_char : A new final character you want to apply to the +// object name. Often a "funny" character, like '~'. +// +// RETURNS +// +// A string pointer (or VB string) containing the file name after the +// new final character has been applied to it. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALName::ChangeTrailingChar() C++ member function for the mName data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// Note that the VB version of this function is almost identical. However, +// instead of returning a pointer to a character string, this routine calls +// ALVBCreateString() to build a VB string, which it returns to the +// calling module. Don't use the VB function from C, it will blow up. +// Don't use the C function from VB, because it returns a string pointer, +// which VB doesn't know how to deal with. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALName::ChangeTrailingChar(). See OBJNAME.CPP for more information. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" char AL_DLL_FAR * AL_FUNCTION +ALStorageChangeTrailingChar( hALStorage this_object, char new_char ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageChangeTrailingChar" ); + return ( (ALStorage *) this_object )->mName.ChangeTrailingChar( new_char ); +} + +#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL ) + +extern "C" long AL_FUNCTION +ALStorageChangeTrailingCharVB( hALStorage this_object, char new_char ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageChangeTrailingChar" ); + char _far * p = ( (ALStorage *) this_object )->mName.ChangeTrailingChar( new_char ); + return ALCreateVBString( p, (unsigned short int) _fstrlen( p ) ); +} + +#endif + +// C TRANSLATION FUNCTION +// +// extern "C" char * ALStorageGetName( hALStorage this_object ) +// +// VB TRANSLATION FUNCTION +// +// extern "C" long ALStorageGetNameVB( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// name you want. +// +// RETURNS +// +// A string pointer (or VB string) containing the file name. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALName::GetSafeName() C++ member function for the mName data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// Note that the VB version of this function is almost identical. However, +// instead of returning a pointer to a character string, this routine calls +// ALVBCreateString() to build a VB string, which it returns to the +// calling module. Don't use the VB function from C, it will blow up. +// Don't use the C function from VB, because it returns a string pointer, +// which VB doesn't know how to deal with. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALName::GetSafeName(). See OBJNAME.CPP for more information. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" char AL_DLL_FAR * AL_FUNCTION +ALStorageGetName( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetName" ); + return (char AL_DLL_FAR *) ( (ALStorage *) this_object )->mName.GetSafeName(); +} + + +#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL ) + +extern "C" long AL_FUNCTION ALStorageGetNameVB( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetName" ); + const char _far *p = ( (ALStorage *) this_object )->mName.GetSafeName(); + return ALCreateVBString( p, (unsigned short int) _fstrlen( p ) ); +} + +#endif + +// C TRANSLATION FUNCTION +// +// extern "C" char * ALStorageGetOldName( hALStorage this_object ) +// +// VB TRANSLATION FUNCTION +// +// extern "C" long ALStorageGetOldNameVB( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// old name you want. +// +// RETURNS +// +// A string pointer (or VB string) containing the old file name. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALName::GetSafeOldName() C++ member function for the mName data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// Note that the VB version of this function is almost identical. However, +// instead of returning a pointer to a character string, this routine calls +// ALVBCreateString() to build a VB string, which it returns to the +// calling module. Don't use the VB function from C, it will blow up. +// Don't use the C function from VB, because it returns a string pointer, +// which VB doesn't know how to deal with. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALName::GetSafeOldName(). See OBJNAME.CPP for more information. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" char AL_DLL_FAR * AL_FUNCTION +ALStorageGetOldName( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetOldName" ); + return (char AL_DLL_FAR *) ( (ALStorage *) this_object )->mName.GetSafeOldName(); +} + + +#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL ) + +extern "C" long AL_FUNCTION ALStorageGetOldNameVB( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetOldNameVB" ); + const char _far *p = ( (ALStorage *) this_object )->mName.GetSafeOldName(); + return ALCreateVBString( p, (unsigned short int) _fstrlen( p ) ); +} + +#endif + +// +// extern "C" int ALStorageGetStatusCode( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// status code you want. +// +// RETURNS +// +// The integer value of the status code. Values of AL_SUCCESS are good, +// values < AL_SUCCESS are bad. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALStatus::GetStatusCode() C++ member function for the mStatus data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// There really isn't too much to know about this function. It just +// returns the current integer status code to the calling routine. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageGetStatusCode( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetStatusCode" ); + return ( (ALStorage *) this_object)->mStatus.GetStatusCode(); +} + +// +// extern "C" int ALStorageSetError( hALArchive this_object, +// int error, +// char *text ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// 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 ALStorage 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 ALStorageSetError( hALStorage this_object, + int error, + char AL_DLL_FAR *text ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSetError" ); + ( (ALStorage *) this_object )->mStatus.SetError( error, text ); + return error; +} + +// C TRANSLATION FUNCTION +// +// extern "C" char * ALStorageGetStatusString( hALStorage this_object ) +// +// VB TRANSLATION FUNCTION +// +// extern "C" long ALStorageGetStatusStringVB( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// status string you want to get. +// +// RETURNS +// +// A string pointer (or VB string) containing the status string. This +// is the short translation string, not the detailed message. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALStatus::GetStatusString() C++ member function for the mStatus data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// Note that the VB version of this function is almost identical. However, +// instead of returning a pointer to a character string, this routine calls +// ALVBCreateString() to build a VB string, which it returns to the +// calling module. Don't use the VB function from C, it will blow up. +// Don't use the C function from VB, because it returns a string pointer, +// which VB doesn't know how to deal with. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALStatus::GetStatusString(). See STATUS.CPP for more information. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" char AL_DLL_FAR * AL_FUNCTION +ALStorageGetStatusString( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetStatusString" ); + const char *status = ( (ALStorage *) this_object)->mStatus.GetStatusString(); + if ( status == 0 ) + status = ""; + return (char AL_DLL_FAR *) status; +} + + +#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL ) + +extern "C" long AL_FUNCTION ALStorageGetStatusStringVB( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetStatusStringVB" ); + const char _far *status = ( (ALStorage *) this_object)->mStatus.GetStatusString(); + if ( status == 0 ) + status = ""; + return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) ); +} + +#endif + +// C TRANSLATION FUNCTION +// +// extern "C" char * ALStorageGetStatusDetail( hALStorage this_object ) +// +// VB TRANSLATION FUNCTION +// +// extern "C" long ALStorageGetStatusDetailVB( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object whose +// status detail string you want to get. +// +// RETURNS +// +// A string pointer (or VB string) containing the status string. This +// is the detailed status message, not the short translated string. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to call the +// ALStatus::GetStatusDetail() C++ member function for the mStatus data +// member of class ALStorage. This function checks the handle argument for +// correct type (in debug mode), then casts and calls the C++ function. +// +// Note that the VB version of this function is almost identical. However, +// instead of returning a pointer to a character string, this routine calls +// ALVBCreateString() to build a VB string, which it returns to the +// calling module. Don't use the VB function from C, it will blow up. +// Don't use the C function from VB, because it returns a string pointer, +// which VB doesn't know how to deal with. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALStatus::GetStatusDetail(). See STATUS.CPP for more information. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" char AL_DLL_FAR * AL_FUNCTION +ALStorageGetStatusDetail( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetStatusDetail" ); + const char *status = ( (ALStorage *) this_object )->mStatus.GetStatusDetail(); + if ( status == 0 ) + status = ""; + return (char AL_DLL_FAR *) status; +} + + +#if defined( AL_BUILDING_DLL ) && defined( AL_WINDOWS_GUI ) && !defined( AL_FLAT_MODEL ) + +extern "C" long AL_FUNCTION +ALStorageGetStatusDetailVB( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetStatusDetailVB" ); + const char _far *status = ( (ALStorage *) this_object)->mStatus.GetStatusDetail(); + if ( status == 0 ) + status = ""; + return ALCreateVBString( status, (unsigned short int) _fstrlen( status ) ); +} + +#endif + +// +// extern "C" long ALStorageGetUnixTime( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// We are going to retrieve the time/date stamp +// for this object. +// RETURNS +// +// The time/date of the object in unix format. Unix format is +// the format that is actually stored in an archive directory +// to record the object's time stamp. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALTimeDate::GetUnixTime(), as applied the mTimeDate data member +// of the ALStorage object. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the appropriate +// member function, with lots of casting. +// +// You won't learn much about much about the way ALTimeDate::GetUnixTime() +// works by looking at this function. See TIMEDATE.CPP for the +// details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" long AL_FUNCTION +ALStorageGetUnixTime( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetUnixTime" ); + return ( (ALStorage *) this_object)->mTimeDate.GetUnixTime(); +} + +// +// extern "C" long ALStorageToJulian( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// We are going to retrieve the time/date stamp +// for this object, in Julian date format. +// RETURNS +// +// The date of the object in julian date format. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALTimeDate::ToJulian(), as applied the mTimeDate data member +// of the ALStorage object. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the appropriate +// member function, with lots of casting. +// +// You won't learn much about much about the way ALTimeDate::ToJulian() +// works by looking at this function. See TIMEDATE.CPP for the +// details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" long AL_FUNCTION +ALStorageToJulian( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageToJulian" ); + return ( (ALStorage *) this_object)->mTimeDate.ToJulian(); +} + +// +// extern "C" void ALStorageFromJulian( hALStorage this_object, long jdn ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// We are going to set the date stamp +// for this object, using Julian date format. +// RETURNS +// +// Nothing. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALTimeDate::FromJulian(), as applied the mTimeDate data member +// of the ALStorage object. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the appropriate +// member function, with lots of casting. +// +// You won't learn much about much about the way ALTimeDate::FromJulian() +// works by looking at this function. See TIMEDATE.CPP for the +// details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION +ALStorageFromJulian( hALStorage this_object, long jdn ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageFromJulian" ); + ( (ALStorage *) this_object)->mTimeDate.FromJulian( jdn ); +} + +// +// extern "C" void +// ALStorageSetTimeDateFromStruc( hALStorage this_object, +// struct tm AL_DLL_FAR * time_struct ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// We are going to set the time/date stamp +// for this object, using C RTL time_struct format +// as our source. +// RETURNS +// +// Nothing. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALTimeDate::SetTimeDate(), as applied the mTimeDate data member +// of the ALStorage object. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the appropriate +// member function, with lots of casting. +// +// You won't learn much about much about the way ALTimeDate::SetTimeDate() +// works by looking at this function. See TIMEDATE.CPP for the +// details. +// +// I don't think this function will be of any value to VB programmers. +// The only place to get this time date structure is from the C run +// time library. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION +ALStorageSetTimeDateFromStruc( hALStorage this_object, + struct tm AL_DLL_FAR * time_struct ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSetTimeDateFromStruc" ); + AL_ASSERT( time_struct != 0, "Null tm struct passed to ALStorageSetTimeDateFromStruc" ); + ( (ALStorage *) this_object )->mTimeDate.SetTimeDate( time_struct ); +} + +// +// extern "C" void +// ALStorageGetStrucFromTimeDate( hALStorage this_object, +// struct tm * time_struct ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// We are going to get the time/date stamp +// for this object, with the result going into +// the time date struct used by the C run time library. +// RETURNS +// +// Nothing. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALTimeDate::GetTimeDate(), as applied the mTimeDate data member +// of the ALStorage object. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the appropriate +// member function, with lots of casting. +// +// You won't learn much about much about the way ALTimeDate::GetTimeDate() +// works by looking at this function. See TIMEDATE.CPP for the +// details. +// +// I don't think this function will be of any value to VB programmers. +// The only place to get this time date structure is from the C run +// time library. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION +ALStorageGetStrucFromTimeDate( hALStorage this_object, + struct tm AL_DLL_FAR * time_struct ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetStrucFromTimeDate" ); + AL_ASSERT( time_struct != 0, "Null tm struct passed to ALStorageGetStrucFromTimeDate" ); + ( (ALStorage *) this_object )->mTimeDate.GetTimeDate( time_struct ); +} + +// +// extern "C" void +// ALStorageSetTimeDateFromUnix( hALStorage this_object, +// long unix_time ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// We are going to set the time/date stamp +// for this object, using the Unix format time/date +// format as a source. +// +// unix_time : The time date in UNIX format. +// +// RETURNS +// +// Nothing. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALTimeDate::SetTimeDate(), as applied to the mTimeDate data member +// of the ALStorage object. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the appropriate +// member function, with lots of casting. +// +// You won't learn much about much about the way ALTimeDate::SetTimeDate() +// works by looking at this function. See TIMEDATE.CPP for the +// details. +// +// The UNIX time/date format is what ArchiveLib uses internally in archives +// created using ALArchiveBase. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION +ALStorageSetTimeDateFromUnix( hALStorage this_object, long unix_time ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSetTimeDateFromUnix" ); + ( (ALStorage *) this_object )->mTimeDate.SetTimeDate( unix_time ); +} + +// +// extern "C" int ALStorageIsOpen( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// 1 if the object is open, 0 if it is closed. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::IsOpen(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way ALStorage::IsOpen() +// works by looking at this function. See STORAGE.CPP for the +// details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageIsOpen( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageIsOpen" ); + return ( (ALStorage *) this_object )->IsOpen(); +} + +// +// extern "C" int ALStorageReadChar( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// A byte from 0 to 255 if any valid characters are present, +// AL_END_OF_FILE if there aren't any, or an error code < AL_SUCCESS +// if the file is now in an error state. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::ReadChar(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way ALStorage::ReadChar() +// works by looking at this function. See STORAGE.H for the +// details. +// +// In C++, this function is implemented as an inline function, and it is +// pretty fast. Normally it just has to get a byte from the I/O buffer. +// This isn't the case when using this translation function, so you lose +// some efficiency. The best way to solve the efficiency problem is to +// try to structure your code to use ReadBuffer() instead. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageReadChar( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageReadChar" ); + return ( (ALStorage *) this_object )->ReadChar(); +} + +// +// extern "C" int ALStorageReadShort( hALStorage this_object, +// short int *data ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// data : Pointer to a short int that is going to receive +// the short int read in from the storage object. +// +// RETURNS +// +// AL_SUCCESS if the short int was read in properly. An error code +// < AL_SUCCESS if something bad happened. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::ReadPortableShort(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way +// ALStorage::ReadPortableShort()works by looking at this function. +// See STORAGE.CPP for the details. +// +// This function is designed for reading data that needs to be stored +// in a system independent fashion. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION +ALStorageReadShort( hALStorage this_object, short int AL_DLL_FAR *data ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageReadShort" ); + AL_ASSERT( data != 0, "Null pointer passed to function" ); + return ( (ALStorage *) this_object )->ReadPortableShort( *data ); +} + +// +// extern "C" int ALStorageReadLong( hALStorage this_object, +// long *data ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// data : Pointer to a long int that is going to receive +// the long int read in from the storage object. +// +// RETURNS +// +// AL_SUCCESS if the long int was read in properly. An error code +// < AL_SUCCESS if something bad happened. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::ReadPortableLong(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way +// ALStorage::ReadPortableLong()works by looking at this function. +// See STORAGE.CPP for the details. +// +// This function is designed for reading data that needs to be stored +// in a system independent fashion. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION +ALStorageReadLong( hALStorage this_object, long AL_DLL_FAR *data ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageReadLong" ); + AL_ASSERT( data != 0, "Null pointer passed to function" ); + return ( (ALStorage *) this_object )->ReadPortableLong( *data ); +} + +// +// extern "C" int ALStorageWriteLong( hALStorage this_object, +// long data ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// data : A long int that is going to be written out to +// to the storage object in a system independent manner. +// +// RETURNS +// +// AL_SUCCESS if the long int was written out properly. An error code +// < AL_SUCCESS if something bad happened. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::WritePortableLong(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way +// ALStorage::WritePortableLong()works by looking at this function. +// See STORAGE.CPP for the details. +// +// This function is designed for writing data that needs to be stored +// in a system independent fashion. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageWriteLong( hALStorage this_object, + long data ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteLong" ); + return ( (ALStorage *) this_object)->WritePortableLong( data ); +} + +// +// extern "C" int ALStorageWriteShort( hALStorage this_object, +// short data ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// data : A short int that is going to be written out to +// to the storage object in a system independent manner. +// +// RETURNS +// +// AL_SUCCESS if the short int was written out properly. An error code +// < AL_SUCCESS if something bad happened. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::WritePortableShort(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way +// ALStorage::WritePortableShort()works by looking at this function. +// See STORAGE.CPP for the details. +// +// This function is designed for writing data that needs to be stored +// in a system independent fashion. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageWriteShort( hALStorage this_object, + short int data ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteShort" ); + return ( (ALStorage *) this_object)->WritePortableShort( data ); +} + +// +// extern "C" int ALStorageWriteString( hALStorage this_object, +// char *string ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// string : A string that we are going to write out to the +// storage object in a system independent manner. +// +// RETURNS +// +// AL_SUCCESS if the string was written out properly. An error code +// < AL_SUCCESS if something bad happened. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::WriteString(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way +// ALStorage::WriteString()works by looking at this function. +// See STORAGE.CPP for the details. +// +// This function is designed for writing variable length blocks of data +// to archives in a consistent fashion. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageWriteString( hALStorage this_object, + char AL_DLL_FAR *string ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteString" ); + AL_ASSERT( string != 0, "Passing null string in ALStorageWriteString()" ); + return ( (ALStorage *) this_object )->WriteString( string ); +} + +// +// extern "C" void ALStorageInitCrc32( hALStorage this_object, +// long seed ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// seed : The initial value for the 32 bit CRC. In C++, the +// default parameter is 0xffffffffL. This is a good +// one to use, and it gives you ARJ/PKWARE compatibility. +// +// RETURNS +// +// Nothing. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::InitCrc32(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// +// You won't learn much about much about the way +// ALStorage::InitCrc32()works by looking at this function. +// See STORAGE.CPP for the details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" void AL_FUNCTION ALStorageInitCrc32( hALStorage this_object, + long seed ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageInitCrc32" ); + ( (ALStorage *) this_object )->InitCrc32( seed ); +} + +// +// extern "C" long ALStorageTell( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// A long value indicating where the read/write pointer to the storage +// object is presently located. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::Tell(). It works a lot like the C RTL tell() or +// ftell() functions. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The long result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::Tell()works by looking at this function. +// See STORAGE.CPP for the details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" long AL_FUNCTION ALStorageTell( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageTell" ); + return ( (ALStorage *) this_object )->Tell(); +} + +// +// extern "C" size_t +// ALStorageReadBuffer( hALStorage this_object, +// unsigned char *buffer, +// size_t length ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// buffer : A pointer to a buffer. Specified as unsigned +// char, but the type doesn't really matter. +// +// length : The number of bytes you want to read into the buffer. +// +// RETURNS +// +// A number >= 0 indicates that number of byte were read into the buffer. +// A number <0 is a status code corresponding to an error. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::ReadBuffer(). It works a lot like the C RTL read() or +// fread() functions. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The short int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::ReadBuffer()works by looking at this function. +// See STORAGE.CPP for the details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" size_t AL_FUNCTION +ALStorageReadBuffer( hALStorage this_object, + unsigned char AL_DLL_FAR *buffer, + size_t length ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageReadBuffer" ); + AL_ASSERT( buffer != 0, "Passed a null buffer to ALStorageReadBuffer" ); + return ( (ALStorage * ) this_object )->ReadBuffer( buffer, length ); +} + +// +// extern "C" size_t +// ALStorageWriteBuffer( hALStorage this_object, +// unsigned char *buffer, +// size_t length ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// buffer : A pointer to a buffer. Specified as unsigned +// char, but the type doesn't really matter. +// +// length : The number of bytes you want to write from the buffer. +// +// RETURNS +// +// A number >= 0 indicates that number of bytes were written to the object. +// A number <0 is a status code corresponding to an error. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::WriteBuffer(). It works a lot like the C RTL write() or +// fwrite() functions. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The short int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::WriteBuffer()works by looking at this function. +// See STORAGE.CPP for the details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" size_t AL_FUNCTION +ALStorageWriteBuffer( hALStorage this_object, + unsigned char AL_DLL_FAR *buffer, + size_t length ) + +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteBuffer" ); + AL_ASSERT( buffer != 0, "Passed a null buffer to ALStorageWriteBuffer" ); + return ( (ALStorage * ) this_object )->WriteBuffer( buffer, length ); +} + +// +// extern "C" long ALStorageGetCrc32( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// A long value corresponding to the current CRC-32 of the storage +// object. A value of -1 indicates that the CRC is unknown. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::GetCrc32(). This is just a simple access routine +// used to get the value of a private data member. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The long result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::GetCrc32()works by looking at this function. +// See STORAGE.CPP for the details. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" long AL_FUNCTION ALStorageGetCrc32( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetCrc32" ); + return ( (ALStorage *) this_object )->GetCrc32(); +} + +// +// extern "C" int ALStorageClose( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// A value of AL_SUCCESS if the object was closed properly. A value +// of < AL_SUCCESS indicates an error state of some sort. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::Close(). This is virtual function that will generally +// be implemented by a derived class. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::Close()works by looking at this function. +// See MEMSTORE.CPP or FILESTOR.CPP for the details. The base +// class version in STORAGE.CPP has good information as well. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageClose( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageClose" ); + return ( (ALStorage *) this_object )->Close(); +} + +// +// extern "C" int ALStorageCreate( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// A value of AL_SUCCESS if the object was created properly. A value +// of < AL_SUCCESS indicates an error state of some sort. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::Create(). This is virtual function that will generally +// be implemented by a derived class. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::Create()works by looking at this function. +// See MEMSTORE.CPP or FILESTOR.CPP for the details. The base +// class version in STORAGE.CPP has good information as well. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageCreate( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageCreate" ); + return ( (ALStorage *) this_object )->Create(); +} + +// +// extern "C" int ALStorageFlushBuffer( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// A value of AL_SUCCESS if flush operation worked properly. A return +// of < AL_SUCCESS indicates an error state of some sort. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::FlushBuffer(). This is virtual function that will generally +// be implemented by a derived class. FlushBuffer() is used internally +// by ALStorage to flush the buffer when a write operation overflows +// the I/O buffer. It can be called externally to force the buffer out +// to the physical storage medium. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::FlushBuffer()works by looking at this function. +// See MEMSTORE.CPP or FILESTOR.CPP for the details. The base +// class version in STORAGE.CPP has good information as well. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// +extern "C" int AL_FUNCTION ALStorageFlushBuffer( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageFlushBuffer" ); + return ( (ALStorage *) this_object )->FlushBuffer(); +} + +// +// extern "C" int ALStorageLoadBuffer( hALStorage this_object, +// long address ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// address : The address that we want to load data from. +// +// RETURNS +// +// An integer >= 0 if the load operation worked properly. A return +// of < AL_SUCCESS indicates an error state of some sort. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::LoadBuffer(). This is virtual function that will generally +// be implemented by a derived class. LoadBuffer() is used internally +// by ALStorage to refresh the I/O buffer when a read operation underflows +// the I/O buffer. It can be called externally to force a load from a +// specific address, equivalent to a Seek() call. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way +// ALStorage::LoadBuffer()works by looking at this function. +// See MEMSTORE.CPP or FILESTOR.CPP for the details. The base +// class version in STORAGE.CPP has good information as well. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageLoadBuffer( hALStorage this_object, + long address ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageLoadBuffer" ); + return ( (ALStorage *) this_object )->LoadBuffer( address ); +} + +// +// extern "C" int ALStorageOpen( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// RETURNS +// +// AL_SUCCESS if the open operation worked properly. A return +// of < AL_SUCCESS indicates an error state of some sort. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::Open(). This is virtual function that will generally +// be implemented by a derived class. Open() opens the physical storage +// device associated with the ALStorageObject, and reads any storage +// time date stamp and other attributes. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way ALStorage::Open() +// works by looking at this function. See MEMSTORE.CPP or FILESTOR.CPP +// for the details. The base class version in STORAGE.CPP also has +// some useful information. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageOpen( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageOpen" ); + return ( (ALStorage *) this_object )->Open(); +} + +// +// extern "C" int ALStorageRename( hALStorage this_object, +// char *new_name, +// int delete_on_clash ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// new_name : The new name you want to assign to the storage +// object. You can pass a parameter of 0 here to +// indicate that you have already assigned the new +// name to the mName member of the storage object. +// +// delete_on_clash : If it turns out that the storage object name is +// already in use, you have a clash. This can happen, +// for example, when renaming a file to a backup. +// Setting this flag indicates that if there is a clash, +// you want to delete the clashing file and let +// your object use the name. +// +// RETURNS +// +// AL_SUCCESS if the rename operation worked properly. AL_RENAME_ERROR +// may be returned by derived classes if specific problems occur. +// Additional error codes < AL_SUCCESS may be returned if some other +// error was detected. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::Rename(). This is virtual function that will generally +// be implemented by a derived class. Rename() operates on the operating +// system level to reassign the name of an object, such as a file. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way ALStorage::Rename() +// works by looking at this function. See FILESTOR.CPP for the details. +// MEMSTORE.CPP doesn't really have any useful info, since ALMemory +// objects don't have a name defined at the O/S level. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageRename( hALStorage this_object, + char *new_name, + int delete_on_clash ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageRename" ); + AL_ASSERT( new_name != 0, "NULL new_name in ALStorageRename" ); + return ( (ALStorage *) this_object )->Rename( new_name, delete_on_clash ); +} + +// +// extern "C" int ALStorageRenameToBackup( hALStorage this_object, +// int delete_on_clash ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// delete_on_clash : If it turns out that the new storage name is +// already in use, you have a clash. This can happen, +// for example, when renaming a file to a backup. +// Setting this flag indicates that if there is a clash, +// you want to delete the clashing file and let +// your object use the name. +// +// RETURNS +// +// AL_SUCCESS if the rename operation worked properly. AL_RENAME_ERROR +// may be returned by derived classes if specific problems occur. +// Additional error codes < AL_SUCCESS may be returned if some other +// error was detected. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::RenameToBackup(). This is virtual function that will +// generally be implemented by a derived class. RenameToBackup() +// operates on the operating system level to reassign the name of an object, such as a file. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way ALStorage::RenameToBackup() +// works by looking at this function. See FILESTOR.CPP for the details. +// MEMSTORE.CPP doesn't really have any useful info, since ALMemory +// objects don't have a name defined at the O/S level. It just approves of +// all name change requests. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageRenameToBackup( hALStorage this_object, + int delete_on_clash ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageRenameToBackup" ); + return ( (ALStorage *) this_object )->RenameToBackup( delete_on_clash ); +} + +// +// extern "C" int ALStorageSeek( hALStorage this_object, +// long address ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// address : The address to seek to within the storage object. +// +// RETURNS +// +// AL_SUCCESS if the seek operation worked properly. AL_SEEK_ERROR +// may be returned by derived classes if specific problems occur. +// Additional error codes < AL_SUCCESS may be returned if some other +// error was detected. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::Seek(). This is virtual function that will +// generally be implemented by a derived class. ALStorage::Seek() often +// operates on the operating system level to seek to a position in a +// physical or O/S object. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way ALStorage::Seek() +// works by looking at this function. See FILESTOR.CPP and MEMSTORE.CPP +// for some insight. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// +extern "C" int AL_FUNCTION ALStorageSeek( hALStorage this_object, + long address ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageSeek" ); + return ( (ALStorage *) this_object )->Seek( address ); +} + +// +// extern "C" int ALStorageUnRename( hALStorage this_object, +// int delete_on_clash ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// delete_on_clash : If it turns out that the new storage name is +// already in use, you have a clash. This can happen, +// for example, when renaming a file to a backup. +// Setting this flag indicates that if there is a clash, +// you want to delete the clashing file and let +// your object use the name. +// +// RETURNS +// +// AL_SUCCESS if the rename operation worked properly. AL_RENAME_ERROR +// may be returned by derived classes if specific problems occur. +// Additional error codes < AL_SUCCESS may be returned if some other +// error was detected. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::UnRename(). This is virtual function that will +// generally be implemented by a derived class. ALStorage::UnRename() +// operates on the operating system level to reassign the name of an object, +// such as a file. +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), the handle is cast to the correct type, and +// a call is made to the C++ member function. The int result from +// the member function is returned unchanged to the calling C or VB +// procedure. +// +// You won't learn much about much about the way ALStorage::UnRename() +// works by looking at this function. See FILESTOR.CPP for the details. +// MEMSTORE.CPP doesn't really have any useful info, since ALMemory +// objects don't have a name defined at the O/S level. It just approves of +// all name change requests. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageUnRename( hALStorage this_object, + int delete_on_clash ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageUnRename" ); + return ( (ALStorage *) this_object )->UnRename( delete_on_clash ); +} + +// +// extern "C" int ALStorageWriteChar( hALStorage this_object, +// int c ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) an ALStorage object. +// +// c : A character to write. +// +// RETURNS +// +// A byte from 0 to 255 if the write was successful. Various error +// codes < AL_SUCCESS if the write failed. +// +// DESCRIPTION +// +// This is the C/VB wrapper function for the C++ member function +// ALStorage::WriteChar(). +// +// All that happens here is that the handle argument is checked for correct +// type (when in debug mode), and a call is made to the member function. +// The integer result is returned to the calling procedure as is. +// +// You won't learn much about much about the way ALStorage:WriteChar() +// works by looking at this function. See STORAGE.H for the +// details. +// +// In C++, this function is implemented as an inline function, and it is +// pretty fast. Normally it just has to put a byte into the I/O buffer. +// This isn't the case when using this translation function, so you lose +// some efficiency. The best way to solve the efficiency problem is to +// try to structure your code to use WriteBuffer() instead. +// +// REVISION HISTORY +// +// May 24, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageWriteChar( hALStorage this_object, + int c ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteChar" ); + return ( (ALStorage *) this_object )->WriteChar( c ); +} + +// +// extern "C" int ALStorageGetType( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// you want to get the type of. +// +// RETURNS +// +// The integer storage type, as defined in ALDEFS.H. AL_MEMORY_OBJECT +// and AL_FILE_OBJECT are popular choices. AL_UNDEFINED is possible +// as well. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ data member ALStorage::miStorageObjectType. This function checks +// its handle argument for correct type (in debug mode), then casts +// and accesses ALStorage::miStorageObjectType. It returns the integer +// result back to the calling procedure unchanged. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALStorage::miStorageObjectType. See STORAGE.H for the details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageGetType( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetType" ); + return ( (ALStorage *) this_object )->miStorageObjectType; +} + +// +// extern "C" unsigned short int +// ALStorageGetDosTime( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// you want to get the DOS time for. +// +// RETURNS +// +// An unsigned int that has the file access time in the format +// used by _dos_setfileattr(). +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALTimeDate::GetDosTime for the mTimeDate +// member of class ALStorage. This function checks its handle argument for +// correct type (in debug mode), then casts and calls +// ALTimeDate::GetDosTime. It returns the short integer result back +// to the calling procedure unchanged. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALTimeDate::GetDosTime. See TIMEDATE.CPP for the details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +#if !defined( AL_WIN32S ) + +extern "C" unsigned short int AL_FUNCTION +ALStorageGetDosTime( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetDosTime" ); + return ( (ALStorage *) this_object )->mTimeDate.GetDosTime(); +} + +#endif + +// +// extern "C" unsigned short int +// ALStorageGetDosDate( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// you want to get the DOS date for. +// +// RETURNS +// +// An unsigned int that has the file access date in the format +// used by _dos_setfileattr(). +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALTimeDate::GetDosDate for the mTimeDate +// member of class ALStorage. This function checks its handle argument for +// correct type (in debug mode), then casts and calls +// ALTimeDate::GetDosDate. It returns the short integer result back +// to the calling procedure unchanged. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALTimeDate::GetDosDate. See TIMEDATE.CPP for the details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +#if !defined( AL_WIN32S ) + +extern "C" unsigned short int AL_FUNCTION +ALStorageGetDosDate( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetDosDate" ); + return ( (ALStorage *) this_object )->mTimeDate.GetDosDate(); +} + +#endif + +// +// extern "C" int ALStorageValidTimeDate( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// you want to check for validity. +// +// RETURNS +// +// A true or false, to indicate whether a valid time has been +// loaded into the mTimeDate member of the ALStorage object. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALTimeDate::Valid() for the mTimeDate +// member of class ALStorage. This function checks its handle argument for +// correct type (in debug mode), then casts and calls +// ALTimeDate::Valid(). It returns the integer result back +// to the calling procedure unchanged. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALTimeDate::Valid(). See TIMEDATE.H for the details on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +extern "C" int AL_FUNCTION ALStorageValidTimeDate( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageValidTimeDate" ); + return ( (ALStorage *) this_object )->mTimeDate.Valid(); +} + + +// +// extern "C" DWORD ALStorageGetWin32Attributes( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// you want to get the Win32s file attributes for. +// +// RETURNS +// +// A DWORD containing the Win32s attributes for the selected +// storage object. The attributes are in the format needed +// by the SetFileAttributes() function. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALFileAttributes::GetWin32Attributes() for the +// mAttributes member of class ALStorage. This function checks its handle +// argument for correct type (in debug mode), then casts and calls +// ALAttributes::GetWin32Attributes(). It returns the long result back +// to the calling procedure unchanged. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALAttributes::GetWin32Attributes). See FILEATTR.CPP for the details +// on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +#if defined( AL_WIN32S ) +extern "C" DWORD AL_FUNCTION +ALStorageGetWin32Attributes( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetWin32Attributes" ); + return ( (ALStorage *) this_object )->mAttributes.GetWin32Attributes(); +} +#endif + +// +// extern "C" unsigned short int +// ALStorageGetDosAttributes( hALStorage this_object ) +// +// ARGUMENTS: +// +// this_object : A handle for (pointer to) the storage object that +// you want to get the DOS file attributes for. +// +// RETURNS +// +// A short int containing the DOS attributes for the selected +// storage object. The attributes are returned in the format +// needed by the _dos_setfileattr() function. +// +// DESCRIPTION +// +// This is the C/VB translation routine that allows you to access the +// C++ member function ALFileAttributes::GetDosAttributes() for the +// mAttributes member of class ALStorage. This function checks its handle +// argument for correct type (in debug mode), then casts and calls +// ALAttributes::GetDosAttributes(). It returns the short result back +// to the calling procedure unchanged. +// +// The C/VB translation code doesn't offer much insight into the operation +// of ALAttributes::GetDosAttributes). See FILEATTR.CPP for the details +// on that. +// +// REVISION HISTORY +// +// May 25, 1994 1.0A : First release +// + +#if !defined( AL_WIN32S ) +extern "C" unsigned short int AL_FUNCTION +ALStorageGetDosAttributes( hALStorage this_object ) +{ + AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageGetDosAttributes" ); + return ( (ALStorage *) this_object )->mAttributes.GetDosAttributes(); +} +#endif + diff --git a/al/cxl_util.cpp b/al/cxl_util.cpp new file mode 100755 index 000000000..47980f9bb --- /dev/null +++ b/al/cxl_util.cpp @@ -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 + + diff --git a/al/cxl_wild.cpp b/al/cxl_wild.cpp new file mode 100755 index 000000000..227ff38a2 --- /dev/null +++ b/al/cxl_wild.cpp @@ -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; +} + diff --git a/al/fileattr.cpp b/al/fileattr.cpp new file mode 100755 index 000000000..a2e277f9c --- /dev/null +++ b/al/fileattr.cpp @@ -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 + +#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 ) diff --git a/al/fileattr.h b/al/fileattr.h new file mode 100755 index 000000000..347b6a926 --- /dev/null +++ b/al/fileattr.h @@ -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 */ diff --git a/al/filestor.cpp b/al/filestor.cpp new file mode 100755 index 000000000..99ede4f30 --- /dev/null +++ b/al/filestor.cpp @@ -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 +#include +#include +#include +#include +//#include +#include +#include +#include + +#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; +} + + diff --git a/al/filestor.h b/al/filestor.h new file mode 100755 index 000000000..d2938055a --- /dev/null +++ b/al/filestor.h @@ -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 */ diff --git a/al/grenengn.cpp b/al/grenengn.cpp new file mode 100755 index 000000000..2b3be5e27 --- /dev/null +++ b/al/grenengn.cpp @@ -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 ); +} + diff --git a/al/grenengn.h b/al/grenengn.h new file mode 100755 index 000000000..f4328f911 --- /dev/null +++ b/al/grenengn.h @@ -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 */ diff --git a/al/memstore.cpp b/al/memstore.cpp new file mode 100755 index 000000000..745b7ba82 --- /dev/null +++ b/al/memstore.cpp @@ -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 // 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; +} + + diff --git a/al/memstore.h b/al/memstore.h new file mode 100755 index 000000000..9d0aa7064 --- /dev/null +++ b/al/memstore.h @@ -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 */ diff --git a/al/monitor.cpp b/al/monitor.cpp new file mode 100755 index 000000000..f58261fc5 --- /dev/null +++ b/al/monitor.cpp @@ -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 * ) +{ +} diff --git a/al/monitor.h b/al/monitor.h new file mode 100755 index 000000000..d60f64aa1 --- /dev/null +++ b/al/monitor.h @@ -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 */ diff --git a/al/objname.cpp b/al/objname.cpp new file mode 100755 index 000000000..532a6ef58 --- /dev/null +++ b/al/objname.cpp @@ -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 +#include + +#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; + } +} + + diff --git a/al/objname.h b/al/objname.h new file mode 100755 index 000000000..c3a3d0093 --- /dev/null +++ b/al/objname.h @@ -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 +#include + +/* + * 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 */ + diff --git a/al/spinner.h b/al/spinner.h new file mode 100755 index 000000000..b95b48ff5 --- /dev/null +++ b/al/spinner.h @@ -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 */ diff --git a/al/status.cpp b/al/status.cpp new file mode 100755 index 000000000..ba5517633 --- /dev/null +++ b/al/status.cpp @@ -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 +#include + +// +// 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; +} + diff --git a/al/status.h b/al/status.h new file mode 100755 index 000000000..7d6a2331f --- /dev/null +++ b/al/status.h @@ -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 */ + diff --git a/al/storage.cpp b/al/storage.cpp new file mode 100755 index 000000000..7d12b97ae --- /dev/null +++ b/al/storage.cpp @@ -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 + +// +// 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; +} diff --git a/al/storage.h b/al/storage.h new file mode 100755 index 000000000..f35a1f5aa --- /dev/null +++ b/al/storage.h @@ -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 /* 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 */ diff --git a/al/storcmp.cpp b/al/storcmp.cpp new file mode 100755 index 000000000..4ccea0890 --- /dev/null +++ b/al/storcmp.cpp @@ -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 + +#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; +} + diff --git a/al/timedate.cpp b/al/timedate.cpp new file mode 100755 index 000000000..81993b1de --- /dev/null +++ b/al/timedate.cpp @@ -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 +#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 ) + diff --git a/al/timedate.h b/al/timedate.h new file mode 100755 index 000000000..d3c3197d0 --- /dev/null +++ b/al/timedate.h @@ -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 + +/* + * 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 diff --git a/al/wildcard.cpp b/al/wildcard.cpp new file mode 100755 index 000000000..e8962eddf --- /dev/null +++ b/al/wildcard.cpp @@ -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 +#ifdef __BORLANDC__ +#include +#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 diff --git a/al/wildcard.h b/al/wildcard.h new file mode 100755 index 000000000..24c3d60ac --- /dev/null +++ b/al/wildcard.h @@ -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 +#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 */ diff --git a/al/winmon.h b/al/winmon.h new file mode 100755 index 000000000..2c8e62a02 --- /dev/null +++ b/al/winmon.h @@ -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 */