campo-sirio/arch/status.cpp

336 lines
9.7 KiB
C++
Executable File

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