📄 cpl_string.cpp
字号:
ppszDst = papszStrList + nInsertAtLineNo;
for (; *ppszSrc != NULL; ppszSrc++, ppszDst++)
{
*ppszDst = CPLStrdup(*ppszSrc);
}
return papszStrList;
}
/**********************************************************************
* CSLInsertString()
*
* Insert a string at a given line number inside a StringList
*
* nInsertAtLineNo is a 0-based line index before which the new string
* should be inserted. If this value is -1 or is larger than the actual
* number of strings in the list then the string is added at the end
* of the source StringList.
*
* Returns the modified StringList.
**********************************************************************/
char **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
const char *pszNewLine)
{
char *apszList[2];
/* Create a temporary StringList and call CSLInsertStrings()
*/
apszList[0] = (char *) pszNewLine;
apszList[1] = NULL;
return CSLInsertStrings(papszStrList, nInsertAtLineNo, apszList);
}
/**********************************************************************
* CSLRemoveStrings()
*
* Remove strings inside a StringList
*
* nFirstLineToDelete is the 0-based line index of the first line to
* remove. If this value is -1 or is larger than the actual
* number of strings in list then the nNumToRemove last strings are
* removed.
*
* If ppapszRetStrings != NULL then the deleted strings won't be
* free'd, they will be stored in a new StringList and the pointer to
* this new list will be returned in *ppapszRetStrings.
*
* Returns the modified StringList.
**********************************************************************/
char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
int nNumToRemove, char ***ppapszRetStrings)
{
int i, nSrcLines, nDstLines;
char **ppszSrc, **ppszDst;
nSrcLines = CSLCount(papszStrList);
nDstLines = nSrcLines - nNumToRemove;
if (nNumToRemove < 1 || nSrcLines == 0)
return papszStrList; /* Nothing to do!*/
/* If operation will result in an empty StringList then don't waste
* time here!
*/
if (nDstLines < 1)
{
CSLDestroy(papszStrList);
return NULL;
}
/* Remove lines from the source StringList...
* Either free() each line or store them to a new StringList depending on
* the caller's choice.
*/
ppszDst = papszStrList + nFirstLineToDelete;
if (ppapszRetStrings == NULL)
{
/* free() all the strings that will be removed.
*/
for (i=0; i < nNumToRemove; i++)
{
CPLFree(*ppszDst);
*ppszDst = NULL;
}
}
else
{
/* Store the strings to remove in a new StringList
*/
*ppapszRetStrings = (char **)CPLCalloc(nNumToRemove+1, sizeof(char*));
for (i=0; i < nNumToRemove; i++)
{
(*ppapszRetStrings)[i] = *ppszDst;
*ppszDst = NULL;
ppszDst++;
}
}
/* Shift down all the lines that follow the lines to remove.
*/
if (nFirstLineToDelete == -1 || nFirstLineToDelete > nSrcLines)
nFirstLineToDelete = nDstLines;
ppszSrc = papszStrList + nFirstLineToDelete + nNumToRemove;
ppszDst = papszStrList + nFirstLineToDelete;
for ( ; *ppszSrc != NULL; ppszSrc++, ppszDst++)
{
*ppszDst = *ppszSrc;
}
/* Move the NULL pointer at the end of the StringList */
*ppszDst = *ppszSrc;
/* At this point, we could realloc() papszStrList to a smaller size, but
* since this array will likely grow again in further operations on the
* StringList we'll leave it as it is.
*/
return papszStrList;
}
/************************************************************************/
/* CSLFindString() */
/* */
/* Find a string within a string list. The string must match */
/* the full length, but the comparison is case insensitive. */
/* Return -1 on failure. */
/************************************************************************/
int CSLFindString( char ** papszList, const char * pszTarget )
{
int i;
if( papszList == NULL )
return -1;
for( i = 0; papszList[i] != NULL; i++ )
{
if( EQUAL(papszList[i],pszTarget) )
return i;
}
return -1;
}
/**********************************************************************
* CSLTokenizeString()
*
* Tokenizes a string and returns a StringList with one string for
* each token.
**********************************************************************/
char **CSLTokenizeString( const char *pszString )
{
return CSLTokenizeString2( pszString, " ", CSLT_HONOURSTRINGS );
}
/************************************************************************/
/* CSLTokenizeStringComplex() */
/* */
/* Obsolete tokenizing api. */
/************************************************************************/
char ** CSLTokenizeStringComplex( const char * pszString,
const char * pszDelimiters,
int bHonourStrings, int bAllowEmptyTokens )
{
int nFlags = 0;
if( bHonourStrings )
nFlags |= CSLT_HONOURSTRINGS;
if( bAllowEmptyTokens )
nFlags |= CSLT_ALLOWEMPTYTOKENS;
return CSLTokenizeString2( pszString, pszDelimiters, nFlags );
}
/************************************************************************/
/* CSLTokenizeString2() */
/* */
/* The ultimate tokenizer? */
/************************************************************************/
char ** CSLTokenizeString2( const char * pszString,
const char * pszDelimiters,
int nCSLTFlags )
{
char **papszRetList = NULL;
int nRetMax = 0, nRetLen = 0;
char *pszToken;
int nTokenMax, nTokenLen;
int bHonourStrings = (nCSLTFlags & CSLT_HONOURSTRINGS);
int bAllowEmptyTokens = (nCSLTFlags & CSLT_ALLOWEMPTYTOKENS);
pszToken = (char *) CPLCalloc(10,1);
nTokenMax = 10;
while( pszString != NULL && *pszString != '\0' )
{
int bInString = FALSE;
nTokenLen = 0;
/* Try to find the next delimeter, marking end of token */
for( ; *pszString != '\0'; pszString++ )
{
/* End if this is a delimeter skip it and break. */
if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
{
pszString++;
break;
}
/* If this is a quote, and we are honouring constant
strings, then process the constant strings, with out delim
but don't copy over the quotes */
if( bHonourStrings && *pszString == '"' )
{
if( nCSLTFlags & CSLT_PRESERVEQUOTES )
{
pszToken[nTokenLen] = *pszString;
nTokenLen++;
}
if( bInString )
{
bInString = FALSE;
continue;
}
else
{
bInString = TRUE;
continue;
}
}
/* Within string constants we allow for escaped quotes, but
in processing them we will unescape the quotes */
if( bInString && pszString[0] == '\\' && pszString[1] == '"' )
{
if( nCSLTFlags & CSLT_PRESERVEESCAPES )
{
pszToken[nTokenLen] = *pszString;
nTokenLen++;
}
pszString++;
}
/* Within string constants a \\ sequence reduces to \ */
else if( bInString
&& pszString[0] == '\\' && pszString[1] == '\\' )
{
if( nCSLTFlags & CSLT_PRESERVEESCAPES )
{
pszToken[nTokenLen] = *pszString;
nTokenLen++;
}
pszString++;
}
if( nTokenLen >= nTokenMax-3 )
{
nTokenMax = nTokenMax * 2 + 10;
pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
}
pszToken[nTokenLen] = *pszString;
nTokenLen++;
}
pszToken[nTokenLen] = '\0';
/*
* Add the token.
*/
if( pszToken[0] != '\0' || bAllowEmptyTokens )
{
if( nRetLen >= nRetMax - 1 )
{
nRetMax = nRetMax * 2 + 10;
papszRetList = (char **)
CPLRealloc(papszRetList, sizeof(char*) * nRetMax );
}
papszRetList[nRetLen++] = CPLStrdup( pszToken );
papszRetList[nRetLen] = NULL;
}
}
/*
* If the last token was empty, then we need to capture
* it now, as the loop would skip it.
*/
if( *pszString == '\0' && bAllowEmptyTokens && nRetLen > 0
&& strchr(pszDelimiters,*(pszString-1)) != NULL )
{
if( nRetLen >= nRetMax - 1 )
{
nRetMax = nRetMax * 2 + 10;
papszRetList = (char **)
CPLRealloc(papszRetList, sizeof(char*) * nRetMax );
}
papszRetList[nRetLen++] = CPLStrdup("");
papszRetList[nRetLen] = NULL;
}
if( papszRetList == NULL )
papszRetList = (char **) CPLCalloc(sizeof(char *),1);
CPLFree( pszToken );
return papszRetList;
}
/**********************************************************************
* CPLSPrintf()
*
* My own version of CPLSPrintf() that works with 10 static buffer.
*
* It returns a ref. to a static buffer that should not be freed and
* is valid only until the next call to CPLSPrintf().
*
* NOTE: This function should move to cpl_conv.cpp.
**********************************************************************/
/* For now, assume that a 8000 chars buffer will be enough.
*/
#define CPLSPrintf_BUF_SIZE 8000
#define CPLSPrintf_BUF_Count 10
static CPL_THREADLOCAL char gszCPLSPrintfBuffer[CPLSPrintf_BUF_Count][CPLSPrintf_BUF_SIZE];
static CPL_THREADLOCAL int gnCPLSPrintfBuffer = 0;
const char *CPLSPrintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
#if defined(HAVE_VSNPRINTF)
vsnprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], CPLSPrintf_BUF_SIZE-1,
fmt, args);
#else
vsprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], fmt, args);
#endif
va_end(args);
int nCurrent = gnCPLSPrintfBuffer;
if (++gnCPLSPrintfBuffer == CPLSPrintf_BUF_Count)
gnCPLSPrintfBuffer = 0;
return gszCPLSPrintfBuffer[nCurrent];
}
/**********************************************************************
* CSLAppendPrintf()
*
* Use CPLSPrintf() to append a new line at the end of a StringList.
*
* Returns the modified StringList.
**********************************************************************/
char **CSLAppendPrintf(char **papszStrList, char *fmt, ...)
{
va_list args;
va_start(args, fmt);
#if defined(HAVE_VSNPRINTF)
vsnprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], CPLSPrintf_BUF_SIZE-1,
fmt, args);
#else
vsprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], fmt, args);
#endif
va_end(args);
int nCurrent = gnCPLSPrintfBuffer;
if (++gnCPLSPrintfBuffer == CPLSPrintf_BUF_Count)
gnCPLSPrintfBuffer = 0;
return CSLAddString(papszStrList, gszCPLSPrintfBuffer[nCurrent]);
}
/************************************************************************/
/* CSLTestBoolean() */
/************************************************************************/
/**
* Test what boolean value contained in the string.
*
* If pszValue is "NO", "FALSE", "OFF" or "0" will be returned FALSE.
* Otherwise, TRUE will be returned.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -