home *** CD-ROM | disk | FTP | other *** search
- /* A set of objects for iterating a collection of files/folders */
- #ifndef _FILEITERATORS_
- #include "FileIterators.h"
- #endif
-
- /* -------------------- TFileIterator --------------------- */
- TFileIterator:: TFileIterator ( long options ) { fOptions = options; }
- TFileIterator:: TFileIterator ( TFileIterator &rhs ) { fOptions = rhs.fOptions; }
- TFileIterator::~TFileIterator () {}
-
- TFileIterator& TFileIterator::operator= ( TFileIterator& rhs ) {
-
- // Check for assignment to self
- if ( &rhs == this )
- return *this;
-
- fOptions = rhs.fOptions;
- return *this;
- }
-
-
-
- /* -------------------- TDirectoryIterator --------------------- */
- TDirectoryIterator:: TDirectoryIterator () {
- // AssertStr ( 0, "\pDefault Constructor for TDirectoryIterator::TDirectoryIterator" );
- }
-
-
- TDirectoryIterator:: TDirectoryIterator ( FSSpec *startPoint, long options ) : TFileIterator ( options ) {
- OSErr err = noErr;
-
- // Resolve the FSSpec to either a file or a folder.
- fPb.hFileInfo.ioCompletion = 0;
- fPb.hFileInfo.ioVRefNum = startPoint->vRefNum;
- fPb.hFileInfo.ioDirID = startPoint->parID;
- fPb.hFileInfo.ioNamePtr = startPoint->name;
- fPb.hFileInfo.ioFDirIndex = 0; // use vrefNum/dirid/ioNamePtr
- err = PBGetCatInfoSync ( &fPb );
- // AssertStr ( err == noErr, "\pCan't get info in TDirectoryIterator::TDirectoryIterator" );
-
- if ( err != noErr ) {
- fVRefNum = -1; // This will have no files!
- fParID = fsRtParID;
- }
- else if (( fPb.hFileInfo.ioFlAttrib & ioDirMask ) == 0 ) { // it's a file!
- fVRefNum = fPb.hFileInfo.ioVRefNum;
- fParID = fPb.hFileInfo.ioFlParID;
- }
- else {
- fVRefNum = fPb.dirInfo.ioVRefNum;
- fParID = fPb.dirInfo.ioDrDirID;
- }
-
- // If it's a file, then walk the directory containing the file.
- fNextIdx = -1;
- fNumItems = -1;
- }
-
- TDirectoryIterator:: TDirectoryIterator ( short vRefNum, long dirID, long options ) : TFileIterator ( options ) {
-
- // If the vRefNum is a WDirID, resolve it.
- fVRefNum = vRefNum;
- fParID = dirID;
- fNextIdx = -1;
- fNumItems = -1;
- }
-
-
- TDirectoryIterator:: TDirectoryIterator ( TFileIterator & /*rhs*/ ) {
- // !!!
- }
-
-
- TDirectoryIterator::~TDirectoryIterator () {}
-
-
- TDirectoryIterator& TDirectoryIterator::operator= ( TDirectoryIterator& rhs ) {
-
- // Check for assignment to self
- if ( &rhs == this )
- return *this;
-
- fOptions = rhs.fOptions;
- return *this;
- }
-
-
- // detects if the directory has changed, and does stuff
- // Currently it updates the number of items in the folder.
- // Later it will attempt to adjust the "current item" pointer.
- void TDirectoryIterator::Synchronize ( void ) {
- OSErr err = noErr;
-
- // Check the mod date
- fPb.hFileInfo.ioNamePtr = nil;
- fPb.hFileInfo.ioFDirIndex = -1; // Ignore namePtr, just use vRefNum/dirID
- fPb.hFileInfo.ioVRefNum = fVRefNum;
- fPb.hFileInfo.ioDirID = fParID;
- err = PBGetCatInfoSync ( &fPb );
- // If we can't get info then there are no files!
- if ( err != noErr )
- fNumItems = 0;
- else if ( fModDate < fPb.dirInfo.ioDrMdDat ) {
- fNumItems = fPb.dirInfo.ioDrNmFls;
- fModDate = fPb.dirInfo.ioDrMdDat;
- }
- }
-
- // Get the next item in the directory
- OSErr TDirectoryIterator::GetNextItem ( FSSpec *theSpec, Boolean *isFolder ) {
- OSErr err = noErr;
-
- if ( fNextIdx > fNumItems )
- err = fnfErr; // It _could_ happen!
- else {
- Str31 fileName;
-
- // Get the n'th item in the directory
- fPb.hFileInfo.ioCompletion = 0;
- fPb.hFileInfo.ioNamePtr = fileName;
- fPb.hFileInfo.ioVRefNum = fVRefNum;
- fPb.hFileInfo.ioDirID = fParID;
- fPb.hFileInfo.ioFDirIndex = fNextIdx++;
- err = PBGetCatInfoSync ( &fPb );
- // We have to resolve aliases, even if the user doesn't want any info
- // because she may be counting the contents
- if ( err == noErr || ( fOptions & kResolveAliases ) != 0 ) {
- FSSpec aSpec;
- Boolean aFolder, wasAlias;
-
- // Get the basic information
- (void) FSMakeFSSpec ( fPb.hFileInfo.ioVRefNum, fPb.hFileInfo.ioFlParID, fPb.hFileInfo.ioNamePtr, &aSpec );
- aFolder = ( fPb.hFileInfo.ioFlAttrib & ioDirMask ) != 0;
-
- // We know we can't have folders that are aliases!
- if (( fOptions & kResolveAliases ) && !aFolder )
- err = ResolveAliasFile ( &aSpec, true, &aFolder, &wasAlias );
-
- if ( theSpec != nil )
- *theSpec = aSpec;
- if ( isFolder != nil )
- *isFolder = aFolder;
- }
- }
-
- // ReportError ( err );
- return err;
- }
-
-
- void TDirectoryIterator::Start ( void ) {
-
- // Set up fNumItems, etc
- fNextIdx = -1; // Flag which says we are "starting"
- fModDate = 0;
- fPb.hFileInfo.ioCompletion = 0;
- fPb.hFileInfo.ioNamePtr = nil;
- fPb.hFileInfo.ioVRefNum = fVRefNum;
- fPb.hFileInfo.ioDirID = fParID;
- this->Synchronize ();
-
- // Start at item 1
- fNextIdx = 1;
- }
-
-
- Boolean TDirectoryIterator::More ( void ) {
-
- // Re-sync if the directory has been changed
- this->Synchronize ();
- return fNextIdx <= fNumItems;
- }
-
-
- OSErr TDirectoryIterator::Next ( FSSpec *theSpec, Boolean *isFolder ) {
- OSErr err = noErr;
- Boolean aFolder = true;
-
- // Figure out how many items there are
- // Re-sync if the number has changed
- this->Synchronize ();
-
- // We need this info
- if ( isFolder == nil )
- isFolder = &aFolder;
-
- // look at items until:
- // 1> We get an error
- // 2> We get a file
- // 3> The options say that a folder is OK
- do {
- // Get the next item, leaving if we got an error
- if (( err = this->GetNextItem ( theSpec, isFolder )) != noErr )
- break;
-
- // If the user asked for just files, and we got a folder, try again
- if (( fOptions & kJustFiles ) != 0 && *isFolder )
- continue;
-
- // If the thing is invisible and the caller asked for visible, try again
- if (( fOptions & kJustVisible ) != 0 &&
- ( fPb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible ) != 0 )
- continue;
-
- // None of those are true, so we're done
- break;
- } while ( true );
-
- // ReportError ( err );
- return err;
- }
-
-
- /* -------------- TFileTreeIterator -------------------------- */
-
- TFileTreeIterator:: TFileTreeIterator () {
- // AssertStr ( 0, "\pDefault Constructor for TFileTreeIterator::TFileTreeIterator" );
- }
-
-
- TFileTreeIterator::TFileTreeIterator ( FSSpec *startPoint, long options ) : TDirectoryIterator ( startPoint, options ) {
- fChild = NULL;
- }
-
-
- TFileTreeIterator::TFileTreeIterator ( short vRefNum, long dirID, long options ) : TDirectoryIterator ( vRefNum, dirID, options ) {
- fChild = NULL;
- }
-
-
- TFileTreeIterator::TFileTreeIterator ( TFileTreeIterator &rhs ) {
- fChild = rhs.fChild;
- }
-
-
- TFileTreeIterator::~TFileTreeIterator () {
- if ( fChild != NULL )
- delete fChild;
- }
-
-
- TFileTreeIterator& TFileTreeIterator::operator= ( TFileTreeIterator& rhs ) {
-
- // Check for assignment to self
- if ( &rhs == this )
- return *this;
-
- // Let the superclass deal with its bits
- * (TDirectoryIterator *) this = * (TDirectoryIterator *) &rhs;
-
- // Do our work
- fChild = rhs.fChild;
- return *this;
- }
-
-
- void TFileTreeIterator::Start ( void ) {
- if ( fChild != NULL ) {
- delete fChild;
- fChild = NULL;
- }
-
- TDirectoryIterator::Start ();
- }
-
-
- Boolean TFileTreeIterator::More ( void ) {
- Boolean retVal = false;
-
- if ( fChild != NULL ) {
- retVal = fChild->More ();
- if ( !retVal ) {
- delete fChild;
- fChild = NULL;
- }
- }
-
- if ( !retVal )
- retVal = TDirectoryIterator::More ();
-
- return retVal;
- }
-
-
- OSErr TFileTreeIterator::Next ( FSSpec *theSpec, Boolean *isFolder ) {
- OSErr err = noErr;
- Boolean fold;
-
- if ( isFolder == NULL )
- isFolder = &fold;
-
- while ( err == noErr ) {
- if ( fChild != NULL )
- err = fChild->Next ( theSpec, isFolder );
- else {
- // Get the next item
- err = GetNextItem ( theSpec, isFolder );
- if ( err == noErr ) {
- // If the thing is invisible and the caller asked for visible, try again
- if (( fOptions & kJustVisible ) != 0 &&
- ( fPb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible ) != 0 )
- continue;
-
- // If we've found a directory, then spawn a new object
- if ( err == noErr && *isFolder ) {
- fChild = new TFileTreeIterator ( theSpec, fOptions );
- // AssertStr ( fChild != NULL, "\pCan't allocate new iterator in TFileTreeIterator::Next" );
- fChild->Start ();
- }
- }
- }
-
- // If we said just files, and we've got a folder, try again
- if ( !*isFolder || ( fOptions & kJustFiles ) == 0 )
- break;
- }
-
- // ReportError ( err );
- return err;
- }
-