📄 cpl_string.cpp
字号:
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 10static 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. * * @param pszValue the string should be tested. * * @return TRUE or FALSE. */int CSLTestBoolean( const char *pszValue ){ if( EQUAL(pszValue,"NO") || EQUAL(pszValue,"FALSE") || EQUAL(pszValue,"OFF") || EQUAL(pszValue,"0") ) return FALSE; else return TRUE;}/********************************************************************** * CSLFetchBoolean() * * Check for boolean key value. * * In a StringList of "Name=Value" pairs, look to see if there is a key * with the given name, and if it can be interpreted as being TRUE. If * the key appears without any "=Value" portion it will be considered true. * If the value is NO, FALSE or 0 it will be considered FALSE otherwise * if the key appears in the list it will be considered TRUE. If the key * doesn't appear at all, the indicated default value will be returned. * * @param papszStrList the string list to search. * @param pszKey the key value to look for (case insensitive). * @param bDefault the value to return if the key isn't found at all. * * @return TRUE or FALSE **********************************************************************/int CSLFetchBoolean( char **papszStrList, const char *pszKey, int bDefault ){ const char *pszValue; if( CSLFindString( papszStrList, pszKey ) != -1 ) return TRUE; pszValue = CSLFetchNameValue(papszStrList, pszKey ); if( pszValue == NULL ) return bDefault; else return CSLTestBoolean( pszValue );}/********************************************************************** * CSLFetchNameValue() * * In a StringList of "Name=Value" pairs, look for the * first value associated with the specified name. The search is not * case sensitive. * ("Name:Value" pairs are also supported for backward compatibility * with older stuff.) * * Returns a reference to the value in the StringList that the caller * should not attempt to free. * * Returns NULL if the name is not found. **********************************************************************/const char *CSLFetchNameValue(char **papszStrList, const char *pszName){ size_t nLen; if (papszStrList == NULL || pszName == NULL) return NULL; nLen = strlen(pszName); while(*papszStrList != NULL) { if (EQUALN(*papszStrList, pszName, nLen) && ( (*papszStrList)[nLen] == '=' || (*papszStrList)[nLen] == ':' ) ) { return (*papszStrList)+nLen+1; } papszStrList++; } return NULL;}/********************************************************************** * CPLParseNameValue() **********************************************************************//** * Parse NAME=VALUE string into name and value components. * * Note that if ppszKey is non-NULL, the key (or name) portion will be * allocated using VSIMalloc(), and returned in that pointer. It is the * applications responsibility to free this string, but the application should * not modify or free the returned value portion. * * This function also support "NAME:VALUE" strings and will strip white * space from around the delimeter when forming name and value strings. * * Eventually CSLFetchNameValue() and friends may be modified to use * CPLParseNameValue(). * * @param pszNameValue string in "NAME=VALUE" format. * @param ppszKey optional pointer though which to return the name * portion. * @return the value portion (pointing into original string). */const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey ){ int i; const char *pszValue; for( i = 0; pszNameValue[i] != '\0'; i++ ) { if( pszNameValue[i] == '=' || pszNameValue[i] == ':' ) { pszValue = pszNameValue + i + 1; while( *pszValue == ' ' || *pszValue == '\t' ) pszValue++; if( ppszKey != NULL ) { *ppszKey = (char *) CPLMalloc(i+1); strncpy( *ppszKey, pszNameValue, i ); (*ppszKey)[i] = '\0'; while( i > 0 && ( (*ppszKey)[i] == ' ' || (*ppszKey)[i] == '\t') ) { (*ppszKey)[i] = '\0'; i--; } } return pszValue; } } return NULL;}/********************************************************************** * CSLFetchNameValueMultiple() * * In a StringList of "Name=Value" pairs, look for all the * values with the specified name. The search is not case * sensitive. * ("Name:Value" pairs are also supported for backward compatibility * with older stuff.) * * Returns stringlist with one entry for each occurence of the * specified name. The stringlist should eventually be destroyed * by calling CSLDestroy(). * * Returns NULL if the name is not found. **********************************************************************/char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName){ size_t nLen; char **papszValues = NULL; if (papszStrList == NULL || pszName == NULL) return NULL; nLen = strlen(pszName); while(*papszStrList != NULL) { if (EQUALN(*papszStrList, pszName, nLen) && ( (*papszStrList)[nLen] == '=' || (*papszStrList)[nLen] == ':' ) ) { papszValues = CSLAddString(papszValues, (*papszStrList)+nLen+1); } papszStrList++; } return papszValues;}/********************************************************************** * CSLAddNameValue() * * Add a new entry to a StringList of "Name=Value" pairs, * ("Name:Value" pairs are also supported for backward compatibility * with older stuff.) * * This function does not check if a "Name=Value" pair already exists * for that name and can generate multiple entryes for the same name. * Use CSLSetNameValue() if you want each name to have only one value. * * Returns the modified stringlist. **********************************************************************/char **CSLAddNameValue(char **papszStrList, const char *pszName, const char *pszValue){ char *pszLine; if (pszName == NULL || pszValue==NULL) return papszStrList; pszLine = (char *) CPLMalloc(strlen(pszName)+strlen(pszValue)+2); sprintf( pszLine, "%s=%s", pszName, pszValue ); papszStrList = CSLAddString(papszStrList, pszLine); CPLFree( pszLine ); return papszStrList;}/************************************************************************//* CSLSetNameValue() *//************************************************************************//** * Assign value to name in StringList. * * Set the value for a given name in a StringList of "Name=Value" pairs * ("Name:Value" pairs are also supported for backward compatibility * with older stuff.) * * If there is already a value for that name in the list then the value * is changed, otherwise a new "Name=Value" pair is added. * * @param papszList the original list, the modified version is returned. * @param pszName the name to be assigned a value. This should be a well * formed token (no spaces or very special characters). * @param pszValue the value to assign to the name. This should not contain * any newlines (CR or LF) but is otherwise pretty much unconstrained. If * NULL any corresponding value will be removed. * * @return modified stringlist. */char **CSLSetNameValue(char **papszList, const char *pszName, const char *pszValue){ char **papszPtr; size_t nLen; if (pszName == NULL ) return papszList; nLen = strlen(pszName); papszPtr = papszList; while(papszPtr && *papszPtr != NULL) { if (EQUALN(*papszPtr, pszName, nLen) && ( (*papszPtr)[nLen] == '=' || (*papszPtr)[nLen] == ':' ) ) { /* Found it! * Change the value... make sure to keep the ':' or '=' */ char cSep; cSep = (*papszPtr)[nLen]; CPLFree(*papszPtr); /* * If the value is NULL, remove this entry completely/ */ if( pszValue == NULL ) { while( papszPtr[1] != NULL ) { *papszPtr = papszPtr[1]; papszPtr++; } *papszPtr = NULL; } /* * Otherwise replace with new value. */ else { *papszPtr = (char *) CPLMalloc(strlen(pszName)+strlen(pszValue)+2); sprintf( *papszPtr, "%s%c%s", pszName, cSep, pszValue ); } return papszList; } papszPtr++; } if( pszValue == NULL ) return papszList; /* The name does not exist yet... create a new entry */ return CSLAddNameValue(papszList, pszName, pszValue);}/************************************************************************//* CSLSetNameValueSeparator() *//************************************************************************//** * Replace the default separator (":" or "=") with the passed separator * in the given name/value list. * * Note that if a separator other than ":" or "=" is used, the resulting * list will not be manipulatable by the CSL name/value functions any more. * * The CPLParseNameValue() function is used to break the existing lines, * and it also strips white space from around the existing delimiter, thus * the old separator, and any white space will be replaced by the new * separator. For formatting purposes it may be desireable to include some * white space in the new separator. eg. ": " or " = ". * * @param papszList the list to update. Component strings may be freed * but the list array will remain at the same location. * * @param pszSeparator the new separator string to insert. * */void CSLSetNameValueSeparator( char ** papszList, const char *pszSeparator ){ int nLines = CSLCount(papszList), iLine; for( iLine = 0; iLine < nLines; iLine++ ) { char *pszKey = NULL; const char *pszValue; char *pszNewLine; pszValue = CPLParseNameValue( papszList[iLine], &pszKey ); pszNewLine = (char *) CPLMalloc( strlen(pszValue) + strlen(pszKey) + strlen(pszSeparator) + 1 ); strcpy( pszNewLine, pszKey ); strcat( pszNewLine, pszSeparator ); strcat( pszNewLine, pszValue ); CPLFree( papszList[iLine] ); papszList[iLine] = pszNewLine; CPLFree( pszKey ); }}/************************************************************************//* CPLEscapeString() *//************************************************************************//** * Apply escaping to string to preserve special characters. * * This function will "escape" a variety of special characters * to make the string suitable to embed within a string constant
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -