Click here to Skip to main content
15,891,567 members
Articles / Containers / Virtual Machine

TOOL

Rate me:
Please Sign up or sign in to vote.
4.98/5 (52 votes)
23 Oct 200676 min read 230.8K   5.4K   147  
TOOL (Tiny Object Oriented Language) is an easily-embedded, object-oriented, C++-like-language interpreter. The purpose of this article is to introduce the TOOL interpreter and language from the perspective of a person who has a desire to include a scripting solution as part of his project.
/*****************************************************************************/
/*                              SOURCE FILE                                  */
/*****************************************************************************/
/*
       $Archive:   $

      $Revision:   $
          $Date:   $
        $Author:   $

    Description:   Contains the implementation of the VMDirScanner class

                      TOOL And XML FORMS License
                      ==========================

                      Except where otherwise noted, all of the documentation 
                      and software included in the TOOL package is 
                      copyrighted by Michael Swartzendruber.

                      Copyright (C) 2005 Michael John Swartzendruber. 
                      All rights reserved.

                      Access to this code, whether intentional or accidental,
                      does NOT IMPLY any transfer of rights.

                      This software is provided "as-is," without any express 
                      or implied warranty. In no event shall the author be held
                      liable for any damages arising from the use of this software.

                      Permission is granted to anyone to use this software for 
                      any purpose, including commercial applications, and to 
                      alter and redistribute it, provided that the following 
                      conditions are met:

                      1. All redistributions of source code files must retain 
                         all copyright notices that are currently in place, 
                         and this list of conditions without modification.

                      2. The origin of this software must not be misrepresented;
                         you must not claim that you wrote the original software.

                      3. If you use this software in another product, an acknowledgment
                         in the product documentation would be appreciated but is
                         not required.

                      4. Modified versions in source or binary form must be plainly 
                         marked as such, and must not be misrepresented as being 
                         the original software.
*/
static char OBJECT_ID[] = "$Revision: 2 $ : $Date: 6/17/98 6:32p $";
/*****************************************************************************/


#include "../../../stdafx.h"
#include <assert.h>
#include "VMLastSystemErrorCode.h"
#include "VMDirScanner.h"



