📄 cpl_string.cpp
字号:
/********************************************************************** * $Id: cpl_string.cpp,v 1.34 2003/05/28 19:22:38 warmerda Exp $ * * 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(). * * $Log: cpl_string.cpp,v $ * Revision 1.34 2003/05/28 19:22:38 warmerda * fixed docs * * Revision 1.33 2003/05/21 04:20:30 warmerda * avoid warnings * * Revision 1.32 2003/04/04 14:57:38 dron * _vsnprintf() hack moved to the cpl_config.h.vc. * * Revision 1.31 2003/04/04 14:16:07 dron * Use _vsnprintf() in Windows environment. * * Revision 1.30 2003/03/28 05:29:53 warmerda * Fixed buffer overflow risk in escaping code (for XML method). Avoid * use of CPLSPrintf() for name/value list assembly to avoid risk with long * key names or values. Use vsnprintf() in CPLSPrintf() on platforms where it * is available. Security audit complete. * * Revision 1.29 2003/03/27 21:32:08 warmerda * Fixed bug with escaped spaces. * * Revision 1.28 2003/03/11 21:33:02 warmerda * added URL encode/decode support, untested * * Revision 1.27 2003/01/30 19:15:55 warmerda * added some docs * * Revision 1.26 2003/01/14 14:31:16 warmerda * Added "OFF" as a negative response to CSLFetchBoolean(). * * Revision 1.25 2002/10/07 19:35:38 dron * Fixed description for CSLFetchBoolean() * * Revision 1.24 2002/07/12 22:37:05 warmerda * added CSLFetchBoolean * * Revision 1.23 2002/07/09 20:25:25 warmerda * expand tabs * * Revision 1.22 2002/05/28 18:53:43 warmerda * added XML escaping support * * Revision 1.21 2002/04/26 14:55:26 warmerda * Added CPLEscapeString() and CPLUnescapeString() (unescape untested) * * Revision 1.20 2002/03/05 14:26:57 warmerda * expanded tabs * * Revision 1.19 2002/01/16 03:59:27 warmerda * added CPLTokenizeString2 * * Revision 1.18 2001/12/11 22:40:26 warmerda * cleanup CPLReadLine buffer in CSLLoad() * * Revision 1.17 2001/11/07 14:31:16 warmerda * doc fix * * Revision 1.16 2001/07/18 04:00:49 warmerda * added CPL_CVSID * * Revision 1.15 2001/01/19 21:16:41 warmerda * expanded tabs * * Revision 1.14 2000/10/06 15:19:03 warmerda * added CPLSetNameValueSeparator * * Revision 1.13 2000/08/22 17:47:50 warmerda * Fixed declaration of gnCPLSPrintfBuffer. * * Revision 1.12 2000/08/18 21:20:54 svillene * *** empty log message *** * * Revision 1.11 2000/03/30 05:38:48 warmerda * added CPLParseNameValue * * Revision 1.10 1999/06/26 14:05:10 warmerda * Added CSLFindString(). * * Revision 1.9 1999/04/28 02:33:02 danmo * CSLInsertStrings(): make sure papszStrList is NULL-terminated properly * * Revision 1.8 1999/03/12 21:19:49 danmo * Fixed TokenizeStringComplex() vs strings ending with empty token, * and fixed a problem with CSLAdd/SetNameValue() vs empty string list. * * Revision 1.7 1999/03/09 21:29:57 warmerda * Added backslash escaping within string constants for tokenize function. * * Revision 1.6 1999/02/25 04:40:46 danmo * Modif. CSLLoad() to use CPLReadLine() (better handling of newlines) * * Revision 1.5 1999/02/17 01:41:58 warmerda * Added CSLGetField * * Revision 1.4 1998/12/15 19:01:40 warmerda * *** empty log message *** * * Revision 1.3 1998/12/05 23:04:21 warmerda * Use EQUALN() instead of strincmp() which doesn't exist on Linux. * * Revision 1.2 1998/12/04 21:40:42 danmo * Added more Name=Value manipulation fuctions * * Revision 1.1 1998/12/03 18:26:02 warmerda * New * **********************************************************************/#include "cpl_string.h"#include "cpl_vsi.h"CPL_CVSID("$Id: cpl_string.cpp,v 1.34 2003/05/28 19:22:38 warmerda Exp $");/*===================================================================== 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 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;}/********************************************************************** * 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 = VSIFOpen(pszFname, "rt"); if (fp) { while(!VSIFEof(fp)) { if ( (pszLine = CPLReadLine(fp)) != NULL ) { papszStrList = CSLAddString(papszStrList, pszLine); } } VSIFClose(fp); CPLReadLine( 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; ppszDst = papszStrList + nInsertAtLineNo; for (; *ppszSrc != NULL; ppszSrc++, ppszDst++) { *ppszDst = CPLStrdup(*ppszSrc); } return papszStrList;}/********************************************************************** * CSLInsertString() *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -