📄 cpl_string.cpp
字号:
* 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, char *pszNewLine){ char *apszList[2]; /* Create a temporary StringList and call CSLInsertStrings() */ apszList[0] = 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; 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'; if( pszToken[0] != '\0' || bAllowEmptyTokens ) { papszRetList = CSLAddString( papszRetList, pszToken ); } /* If the last token is an empty token, then we have to catch * it now, otherwise we won't reenter the loop and it will be lost. */ if ( *pszString == '\0' && bAllowEmptyTokens && strchr(pszDelimiters, *(pszString-1)) ) { papszRetList = CSLAddString( papszRetList, "" ); } } 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 char gszCPLSPrintfBuffer[CPLSPrintf_BUF_Count][CPLSPrintf_BUF_SIZE];static int gnCPLSPrintfBuffer = 0;const char *CPLSPrintf(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]);}/********************************************************************** * 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 if( EQUAL(pszValue,"NO") || EQUAL(pszValue,"FALSE") || EQUAL(pszValue,"OFF") || EQUAL(pszValue,"0") ) return FALSE; else return TRUE;}/********************************************************************** * 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){ int 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 &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -