//----------------------------------------------------------------------------- // Purpose: // Input : *in - // *out - // outSize - //----------------------------------------------------------------------------- void V_StripExtension( const char *in, char *out, int outSize ) { // Find the last dot. If it's followed by a dot or a slash, then it's part of a // directory specifier like ../../somedir/./blah. // scan backward for '.' int end = V_strlen( in ) - 1; while ( end > 0 && in[end] != '.' && !PATHSEPARATOR( in[end] ) ) { --end; } if (end > 0 && !PATHSEPARATOR( in[end] ) && end < outSize) { int nChars = min( end, outSize-1 ); if ( out != in ) { memcpy( out, in, nChars ); } out[nChars] = 0; } else { // nothing found if ( out != in ) { V_strncpy( out, in, outSize ); } } }
bool DoesPathExistAlready( const char *pPathEnvVar, const char *pTestPath ) { // Fix the slashes in the input arguments. char correctedPathEnvVar[8192], correctedTestPath[MAX_PATH]; Q_strncpy( correctedPathEnvVar, pPathEnvVar, sizeof( correctedPathEnvVar ) ); Q_FixSlashes( correctedPathEnvVar ); pPathEnvVar = correctedPathEnvVar; Q_strncpy( correctedTestPath, pTestPath, sizeof( correctedTestPath ) ); Q_FixSlashes( correctedTestPath ); if ( strlen( correctedTestPath ) > 0 && PATHSEPARATOR( correctedTestPath[strlen(correctedTestPath)-1] ) ) correctedTestPath[ strlen(correctedTestPath) - 1 ] = 0; pTestPath = correctedTestPath; const char *pCurPos = pPathEnvVar; while ( 1 ) { const char *pTestPos = Q_stristr( pCurPos, pTestPath ); if ( !pTestPos ) return false; // Ok, we found pTestPath in the path, but it's only valid if it's followed by an optional slash and a semicolon. pTestPos += strlen( pTestPath ); if ( pTestPos[0] == 0 || pTestPos[0] == ';' || (PATHSEPARATOR( pTestPos[0] ) && pTestPos[1] == ';') ) return true; // Advance our marker.. pCurPos = pTestPos; } }
//----------------------------------------------------------------------------- // Purpose: Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator) // Input : *in - // *out - // maxlen - //----------------------------------------------------------------------------- void V_FileBase( const char *in, char *out, int maxlen ) { Assert( maxlen >= 1 ); Assert( in ); Assert( out ); if ( !in || !in[ 0 ] ) { *out = 0; return; } int len, start, end; len = V_strlen( in ); // scan backward for '.' end = len - 1; while ( end&& in[end] != '.' && !PATHSEPARATOR( in[end] ) ) { end--; } if ( in[end] != '.' ) // no '.', copy to end { end = len-1; } else { end--; // Found ',', copy to left of '.' } // Scan backward for '/' start = len-1; while ( start >= 0 && !PATHSEPARATOR( in[start] ) ) { start--; } if ( start < 0 || !PATHSEPARATOR( in[start] ) ) { start = 0; } else { start++; } // Length of new sting len = end - start + 1; int maxcopy = min( len + 1, maxlen ); // Copy partial string V_strncpy( out, &in[start], maxcopy ); }
//----------------------------------------------------------------------------- // Purpose: // Input : *path - // *extension - // pathStringLength - //----------------------------------------------------------------------------- void V_DefaultExtension( char *path, const char *extension, int pathStringLength ) { Assert( path ); Assert( pathStringLength >= 1 ); Assert( extension ); Assert( extension[0] == '.' ); char *src; // if path doesn't have a .EXT, append extension // (extension should include the .) src = path + V_strlen(path) - 1; while ( !PATHSEPARATOR( *src ) && ( src > path ) ) { if (*src == '.') { // it has an extension return; } src--; } // Concatenate the desired extension V_strncat( path, extension, pathStringLength, COPY_ALL_CHARACTERS ); }
//----------------------------------------------------------------------------- // Purpose: Returns a pointer to the beginning of the unqualified file name // (no path information) // Input: in - file name (may be unqualified, relative or absolute path) // Output: pointer to unqualified file name //----------------------------------------------------------------------------- const char * V_UnqualifiedFileName( const char * in ) { // back up until the character after the first path separator we find, // or the beginning of the string const char * out = in + strlen( in ) - 1; while ( ( out > in ) && ( !PATHSEPARATOR( *( out-1 ) ) ) ) out--; return out; }
void V_FileBase(const char *in, char *out, int maxlen) { assert(maxlen >= 1); assert(in); assert(out); if (!in || !in[0]) { *out = 0; return; } int len, start, end; len = strlen(in); end = len - 1; while (end && in[end] != '.' && !PATHSEPARATOR(in[end])) end--; if (in[end] != '.') end = len - 1; else end--; start = len - 1; while (start >= 0 && !PATHSEPARATOR(in[start])) start--; if (start < 0 || !PATHSEPARATOR(in[start])) start = 0; else start++; len = end - start + 1; int maxcopy = min(len + 1, maxlen); strncpy(out, &in[start], maxcopy); out[maxcopy - 1] = 0; }
void V_AppendSlash( char *pStr, int strSize ) { int len = V_strlen( pStr ); if ( len > 0 && !PATHSEPARATOR(pStr[len-1]) ) { if ( len+1 >= strSize ) Error( "V_AppendSlash: ran out of space on %s.", pStr ); pStr[len] = CORRECT_PATH_SEPARATOR; pStr[len+1] = 0; } }
char *V_StripFirstDir (char *path) { int len_max; len_max = V_strlen( path )-1; if ( len_max <= 0 ) return NULL; int pos = 0; while ( pos <= len_max && !PATHSEPARATOR( path[pos] ) ) { pos++; } if ( PATHSEPARATOR( path[pos] ) && pos < len_max ) pos++; //path[ pos ] = 0; return &path[ pos ]; }
//----------------------------------------------------------------------------- // Purpose: // Input : *ppath - //----------------------------------------------------------------------------- void V_StripTrailingSlash( char *ppath ) { Assert( ppath ); int len = V_strlen( ppath ); if ( len > 0 ) { if ( PATHSEPARATOR( ppath[ len - 1 ] ) ) { ppath[ len - 1 ] = 0; } } }
//----------------------------------------------------------------------------- // Purpose: Strip off the last directory from dirName // Input : *dirName - // maxlen - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool V_StripLastDir( char *dirName, int maxlen ) { if( dirName[0] == 0 || !V_stricmp( dirName, "./" ) || !V_stricmp( dirName, ".\\" ) ) return false; int len = V_strlen( dirName ); Assert( len < maxlen ); // skip trailing slash if ( PATHSEPARATOR( dirName[len-1] ) ) { len--; } while ( len > 0 ) { if ( PATHSEPARATOR( dirName[len-1] ) ) { dirName[len] = 0; V_FixSlashes( dirName, CORRECT_PATH_SEPARATOR ); return true; } len--; } // Allow it to return an empty string and true. This can happen if something like "tf2/" is passed in. // The correct behavior is to strip off the last directory ("tf2") and return true. if( len == 0 ) { V_snprintf( dirName, maxlen, ".%c", CORRECT_PATH_SEPARATOR ); return true; } return true; }
bool V_AppendSlash( char *pStr, int strSize ) { int len = V_strlen( pStr ); if ( len > 0 && !PATHSEPARATOR(pStr[len-1]) ) { if ( len+1 >= strSize ) { ptERROR( "V_AppendSlash: ran out of space on %s.", pStr ); return false; } pStr[len] = CORRECT_PATH_SEPARATOR; pStr[len+1] = 0; } return true; }
//----------------------------------------------------------------------------- // Purpose: Remove final filename from string // Input : *path - // Output : void V_StripFilename //----------------------------------------------------------------------------- void V_StripFilename (char *path) { int length; length = V_strlen( path )-1; if ( length <= 0 ) return; while ( length > 0 && !PATHSEPARATOR( path[length] ) ) { length--; } path[ length ] = 0; }
void V_IsolateFirstDir (char *path) { int lengthMax; int pos = 0; lengthMax = V_strlen( path )-1; if ( lengthMax <= 0 ) return; while ( pos <= lengthMax && !PATHSEPARATOR( path[pos] ) ) { pos++; } path[ pos ] = 0; }
//----------------------------------------------------------------------------- // Purpose: Returns a pointer to the file extension within a file name string // Input: in - file name // Output: pointer to beginning of extension (after the "."), or NULL // if there is no extension //----------------------------------------------------------------------------- const char * V_GetFileExtension( const char * path ) { const char *src; src = path + strlen(path) - 1; // // back up until a . or the start // while (src != path && *(src-1) != '.' ) src--; // check to see if the '.' is part of a pathname if (src == path || PATHSEPARATOR( *src ) ) { return NULL; // no extension } return src; }
//----------------------------------------------------------------------------- // Purpose: // Input : *path - // *dest - // destSize - // Output : void V_ExtractFilePath //----------------------------------------------------------------------------- bool V_ExtractFilePath (const char *path, char *dest, int destSize ) { Assert( destSize >= 1 ); if ( destSize < 1 ) { return false; } // Last char int len = V_strlen(path); const char *src = path + (len ? len-1 : 0); // back up until a \ or the start while ( src != path && !PATHSEPARATOR( *(src-1) ) ) { src--; } int copysize = min( src - path, destSize - 1 ); memcpy( dest, path, copysize ); dest[copysize] = 0; return copysize != 0 ? true : false; }
//----------------------------------------------------------------------------- // Makes a relative path //----------------------------------------------------------------------------- bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen ) { pRelativePath[0] = 0; const char *pPath = pFullPath; const char *pDir = pDirectory; // Strip out common parts of the path const char *pLastCommonPath = NULL; const char *pLastCommonDir = NULL; while ( *pPath && ( tolower( *pPath ) == tolower( *pDir ) || ( PATHSEPARATOR( *pPath ) && ( PATHSEPARATOR( *pDir ) || (*pDir == 0) ) ) ) ) { if ( PATHSEPARATOR( *pPath ) ) { pLastCommonPath = pPath + 1; pLastCommonDir = pDir + 1; } if ( *pDir == 0 ) { --pLastCommonDir; break; } ++pDir; ++pPath; } // Nothing in common if ( !pLastCommonPath ) return false; // For each path separator remaining in the dir, need a ../ int nOutLen = 0; bool bLastCharWasSeparator = true; for ( ; *pLastCommonDir; ++pLastCommonDir ) { if ( PATHSEPARATOR( *pLastCommonDir ) ) { pRelativePath[nOutLen++] = '.'; pRelativePath[nOutLen++] = '.'; pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; bLastCharWasSeparator = true; } else { bLastCharWasSeparator = false; } } // Deal with relative paths not specified with a trailing slash if ( !bLastCharWasSeparator ) { pRelativePath[nOutLen++] = '.'; pRelativePath[nOutLen++] = '.'; pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; } // Copy the remaining part of the relative path over, fixing the path separators for ( ; *pLastCommonPath; ++pLastCommonPath ) { if ( PATHSEPARATOR( *pLastCommonPath ) ) { pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; } else { pRelativePath[nOutLen++] = *pLastCommonPath; } // Check for overflow if ( nOutLen == nBufLen - 1 ) break; } pRelativePath[nOutLen] = 0; return true; }
bool V_RemoveDotSlashes( char *pFilename, char separator ) { // Remove '//' or '\\' char *pIn = pFilename; char *pOut = pFilename; bool bPrevPathSep = false; while ( *pIn ) { bool bIsPathSep = PATHSEPARATOR( *pIn ); if ( !bIsPathSep || !bPrevPathSep ) { *pOut++ = *pIn; } bPrevPathSep = bIsPathSep; ++pIn; } *pOut = 0; // Get rid of "./"'s pIn = pFilename; pOut = pFilename; while ( *pIn ) { // The logic on the second line is preventing it from screwing up "../" if ( pIn[0] == '.' && PATHSEPARATOR( pIn[1] ) && (pIn == pFilename || pIn[-1] != '.') ) { pIn += 2; } else { *pOut = *pIn; ++pIn; ++pOut; } } *pOut = 0; // Get rid of a trailing "/." (needless). int len = strlen( pFilename ); if ( len > 2 && pFilename[len-1] == '.' && PATHSEPARATOR( pFilename[len-2] ) ) { pFilename[len-2] = 0; } // Each time we encounter a "..", back up until we've read the previous directory name, // then get rid of it. pIn = pFilename; while ( *pIn ) { if ( pIn[0] == '.' && pIn[1] == '.' && (pIn == pFilename || PATHSEPARATOR(pIn[-1])) && // Preceding character must be a slash. (pIn[2] == 0 || PATHSEPARATOR(pIn[2])) ) // Following character must be a slash or the end of the string. { char *pEndOfDots = pIn + 2; char *pStart = pIn - 2; // Ok, now scan back for the path separator that starts the preceding directory. while ( 1 ) { if ( pStart < pFilename ) return false; if ( PATHSEPARATOR( *pStart ) ) break; --pStart; } // Now slide the string down to get rid of the previous directory and the ".." memmove( pStart, pEndOfDots, strlen( pEndOfDots ) + 1 ); // Start over. pIn = pFilename; } else { ++pIn; } } V_FixSlashes( pFilename, separator ); return true; }