/*****************************************************************************/
/*
     FUNCTION NAME:  VMDirScanner::VMDirScanner

       DESCRIPTION:  ctor

             INPUT:  pchRoot - the root of the search
                     pchMask - the file mask for 'filtering' the list
                     bRecurse - TRUE if should recurse, FALSE otherwise
            OUTPUT:  none

           RETURNS:  none
*/
VMDirScanner::VMDirScanner( const char* pchRoot, const char* pchMask, bool bRecurse )
: VMSysLastError()
{
  assert( NULL != pchRoot );
  assert( NULL != pchMask );
  strcpy( m_achMask, pchMask );
  strcpy( m_achCurSearchDir, pchRoot );

  GetCurrentDirectory( MAX_PATH, m_achCurrentDir );
  SetCurrentDirectory( pchRoot );

  m_oFilesIter = m_oFilesFound.begin();
  m_oDirsIter  = m_oDirsFound.begin();

  m_bRecurse  = bRecurse;
  m_bFirstSet = FALSE;

  if ( !m_bRecurse )
  {
    CurDirFileScan();
  }
  else
  {
    m_oDirsFound.push_back( pchRoot );
    ScanForAllFiles( 0 );
  }
  SetCurrentDirectory( m_achCurrentDir );
}
/* End of function "VMDirScanner::VMDirScanner"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMDirScanner::~VMDirScanner

       DESCRIPTION:  dtor. cleans out entries in the list

             INPUT:  void
            OUTPUT:  none

           RETURNS:  none
*/
VMDirScanner::~VMDirScanner( void )
{
  m_oFilesFound.clear();
  m_oDirsFound.clear();
}
/* End of function "VMDirScanner::~VMDirScanner"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  VMDirScanner::FindFile

       DESCRIPTION:  looks for the given file in the find set

             INPUT:  pchFileToFind - pointer to the name of the file to find
            OUTPUT:  none

           RETURNS:  true if found, false if not
*/
bool VMDirScanner::FindFile( const char* pchFileToFind )
{
  VM_FILE_FIND_ITER oIter;
 
  for ( oIter  = m_oFilesFound.begin();
        oIter != m_oFilesFound.end();
        oIter++ )
  {
    if ( 0 == strcmp( (*oIter).c_str(), pchFileToFind ) )
    {
      return( true );
    }
  }
  return( false );
}
/* End of function "VMDirScanner::FindFile"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMDirScanner::GetFirstFile

       DESCRIPTION:  returns the first string in the found file list (if it
                     exists) 

             INPUT:  void 
            OUTPUT:  none

           RETURNS:  CFastString that is the first entry in the list 
*/
VMString VMDirScanner::GetFirstFile( void )
{
  VMString  oReturn = _T("");

  if ( m_oFilesFound.size() > 0 )
  {
    m_bFirstSet  = TRUE;
    m_oFilesIter = m_oFilesFound.begin();
    oReturn      = (*m_oFilesIter).c_str();
  }
  return( oReturn );
}
/* End of function "VMDirScanner::GetFirstFile"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMDirScanner::GetNextFile

       DESCRIPTION:  Gets the next entry in the list, or the first one if
                     the iterator was not initialized

             INPUT:  void
            OUTPUT:  none

           RETURNS:  CString 
*/
VMString VMDirScanner::GetNextFile( void )
{
  VMString  oReturn = _T("");

  if ( m_oFilesFound.size() > 0 )
  {
    if ( !m_bFirstSet )
    {
      m_bFirstSet  = TRUE;
      m_oFilesIter = m_oFilesFound.begin();
      oReturn      = (*m_oFilesIter).c_str();
    }
    else
    {
      m_oFilesIter++;
      if ( m_oFilesIter != m_oFilesFound.end() )
      {
        oReturn = (*m_oFilesIter).c_str();
      }
    }
  }
  return( oReturn );
}
/* End of function "VMDirScanner::GetNextFile"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMDirScanner::GetLastDirectory

       DESCRIPTION:  returns the first string in the found file list (if it
                     exists) 

             INPUT:  void 
            OUTPUT:  none

           RETURNS:  CFastString that is the first entry in the list 
*/
VMString VMDirScanner::GetLastDirectory( void )
{
  VMString  oReturn = _T("");

  if (  0 < m_oDirsFound.size() )
  {
    m_oDirsIter = m_oDirsFound.begin();
    if ( m_oDirsIter != m_oDirsFound.end() )
    {  
      m_bFirstSet = true;
      oReturn = (*m_oDirsIter).c_str();
    }
  }
  return( oReturn );
}
/* End of function "VMDirScanner::GetLastDirectory"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:  VMDirScanner::GetPrevDirectory

       DESCRIPTION:  Gets the next entry in the list, or the first one if
                     the iterator was not initialized

             INPUT:  void
            OUTPUT:  none

           RETURNS:  CFastString 
*/
VMString VMDirScanner::GetPrevDirectory( void )
{
  VMString  oReturn = _T("");

  if ( m_oDirsFound.size() > 0 )
  {
    if ( !m_bFirstSet )
    {
      m_bFirstSet = TRUE;
      m_oDirsIter = m_oDirsFound.begin();
      oReturn     = (*m_oDirsIter).c_str();
    }
    else
    {
      m_oDirsIter++;
      if ( m_oDirsIter != m_oDirsFound.end() )
      {
        oReturn = (*m_oDirsIter).c_str();
      }
    }
  }
  return( oReturn );
}
/* End of function "VMDirScanner::GetPrevDirectory"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:	VMDirScanner::CurDirFileScan

       DESCRIPTION:	scans a single directory for the files contained in it.
                    does not recurse

             INPUT: void
            OUTPUT:	none
           RETURNS:	FALSE if any errors occurred
*/
bool VMDirScanner::CurDirFileScan( void ) 
{
  char            achCurrentDir[MAX_PATH+1];
  char            achFullPath[MAX_PATH+1];
  WIN32_FIND_DATA xFileInfo;
  HANDLE          hFind;

  if ( !GetCurrentDirectory( MAX_PATH+1, achCurrentDir ) )
  {
    SetLastError();
    return( false );
  }

  if ( 0 != strcmp( achCurrentDir, m_achCurSearchDir ) )
  { 
    if ( !SetCurrentDirectory( m_achCurSearchDir ) )
    {
      SetLastError();
      SetCurrentDirectory( achCurrentDir );
      return( false );
    }
  }

  hFind = FindFirstFile( m_achMask, &xFileInfo );

  if ( INVALID_HANDLE_VALUE != hFind ) 
  {
    do
    {
      if ( xFileInfo.dwFileAttributes 
         & ( FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE ) )
      {
        sprintf( achFullPath, "%s%s", m_achCurSearchDir, xFileInfo.cFileName );
        std::string oFullPath = achFullPath;
        m_oFilesFound.push_back( oFullPath );
      }
    } while ( FindNextFile( hFind, &xFileInfo ) );
  }
  FindClose( hFind );

  return ( SetCurrentDirectory( achCurrentDir ) != 0 );
}
/* end of function "VMDirScanner::CurDirFileScan" */
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME: GoUpOneDir

       DESCRIPTION: Sets the desination string up one directory	

             INPUT: pchDir - the destination directory string
            OUTPUT:	pchDir - contents are modified

           RETURNS: void	
