📄 cpl_path.cpp
字号:
/**********************************************************************
* $Id: cpl_path.cpp 10646 2007-01-18 02:38:10Z warmerdam $
*
* Project: CPL - Common Portability Library
* Purpose: Portable filename/path parsing, and forming ala "Glob API".
* Author: Frank Warmerdam, warmerda@home.com
*
**********************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* 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, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* 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. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#include "cpl_conv.h"
#include "cpl_string.h"
#include "cpl_multiproc.h"
CPL_CVSID("$Id: cpl_path.cpp 10646 2007-01-18 02:38:10Z warmerdam $");
/* should be size of larged possible filename */
#define CPL_PATH_BUF_SIZE 2048
#if defined(WIN32) || defined(WIN32CE)
#define SEP_CHAR '\\'
#define SEP_STRING "\\"
#else
#define SEP_CHAR '/'
#define SEP_STRING "/"
#endif
/************************************************************************/
/* CPLGetStaticResult() */
/************************************************************************/
static char *CPLGetStaticResult()
{
char *pszStaticResult = (char *) CPLGetTLS( CTLS_PATHBUF );
if( pszStaticResult == NULL )
{
pszStaticResult = (char *) CPLMalloc(CPL_PATH_BUF_SIZE);
CPLSetTLS( CTLS_PATHBUF, pszStaticResult, TRUE );
}
return pszStaticResult;
}
/************************************************************************/
/* CPLFindFilenameStart() */
/************************************************************************/
static int CPLFindFilenameStart( const char * pszFilename )
{
size_t iFileStart;
for( iFileStart = strlen(pszFilename);
iFileStart > 0
&& pszFilename[iFileStart-1] != '/'
&& pszFilename[iFileStart-1] != '\\';
iFileStart-- ) {}
return (int)iFileStart;
}
/************************************************************************/
/* CPLGetPath() */
/************************************************************************/
/**
* Extract directory path portion of filename.
*
* Returns a string containing the directory path portion of the passed
* filename. If there is no path in the passed filename an empty string
* will be returned (not NULL).
*
* <pre>
* CPLGetPath( "abc/def.xyz" ) == "abc"
* CPLGetPath( "/abc/def/" ) == "/abc/def"
* CPLGetPath( "/" ) == "/"
* CPLGetPath( "/abc/def" ) == "/abc"
* CPLGetPath( "abc" ) == ""
* </pre>
*
* @param pszFilename the filename potentially including a path.
*
* @return Path in an internal string which must not be freed. The string
* may be destroyed by the next CPL filename handling call. The returned
* will generally not contain a trailing path separator.
*/
const char *CPLGetPath( const char *pszFilename )
{
int iFileStart = CPLFindFilenameStart(pszFilename);
char *pszStaticResult = CPLGetStaticResult();
CPLAssert( iFileStart < CPL_PATH_BUF_SIZE );
if( iFileStart == 0 )
{
strcpy( pszStaticResult, "" );
return pszStaticResult;
}
strncpy( pszStaticResult, pszFilename, iFileStart );
pszStaticResult[iFileStart] = '\0';
if( iFileStart > 1
&& (pszStaticResult[iFileStart-1] == '/'
|| pszStaticResult[iFileStart-1] == '\\') )
pszStaticResult[iFileStart-1] = '\0';
return pszStaticResult;
}
/************************************************************************/
/* CPLGetDirname() */
/************************************************************************/
/**
* Extract directory path portion of filename.
*
* Returns a string containing the directory path portion of the passed
* filename. If there is no path in the passed filename the dot will be
* returned. It is the only difference from CPLGetPath().
*
* <pre>
* CPLGetDirname( "abc/def.xyz" ) == "abc"
* CPLGetDirname( "/abc/def/" ) == "/abc/def"
* CPLGetDirname( "/" ) == "/"
* CPLGetDirname( "/abc/def" ) == "/abc"
* CPLGetDirname( "abc" ) == "."
* </pre>
*
* @param pszFilename the filename potentially including a path.
*
* @return Path in an internal string which must not be freed. The string
* may be destroyed by the next CPL filename handling call. The returned
* will generally not contain a trailing path separator.
*/
const char *CPLGetDirname( const char *pszFilename )
{
int iFileStart = CPLFindFilenameStart(pszFilename);
char *pszStaticResult = CPLGetStaticResult();
CPLAssert( iFileStart < CPL_PATH_BUF_SIZE );
if( iFileStart == 0 )
{
strcpy( pszStaticResult, "." );
return pszStaticResult;
}
strncpy( pszStaticResult, pszFilename, iFileStart );
pszStaticResult[iFileStart] = '\0';
if( iFileStart > 1
&& (pszStaticResult[iFileStart-1] == '/'
|| pszStaticResult[iFileStart-1] == '\\') )
pszStaticResult[iFileStart-1] = '\0';
return pszStaticResult;
}
/************************************************************************/
/* CPLGetFilename() */
/************************************************************************/
/**
* Extract non-directory portion of filename.
*
* Returns a string containing the bare filename portion of the passed
* filename. If there is no filename (passed value ends in trailing directory
* separator) an empty string is returned.
*
* <pre>
* CPLGetFilename( "abc/def.xyz" ) == "def.xyz"
* CPLGetFilename( "/abc/def/" ) == ""
* CPLGetFilename( "abc/def" ) == "def"
* </pre>
*
* @param pszFullFilename the full filename potentially including a path.
*
* @return just the non-directory portion of the path in an internal string
* which must not be freed. The string
* may be destroyed by the next CPL filename handling call.
*/
const char *CPLGetFilename( const char *pszFullFilename )
{
int iFileStart = CPLFindFilenameStart( pszFullFilename );
char *pszStaticResult = CPLGetStaticResult();
strncpy( pszStaticResult, pszFullFilename + iFileStart,
CPL_PATH_BUF_SIZE );
pszStaticResult[CPL_PATH_BUF_SIZE - 1] = '\0';
return pszStaticResult;
}
/************************************************************************/
/* CPLGetBasename() */
/************************************************************************/
/**
* Extract basename (non-directory, non-extension) portion of filename.
*
* Returns a string containing the file basename portion of the passed
* name. If there is no basename (passed value ends in trailing directory
* separator, or filename starts with a dot) an empty string is returned.
*
* <pre>
* CPLGetBasename( "abc/def.xyz" ) == "def"
* CPLGetBasename( "abc/def" ) == "def"
* CPLGetBasename( "abc/def/" ) == ""
* </pre>
*
* @param pszFullFilename the full filename potentially including a path.
*
* @return just the non-directory, non-extension portion of the path in
* an internal string which must not be freed. The string
* may be destroyed by the next CPL filename handling call.
*/
const char *CPLGetBasename( const char *pszFullFilename )
{
size_t iFileStart = CPLFindFilenameStart( pszFullFilename );
size_t iExtStart, nLength;
char *pszStaticResult = CPLGetStaticResult();
for( iExtStart = strlen(pszFullFilename);
iExtStart > iFileStart && pszFullFilename[iExtStart] != '.';
iExtStart-- ) {}
if( iExtStart == iFileStart )
iExtStart = strlen(pszFullFilename);
nLength = iExtStart - iFileStart;
CPLAssert( nLength < CPL_PATH_BUF_SIZE );
strncpy( pszStaticResult, pszFullFilename + iFileStart, nLength );
pszStaticResult[nLength] = '\0';
return pszStaticResult;
}
/************************************************************************/
/* CPLGetExtension() */
/************************************************************************/
/**
* Extract filename extension from full filename.
*
* Returns a string containing the extention portion of the passed
* name. If there is no extension (the filename has no dot) an empty string
* is returned. The returned extension will not include the period.
*
* <pre>
* CPLGetExtension( "abc/def.xyz" ) == "xyz"
* CPLGetExtension( "abc/def" ) == ""
* </pre>
*
* @param pszFullFilename the full filename potentially including a path.
*
* @return just the extension portion of the path in
* an internal string which must not be freed. The string
* may be destroyed by the next CPL filename handling call.
*/
const char *CPLGetExtension( const char *pszFullFilename )
{
size_t iFileStart = CPLFindFilenameStart( pszFullFilename );
size_t iExtStart;
char *pszStaticResult = CPLGetStaticResult();
for( iExtStart = strlen(pszFullFilename);
iExtStart > iFileStart && pszFullFilename[iExtStart] != '.';
iExtStart-- ) {}
if( iExtStart == iFileStart )
iExtStart = strlen(pszFullFilename)-1;
strncpy( pszStaticResult, pszFullFilename+iExtStart+1, CPL_PATH_BUF_SIZE );
pszStaticResult[CPL_PATH_BUF_SIZE - 1] = '\0';
return pszStaticResult;
}
/************************************************************************/
/* CPLGetCurrentDir() */
/************************************************************************/
/**
* Get the current working directory name.
*
* @return a pointer to buffer, containing current working directory path
* or NULL in case of error. User is responsible to free that buffer
* after usage with CPLFree() function.
* If HAVE_GETCWD macro is not defined, the function returns NULL.
**/
char *CPLGetCurrentDir()
{
size_t nPathMax;
char *pszDirPath;
# ifdef _MAX_PATH
nPathMax = _MAX_PATH;
# elif PATH_MAX
nPathMax = PATH_MAX;
# else
nPathMax = 8192;
# endif
pszDirPath = (char*)CPLMalloc( nPathMax );
if ( !pszDirPath )
return NULL;
#ifdef HAVE_GETCWD
return getcwd( pszDirPath, nPathMax );
#else
return NULL;
#endif /* HAVE_GETCWD */
}
/************************************************************************/
/* CPLResetExtension() */
/************************************************************************/
/**
* Replace the extension with the provided one.
*
* @param pszPath the input path, this string is not altered.
* @param pszExt the new extension to apply to the given path.
*
* @return an altered filename with the new extension. Do not
* modify or free the returned string. The string may be destroyed by the
* next CPL call.
*/
const char *CPLResetExtension( const char *pszPath, const char *pszExt )
{
char *pszStaticResult = CPLGetStaticResult();
size_t i;
/* -------------------------------------------------------------------- */
/* First, try and strip off any existing extension. */
/* -------------------------------------------------------------------- */
strncpy( pszStaticResult, pszPath, CPL_PATH_BUF_SIZE );
pszStaticResult[CPL_PATH_BUF_SIZE - 1] = '\0';
for( i = strlen(pszStaticResult) - 1; i > 0; i-- )
{
if( pszStaticResult[i] == '.' )
{
pszStaticResult[i] = '\0';
break;
}
if( pszStaticResult[i] == '/' || pszStaticResult[i] == '\\'
|| pszStaticResult[i] == ':' )
break;
}
/* -------------------------------------------------------------------- */
/* Append the new extension. */
/* -------------------------------------------------------------------- */
CPLAssert( strlen(pszExt) + 2 < CPL_PATH_BUF_SIZE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -