Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

cpl_string.cpp

00001 /**********************************************************************
00002  * $Id: cpl_string_cpp-source.html,v 1.8 2001/07/05 13:24:08 warmerda Exp $
00003  *
00004  * Name:     cpl_string.cpp
00005  * Project:  CPL - Common Portability Library
00006  * Purpose:  String and Stringlist manipulation functions.
00007  * Author:   Daniel Morissette, danmo@videotron.ca
00008  *
00009  **********************************************************************
00010  * Copyright (c) 1998, Daniel Morissette
00011  *
00012  * Permission is hereby granted, free of charge, to any person obtaining a
00013  * copy of this software and associated documentation files (the "Software"),
00014  * to deal in the Software without restriction, including without limitation
00015  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00016  * and/or sell copies of the Software, and to permit persons to whom the
00017  * Software is furnished to do so, subject to the following conditions:
00018  * 
00019  * The above copyright notice and this permission notice shall be included
00020  * in all copies or substantial portions of the Software.
00021  * 
00022  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00023  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00024  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00025  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00026  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00027  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
00028  * DEALINGS IN THE SOFTWARE.
00029  **********************************************************************
00030  *
00031  * $Log: cpl_string_cpp-source.html,v $
00031  * Revision 1.8  2001/07/05 13:24:08  warmerda
00031  * *** empty log message ***
00031  *
00032  * Revision 1.15  2001/01/19 21:16:41  warmerda
00033  * expanded tabs
00034  *
00035  * Revision 1.14  2000/10/06 15:19:03  warmerda
00036  * added CPLSetNameValueSeparator
00037  *
00038  * Revision 1.13  2000/08/22 17:47:50  warmerda
00039  * Fixed declaration of gnCPLSPrintfBuffer.
00040  *
00041  * Revision 1.12  2000/08/18 21:20:54  svillene
00042  * *** empty log message ***
00043  *
00044  * Revision 1.11  2000/03/30 05:38:48  warmerda
00045  * added CPLParseNameValue
00046  *
00047  * Revision 1.10  1999/06/26 14:05:10  warmerda
00048  * Added CSLFindString().
00049  *
00050  * Revision 1.9  1999/04/28 02:33:02  danmo
00051  * CSLInsertStrings(): make sure papszStrList is NULL-terminated properly
00052  *
00053  * Revision 1.8  1999/03/12 21:19:49  danmo
00054  * Fixed TokenizeStringComplex() vs strings ending with empty token,
00055  * and fixed a problem with CSLAdd/SetNameValue() vs empty string list.
00056  *
00057  * Revision 1.7  1999/03/09 21:29:57  warmerda
00058  * Added backslash escaping within string constants for tokenize function.
00059  *
00060  * Revision 1.6  1999/02/25 04:40:46  danmo
00061  * Modif. CSLLoad() to use CPLReadLine() (better handling of newlines)
00062  *
00063  * Revision 1.5  1999/02/17 01:41:58  warmerda
00064  * Added CSLGetField
00065  *
00066  * Revision 1.4  1998/12/15 19:01:40  warmerda
00067  * *** empty log message ***
00068  *
00069  * Revision 1.3  1998/12/05 23:04:21  warmerda
00070  * Use EQUALN() instead of strincmp() which doesn't exist on Linux.
00071  *
00072  * Revision 1.2  1998/12/04 21:40:42  danmo
00073  * Added more Name=Value manipulation fuctions
00074  *
00075  * Revision 1.1  1998/12/03 18:26:02  warmerda
00076  * New
00077  *
00078  **********************************************************************/
00079 
00080 #include "cpl_string.h"
00081 #include "cpl_vsi.h"
00082 
00083 /*=====================================================================
00084                     StringList manipulation functions.
00085  =====================================================================*/
00086 
00087 /**********************************************************************
00088  *                       CSLAddString()
00089  *
00090  * Append a string to a StringList and return a pointer to the modified
00091  * StringList.
00092  * If the input StringList is NULL, then a new StringList is created.
00093  **********************************************************************/
00094 char **CSLAddString(char **papszStrList, const char *pszNewString)
00095 {
00096     int nItems=0;
00097 
00098     if (pszNewString == NULL)
00099         return papszStrList;    /* Nothing to do!*/
00100 
00101     /* Allocate room for the new string */
00102     if (papszStrList == NULL)
00103         papszStrList = (char**) CPLCalloc(2,sizeof(char*));
00104     else
00105     {
00106         nItems = CSLCount(papszStrList);
00107         papszStrList = (char**)CPLRealloc(papszStrList, 
00108                                           (nItems+2)*sizeof(char*));
00109     }
00110 
00111     /* Copy the string in the list */
00112     papszStrList[nItems] = CPLStrdup(pszNewString);
00113     papszStrList[nItems+1] = NULL;
00114 
00115     return papszStrList;
00116 }
00117 
00118 /**********************************************************************
00119  *                       CSLCount()
00120  *
00121  * Return the number of lines in a Stringlist.
00122  **********************************************************************/
00123 int CSLCount(char **papszStrList)
00124 {
00125     int nItems=0;
00126 
00127     if (papszStrList)
00128     {
00129         while(*papszStrList != NULL)
00130         {
00131             nItems++;
00132             papszStrList++;
00133         }
00134     }
00135 
00136     return nItems;
00137 }
00138 
00139 
00140 /************************************************************************/
00141 /*                            CSLGetField()                             */
00142 /*                                                                      */
00143 /*      Fetches the indicated field, being careful not to crash if      */
00144 /*      the field doesn't exist within this string list.  The           */
00145 /*      returned pointer should not be freed, and doesn't               */
00146 /*      necessarily last long.                                          */
00147 /************************************************************************/
00148 
00149 const char * CSLGetField( char ** papszStrList, int iField )
00150 
00151 {
00152     int         i;
00153 
00154     if( papszStrList == NULL || iField < 0 )
00155         return( "" );
00156 
00157     for( i = 0; i < iField+1; i++ )
00158     {
00159         if( papszStrList[i] == NULL )
00160             return "";
00161     }
00162 
00163     return( papszStrList[iField] );
00164 }
00165 
00166 /**********************************************************************
00167  *                       CSLDestroy()
00168  *
00169  * Free all memory used by a StringList.
00170  **********************************************************************/
00171 void CSLDestroy(char **papszStrList)
00172 {
00173     char **papszPtr;
00174 
00175     if (papszStrList)
00176     {
00177         papszPtr = papszStrList;
00178         while(*papszPtr != NULL)
00179         {
00180             CPLFree(*papszPtr);
00181             papszPtr++;
00182         }
00183 
00184         CPLFree(papszStrList);
00185     }
00186 }
00187 
00188 
00189 /**********************************************************************
00190  *                       CSLDuplicate()
00191  *
00192  * Allocate and return a copy of a StringList.
00193  **********************************************************************/
00194 char    **CSLDuplicate(char **papszStrList)
00195 {
00196     char **papszNewList, **papszSrc, **papszDst;
00197     int  nLines;
00198 
00199     nLines = CSLCount(papszStrList);
00200 
00201     if (nLines == 0)
00202         return NULL;
00203 
00204     papszNewList = (char **)CPLMalloc((nLines+1)*sizeof(char*));
00205     papszSrc = papszStrList;
00206     papszDst = papszNewList;
00207 
00208     while(*papszSrc != NULL)
00209     {
00210         *papszDst = CPLStrdup(*papszSrc);
00211 
00212         papszSrc++;
00213         papszDst++;
00214     }
00215     *papszDst = NULL;
00216 
00217     return papszNewList;
00218 }
00219 
00220 /**********************************************************************
00221  *                       CSLLoad()
00222  *
00223  * Load a test file into a stringlist.
00224  *
00225  * Lines are limited in length by the size fo the CPLReadLine() buffer.
00226  **********************************************************************/
00227 char **CSLLoad(const char *pszFname)
00228 {
00229     FILE        *fp;
00230     const char  *pszLine;
00231     char        **papszStrList=NULL;
00232 
00233     fp = VSIFOpen(pszFname, "rt");
00234 
00235     if (fp)
00236     {
00237         while(!VSIFEof(fp))
00238         {
00239             if ( (pszLine = CPLReadLine(fp)) != NULL )
00240             {
00241                 papszStrList = CSLAddString(papszStrList, pszLine);
00242             }
00243         }
00244 
00245         VSIFClose(fp);
00246     }
00247     else
00248     {
00249         /* Unable to open file */
00250         CPLError(CE_Failure, CPLE_OpenFailed,
00251                  "CSLLoad(%s): %s", pszFname, strerror(errno));
00252     }
00253 
00254     return papszStrList;
00255 }
00256 
00257 /**********************************************************************
00258  *                       CSLSave()
00259  *
00260  * Write a stringlist to a text file.
00261  *
00262  * Returns the number of lines written, or 0 if the file could not 
00263  * be written.
00264  **********************************************************************/
00265 int  CSLSave(char **papszStrList, const char *pszFname)
00266 {
00267     FILE    *fp;
00268     int     nLines=0;
00269 
00270     if (papszStrList)
00271     {
00272         if ((fp = VSIFOpen(pszFname, "wt")) != NULL)
00273         {
00274             while(*papszStrList != NULL)
00275             {
00276                 if (VSIFPuts(*papszStrList, fp) == EOF ||
00277                     VSIFPutc('\n', fp) == EOF)
00278                 {
00279                     CPLError(CE_Failure, CPLE_FileIO,
00280                              "CSLSave(%s): %s", pszFname, 
00281                              strerror(errno));
00282                     break;  /* A Problem happened... abort */
00283                 }
00284 
00285                 nLines++;
00286                 papszStrList++;
00287             }
00288 
00289             VSIFClose(fp);
00290         }
00291         else
00292         {
00293             /* Unable to open file */
00294             CPLError(CE_Failure, CPLE_OpenFailed,
00295                      "CSLSave(%s): %s", pszFname, strerror(errno));
00296         }
00297     }
00298 
00299     return nLines;
00300 }
00301 
00302 /**********************************************************************
00303  *                       CSLPrint()
00304  *
00305  * Print a StringList to fpOut.  If fpOut==NULL, then output is sent
00306  * to stdout.
00307  *
00308  * Returns the number of lines printed.
00309  **********************************************************************/
00310 int  CSLPrint(char **papszStrList, FILE *fpOut)
00311 {
00312     int     nLines=0;
00313 
00314     if (fpOut == NULL)
00315         fpOut = stdout;
00316 
00317     if (papszStrList)
00318     {
00319         while(*papszStrList != NULL)
00320         {
00321             VSIFPrintf(fpOut, "%s\n", *papszStrList);
00322             nLines++;
00323             papszStrList++;
00324         }
00325     }
00326 
00327     return nLines;
00328 }
00329 
00330 
00331 /**********************************************************************
00332  *                       CSLInsertStrings()
00333  *
00334  * Copies the contents of a StringList inside another StringList 
00335  * before the specified line.
00336  *
00337  * nInsertAtLineNo is a 0-based line index before which the new strings
00338  * should be inserted.  If this value is -1 or is larger than the actual 
00339  * number of strings in the list then the strings are added at the end
00340  * of the source StringList.
00341  *
00342  * Returns the modified StringList.
00343  **********************************************************************/
00344 char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo, 
00345                         char **papszNewLines)
00346 {
00347     int     i, nSrcLines, nDstLines, nToInsert;
00348     char    **ppszSrc, **ppszDst;
00349 
00350     if (papszNewLines == NULL ||
00351         ( nToInsert = CSLCount(papszNewLines) ) == 0)
00352         return papszStrList;    /* Nothing to do!*/
00353 
00354     nSrcLines = CSLCount(papszStrList);
00355     nDstLines = nSrcLines + nToInsert;
00356 
00357     /* Allocate room for the new strings */
00358     papszStrList = (char**)CPLRealloc(papszStrList, 
00359                                       (nDstLines+1)*sizeof(char*));
00360 
00361     /* Make sure the array is NULL-terminated... it may not be if
00362      * papszStrList was NULL before Realloc()
00363      */
00364     papszStrList[nSrcLines] = NULL;
00365 
00366     /* Make some room in the original list at the specified location 
00367      * Note that we also have to move the NULL pointer at the end of
00368      * the source StringList.
00369      */
00370     if (nInsertAtLineNo == -1 || nInsertAtLineNo > nSrcLines)
00371         nInsertAtLineNo = nSrcLines;
00372 
00373     ppszSrc = papszStrList + nSrcLines;
00374     ppszDst = papszStrList + nDstLines;
00375 
00376     for (i=nSrcLines; i>=nInsertAtLineNo; i--)
00377     {
00378         *ppszDst = *ppszSrc;
00379         ppszDst--;
00380         ppszSrc--;
00381     }
00382 
00383     /* Copy the strings to the list */
00384     ppszSrc = papszNewLines;
00385     ppszDst = papszStrList + nInsertAtLineNo;
00386 
00387     for (; *ppszSrc != NULL; ppszSrc++, ppszDst++)
00388     {
00389         *ppszDst = CPLStrdup(*ppszSrc);
00390     }
00391     
00392     return papszStrList;
00393 }
00394 
00395 /**********************************************************************
00396  *                       CSLInsertString()
00397  *
00398  * Insert a string at a given line number inside a StringList 
00399  *
00400  * nInsertAtLineNo is a 0-based line index before which the new string
00401  * should be inserted.  If this value is -1 or is larger than the actual 
00402  * number of strings in the list then the string is added at the end
00403  * of the source StringList.
00404  *
00405  * Returns the modified StringList.
00406  **********************************************************************/
00407 char **CSLInsertString(char **papszStrList, int nInsertAtLineNo, 
00408                            char *pszNewLine)
00409 {
00410     char *apszList[2];
00411 
00412     /* Create a temporary StringList and call CSLInsertStrings()
00413      */
00414     apszList[0] = pszNewLine;
00415     apszList[1] = NULL;
00416 
00417     return CSLInsertStrings(papszStrList, nInsertAtLineNo, apszList);
00418 }
00419 
00420 
00421 /**********************************************************************
00422  *                       CSLRemoveStrings()
00423  *
00424  * Remove strings inside a StringList 
00425  *
00426  * nFirstLineToDelete is the 0-based line index of the first line to 
00427  * remove. If this value is -1 or is larger than the actual 
00428  * number of strings in list then the nNumToRemove last strings are
00429  * removed.
00430  *
00431  * If ppapszRetStrings != NULL then the deleted strings won't be
00432  * free'd, they will be stored in a new StringList and the pointer to
00433  * this new list will be returned in *ppapszRetStrings.
00434  *
00435  * Returns the modified StringList.
00436  **********************************************************************/
00437 char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
00438                         int nNumToRemove, char ***ppapszRetStrings)
00439 {
00440     int     i, nSrcLines, nDstLines;
00441     char    **ppszSrc, **ppszDst;
00442 
00443     nSrcLines = CSLCount(papszStrList);
00444     nDstLines = nSrcLines - nNumToRemove;
00445 
00446     if (nNumToRemove < 1 || nSrcLines == 0)
00447         return papszStrList;    /* Nothing to do!*/
00448 
00449     /* If operation will result in an empty StringList then don't waste
00450      * time here!
00451      */
00452     if (nDstLines < 1)
00453     {
00454         CSLDestroy(papszStrList);
00455         return NULL;
00456     }
00457 
00458     
00459     /* Remove lines from the source StringList...
00460      * Either free() each line or store them to a new StringList depending on
00461      * the caller's choice.
00462      */
00463     ppszDst = papszStrList + nFirstLineToDelete;
00464 
00465     if (ppapszRetStrings == NULL)
00466     {
00467         /* free() all the strings that will be removed.
00468          */
00469         for (i=0; i < nNumToRemove; i++)
00470         {
00471             CPLFree(*ppszDst);
00472             *ppszDst = NULL;
00473         }
00474     }
00475     else
00476     {
00477         /* Store the strings to remove in a new StringList
00478          */
00479         *ppapszRetStrings = (char **)CPLCalloc(nNumToRemove+1, sizeof(char*));
00480 
00481         for (i=0; i < nNumToRemove; i++)
00482         {
00483             (*ppapszRetStrings)[i] = *ppszDst;
00484             *ppszDst = NULL;
00485             ppszDst++;
00486         }
00487     }
00488 
00489 
00490     /* Shift down all the lines that follow the lines to remove.
00491      */
00492     if (nFirstLineToDelete == -1 || nFirstLineToDelete > nSrcLines)
00493         nFirstLineToDelete = nDstLines;
00494 
00495     ppszSrc = papszStrList + nFirstLineToDelete + nNumToRemove;
00496     ppszDst = papszStrList + nFirstLineToDelete;
00497 
00498     for ( ; *ppszSrc != NULL; ppszSrc++, ppszDst++)
00499     {
00500         *ppszDst = *ppszSrc;
00501     }
00502     /* Move the NULL pointer at the end of the StringList     */
00503     *ppszDst = *ppszSrc; 
00504 
00505     /* At this point, we could realloc() papszStrList to a smaller size, but
00506      * since this array will likely grow again in further operations on the
00507      * StringList we'll leave it as it is.
00508      */
00509 
00510     return papszStrList;
00511 }
00512 
00513 /************************************************************************/
00514 /*                           CSLFindString()                            */
00515 /*                                                                      */
00516 /*      Find a string within a string list.  The string must match      */
00517 /*      the full length, but the comparison is case insensitive.        */
00518 /*      Return -1 on failure.                                           */
00519 /************************************************************************/
00520 
00521 int CSLFindString( char ** papszList, const char * pszTarget )
00522 
00523 {
00524     int         i;
00525 
00526     if( papszList == NULL )
00527         return -1;
00528 
00529     for( i = 0; papszList[i] != NULL; i++ )
00530     {
00531         if( EQUAL(papszList[i],pszTarget) )
00532             return i;
00533     }
00534 
00535     return -1;
00536 }
00537 
00538 /**********************************************************************
00539  *                       CSLTokenizeString()
00540  *
00541  * Tokenizes a string and returns a StringList with one string for
00542  * each token.
00543  **********************************************************************/
00544 char    **CSLTokenizeString( const char *pszString )
00545 {
00546     return CSLTokenizeStringComplex( pszString, " ", TRUE, FALSE );
00547 }
00548 
00549 /************************************************************************/
00550 /*                      CSLTokenizeStringComplex()                      */
00551 /*                                                                      */
00552 /*      The ultimate tokenizer?                                         */
00553 /************************************************************************/
00554 
00555 char ** CSLTokenizeStringComplex( const char * pszString,
00556                                   const char * pszDelimiters,
00557                                   int bHonourStrings, int bAllowEmptyTokens )
00558 
00559 {
00560     char        **papszRetList = NULL;
00561     char        *pszToken;
00562     int         nTokenMax, nTokenLen;
00563 
00564     pszToken = (char *) CPLCalloc(10,1);
00565     nTokenMax = 10;
00566     
00567     while( pszString != NULL && *pszString != '\0' )
00568     {
00569         int     bInString = FALSE;
00570 
00571         nTokenLen = 0;
00572         
00573         /* Try to find the next delimeter, marking end of token */
00574         for( ; *pszString != '\0'; pszString++ )
00575         {
00576 
00577             /* End if this is a delimeter skip it and break. */
00578             if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
00579             {
00580                 pszString++;
00581                 break;
00582             }
00583             
00584             /* If this is a quote, and we are honouring constant
00585                strings, then process the constant strings, with out delim
00586                but don't copy over the quotes */
00587             if( bHonourStrings && *pszString == '"' )
00588             {
00589                 if( bInString )
00590                 {
00591                     bInString = FALSE;
00592                     continue;
00593                 }
00594                 else
00595                 {
00596                     bInString = TRUE;
00597                     continue;
00598                 }
00599             }
00600 
00601             /* Within string constants we allow for escaped quotes, but
00602                in processing them we will unescape the quotes */
00603             if( bInString && pszString[0] == '\\' && pszString[1] == '"' )
00604             {
00605                 pszString++;
00606             }
00607 
00608             /* Within string constants a \\ sequence reduces to \ */
00609             else if( bInString
00610                      && pszString[0] == '\\' && pszString[1] == '\\' )
00611             {
00612                 pszString++;
00613             }
00614 
00615             if( nTokenLen >= nTokenMax-1 )
00616             {
00617                 nTokenMax = nTokenMax * 2 + 10;
00618                 pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
00619             }
00620 
00621             pszToken[nTokenLen] = *pszString;
00622             nTokenLen++;
00623         }
00624 
00625         pszToken[nTokenLen] = '\0';
00626 
00627         if( pszToken[0] != '\0' || bAllowEmptyTokens )
00628         {
00629             papszRetList = CSLAddString( papszRetList, pszToken );
00630         }
00631 
00632         /* If the last token is an empty token, then we have to catch
00633          * it now, otherwise we won't reenter the loop and it will be lost. 
00634          */
00635         if ( *pszString == '\0' && bAllowEmptyTokens &&
00636              strchr(pszDelimiters, *(pszString-1)) )
00637         {
00638             papszRetList = CSLAddString( papszRetList, "" );
00639         }
00640     }
00641 
00642     if( papszRetList == NULL )
00643         papszRetList = (char **) CPLCalloc(sizeof(char *),1);
00644 
00645     CPLFree( pszToken );
00646 
00647     return papszRetList;
00648 }
00649 
00650 /**********************************************************************
00651  *                       CPLSPrintf()
00652  *
00653  * My own version of CPLSPrintf() that works with 10 static buffer.
00654  *
00655  * It returns a ref. to a static buffer that should not be freed and
00656  * is valid only until the next call to CPLSPrintf().
00657  *
00658  * NOTE: This function should move to cpl_conv.cpp. 
00659  **********************************************************************/
00660 /* For now, assume that a 8000 chars buffer will be enough.
00661  */
00662 #define CPLSPrintf_BUF_SIZE 8000
00663 #define CPLSPrintf_BUF_Count 10
00664 static char gszCPLSPrintfBuffer[CPLSPrintf_BUF_Count][CPLSPrintf_BUF_SIZE];
00665 static int gnCPLSPrintfBuffer = 0;
00666 
00667 const char *CPLSPrintf(char *fmt, ...)
00668 {
00669     va_list args;
00670 
00671     va_start(args, fmt);
00672     vsprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], fmt, args);
00673     va_end(args);
00674     
00675    int nCurrent = gnCPLSPrintfBuffer;
00676 
00677     if (++gnCPLSPrintfBuffer == CPLSPrintf_BUF_Count)
00678       gnCPLSPrintfBuffer = 0;
00679 
00680     return gszCPLSPrintfBuffer[nCurrent];
00681 }
00682 
00683 /**********************************************************************
00684  *                       CSLAppendPrintf()
00685  *
00686  * Use CPLSPrintf() to append a new line at the end of a StringList.
00687  *
00688  * Returns the modified StringList.
00689  **********************************************************************/
00690 char **CSLAppendPrintf(char **papszStrList, char *fmt, ...)
00691 {
00692     va_list args;
00693 
00694     va_start(args, fmt);
00695     vsprintf(gszCPLSPrintfBuffer[gnCPLSPrintfBuffer], fmt, args);
00696     va_end(args);
00697 
00698     int nCurrent = gnCPLSPrintfBuffer;
00699 
00700     if (++gnCPLSPrintfBuffer == CPLSPrintf_BUF_Count)
00701       gnCPLSPrintfBuffer = 0;
00702 
00703     return CSLAddString(papszStrList, gszCPLSPrintfBuffer[nCurrent]);
00704 }
00705 
00706 
00707 /**********************************************************************
00708  *                       CSLFetchNameValue()
00709  *
00710  * In a StringList of "Name=Value" pairs, look for the
00711  * first value associated with the specified name.  The search is not
00712  * case sensitive.
00713  * ("Name:Value" pairs are also supported for backward compatibility
00714  * with older stuff.)
00715  * 
00716  * Returns a reference to the value in the StringList that the caller
00717  * should not attempt to free.
00718  *
00719  * Returns NULL if the name is not found.
00720  **********************************************************************/
00721 const char *CSLFetchNameValue(char **papszStrList, const char *pszName)
00722 {
00723     int nLen;
00724 
00725     if (papszStrList == NULL || pszName == NULL)
00726         return NULL;
00727 
00728     nLen = strlen(pszName);
00729     while(*papszStrList != NULL)
00730     {
00731         if (EQUALN(*papszStrList, pszName, nLen)
00732             && ( (*papszStrList)[nLen] == '=' || 
00733                  (*papszStrList)[nLen] == ':' ) )
00734         {
00735             return (*papszStrList)+nLen+1;
00736         }
00737         papszStrList++;
00738     }
00739     return NULL;
00740 }
00741 
00742 /**********************************************************************
00743  *                       CPLParseNameValue()
00744  **********************************************************************/
00745 
00766 const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
00767 
00768 {
00769     int  i;
00770     const char *pszValue;
00771 
00772     for( i = 0; pszNameValue[i] != '\0'; i++ )
00773     {
00774         if( pszNameValue[i] == '=' || pszNameValue[i] == ':' )
00775         {
00776             pszValue = pszNameValue + i + 1;
00777             while( *pszValue == ' ' || *pszValue == '\t' )
00778                 pszValue++;
00779 
00780             if( ppszKey != NULL )
00781             {
00782                 *ppszKey = (char *) CPLMalloc(i+1);
00783                 strncpy( *ppszKey, pszNameValue, i );
00784                 (*ppszKey)[i] = '\0';
00785                 while( i > 0 && 
00786                        ( (*ppszKey)[i] == ' ' || (*ppszKey)[i] == '\t') )
00787                 {
00788                     (*ppszKey)[i] = '\0';
00789                     i--;
00790                 }
00791             }
00792 
00793             return pszValue;
00794         }
00795 
00796     }
00797 
00798     return NULL;
00799 }
00800 
00801 /**********************************************************************
00802  *                       CSLFetchNameValueMultiple()
00803  *
00804  * In a StringList of "Name=Value" pairs, look for all the
00805  * values with the specified name.  The search is not case
00806  * sensitive.
00807  * ("Name:Value" pairs are also supported for backward compatibility
00808  * with older stuff.)
00809  * 
00810  * Returns stringlist with one entry for each occurence of the
00811  * specified name.  The stringlist should eventually be destroyed
00812  * by calling CSLDestroy().
00813  *
00814  * Returns NULL if the name is not found.
00815  **********************************************************************/
00816 char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName)
00817 {
00818     int nLen;
00819     char **papszValues = NULL;
00820 
00821     if (papszStrList == NULL || pszName == NULL)
00822         return NULL;
00823 
00824     nLen = strlen(pszName);
00825     while(*papszStrList != NULL)
00826     {
00827         if (EQUALN(*papszStrList, pszName, nLen)
00828             && ( (*papszStrList)[nLen] == '=' || 
00829                  (*papszStrList)[nLen] == ':' ) )
00830         {
00831             papszValues = CSLAddString(papszValues, 
00832                                           (*papszStrList)+nLen+1);
00833         }
00834         papszStrList++;
00835     }
00836 
00837     return papszValues;
00838 }
00839 
00840 
00841 /**********************************************************************
00842  *                       CSLAddNameValue()
00843  *
00844  * Add a new entry to a StringList of "Name=Value" pairs,
00845  * ("Name:Value" pairs are also supported for backward compatibility
00846  * with older stuff.)
00847  * 
00848  * This function does not check if a "Name=Value" pair already exists
00849  * for that name and can generate multiple entryes for the same name.
00850  * Use CSLSetNameValue() if you want each name to have only one value.
00851  *
00852  * Returns the modified stringlist.
00853  **********************************************************************/
00854 char **CSLAddNameValue(char **papszStrList, 
00855                     const char *pszName, const char *pszValue)
00856 {
00857     const char *pszLine;
00858 
00859     if (pszName == NULL || pszValue==NULL)
00860         return papszStrList;
00861 
00862     pszLine = CPLSPrintf("%s=%s", pszName, pszValue);
00863 
00864     return CSLAddString(papszStrList, pszLine);
00865 }
00866 
00867 /**********************************************************************
00868  *                       CSLSetNameValue()
00869  *
00870  * Set the value for a given name in a StringList of "Name=Value" pairs
00871  * ("Name:Value" pairs are also supported for backward compatibility
00872  * with older stuff.)
00873  * 
00874  * If there is already a value for that name in the list then the value
00875  * is changed, otherwise a new "Name=Value" pair is added.
00876  *
00877  * Returns the modified stringlist.
00878  **********************************************************************/
00879 char **CSLSetNameValue(char **papszList, 
00880                     const char *pszName, const char *pszValue)
00881 {
00882     char **papszPtr;
00883     int nLen;
00884 
00885     if (pszName == NULL || pszValue==NULL)
00886         return papszList;
00887 
00888     nLen = strlen(pszName);
00889     papszPtr = papszList;
00890     while(papszPtr && *papszPtr != NULL)
00891     {
00892         if (EQUALN(*papszPtr, pszName, nLen)
00893             && ( (*papszPtr)[nLen] == '=' || 
00894                  (*papszPtr)[nLen] == ':' ) )
00895         {
00896             /* Found it!  
00897              * Change the value... make sure to keep the ':' or '='
00898              */
00899             char cSep;
00900             cSep = (*papszPtr)[nLen];
00901 
00902             free(*papszPtr);
00903             *papszPtr = CPLStrdup(CPLSPrintf("%s%c%s", pszName,
00904                                                        cSep, pszValue));
00905 
00906             return papszList;
00907         }
00908         papszPtr++;
00909     }
00910 
00911     /* The name does not exist yet... create a new entry
00912      */
00913     return CSLAddString(papszList, 
00914                            CPLSPrintf("%s=%s", pszName, pszValue));
00915 }
00916 
00917 /************************************************************************/
00918 /*                      CSLSetNameValueSeparator()                      */
00919 /************************************************************************/
00920 
00941 void CSLSetNameValueSeparator( char ** papszList, const char *pszSeparator )
00942 
00943 {
00944     int         nLines = CSLCount(papszList), iLine;
00945 
00946     for( iLine = 0; iLine < nLines; iLine++ )
00947     {
00948         char    *pszKey = NULL;
00949         const char *pszValue;
00950         char    *pszNewLine;
00951 
00952         pszValue = CPLParseNameValue( papszList[iLine], &pszKey );
00953         
00954         pszNewLine = (char *) CPLMalloc(strlen(pszValue)+strlen(pszKey)
00955                                         +strlen(pszSeparator)+1);
00956         strcpy( pszNewLine, pszKey );
00957         strcat( pszNewLine, pszSeparator );
00958         strcat( pszNewLine, pszValue );
00959         CPLFree( papszList[iLine] );
00960         papszList[iLine] = pszNewLine;
00961     }
00962 }

Generated at Thu Jul 5 09:16:12 2001 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000