// GetExtraOutputPath //------------------------------------------------------------------------------ void FunctionObjectList::GetExtraOutputPath( const AString * it, const AString * end, const char * option, AString & path ) const { const char * bodyStart = it->Get() + strlen( option ) + 1; // +1 for - or / const char * bodyEnd = it->GetEnd(); // if token is exactly matched then value is next token if ( bodyStart == bodyEnd ) { ++it; // handle missing next value if ( it == end ) { return; // we just pretend it doesn't exist and let the compiler complain } bodyStart = it->Get(); bodyEnd = it->GetEnd(); } // Strip quotes Args::StripQuotes( bodyStart, bodyEnd, path ); // If it's not already a path (i.e. includes filename.ext) then // truncate to just the path const char * lastSlash = path.FindLast( '\\' ); lastSlash = lastSlash ? lastSlash : path.FindLast( '/' ); lastSlash = lastSlash ? lastSlash : path.Get(); // no slash, means it's just a filename if ( lastSlash != ( path.GetEnd() - 1 ) ) { path.SetLength( uint32_t(lastSlash - path.Get()) ); } }
// GetCodeDir //------------------------------------------------------------------------------ void FBuildTest::GetCodeDir( AString & codeDir ) const { // we want the working dir to be the 'Code' directory TEST_ASSERT( FileIO::GetCurrentDir( codeDir ) ); #if defined( __WINDOWS__ ) const char * codePos = codeDir.FindI( "\\code\\" ); #else const char * codePos = codeDir.FindI( "/code/" ); #endif TEST_ASSERT( codePos ); codeDir.SetLength( (uint16_t)( codePos - codeDir.Get() + 6 ) ); }
// GetEnvVariable //------------------------------------------------------------------------------ /*static*/ bool Env::GetEnvVariable( const char * envVarName, AString & envVarValue ) { #if defined( __WINDOWS__ ) // try to get the env variable into whatever storage we have available uint32_t maxSize = envVarValue.GetReserved(); DWORD ret = ::GetEnvironmentVariable( envVarName, envVarValue.Get(), maxSize ); // variable does not exist if ( ret == 0 ) { return false; } // variable exists - was there enough space? if ( ret > maxSize ) { // not enough space, allocate enough envVarValue.SetReserved( ret ); maxSize = envVarValue.GetReserved(); ret = ::GetEnvironmentVariable( envVarName, envVarValue.Get(), maxSize ); ASSERT( ret <= maxSize ); // should have fit } // make string aware of valid buffer length as populated by ::GetEnvironmentVariable envVarValue.SetLength( ret ); return true; #elif defined( __LINUX__ ) || defined( __APPLE__ ) const char * envVar = ::getenv( envVarName ); if ( envVar ) { envVarValue = envVar; return true; } return false; #else #error Unknown platform #endif }
// GetFilesRecurse //------------------------------------------------------------------------------ /*static*/ void FileIO::GetFilesRecurseEx( AString & pathCopy, const Array< AString > * patterns, Array< FileInfo > * results ) { const uint32_t baseLength = pathCopy.GetLength(); #if defined( __WINDOWS__ ) pathCopy += '*'; // don't want to use wildcard to filter folders // recurse into directories WIN32_FIND_DATA findData; HANDLE hFind = FindFirstFileEx( pathCopy.Get(), FindExInfoBasic, &findData, FindExSearchLimitToDirectories, nullptr, 0 ); if ( hFind == INVALID_HANDLE_VALUE) { return; } do { if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { // ignore magic '.' and '..' folders // (don't need to check length of name, as all names are at least 1 char // which means index 0 and 1 are valid to access) if ( findData.cFileName[ 0 ] == '.' && ( ( findData.cFileName[ 1 ] == '.' ) || ( findData.cFileName[ 1 ] == '\000' ) ) ) { continue; } pathCopy.SetLength( baseLength ); pathCopy += findData.cFileName; pathCopy += NATIVE_SLASH; GetFilesRecurseEx( pathCopy, patterns, results ); } } while ( FindNextFile( hFind, &findData ) != 0 ); FindClose( hFind ); // do files in this directory pathCopy.SetLength( baseLength ); pathCopy += '*'; hFind = FindFirstFileEx( pathCopy.Get(), FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, 0 ); if ( hFind == INVALID_HANDLE_VALUE) { return; } do { if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { continue; } if ( IsMatch( patterns, findData.cFileName ) ) { pathCopy.SetLength( baseLength ); pathCopy += findData.cFileName; if ( results->GetSize() == results->GetCapacity() ) { results->SetCapacity( results->GetSize() * 2 ); } results->SetSize( results->GetSize() + 1 ); FileInfo & newInfo = results->Top(); newInfo.m_Name = pathCopy; newInfo.m_Attributes = findData.dwFileAttributes; newInfo.m_LastWriteTime = (uint64_t)findData.ftLastWriteTime.dwLowDateTime | ( (uint64_t)findData.ftLastWriteTime.dwHighDateTime << 32 ); newInfo.m_Size = (uint64_t)findData.nFileSizeLow | ( (uint64_t)findData.nFileSizeHigh << 32 ); } } while ( FindNextFile( hFind, &findData ) != 0 ); FindClose( hFind ); #elif defined( __LINUX__ ) || defined( __APPLE__ ) DIR * dir = opendir( pathCopy.Get() ); if ( dir == nullptr ) { return; } for ( ;; ) { dirent * entry = readdir( dir ); if ( entry == nullptr ) { break; // no more entries } // dir? if ( ( entry->d_type & DT_DIR ) == DT_DIR ) { // ignore . and .. if ( entry->d_name[ 0 ] == '.' ) { if ( ( entry->d_name[ 1 ] == 0 ) || ( ( entry->d_name[ 1 ] == '.' ) && ( entry->d_name[ 2 ] == 0 ) ) ) { continue; } } // regular dir pathCopy.SetLength( baseLength ); pathCopy += entry->d_name; pathCopy += NATIVE_SLASH; GetFilesRecurseEx( pathCopy, patterns, results ); continue; } // file - does it match wildcard? if ( IsMatch( patterns, entry->d_name ) ) { pathCopy.SetLength( baseLength ); pathCopy += entry->d_name; if ( results->GetSize() == results->GetCapacity() ) { results->SetCapacity( results->GetSize() * 2 ); } results->SetSize( results->GetSize() + 1 ); FileInfo & newInfo = results->Top(); newInfo.m_Name = pathCopy; // get additional info struct stat info; VERIFY( stat( pathCopy.Get(), &info ) == 0 ); newInfo.m_Attributes = info.st_mode; #if defined( __APPLE__ ) newInfo.m_LastWriteTime = ( ( (uint64_t)info.st_mtimespec.tv_sec * 1000000000ULL ) + (uint64_t)info.st_mtimespec.tv_nsec ); #else newInfo.m_LastWriteTime = ( ( (uint64_t)info.st_mtim.tv_sec * 1000000000ULL ) + (uint64_t)info.st_mtim.tv_nsec ); #endif newInfo.m_Size = info.st_size; } } closedir( dir ); #else #error Unknown platform #endif }
// GetFilesRecurse //------------------------------------------------------------------------------ /*static*/ void FileIO::GetFilesRecurse( AString & pathCopy, const AString & wildCard, Array< AString > * results ) { const uint32_t baseLength = pathCopy.GetLength(); #if defined( __WINDOWS__ ) pathCopy += '*'; // don't want to use wildcard to filter folders // recurse into directories WIN32_FIND_DATA findData; HANDLE hFind = FindFirstFileEx( pathCopy.Get(), FindExInfoBasic, &findData, FindExSearchLimitToDirectories, nullptr, 0 ); if ( hFind == INVALID_HANDLE_VALUE) { return; } do { if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { // ignore magic '.' and '..' folders // (don't need to check length of name, as all names are at least 1 char // which means index 0 and 1 are valid to access) if ( findData.cFileName[ 0 ] == '.' && ( ( findData.cFileName[ 1 ] == '.' ) || ( findData.cFileName[ 1 ] == '\000' ) ) ) { continue; } pathCopy.SetLength( baseLength ); pathCopy += findData.cFileName; pathCopy += NATIVE_SLASH; GetFilesRecurse( pathCopy, wildCard, results ); } } while ( FindNextFile( hFind, &findData ) != 0 ); FindClose( hFind ); // do files in this directory pathCopy.SetLength( baseLength ); pathCopy += '*'; hFind = FindFirstFileEx( pathCopy.Get(), FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, 0 ); if ( hFind == INVALID_HANDLE_VALUE) { return; } do { if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { continue; } if ( PathUtils::IsWildcardMatch( wildCard.Get(), findData.cFileName ) ) { pathCopy.SetLength( baseLength ); pathCopy += findData.cFileName; results->Append( pathCopy ); } } while ( FindNextFile( hFind, &findData ) != 0 ); FindClose( hFind ); #elif defined( __LINUX__ ) || defined( __APPLE__ ) DIR * dir = opendir( pathCopy.Get() ); if ( dir == nullptr ) { return; } for ( ;; ) { dirent * entry = readdir( dir ); if ( entry == nullptr ) { break; // no more entries } // dir? if ( ( entry->d_type & DT_DIR ) == DT_DIR ) { // ignore . and .. if ( entry->d_name[ 0 ] == '.' ) { if ( ( entry->d_name[ 1 ] == 0 ) || ( ( entry->d_name[ 1 ] == '.' ) && ( entry->d_name[ 2 ] == 0 ) ) ) { continue; } } // regular dir pathCopy.SetLength( baseLength ); pathCopy += entry->d_name; pathCopy += NATIVE_SLASH; GetFilesRecurse( pathCopy, wildCard, results ); continue; } // file - does it match wildcard? if ( PathUtils::IsWildcardMatch( wildCard.Get(), entry->d_name ) ) { pathCopy.SetLength( baseLength ); pathCopy += entry->d_name; results->Append( pathCopy ); } } closedir( dir ); #else #error Unknown platform #endif }