📄 cpl_string.cpp
字号:
/**********************************************************************
* $Id: cpl_string.cpp 10646 2007-01-18 02:38:10Z warmerdam $
*
* Name: cpl_string.cpp
* Project: CPL - Common Portability Library
* Purpose: String and Stringlist manipulation functions.
* Author: Daniel Morissette, danmo@videotron.ca
*
**********************************************************************
* Copyright (c) 1998, Daniel Morissette
*
* 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.
**********************************************************************
*
* Independent Security Audit 2003/04/04 Andrey Kiselev:
* Completed audit of this module. All functions may be used without buffer
* overflows and stack corruptions with any kind of input data strings with
* except of CPLSPrintf() and CSLAppendPrintf() (see note below).
*
* Security Audit 2003/03/28 warmerda:
* Completed security audit. I believe that this module may be safely used
* to parse tokenize arbitrary input strings, assemble arbitrary sets of
* names values into string lists, unescape and escape text even if provided
* by a potentially hostile source.
*
* CPLSPrintf() and CSLAppendPrintf() may not be safely invoked on
* arbitrary length inputs since it has a fixed size output buffer on system
* without vsnprintf().
*
**********************************************************************/
#include "cpl_string.h"
#include "cpl_vsi.h"
#if defined(WIN32CE)
# include <wce_errno.h>
# include <wce_string.h>
#endif
CPL_CVSID("$Id: cpl_string.cpp 10646 2007-01-18 02:38:10Z warmerdam $");
/*=====================================================================
StringList manipulation functions.
=====================================================================*/
/**********************************************************************
* CSLAddString()
*
* Append a string to a StringList and return a pointer to the modified
* StringList.
* If the input StringList is NULL, then a new StringList is created.
**********************************************************************/
char **CSLAddString(char **papszStrList, const char *pszNewString)
{
int nItems=0;
if (pszNewString == NULL)
return papszStrList; /* Nothing to do!*/
/* Allocate room for the new string */
if (papszStrList == NULL)
papszStrList = (char**) CPLCalloc(2,sizeof(char*));
else
{
nItems = CSLCount(papszStrList);
papszStrList = (char**)CPLRealloc(papszStrList,
(nItems+2)*sizeof(char*));
}
/* Copy the string in the list */
papszStrList[nItems] = CPLStrdup(pszNewString);
papszStrList[nItems+1] = NULL;
return papszStrList;
}
/**********************************************************************
* CSLCount()
*
* Return the number of lines in a Stringlist.
**********************************************************************/
int CSLCount(char **papszStrList)
{
int nItems=0;
if (papszStrList)
{
while(*papszStrList != NULL)
{
nItems++;
papszStrList++;
}
}
return nItems;
}
/************************************************************************/
/* CSLGetField() */
/* */
/* Fetches the indicated field, being careful not to crash if */
/* the field doesn't exist within this string list. The */
/* returned pointer should not be freed, and doesn't */
/* necessarily last long. */
/************************************************************************/
const char * CSLGetField( char ** papszStrList, int iField )
{
int i;
if( papszStrList == NULL || iField < 0 )
return( "" );
for( i = 0; i < iField+1; i++ )
{
if( papszStrList[i] == NULL )
return "";
}
return( papszStrList[iField] );
}
/**********************************************************************
* CSLDestroy()
*
* Free all memory used by a StringList.
**********************************************************************/
void CPL_STDCALL CSLDestroy(char **papszStrList)
{
char **papszPtr;
if (papszStrList)
{
papszPtr = papszStrList;
while(*papszPtr != NULL)
{
CPLFree(*papszPtr);
papszPtr++;
}
CPLFree(papszStrList);
}
}
/**********************************************************************
* CSLDuplicate()
*
* Allocate and return a copy of a StringList.
**********************************************************************/
char **CSLDuplicate(char **papszStrList)
{
char **papszNewList, **papszSrc, **papszDst;
int nLines;
nLines = CSLCount(papszStrList);
if (nLines == 0)
return NULL;
papszNewList = (char **)CPLMalloc((nLines+1)*sizeof(char*));
papszSrc = papszStrList;
papszDst = papszNewList;
while(*papszSrc != NULL)
{
*papszDst = CPLStrdup(*papszSrc);
papszSrc++;
papszDst++;
}
*papszDst = NULL;
return papszNewList;
}
/************************************************************************/
/* CSLMerge */
/************************************************************************/
/**
* \brief Merge two lists.
*
* The two lists are merged, ensuring that if any keys appear in both
* that the value from the second (papszOverride) list take precidence.
*
* @param papszOrig the original list, being modified.
* @param papszOverride the list of items being merged in. This list
* is unaltered and remains owned by the caller.
*
* @return updated list.
*/
char **CSLMerge( char **papszOrig, char **papszOverride )
{
int i;
if( papszOrig == NULL && papszOverride != NULL )
return CSLDuplicate( papszOverride );
if( papszOverride == NULL )
return papszOrig;
for( i = 0; papszOverride[i] != NULL; i++ )
{
char *pszKey = NULL;
const char *pszValue = CPLParseNameValue( papszOverride[i], &pszKey );
papszOrig = CSLSetNameValue( papszOrig, pszKey, pszValue );
CPLFree( pszKey );
}
return papszOrig;
}
/**********************************************************************
* CSLLoad()
*
* Load a test file into a stringlist.
*
* Lines are limited in length by the size of the CPLReadLine() buffer.
**********************************************************************/
char **CSLLoad(const char *pszFname)
{
FILE *fp;
const char *pszLine;
char **papszStrList=NULL;
fp = VSIFOpenL(pszFname, "rb");
if (fp)
{
while(!VSIFEofL(fp))
{
if ( (pszLine = CPLReadLineL(fp)) != NULL )
{
papszStrList = CSLAddString(papszStrList, pszLine);
}
}
VSIFCloseL(fp);
CPLReadLineL( NULL );
}
else
{
/* Unable to open file */
CPLError(CE_Failure, CPLE_OpenFailed,
"CSLLoad(%s): %s", pszFname, strerror(errno));
}
return papszStrList;
}
/**********************************************************************
* CSLSave()
*
* Write a stringlist to a text file.
*
* Returns the number of lines written, or 0 if the file could not
* be written.
**********************************************************************/
int CSLSave(char **papszStrList, const char *pszFname)
{
FILE *fp;
int nLines = 0;
if (papszStrList)
{
if ((fp = VSIFOpen(pszFname, "wt")) != NULL)
{
while(*papszStrList != NULL)
{
if (VSIFPuts(*papszStrList, fp) == EOF ||
VSIFPutc('\n', fp) == EOF)
{
CPLError(CE_Failure, CPLE_FileIO,
"CSLSave(%s): %s", pszFname,
strerror(errno));
break; /* A Problem happened... abort */
}
nLines++;
papszStrList++;
}
VSIFClose(fp);
}
else
{
/* Unable to open file */
CPLError(CE_Failure, CPLE_OpenFailed,
"CSLSave(%s): %s", pszFname, strerror(errno));
}
}
return nLines;
}
/**********************************************************************
* CSLPrint()
*
* Print a StringList to fpOut. If fpOut==NULL, then output is sent
* to stdout.
*
* Returns the number of lines printed.
**********************************************************************/
int CSLPrint(char **papszStrList, FILE *fpOut)
{
int nLines=0;
if (fpOut == NULL)
fpOut = stdout;
if (papszStrList)
{
while(*papszStrList != NULL)
{
VSIFPrintf(fpOut, "%s\n", *papszStrList);
nLines++;
papszStrList++;
}
}
return nLines;
}
/**********************************************************************
* CSLInsertStrings()
*
* Copies the contents of a StringList inside another StringList
* before the specified line.
*
* nInsertAtLineNo is a 0-based line index before which the new strings
* should be inserted. If this value is -1 or is larger than the actual
* number of strings in the list then the strings are added at the end
* of the source StringList.
*
* Returns the modified StringList.
**********************************************************************/
char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
char **papszNewLines)
{
int i, nSrcLines, nDstLines, nToInsert;
char **ppszSrc, **ppszDst;
if (papszNewLines == NULL ||
( nToInsert = CSLCount(papszNewLines) ) == 0)
return papszStrList; /* Nothing to do!*/
nSrcLines = CSLCount(papszStrList);
nDstLines = nSrcLines + nToInsert;
/* Allocate room for the new strings */
papszStrList = (char**)CPLRealloc(papszStrList,
(nDstLines+1)*sizeof(char*));
/* Make sure the array is NULL-terminated... it may not be if
* papszStrList was NULL before Realloc()
*/
papszStrList[nSrcLines] = NULL;
/* Make some room in the original list at the specified location
* Note that we also have to move the NULL pointer at the end of
* the source StringList.
*/
if (nInsertAtLineNo == -1 || nInsertAtLineNo > nSrcLines)
nInsertAtLineNo = nSrcLines;
ppszSrc = papszStrList + nSrcLines;
ppszDst = papszStrList + nDstLines;
for (i=nSrcLines; i>=nInsertAtLineNo; i--)
{
*ppszDst = *ppszSrc;
ppszDst--;
ppszSrc--;
}
/* Copy the strings to the list */
ppszSrc = papszNewLines;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -