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