Files
itgmania212121/stepmania/src/RageUtil_FileDB.cpp
T

624 lines
16 KiB
C++
Raw Normal View History

2003-07-03 02:41:27 +00:00
#include "global.h"
#include "RageUtil_FileDB.h"
#include "RageUtil.h"
#include "RageLog.h"
/* Search for "beginning*containing*ending". */
2005-12-28 03:09:53 +00:00
void FileSet::GetFilesMatching( const RString &sBeginning_, const RString &sContaining_, const RString &sEnding_, vector<RString> &asOut, bool bOnlyDirs ) const
2003-07-03 02:41:27 +00:00
{
2003-10-19 22:20:56 +00:00
/* "files" is a case-insensitive mapping, by filename. Use lower_bound to figure
* out where to start. */
2005-12-28 03:09:53 +00:00
RString sBeginning = sBeginning_;
2005-09-03 19:00:27 +00:00
sBeginning.ToLower();
2005-12-28 03:09:53 +00:00
RString sContaining = sContaining_;
2005-09-03 19:00:27 +00:00
sContaining.ToLower();
2005-12-28 03:09:53 +00:00
RString sEnding = sEnding_;
2005-09-03 19:00:27 +00:00
sEnding.ToLower();
2005-09-03 18:40:21 +00:00
set<File>::const_iterator i = files.lower_bound( File(sBeginning) );
for( ; i != files.end(); ++i )
2003-07-03 02:41:27 +00:00
{
const File &f = *i;
if( bOnlyDirs && !f.dir )
continue;
2003-07-03 02:41:27 +00:00
2005-12-28 03:09:53 +00:00
const RString &sPath = f.lname;
2005-09-03 19:00:27 +00:00
2005-09-03 18:40:21 +00:00
/* Check sBeginning. Once we hit a filename that no longer matches sBeginning,
2003-10-19 22:20:56 +00:00
* we're past all possible matches in the sort, so stop. */
2005-09-03 19:00:27 +00:00
if( sBeginning.size() > sPath.size() )
break; /* can't start with it */
2005-09-03 19:00:27 +00:00
if( sPath.compare(0, sBeginning.size(), sBeginning) )
break; /* doesn't start with it */
2003-07-03 02:41:27 +00:00
/* Position the end starts on: */
2005-09-03 19:00:27 +00:00
int end_pos = int(sPath.size())-int(sEnding.size());
2003-07-03 02:41:27 +00:00
/* Check end. */
if( end_pos < 0 )
continue; /* can't end with it */
2005-09-03 19:00:27 +00:00
if( sPath.compare(end_pos, string::npos, sEnding) )
continue; /* doesn't end with it */
2003-07-03 02:41:27 +00:00
2005-09-03 18:40:21 +00:00
/* Check sContaining. Do this last, since it's the slowest (substring
2003-07-03 02:41:27 +00:00
* search instead of string match). */
2005-09-03 19:00:27 +00:00
if( !sContaining.empty() )
2003-07-03 02:41:27 +00:00
{
2005-09-03 19:00:27 +00:00
size_t pos = sPath.find( sContaining, sBeginning.size() );
if( pos == sPath.npos )
continue; /* doesn't contain it */
2005-09-03 18:40:21 +00:00
if( pos + sContaining.size() > unsigned(end_pos) )
continue; /* found it but it overlaps with the end */
2003-07-03 02:41:27 +00:00
}
2005-09-03 18:40:21 +00:00
asOut.push_back( f.name );
2003-07-03 02:41:27 +00:00
}
}
2005-12-28 03:09:53 +00:00
void FileSet::GetFilesEqualTo( const RString &sStr, vector<RString> &asOut, bool bOnlyDirs ) const
2003-07-03 02:41:27 +00:00
{
2005-09-03 18:40:21 +00:00
set<File>::const_iterator i = files.find( File(sStr) );
if( i == files.end() )
2003-07-03 02:41:27 +00:00
return;
2005-09-03 18:40:21 +00:00
if( bOnlyDirs && !i->dir )
2003-07-03 02:41:27 +00:00
return;
2005-09-03 18:40:21 +00:00
asOut.push_back( i->name );
2003-07-03 02:41:27 +00:00
}
2005-12-28 03:09:53 +00:00
RageFileManager::FileType FileSet::GetFileType( const RString &sPath ) const
2003-07-03 02:41:27 +00:00
{
2005-09-03 18:40:21 +00:00
set<File>::const_iterator i = files.find( File(sPath) );
if( i == files.end() )
2004-01-06 05:44:28 +00:00
return RageFileManager::TYPE_NONE;
2003-07-03 02:41:27 +00:00
2004-01-06 05:44:28 +00:00
return i->dir? RageFileManager::TYPE_DIR:RageFileManager::TYPE_FILE;
2003-07-03 02:41:27 +00:00
}
2005-12-28 03:09:53 +00:00
int FileSet::GetFileSize( const RString &sPath ) const
2003-09-22 05:14:00 +00:00
{
2005-09-03 18:40:21 +00:00
set<File>::const_iterator i = files.find( File(sPath) );
if( i == files.end() )
2003-09-22 05:14:00 +00:00
return -1;
return i->size;
}
2005-12-28 03:09:53 +00:00
int FileSet::GetFileHash( const RString &sPath ) const
2003-09-23 00:09:10 +00:00
{
2005-09-03 18:40:21 +00:00
set<File>::const_iterator i = files.find( File(sPath) );
if( i == files.end() )
2003-09-23 00:09:10 +00:00
return -1;
2003-12-10 07:07:42 +00:00
return i->hash + i->size;
2003-09-23 00:09:10 +00:00
}
2003-12-11 07:24:32 +00:00
/*
* Given "foo/bar/baz/" or "foo/bar/baz", return "foo/bar/" and "baz".
* "foo" -> "", "foo"
*/
2005-12-28 03:09:53 +00:00
static void SplitPath( RString sPath, RString &sDir, RString &sName )
2003-07-03 02:41:27 +00:00
{
2005-09-03 18:40:21 +00:00
CollapsePath( sPath );
if( sPath.Right(1) == "/" )
sPath.erase( sPath.size()-1 );
2003-09-06 22:55:20 +00:00
2005-09-03 18:40:21 +00:00
size_t iSep = sPath.find_last_of( '/' );
2005-12-28 03:09:53 +00:00
if( iSep == RString::npos )
2003-12-11 07:24:32 +00:00
{
2005-09-03 18:40:21 +00:00
sDir = "";
sName = sPath;
2003-07-03 02:41:27 +00:00
}
2003-12-11 07:24:32 +00:00
else
{
2005-09-03 18:40:21 +00:00
sDir = sPath.substr( 0, iSep+1 );
sName = sPath.substr( iSep+1 );
2003-12-11 07:24:32 +00:00
}
2003-07-03 02:41:27 +00:00
}
2005-12-28 03:09:53 +00:00
RageFileManager::FileType FilenameDB::GetFileType( const RString &sPath )
2003-07-03 02:41:27 +00:00
{
ASSERT( !m_Mutex.IsLockedByThisThread() );
2005-12-28 03:09:53 +00:00
RString sDir, sName;
2005-09-03 18:40:21 +00:00
SplitPath( sPath, sDir, sName );
2003-12-15 02:40:41 +00:00
2005-09-03 18:40:21 +00:00
if( sName == "/" )
2004-01-06 05:44:28 +00:00
return RageFileManager::TYPE_DIR;
2003-12-15 02:40:41 +00:00
2005-09-03 18:40:21 +00:00
const FileSet *fs = GetFileSet( sDir );
RageFileManager::FileType ret = fs->GetFileType( sName );
m_Mutex.Unlock(); /* locked by GetFileSet */
return ret;
2003-07-03 02:41:27 +00:00
}
2005-12-28 03:09:53 +00:00
int FilenameDB::GetFileSize( const RString &sPath )
2003-09-22 05:14:00 +00:00
{
ASSERT( !m_Mutex.IsLockedByThisThread() );
2005-12-28 03:09:53 +00:00
RString sDir, sName;
2005-09-03 18:40:21 +00:00
SplitPath( sPath, sDir, sName );
2005-09-03 18:40:21 +00:00
const FileSet *fs = GetFileSet( sDir );
int ret = fs->GetFileSize( sName );
m_Mutex.Unlock(); /* locked by GetFileSet */
return ret;
2003-09-22 05:14:00 +00:00
}
2005-12-28 03:09:53 +00:00
int FilenameDB::GetFileHash( const RString &sPath )
2003-09-23 00:09:10 +00:00
{
ASSERT( !m_Mutex.IsLockedByThisThread() );
2005-12-28 03:09:53 +00:00
RString sDir, sName;
2005-09-03 18:40:21 +00:00
SplitPath( sPath, sDir, sName );
2005-09-03 18:40:21 +00:00
const FileSet *fs = GetFileSet( sDir );
int ret = fs->GetFileHash( sName );
m_Mutex.Unlock(); /* locked by GetFileSet */
return ret;
2003-09-23 00:09:10 +00:00
}
2003-07-03 02:41:27 +00:00
/* path should be fully collapsed, so we can operate in-place: no . or .. */
2005-12-28 03:09:53 +00:00
bool FilenameDB::ResolvePath( RString &sPath )
2003-07-03 02:41:27 +00:00
{
2005-09-03 18:40:21 +00:00
if( sPath == "/" || sPath == "" )
2004-02-27 05:49:24 +00:00
return true;
2003-07-03 02:41:27 +00:00
/* Split path into components. */
2005-09-03 18:40:21 +00:00
int iBegin = 0, iSize = -1;
2003-07-03 02:41:27 +00:00
2003-12-15 02:40:41 +00:00
/* Resolve each component. */
2005-12-28 03:09:53 +00:00
RString ret = "";
2004-08-30 04:49:57 +00:00
const FileSet *fs = NULL;
2005-12-28 03:09:53 +00:00
static const RString slash("/");
2003-12-15 05:36:27 +00:00
while( 1 )
2003-07-03 02:41:27 +00:00
{
2005-09-03 18:40:21 +00:00
split( sPath, slash, iBegin, iSize, true );
if( iBegin == (int) sPath.size() )
2003-12-15 05:36:27 +00:00
break;
if( fs == NULL )
2003-12-16 07:22:43 +00:00
fs = GetFileSet( ret );
else
m_Mutex.Lock(); /* for access to fs */
2003-07-03 02:41:27 +00:00
2005-12-28 03:09:53 +00:00
RString p = sPath.substr( iBegin, iSize );
2005-09-03 18:40:21 +00:00
ASSERT_M( p.size() != 1 || p[0] != '.', sPath ); // no .
ASSERT_M( p.size() != 2 || p[0] != '.' || p[1] != '.', sPath ); // no ..
2004-08-30 04:49:57 +00:00
set<File>::const_iterator it = fs->files.find( File(p) );
2003-07-03 02:41:27 +00:00
/* If there were no matches, the path isn't found. */
2003-12-15 05:36:27 +00:00
if( it == fs->files.end() )
{
m_Mutex.Unlock(); /* locked by GetFileSet */
2003-12-15 05:36:27 +00:00
return false;
}
2003-07-03 02:41:27 +00:00
ret += "/" + it->name;
2003-07-03 02:41:27 +00:00
2003-12-15 05:36:27 +00:00
fs = it->dirp;
m_Mutex.Unlock(); /* locked by GetFileSet */
2003-12-15 05:36:27 +00:00
}
2005-09-03 18:40:21 +00:00
if( sPath.size() && sPath[sPath.size()-1] == '/' )
sPath = ret + "/";
2003-07-03 02:41:27 +00:00
else
2005-09-03 18:40:21 +00:00
sPath = ret;
2003-07-03 02:41:27 +00:00
return true;
}
2005-12-28 03:09:53 +00:00
void FilenameDB::GetFilesMatching( const RString &sDir, const RString &sBeginning, const RString &sContaining, const RString &sEnding, vector<RString> &asOut, bool bOnlyDirs )
2003-07-03 02:41:27 +00:00
{
ASSERT( !m_Mutex.IsLockedByThisThread() );
2005-09-03 18:40:21 +00:00
const FileSet *fs = GetFileSet( sDir );
fs->GetFilesMatching( sBeginning, sContaining, sEnding, asOut, bOnlyDirs );
m_Mutex.Unlock(); /* locked by GetFileSet */
2003-07-03 02:41:27 +00:00
}
2005-12-28 03:09:53 +00:00
void FilenameDB::GetFilesEqualTo( const RString &sDir, const RString &sFile, vector<RString> &asOut, bool bOnlyDirs )
2003-07-03 02:41:27 +00:00
{
ASSERT( !m_Mutex.IsLockedByThisThread() );
2005-09-03 18:40:21 +00:00
const FileSet *fs = GetFileSet( sDir );
fs->GetFilesEqualTo( sFile, asOut, bOnlyDirs );
m_Mutex.Unlock(); /* locked by GetFileSet */
2003-07-03 02:41:27 +00:00
}
2005-12-28 03:09:53 +00:00
void FilenameDB::GetFilesSimpleMatch( const RString &sDir, const RString &sMask, vector<RString> &asOut, bool bOnlyDirs )
2003-07-03 02:41:27 +00:00
{
/* Does this contain a wildcard? */
2005-11-02 15:45:45 +00:00
size_t first_pos = sMask.find_first_of( '*' );
2005-09-03 18:40:21 +00:00
if( first_pos == sMask.npos )
2003-07-03 02:41:27 +00:00
{
/* No; just do a regular search. */
2005-09-03 18:40:21 +00:00
GetFilesEqualTo( sDir, sMask, asOut, bOnlyDirs );
2005-11-02 15:45:45 +00:00
return;
2005-09-03 18:40:21 +00:00
}
2005-11-02 15:45:45 +00:00
size_t second_pos = sMask.find_first_of( '*', first_pos+1 );
if( second_pos == sMask.npos )
2005-09-03 18:40:21 +00:00
{
2005-11-02 15:45:45 +00:00
/* Only one *: "A*B". */
/* XXX: "_blank.png*.png" shouldn't match the file "_blank.png". */
2005-12-28 03:09:53 +00:00
GetFilesMatching( sDir, sMask.substr(0, first_pos), RString(), sMask.substr(first_pos+1), asOut, bOnlyDirs );
2005-11-02 15:45:45 +00:00
return;
2003-07-03 02:41:27 +00:00
}
2005-11-02 15:45:45 +00:00
/* Two *s: "A*B*C". */
GetFilesMatching( sDir,
sMask.substr(0, first_pos),
sMask.substr(first_pos+1, second_pos-first_pos-1),
sMask.substr(second_pos+1), asOut, bOnlyDirs );
2003-07-03 02:41:27 +00:00
}
/*
* Get the FileSet for dir; if create is true, create the FileSet if necessary.
*
* We want to unlock the object while we populate FileSets, so m_Mutex should not
* be locked when this is called. It will be locked on return; the caller must
* unlock it.
*/
2005-12-28 03:09:53 +00:00
FileSet *FilenameDB::GetFileSet( const RString &sDir_, bool bCreate )
2003-07-03 02:41:27 +00:00
{
2005-12-28 03:09:53 +00:00
RString sDir = sDir_;
/* Creating can take a long time; don't hold the lock if we might do that. */
2005-09-03 18:40:21 +00:00
if( bCreate && m_Mutex.IsLockedByThisThread() && LOG )
LOG->Warn( "FilenameDB::GetFileSet: m_Mutex was locked" );
2003-07-03 02:41:27 +00:00
/* Normalize the path. */
2005-09-03 18:40:21 +00:00
sDir.Replace("\\", "/"); /* foo\bar -> foo/bar */
sDir.Replace("//", "/"); /* foo//bar -> foo/bar */
2003-12-07 04:14:52 +00:00
2005-09-03 18:40:21 +00:00
if( sDir == "" )
sDir = "/";
2003-12-11 07:24:32 +00:00
2005-12-28 03:09:53 +00:00
RString sLower = sDir;
2005-09-03 18:40:21 +00:00
sLower.MakeLower();
2003-07-03 02:41:27 +00:00
m_Mutex.Lock();
while(1)
2003-12-16 07:22:43 +00:00
{
/* Look for the directory. */
2005-12-28 03:09:53 +00:00
map<RString, FileSet *>::iterator i = dirs.find( sLower );
2005-09-03 18:40:21 +00:00
if( !bCreate )
{
if( i == dirs.end() )
return NULL;
return i->second;
}
/* We're allowed to create. If the directory wasn't found, break out and
* create it. */
2003-12-16 07:22:43 +00:00
if( i == dirs.end() )
break;
2003-12-16 07:22:43 +00:00
/* This directory already exists. If it's still being filled in by another
* thread, wait for it. */
FileSet *pFileSet = i->second;
if( !pFileSet->m_bFilled )
{
m_Mutex.Wait();
/* Beware: when we unlock m_Mutex to wait for it to finish filling,
* we give up our claim to dirs, so i may be invalid. Start over
* and re-search. */
continue;
}
if( ExpireSeconds == -1 || pFileSet->age.PeekDeltaTime() < ExpireSeconds )
{
/* Found it, and it hasn't expired. */
return pFileSet;
}
/* It's expired. Delete the old entry. */
this->DelFileSet( i );
break;
2004-08-31 09:35:12 +00:00
}
2004-09-05 04:12:42 +00:00
2004-11-12 23:16:08 +00:00
/* Create the FileSet and insert it. Set it to !m_bFilled, so if other threads
* happen to try to use this directory before we finish filling it, they'll wait. */
2005-09-03 18:40:21 +00:00
FileSet *pRet = new FileSet;
pRet->m_bFilled = false;
dirs[sLower] = pRet;
2004-09-05 04:12:42 +00:00
/* Unlock while we populate the directory. This way, reads to other directories
* won't block if this takes a while. */
m_Mutex.Unlock();
ASSERT( !m_Mutex.IsLockedByThisThread() );
2005-09-03 18:40:21 +00:00
PopulateFileSet( *pRet, sDir );
/* If this isn't the root directory, we want to set the dirp pointer of our parent
* to the newly-created directory. Find the pointer we need to set. Be careful of
* order of operations, here: since we just unlocked, any this->dirs searches we did
* previously are no longer valid. */
2005-09-03 18:40:21 +00:00
FileSet **pParentDirp = NULL;
if( sDir != "/" )
{
2005-12-28 03:09:53 +00:00
RString sParent = Dirname( sDir );
if( sParent == "./" )
sParent = "";
/* This also re-locks m_Mutex for us. */
FileSet *pParent = GetFileSet( sParent );
if( pParent != NULL )
{
2005-09-03 18:40:21 +00:00
set<File>::iterator it = pParent->files.find( File(Basename(sDir)) );
if( it != pParent->files.end() )
2005-09-03 18:40:21 +00:00
pParentDirp = const_cast<FileSet **>(&it->dirp);
}
2003-07-03 02:41:27 +00:00
}
else
2006-01-05 07:35:27 +00:00
{
m_Mutex.Lock();
2006-01-05 07:35:27 +00:00
}
2005-09-03 18:40:21 +00:00
if( pParentDirp != NULL )
*pParentDirp = pRet;
2005-09-03 18:40:21 +00:00
pRet->age.Touch();
pRet->m_bFilled = true;
/* Signal the event, to wake up any other threads that might be waiting for this
* directory. Leave the mutex locked; those threads will wake up when the current
* operation completes. */
m_Mutex.Broadcast();
2003-07-03 02:41:27 +00:00
2005-09-03 18:40:21 +00:00
return pRet;
2003-07-03 02:41:27 +00:00
}
2003-12-08 00:04:47 +00:00
/* Add the file or directory "sPath". sPath is a directory if it ends with
* a slash. */
2005-12-28 03:09:53 +00:00
void FilenameDB::AddFile( const RString &sPath_, int iSize, int iHash, void *pPriv )
2003-12-08 00:04:47 +00:00
{
2005-12-28 03:09:53 +00:00
RString sPath(sPath_);
if( sPath == "" || sPath == "/" )
2004-04-22 20:17:27 +00:00
return;
if( sPath[0] != '/' )
sPath = "/" + sPath;
2005-12-28 03:09:53 +00:00
vector<RString> asParts;
2005-09-03 18:40:21 +00:00
split( sPath, "/", asParts, false );
2003-12-08 00:04:47 +00:00
2005-12-28 03:09:53 +00:00
vector<RString>::const_iterator begin = asParts.begin();
vector<RString>::const_iterator end = asParts.end();
2003-12-08 00:04:47 +00:00
bool IsDir = true;
if( sPath[sPath.size()-1] != '/' )
IsDir = false;
else
--end;
/* Skip the leading slash. */
++begin;
2003-12-08 00:04:47 +00:00
do
{
/* Combine all but the last part. */
2005-12-28 03:09:53 +00:00
RString dir = "/" + join( "/", begin, end-1 );
if( dir != "/" )
2004-02-11 20:36:48 +00:00
dir += "/";
2005-12-28 03:09:53 +00:00
const RString &fn = *(end-1);
2003-12-16 07:22:43 +00:00
FileSet *fs = GetFileSet( dir );
ASSERT( m_Mutex.IsLockedByThisThread() );
2003-12-08 00:04:47 +00:00
File f;
f.SetName( fn );
2003-12-16 07:22:43 +00:00
if( fs->files.find( f ) == fs->files.end() )
2003-12-08 00:04:47 +00:00
{
f.dir = IsDir;
if( !IsDir )
{
2005-09-03 18:40:21 +00:00
f.size = iSize;
f.hash = iHash;
f.priv = pPriv;
}
2003-12-16 07:22:43 +00:00
fs->files.insert( f );
2003-12-08 00:04:47 +00:00
}
m_Mutex.Unlock(); /* locked by GetFileSet */
2003-12-08 00:04:47 +00:00
IsDir = true;
--end;
} while( begin != end );
}
2004-09-05 03:49:45 +00:00
/* Remove the given FileSet, and all dirp pointers to it. This means the cache has
* expired, not that the directory is necessarily gone; don't actually delete the file
* from the parent. */
2005-12-28 03:09:53 +00:00
void FilenameDB::DelFileSet( map<RString, FileSet *>::iterator dir )
2003-12-16 07:22:43 +00:00
{
/* If this isn't locked, dir may not be valid. */
ASSERT( m_Mutex.IsLockedByThisThread() );
2004-09-05 03:49:45 +00:00
if( dir == dirs.end() )
return;
2003-12-16 07:22:43 +00:00
2004-09-05 03:49:45 +00:00
FileSet *fs = dir->second;
2003-12-16 07:22:43 +00:00
2004-09-05 03:49:45 +00:00
/* Remove any stale dirp pointers. */
2005-12-28 03:09:53 +00:00
for( map<RString, FileSet *>::iterator it = dirs.begin(); it != dirs.end(); ++it )
2004-09-05 03:49:45 +00:00
{
FileSet *Clean = it->second;
for( set<File>::iterator f = Clean->files.begin(); f != Clean->files.end(); ++f )
2003-12-16 07:22:43 +00:00
{
2004-09-05 03:49:45 +00:00
File &ff = (File &) *f;
if( ff.dirp == fs )
ff.dirp = NULL;
2003-12-16 07:22:43 +00:00
}
}
2004-09-05 03:49:45 +00:00
delete fs;
dirs.erase( dir );
}
2005-12-28 03:09:53 +00:00
void FilenameDB::DelFile( const RString &sPath )
2004-09-05 03:49:45 +00:00
{
LockMut(m_Mutex);
2005-12-28 03:09:53 +00:00
RString lower = sPath;
2004-09-05 03:49:45 +00:00
lower.MakeLower();
2005-12-28 03:09:53 +00:00
map<RString, FileSet *>::iterator fsi = dirs.find( lower );
2004-09-05 03:49:45 +00:00
DelFileSet( fsi );
2003-12-16 07:22:43 +00:00
/* Delete sPath from its parent. */
2005-12-28 03:09:53 +00:00
RString Dir, Name;
2003-12-16 07:22:43 +00:00
SplitPath(sPath, Dir, Name);
FileSet *Parent = GetFileSet( Dir, false );
if( Parent )
{
set<File>::iterator i = Parent->files.find( File(Name) );
if( i != Parent->files.end() )
{
Parent->files.erase( i );
}
}
m_Mutex.Unlock(); /* locked by GetFileSet */
2003-12-16 07:22:43 +00:00
}
2003-07-03 02:41:27 +00:00
void FilenameDB::FlushDirCache()
{
while(1)
{
m_Mutex.Lock();
if( dirs.empty() )
{
m_Mutex.Unlock();
break;
}
/* Grab the first entry. Take it out of the list while we hold the
* lock, to guarantee that we own it. */
FileSet *pFileSet = dirs.begin()->second;
dirs.erase( dirs.begin() );
/* If it's being filled, we don't really own it until it's finished being
* filled, so wait. */
while( !pFileSet->m_bFilled )
m_Mutex.Wait();
m_Mutex.Unlock();
delete pFileSet;
}
2003-07-03 02:41:27 +00:00
}
2005-12-28 03:09:53 +00:00
const File *FilenameDB::GetFile( const RString &sPath )
{
if( m_Mutex.IsLockedByThisThread() && LOG )
LOG->Warn( "FilenameDB::GetFile: m_Mutex was locked" );
2005-12-28 03:09:53 +00:00
RString Dir, Name;
SplitPath(sPath, Dir, Name);
2003-12-16 07:22:43 +00:00
FileSet *fs = GetFileSet( Dir );
2003-12-10 07:27:18 +00:00
set<File>::iterator it;
2003-12-16 07:22:43 +00:00
it = fs->files.find( File(Name) );
if( it == fs->files.end() )
return NULL;
2003-12-10 07:27:18 +00:00
/* Oops. &*it is a const File &, because you can't change the order
* of something once it's in a list. Cast away the const; we won't
* change the filename (used for the ordering), but the rest of the
* values are non-const. */
return const_cast<File *> (&*it);
}
2005-12-28 03:09:53 +00:00
const void *FilenameDB::GetFilePriv( const RString &path )
2004-09-05 03:40:19 +00:00
{
ASSERT( !m_Mutex.IsLockedByThisThread() );
2004-09-05 03:40:19 +00:00
const File *pFile = GetFile( path );
void *pRet = NULL;
if( pFile != NULL )
pRet = pFile->priv;
m_Mutex.Unlock(); /* locked by GetFileSet */
2004-09-05 03:40:19 +00:00
return pRet;
}
2003-07-03 02:41:27 +00:00
2005-12-28 03:09:53 +00:00
void FilenameDB::GetDirListing( const RString &sPath_, vector<RString> &asAddTo, bool bOnlyDirs, bool bReturnPathToo )
2003-07-03 02:41:27 +00:00
{
2005-12-28 03:09:53 +00:00
RString sPath = sPath_;
2003-07-22 07:47:27 +00:00
// LOG->Trace( "GetDirListing( %s )", sPath.c_str() );
2005-09-03 18:40:21 +00:00
ASSERT( !sPath.empty() );
2003-07-03 02:41:27 +00:00
/* Strip off the last path element and use it as a mask. */
2004-06-16 07:01:12 +00:00
size_t pos = sPath.find_last_of( '/' );
2005-12-28 03:09:53 +00:00
RString fn;
2003-12-18 08:48:36 +00:00
if( pos == sPath.npos )
2003-07-03 02:41:27 +00:00
{
2003-12-18 08:48:36 +00:00
fn = sPath;
sPath = "";
2005-09-03 18:40:21 +00:00
}
else
{
2003-07-03 02:41:27 +00:00
fn = sPath.substr(pos+1);
sPath = sPath.substr(0, pos+1);
}
2003-12-18 08:48:36 +00:00
/* If the last element was empty, use "*". */
if( fn.size() == 0 )
2003-07-03 02:41:27 +00:00
fn = "*";
2005-09-03 18:40:21 +00:00
unsigned iStart = asAddTo.size();
GetFilesSimpleMatch( sPath, fn, asAddTo, bOnlyDirs );
2003-07-03 02:41:27 +00:00
2005-09-03 18:40:21 +00:00
if( bReturnPathToo && iStart < asAddTo.size() )
2003-07-03 02:41:27 +00:00
{
2005-09-03 18:40:21 +00:00
while( iStart < asAddTo.size() )
2003-07-03 02:41:27 +00:00
{
2005-09-03 18:42:28 +00:00
asAddTo[iStart].insert( 0, sPath );
2005-09-03 18:40:21 +00:00
iStart++;
2003-07-03 02:41:27 +00:00
}
}
}
2005-01-27 02:00:55 +00:00
/* Get a complete copy of a FileSet. This isn't very efficient, since it's a deep
* copy, but allows retrieving a copy from elsewhere without having to worry about
* our locking semantics. */
2005-12-28 03:09:53 +00:00
void FilenameDB::GetFileSetCopy( const RString &sDir, FileSet &out )
2005-01-27 02:00:55 +00:00
{
FileSet *pFileSet = GetFileSet( sDir );
out = *pFileSet;
m_Mutex.Unlock(); /* locked by GetFileSet */
}
2004-05-06 02:40:33 +00:00
/*
* Copyright (c) 2003-2004 Glenn Maynard
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, provided that the above
* copyright notice(s) and this permission notice appear in all copies of
* the Software and that both the above copyright notice(s) and this
* permission notice appear in supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/