*/
void VMDirScanner::GoUpOneDir( char* pchDir )
{
  for ( int iLength = strlen( pchDir )  - 1; iLength > 0; iLength-- )
  {
    if ( pchDir[ iLength ] == '\\' )
    {
      pchDir[ iLength ] = '\0';
      return;
    }
  }
  return;
}
/*	end of function "GoUpOneDir" */
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME: AddBackSlash

       DESCRIPTION: Check end of string and add a backshash if one does not 
                    exist	

             INPUT: pchWorking - a pointer to the string to add the '\' to
            OUTPUT:	pchWorking - contents are modified

           RETURNS: void	
*/
void VMDirScanner::AddBackSlash( char* pchWorking )
{
  short iLength;

  // add a \ if needed
  iLength = strlen( pchWorking );

  if ( iLength )
  {
    if ( pchWorking[ iLength - 1 ] != '\\' )
    {
      strcat( pchWorking, "\\" );
    }
  }
}
/*	end of function "AddBackSlash" */
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME: ScanForAllFiles

       DESCRIPTION: finds a subdirectory in the current working directory,
                    changes the current working directory to this sub-
                    directory, and recusively calls itself until there are 
                    no more subdirectories

          COMMENTS: When a new directory is entered from above, a handle for
                    the new directory is obtained using FindFirstDirectory.
                    Once the first directory is found, the current working 
                    directory is changed to this first directory and 
                    ScanForAllFiles() is recursively called again. At this 
                    point, the next available directory is searched for 
                    using FindNextFile, entered and a recursive call is made 
                    to ScanForAllFiles(). When each directory has been searched,
                    until no more directories exist, the current working directory
                    is changed to the parent directory (..). This continues until
                    the current working directory is equal to the original
                    directory.	

             INPUT: wLevel - bookmark, when wLevel is greater than 0, then 
                    the current working directory is a subdirectory of the 
                    original directory.  If wLevel is equal to 0, then the
                    directory is the original directory and the recursive 
                    calls stop

           RETURNS: FALSE if any errors
