00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026 00027 00028 00029 00030 00031 00031 00031 00031 00032 00033 00034 00035 00036 00037 00038 00039 00040 00041 00042 00043 00044 00045 00046 00047 00048 00049 00050 00051 00052 00053 00054 00055 00056 00057 00058 00059 00060 00061 00062 00063 00064 00065 00066 00067 00068 00069 00070 00071 00072
00073
00074 #include "cpl_string.h"
00075 #include "cpl_vsi.h"
00076
00077 00078 00079
00080
00081 00082 00083 00084 00085 00086 00087
00088 char **CSLAddString(char **papszStrList, const char *pszNewString)
00089 {
00090 int nItems=0;
00091
00092 if (pszNewString == NULL)
00093 return papszStrList;
00094
00095
00096 if (papszStrList == NULL)
00097 papszStrList = (char**) CPLCalloc(2,sizeof(char*));
00098 else
00099 {
00100 nItems = CSLCount(papszStrList);
00101 papszStrList = (char**)CPLRealloc(papszStrList,
00102 (nItems+2)*sizeof(char*));
00103 }
00104
00105
00106 papszStrList[nItems] = CPLStrdup(pszNewString);
00107 papszStrList[nItems+1] = NULL;
00108
00109 return papszStrList;
00110 }
00111
00112 00113 00114 00115 00116
00117 int CSLCount(char **papszStrList)
00118 {
00119 int nItems=0;
00120
00121 if (papszStrList)
00122 {
00123 while(*papszStrList != NULL)
00124 {
00125 nItems++;
00126 papszStrList++;
00127 }
00128 }
00129
00130 return nItems;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 const char * CSLGetField( char ** papszStrList, int iField )
00144
00145 {
00146 int i;
00147
00148 if( papszStrList == NULL || iField < 0 )
00149 return( "" );
00150
00151 for( i = 0; i < iField+1; i++ )
00152 {
00153 if( papszStrList[i] == NULL )
00154 return "";
00155 }
00156
00157 return( papszStrList[iField] );
00158 }
00159
00160 00161 00162 00163 00164
00165 void CSLDestroy(char **papszStrList)
00166 {
00167 char **papszPtr;
00168
00169 if (papszStrList)
00170 {
00171 papszPtr = papszStrList;
00172 while(*papszPtr != NULL)
00173 {
00174 CPLFree(*papszPtr);
00175 papszPtr++;
00176 }
00177
00178 CPLFree(papszStrList);
00179 }
00180 }
00181
00182
00183 00184 00185 00186 00187
00188 char **CSLDuplicate(char **papszStrList)
00189 {
00190 char **papszNewList, **papszSrc, **papszDst;
00191 int nLines;
00192
00193 nLines = CSLCount(papszStrList);
00194
00195 if (nLines == 0)
00196 return NULL;
00197
00198 papszNewList = (char **)CPLMalloc((nLines+1)*sizeof(char*));
00199 papszSrc = papszStrList;
00200 papszDst = papszNewList;
00201
00202 while(*papszSrc != NULL)
00203 {
00204 *papszDst = CPLStrdup(*papszSrc);
00205
00206 papszSrc++;
00207 papszDst++;
00208 }
00209 *papszDst = NULL;
00210
00211 return papszNewList;
00212 }
00213
00214 00215 00216 00217 00218 00219 00220
00221 char **CSLLoad(const char *pszFname)
00222 {
00223 FILE *fp;
00224 const char *pszLine;
00225 char **papszStrList=NULL;
00226
00227 fp = VSIFOpen(pszFname, "rt");
00228
00229 if (fp)
00230 {
00231 while(!VSIFEof(fp))
00232 {
00233 if ( (pszLine = CPLReadLine(fp)) != NULL )
00234 {
00235 papszStrList = CSLAddString(papszStrList, pszLine);
00236 }
00237 }
00238
00239 VSIFClose(fp);
00240 }
00241 else
00242 {
00243
00244 CPLError(CE_Failure, CPLE_OpenFailed,
00245 "CSLLoad(%s): %s", pszFname, strerror(errno));
00246 }
00247
00248 return papszStrList;
00249 }
00250
00251 00252 00253 00254 00255 00256 00257 00258
00259 int CSLSave(char **papszStrList, const char *pszFname)
00260 {
00261 FILE *fp;
00262 int nLines=0;
00263
00264 if (papszStrList)
00265 {
00266 if ((fp = VSIFOpen(pszFname, "wt")) != NULL)
00267 {
00268 while(*papszStrList != NULL)
00269 {
00270 if (VSIFPuts(*papszStrList, fp) == EOF ||
00271 VSIFPutc('\n', fp) == EOF)
00272 {
00273 CPLError(CE_Failure, CPLE_FileIO,
00274 "CSLSave(%s): %s", pszFname,
00275 strerror(errno));
00276 break;
00277 }
00278
00279 nLines++;
00280 papszStrList++;
00281 }
00282
00283 VSIFClose(fp);
00284 }
00285 else
00286 {
00287
00288 CPLError(CE_Failure, CPLE_OpenFailed,
00289 "CSLSave(%s): %s", pszFname, strerror(errno));
00290 }
00291 }
00292
00293 return nLines;
00294 }
00295
00296 00297 00298 00299 00300 00301 00302 00303
00304 int CSLPrint(char **papszStrList, FILE *fpOut)
00305 {
00306 int nLines=0;
00307
00308 if (fpOut == NULL)
00309 fpOut = stdout;
00310
00311 if (papszStrList)
00312 {
00313 while(*papszStrList != NULL)
00314 {
00315 VSIFPrintf(fpOut, "%s\n", *papszStrList);
00316 nLines++;
00317 papszStrList++;
00318 }
00319 }
00320
00321 return nLines;
00322 }
00323
00324
00325 00326 00327 00328 00329 00330 00331 00332 00333 00334 00335 00336 00337
00338 char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
00339 char **papszNewLines)
00340 {
00341 int i, nSrcLines, nDstLines, nToInsert;
00342 char **ppszSrc, **ppszDst;
00343
00344 if (papszNewLines == NULL ||
00345 ( nToInsert = CSLCount(papszNewLines) ) == 0)
00346 return papszStrList;
00347
00348 nSrcLines = CSLCount(papszStrList);
00349 nDstLines = nSrcLines + nToInsert;
00350
00351
00352 papszStrList = (char**)CPLRealloc(papszStrList,
00353 (nDstLines+1)*sizeof(char*));
00354
00355 00356 00357
00358 papszStrList[nSrcLines] = NULL;
00359
00360 00361 00362 00363
00364 if (nInsertAtLineNo == -1 || nInsertAtLineNo > nSrcLines)
00365 nInsertAtLineNo = nSrcLines;
00366
00367 ppszSrc = papszStrList + nSrcLines;
00368 ppszDst = papszStrList + nDstLines;
00369
00370 for (i=nSrcLines; i>=nInsertAtLineNo; i--)
00371 {
00372 *ppszDst = *ppszSrc;
00373 ppszDst--;
00374 ppszSrc--;
00375 }
00376
00377
00378 ppszSrc = papszNewLines;
00379 ppszDst = papszStrList + nInsertAtLineNo;
00380
00381 for (; *ppszSrc != NULL; ppszSrc++, ppszDst++)
00382 {
00383 *ppszDst = CPLStrdup(*ppszSrc);
00384 }
00385
00386 return papszStrList;
00387 }
00388
00389 00390 00391 00392 00393 00394 00395 00396 00397 00398 00399 00400
00401 char **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
00402 char *pszNewLine)
00403 {
00404 char *apszList[2];
00405
00406 00407
00408 apszList[0] = pszNewLine;
00409 apszList[1] = NULL;
00410
00411 return CSLInsertStrings(papszStrList, nInsertAtLineNo, apszList);
00412 }
00413
00414
00415 00416 00417 00418 00419 00420 00421 00422 00423 00424 00425 00426 00427 00428 00429 00430
00431 char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
00432 int nNumToRemove, char ***ppapszRetStrings)
00433 {
00434 int i, nSrcLines, nDstLines;
00435 char **ppszSrc, **ppszDst;
00436
00437 nSrcLines = CSLCount(papszStrList);
00438 nDstLines = nSrcLines - nNumToRemove;
00439
00440 if (nNumToRemove < 1 || nSrcLines == 0)
00441 return papszStrList;
00442
00443 00444 00445
00446 if (nDstLines < 1)
00447 {
00448 CSLDestroy(papszStrList);
00449 return NULL;
00450 }
00451
00452
00453 00454 00455 00456
00457 ppszDst = papszStrList + nFirstLineToDelete;
00458
00459 if (ppapszRetStrings == NULL)
00460 {
00461 00462
00463 for (i=0; i < nNumToRemove; i++)
00464 {
00465 CPLFree(*ppszDst);
00466 *ppszDst = NULL;
00467 }
00468 }
00469 else
00470 {
00471 00472
00473 *ppapszRetStrings = (char **)CPLCalloc(nNumToRemove+1, sizeof(char*));
00474
00475 for (i=0; i < nNumToRemove; i++)
00476 {
00477 (*ppapszRetStrings)[i] = *ppszDst;
00478 *ppszDst = NULL;
00479 ppszDst++;
00480 }
00481 }
00482
00483
00484 00485
00486 if (nFirstLineToDelete == -1 || nFirstLineToDelete > nSrcLines)
00487 nFirstLineToDelete = nDstLines;
00488
00489 ppszSrc = papszStrList + nFirstLineToDelete + nNumToRemove;
00490 ppszDst = papszStrList + nFirstLineToDelete;
00491
00492 for ( ; *ppszSrc != NULL; ppszSrc++, ppszDst++)
00493 {
00494 *ppszDst = *ppszSrc;
00495 }
00496
00497 *ppszDst = *ppszSrc;
00498
00499 00500 00501 00502
00503
00504 return papszStrList;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 int CSLFindString( char ** papszList, const char * pszTarget )
00516
00517 {
00518 int i;
00519
00520 if( papszList == NULL )
00521 return -1;
00522
00523 for( i = 0; papszList[i] != NULL; i++ )
00524 {
00525 if( EQUAL(papszList[i],pszTarget) )
00526 return i;
00527 }
00528
00529 return -1;
00530 }
00531
00532 00533 00534 00535 00536 00537
00538 char **CSLTokenizeString( const char *pszString )
00539 {
00540 return CSLTokenizeStringComplex( pszString, " ", TRUE, FALSE );
00541 }
00542
00543
00544
00545
00546
00547
00548
00549 char ** CSLTokenizeStringComplex( const char * pszString,
00550 const char * pszDelimiters,
00551 int bHonourStrings, int bAllowEmptyTokens )
00552
00553 {
00554 char **papszRetList = NULL;
00555 char *pszToken;
00556 int nTokenMax, nTokenLen;
00557
00558 pszToken = (char *) CPLCalloc(10,1);
00559 nTokenMax = 10;
00560
00561 while( pszString != NULL && *pszString != '\0' )
00562 {
00563 int bInString = FALSE;
00564
00565 nTokenLen = 0;
00566
00567
00568 for( ; *pszString != '\0'; pszString++ )
00569 {
00570
00571
00572 if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
00573 {
00574 pszString++;
00575 break;
00576 }
00577
00578 00579 00580
00581 if( bHonourStrings && *pszString == '"' )
00582 {
00583 if( bInString )
00584 {
00585 bInString = FALSE;
00586 continue;
00587 }
00588 else
00589 {
00590 bInString = TRUE;
00591 continue;
00592 }
00593 }
00594
00595 00596
00597 if( bInString && pszString[0] == '\\' && pszString[1] == '"' )
00598 {
00599 pszString++;
00600 }
00601
00602
00603 else if( bInString
00604 && pszString[0] == '\\' && pszString[1] == '\\' )
00605 {
00606 pszString++;
00607 }
00608
00609 if( nTokenLen >= nTokenMax-1 )
00610 {
00611 nTokenMax = nTokenMax * 2 + 10;
00612 pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
00613 }
00614
00615 pszToken[nTokenLen] = *pszString;
00616 nTokenLen++;
00617 }
00618
00619 pszToken[nTokenLen] = '\0';
00620
00621 if( pszToken[0] != '\0' || bAllowEmptyTokens )
00622 {
00623 papszRetList = CSLAddString( papszRetList, pszToken );
00624 }
00625
00626 00627 00628
00629 if ( *pszString == '\0' && bAllowEmptyTokens &&
00630 strchr(pszDelimiters, *(pszString-1)) )
00631 {
00632 papszRetList = CSLAddString( papszRetList, "" );
00633 }
00634 }
00635
00636 if( papszRetList == NULL )
00637 papszRetList = (char **) CPLCalloc(sizeof(char *),1);
00638
00639 CPLFree( pszToken );
00640
00641 return papszRetList;
00642 }
00643
00644 00645 00646 00647 00648 00649 00650 00651 00652 00653
00654 00655
00656 #define CPLSPrintf_BUF_SIZE 8000
00657 #define CPLSPrintf_BUF_Count 10
00658 static char gszCPLSPrintfBuffer[CPLSPrintf_BUF_Count][CPLSPrintf_BUF_SIZE];
00659 static int gnCPLSPrintfBuffer = 0;
00660
00661 const char *CPLSPrintf(char *fmt, ...)
00662 {
00663 va_list args;
00664
00665 va_start(args, fmt);
00666 vsprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], fmt, args);
00667 va_end(args);
00668
00669 int nCurrent = gnCPLSPrintfBuffer;
00670
00671 if (++gnCPLSPrintfBuffer == CPLSPrintf_BUF_Count)
00672 gnCPLSPrintfBuffer = 0;
00673
00674 return gszCPLSPrintfBuffer[nCurrent];
00675 }
00676
00677 00678 00679 00680 00681 00682 00683
00684 char **CSLAppendPrintf(char **papszStrList, char *fmt, ...)
00685 {
00686 va_list args;
00687
00688 va_start(args, fmt);
00689 vsprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], fmt, args);
00690 va_end(args);
00691
00692 int nCurrent = gnCPLSPrintfBuffer;
00693
00694 if (++gnCPLSPrintfBuffer == CPLSPrintf_BUF_Count)
00695 gnCPLSPrintfBuffer = 0;
00696
00697 return CSLAddString(papszStrList, gszCPLSPrintfBuffer[nCurrent]);
00698 }
00699
00700
00701 00702 00703 00704 00705 00706 00707 00708 00709 00710 00711 00712 00713 00714
00715 const char *CSLFetchNameValue(char **papszStrList, const char *pszName)
00716 {
00717 int nLen;
00718
00719 if (papszStrList == NULL || pszName == NULL)
00720 return NULL;
00721
00722 nLen = strlen(pszName);
00723 while(*papszStrList != NULL)
00724 {
00725 if (EQUALN(*papszStrList, pszName, nLen)
00726 && ( (*papszStrList)[nLen] == '=' ||
00727 (*papszStrList)[nLen] == ':' ) )
00728 {
00729 return (*papszStrList)+nLen+1;
00730 }
00731 papszStrList++;
00732 }
00733 return NULL;
00734 }
00735
00736 00737 00738
00739
00760 const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
00761
00762 {
00763 int i;
00764 const char *pszValue;
00765
00766 for( i = 0; pszNameValue[i] != '\0'; i++ )
00767 {
00768 if( pszNameValue[i] == '=' || pszNameValue[i] == ':' )
00769 {
00770 pszValue = pszNameValue + i + 1;
00771 while( *pszValue == ' ' || *pszValue == '\t' )
00772 pszValue++;
00773
00774 if( ppszKey != NULL )
00775 {
00776 *ppszKey = (char *) CPLMalloc(i+1);
00777 strncpy( *ppszKey, pszNameValue, i );
00778 (*ppszKey)[i] = '\0';
00779 while( i > 0 &&
00780 ( (*ppszKey)[i] == ' ' || (*ppszKey)[i] == '\t') )
00781 {
00782 (*ppszKey)[i] = '\0';
00783 i--;
00784 }
00785 }
00786
00787 return pszValue;
00788 }
00789
00790 }
00791
00792 return NULL;
00793 }
00794
00795 00796 00797 00798 00799 00800 00801 00802 00803 00804 00805 00806 00807 00808 00809
00810 char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName)
00811 {
00812 int nLen;
00813 char **papszValues = NULL;
00814
00815 if (papszStrList == NULL || pszName == NULL)
00816 return NULL;
00817
00818 nLen = strlen(pszName);
00819 while(*papszStrList != NULL)
00820 {
00821 if (EQUALN(*papszStrList, pszName, nLen)
00822 && ( (*papszStrList)[nLen] == '=' ||
00823 (*papszStrList)[nLen] == ':' ) )
00824 {
00825 papszValues = CSLAddString(papszValues,
00826 (*papszStrList)+nLen+1);
00827 }
00828 papszStrList++;
00829 }
00830
00831 return papszValues;
00832 }
00833
00834
00835 00836 00837 00838 00839 00840 00841 00842 00843 00844 00845 00846 00847
00848 char **CSLAddNameValue(char **papszStrList,
00849 const char *pszName, const char *pszValue)
00850 {
00851 const char *pszLine;
00852
00853 if (pszName == NULL || pszValue==NULL)
00854 return papszStrList;
00855
00856 pszLine = CPLSPrintf("%s=%s", pszName, pszValue);
00857
00858 return CSLAddString(papszStrList, pszLine);
00859 }
00860
00861 00862 00863 00864 00865 00866 00867 00868 00869 00870 00871 00872
00873 char **CSLSetNameValue(char **papszList,
00874 const char *pszName, const char *pszValue)
00875 {
00876 char **papszPtr;
00877 int nLen;
00878
00879 if (pszName == NULL || pszValue==NULL)
00880 return papszList;
00881
00882 nLen = strlen(pszName);
00883 papszPtr = papszList;
00884 while(papszPtr && *papszPtr != NULL)
00885 {
00886 if (EQUALN(*papszPtr, pszName, nLen)
00887 && ( (*papszPtr)[nLen] == '=' ||
00888 (*papszPtr)[nLen] == ':' ) )
00889 {
00890 00891 00892
00893 char cSep;
00894 cSep = (*papszPtr)[nLen];
00895
00896 free(*papszPtr);
00897 *papszPtr = CPLStrdup(CPLSPrintf("%s%c%s", pszName,
00898 cSep, pszValue));
00899
00900 return papszList;
00901 }
00902 papszPtr++;
00903 }
00904
00905 00906
00907 return CSLAddString(papszList,
00908 CPLSPrintf("%s=%s", pszName, pszValue));
00909 }