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