*/
bool VMDirScanner::ScanForAllFiles( WORD wLevel )
{
  bool              bRC=TRUE;
  HANDLE            hSearch;
  WIN32_FIND_DATA   xFindInfo;


  if ( !GetCurrentDirectory( MAX_PATH, m_achCurSearchDir ) )
  {
    SetLastError();
    return( false );
  }

  hSearch = FindFirstFile( "*", &xFindInfo );

  if ( INVALID_HANDLE_VALUE == hSearch ) 
  {
    FindClose( hSearch );
    if ( wLevel )
    {
      GoUpOneDir( m_achCurSearchDir );
      if ( FALSE == SetCurrentDirectory("..") )
      {
         SetLastError();
         return( false );
      }
      else
      {
        return( true );
      }
    }
    else
    {
      return( true );
    }
  }
	
  for (;;)
  {
    // if this "file" is ".." or "." then get next and continue
    //
    if ( strcmp( xFindInfo.cFileName,"." ) == 0 
      || strcmp( xFindInfo.cFileName,".." ) == 0 )
    {
      if ( FindNextFile( hSearch, &xFindInfo ) == FALSE )
      {
        GoUpOneDir( m_achCurSearchDir );
        if ( SetCurrentDirectory( ".." ) == FALSE )
        {
          SetLastError();
          FindClose( hSearch );
          return( false );
        }
        else
        {
          FindClose( hSearch );
          return( true );
        }
      }
      else
      {
        continue;
      }
    }



    // if this is a directory scan it
    //
    if ( xFindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
    {
      AddBackSlash( m_achCurSearchDir );
      strcat( m_achCurSearchDir, xFindInfo.cFileName );
      m_oDirsFound.insert( m_oDirsFound.begin(), m_achCurSearchDir );
      if ( FALSE == SetCurrentDirectory( m_achCurSearchDir ) )
      {
        SetLastError();
        FindClose( hSearch );
        return( false );
      }

      if ( !ScanForAllFiles( ++wLevel ) )
      {
        FindClose( hSearch );
        return( false );
      }
    }
    else
    {
      // if wild card search, then just add each
      // file found to the list of files that match
      // the mask
      //
      if ( ( 0 == strcmp( m_achMask , "*.*" ) )
        || ( 0 == strcmp( m_achMask , "*.?" ) )
        || ( 0 == strcmp( m_achMask , "?.*" ) )
        || ( 0 == strcmp( m_achMask , "?.?" ) ) )
      {
        std::string oFullPath;
        char        achPartialPath[ MAX_PATH + 1 ];

        strcpy( achPartialPath, m_achCurSearchDir );
        AddBackSlash( achPartialPath );
        strcat( achPartialPath, xFindInfo.cFileName );
        oFullPath = achPartialPath;
        m_oFilesFound.push_back( oFullPath );
      }
      else
      {
        if ( ( NULL != strchr( m_achMask, '*' ) )
          || ( NULL != strchr( m_achMask, '?' ) ) )
        {
          // need to 'fix up' the mask so that the
          // next test will work. This fix up is a little
          // out of place here, but it will only fire once
          // so we'll live with it....
          //
          char  achNewMask[MAX_PATH+1];
          ZeroMemory( achNewMask, MAX_PATH + 1 );
          int   iCurDestPos = 0;
          for ( unsigned int iLoop = 0; iLoop < strlen( m_achMask ); iLoop++ )
          {
            if ( ( '*' != m_achMask[ iLoop ] ) && ( '?' != m_achMask[ iLoop ] ) )
            {
              achNewMask[ iCurDestPos ] = m_achMask[ iLoop ];
              iCurDestPos++;
            }
          }
          strcpy( m_achMask, achNewMask );
        } 
        // if it is a file that matches the mask,
        // then add that file path to the 'found file' list
        //
        if ( NULL != strstr( xFindInfo.cFileName, m_achMask ) )
        {
          std::string oFullPath;
          char    achPartialPath[ MAX_PATH + 1 ];
          strcpy( achPartialPath, m_achCurSearchDir );
          AddBackSlash( achPartialPath );
          strcat( achPartialPath, xFindInfo.cFileName );
          oFullPath = achPartialPath;
          m_oFilesFound.push_back( oFullPath );
        }
      }
    }

    if ( FindNextFile( hSearch, &xFindInfo ) == FALSE )
    {
      GoUpOneDir( m_achCurSearchDir );
      if ( SetCurrentDirectory( ".." ) == FALSE )
      {
        SetLastError();
        FindClose( hSearch );
        return( false );
      }
      else
      {
        FindClose( hSearch );
        return( true );
      }
    }
  }
  FindClose( hSearch );
  return( true );
}
/*	end of function "ScanForAllFiles" */
/*****************************************************************************/



/*****************************************************************************/
/* Check-in history */
/*
 *$Log:   $
*/
/*****************************************************************************/


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions