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

Generated at Thu Mar 28 09:47:28 2002 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000