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

cpl_serv.c

00001 /******************************************************************************
00002  * Copyright (c) 1998, Frank Warmerdam
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00017  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00019  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00020  * DEALINGS IN THE SOFTWARE.
00021  ******************************************************************************
00022  *
00023  * cpl_serv.c: Various Common Portability Library derived convenience functions
00024  *
00025  * $Log$
00025  * Revision 1.2  2001/03/05 04:58:33  warmerda
00025  * updated
00025  *
00026  * Revision 1.5  2000/09/30 03:35:05  warmerda
00027  * Fixed CPLReadLine() to use avoid calling VSIRealloc() on a NULL pointer.
00028  *
00029  * Revision 1.4  1999/06/25 04:35:26  warmerda
00030  * Fixed to actually support long lines.
00031  *
00032  * Revision 1.3  1999/03/17 20:43:03  geotiff
00033  * Avoid use of size_t keyword
00034  *
00035  * Revision 1.2  1999/03/10 18:22:39  geotiff
00036  * Added string.h, fixed backslash escaping
00037  *
00038  * Revision 1.1  1999/03/09 15:57:04  geotiff
00039  * New
00040  *
00041  */
00042 
00043 #include "cpl_serv.h"
00044 #include "geo_tiffp.h"
00045 
00046 #ifdef HAVE_STRING_H
00047 #  include <string.h>
00048 #endif
00049 #if defined(HAVE_STRINGS_H) && !defined(HAVE_STRING_H)
00050 #  include <strings.h>
00051 #endif
00052 
00053 /************************************************************************/
00054 /*                             CPLCalloc()                              */
00055 /************************************************************************/
00056 
00057 void *CPLCalloc( int nCount, int nSize )
00058 
00059 {
00060     void        *pReturn;
00061 
00062     if( nSize == 0 )
00063         return NULL;
00064     
00065     pReturn = VSICalloc( nCount, nSize );
00066     if( pReturn == NULL )
00067     {
00068         CPLError( CE_Fatal, CPLE_OutOfMemory,
00069                   "CPLCalloc(): Out of memory allocating %d bytes.\n",
00070                   nSize * nCount );
00071     }
00072 
00073     return pReturn;
00074 }
00075 
00076 /************************************************************************/
00077 /*                             CPLMalloc()                              */
00078 /************************************************************************/
00079 
00080 void *CPLMalloc( int nSize )
00081 
00082 {
00083     void        *pReturn;
00084 
00085     if( nSize == 0 )
00086         return NULL;
00087     
00088     pReturn = VSIMalloc( nSize );
00089     if( pReturn == NULL )
00090     {
00091         CPLError( CE_Fatal, CPLE_OutOfMemory,
00092                   "CPLMalloc(): Out of memory allocating %d bytes.\n",
00093                   nSize );
00094     }
00095 
00096     return pReturn;
00097 }
00098 
00099 /************************************************************************/
00100 /*                             CPLRealloc()                             */
00101 /************************************************************************/
00102 
00103 void * CPLRealloc( void * pData, int nNewSize )
00104 
00105 {
00106     void        *pReturn;
00107 
00108     if( pData == NULL )
00109         pReturn = VSIMalloc( nNewSize );
00110     else
00111         pReturn = VSIRealloc( pData, nNewSize );
00112     
00113     if( pReturn == NULL )
00114     {
00115         CPLError( CE_Fatal, CPLE_OutOfMemory,
00116                   "CPLRealloc(): Out of memory allocating %d bytes.\n",
00117                   nNewSize );
00118     }
00119 
00120     return pReturn;
00121 }
00122 
00123 /************************************************************************/
00124 /*                             CPLStrdup()                              */
00125 /************************************************************************/
00126 
00127 char *CPLStrdup( const char * pszString )
00128 
00129 {
00130     char        *pszReturn;
00131 
00132     if( pszString == NULL )
00133         pszString = "";
00134 
00135     pszReturn = VSIMalloc( strlen(pszString)+1 );
00136         
00137     if( pszReturn == NULL )
00138     {
00139         CPLError( CE_Fatal, CPLE_OutOfMemory,
00140                   "CPLStrdup(): Out of memory allocating %d bytes.\n",
00141                   strlen(pszString) );
00142         
00143     }
00144 
00145     strcpy( pszReturn, pszString );
00146     
00147     return( pszReturn );
00148 }
00149 
00150 /************************************************************************/
00151 /*                            CPLReadLine()                             */
00152 /*                                                                      */
00153 /*      Read a line of text from the given file handle, taking care     */
00154 /*      to capture CR and/or LF and strip off ... equivelent of         */
00155 /*      DKReadLine().  Pointer to an internal buffer is returned.       */
00156 /*      The application shouldn't free it, or depend on it's value      */
00157 /*      past the next call to CPLReadLine()                             */
00158 /************************************************************************/
00159 
00160 const char *CPLReadLine( FILE * fp )
00161 
00162 {
00163     static char *pszRLBuffer = NULL;
00164     static int  nRLBufferSize = 0;
00165     int         nLength, nReadSoFar = 0;
00166 
00167 /* -------------------------------------------------------------------- */
00168 /*      Cleanup case.                                                   */
00169 /* -------------------------------------------------------------------- */
00170     if( fp == NULL )
00171     {
00172         CPLFree( pszRLBuffer );
00173         nRLBufferSize = 0;
00174         return NULL;
00175     }
00176 
00177 /* -------------------------------------------------------------------- */
00178 /*      Loop reading chunks of the line till we get to the end of       */
00179 /*      the line.                                                       */
00180 /* -------------------------------------------------------------------- */
00181     do {
00182 /* -------------------------------------------------------------------- */
00183 /*      Grow the working buffer if we have it nearly full.  Fail out    */
00184 /*      of read line if we can't reallocate it big enough (for          */
00185 /*      instance for a _very large_ file with no newlines).             */
00186 /* -------------------------------------------------------------------- */
00187         if( nRLBufferSize-nReadSoFar < 128 )
00188         {
00189             nRLBufferSize = nRLBufferSize*2 + 128;
00190             if( pszRLBuffer == NULL )
00191                 pszRLBuffer = (char *) VSIMalloc(nRLBufferSize);
00192             else
00193                 pszRLBuffer = (char *) VSIRealloc(pszRLBuffer, nRLBufferSize);
00194             if( pszRLBuffer == NULL )
00195             {
00196                 nRLBufferSize = 0;
00197                 return NULL;
00198             }
00199         }
00200 
00201 /* -------------------------------------------------------------------- */
00202 /*      Do the actual read.                                             */
00203 /* -------------------------------------------------------------------- */
00204         if( VSIFGets( pszRLBuffer+nReadSoFar, nRLBufferSize-nReadSoFar, fp )
00205             == NULL )
00206         {
00207             CPLFree( pszRLBuffer );
00208             nRLBufferSize = 0;
00209 
00210             return NULL;
00211         }
00212 
00213         nReadSoFar = strlen(pszRLBuffer);
00214 
00215     } while( nReadSoFar == nRLBufferSize - 1
00216              && pszRLBuffer[nRLBufferSize-2] != 13
00217              && pszRLBuffer[nRLBufferSize-2] != 10 );
00218 
00219 /* -------------------------------------------------------------------- */
00220 /*      Clear CR and LF off the end.                                    */
00221 /* -------------------------------------------------------------------- */
00222     nLength = strlen(pszRLBuffer);
00223     if( nLength > 0
00224         && (pszRLBuffer[nLength-1] == 10 || pszRLBuffer[nLength-1] == 13) )
00225     {
00226         pszRLBuffer[--nLength] = '\0';
00227     }
00228     
00229     if( nLength > 0
00230         && (pszRLBuffer[nLength-1] == 10 || pszRLBuffer[nLength-1] == 13) )
00231     {
00232         pszRLBuffer[--nLength] = '\0';
00233     }
00234 
00235     return( pszRLBuffer );
00236 }
00237 
00238 
00239 /*=====================================================================
00240                     StringList manipulation functions.
00241  =====================================================================*/
00242 
00243 /**********************************************************************
00244  *                       CSLAddString()
00245  *
00246  * Append a string to a StringList and return a pointer to the modified
00247  * StringList.
00248  * If the input StringList is NULL, then a new StringList is created.
00249  **********************************************************************/
00250 char **CSLAddString(char **papszStrList, const char *pszNewString)
00251 {
00252     int nItems=0;
00253 
00254     if (pszNewString == NULL)
00255         return papszStrList;    /* Nothing to do!*/
00256 
00257     /* Allocate room for the new string */
00258     if (papszStrList == NULL)
00259         papszStrList = (char**) CPLCalloc(2,sizeof(char*));
00260     else
00261     {
00262         nItems = CSLCount(papszStrList);
00263         papszStrList = (char**)CPLRealloc(papszStrList, 
00264                                           (nItems+2)*sizeof(char*));
00265     }
00266 
00267     /* Copy the string in the list */
00268     papszStrList[nItems] = CPLStrdup(pszNewString);
00269     papszStrList[nItems+1] = NULL;
00270 
00271     return papszStrList;
00272 }
00273 
00274 /**********************************************************************
00275  *                       CSLCount()
00276  *
00277  * Return the number of lines in a Stringlist.
00278  **********************************************************************/
00279 int CSLCount(char **papszStrList)
00280 {
00281     int nItems=0;
00282 
00283     if (papszStrList)
00284     {
00285         while(*papszStrList != NULL)
00286         {
00287             nItems++;
00288             papszStrList++;
00289         }
00290     }
00291 
00292     return nItems;
00293 }
00294 
00295 
00296 /************************************************************************/
00297 /*                            CSLGetField()                             */
00298 /*                                                                      */
00299 /*      Fetches the indicated field, being careful not to crash if      */
00300 /*      the field doesn't exist within this string list.  The           */
00301 /*      returned pointer should not be freed, and doesn't               */
00302 /*      necessarily last long.                                          */
00303 /************************************************************************/
00304 
00305 const char * CSLGetField( char ** papszStrList, int iField )
00306 
00307 {
00308     int         i;
00309 
00310     if( papszStrList == NULL || iField < 0 )
00311         return( "" );
00312 
00313     for( i = 0; i < iField+1; i++ )
00314     {
00315         if( papszStrList[i] == NULL )
00316             return "";
00317     }
00318 
00319     return( papszStrList[iField] );
00320 }
00321 
00322 /**********************************************************************
00323  *                       CSLDestroy()
00324  *
00325  * Free all memory used by a StringList.
00326  **********************************************************************/
00327 void CSLDestroy(char **papszStrList)
00328 {
00329     char **papszPtr;
00330 
00331     if (papszStrList)
00332     {
00333         papszPtr = papszStrList;
00334         while(*papszPtr != NULL)
00335         {
00336             CPLFree(*papszPtr);
00337             papszPtr++;
00338         }
00339 
00340         CPLFree(papszStrList);
00341     }
00342 }
00343 
00344 
00345 /**********************************************************************
00346  *                       CSLDuplicate()
00347  *
00348  * Allocate and return a copy of a StringList.
00349  **********************************************************************/
00350 char    **CSLDuplicate(char **papszStrList)
00351 {
00352     char **papszNewList, **papszSrc, **papszDst;
00353     int  nLines;
00354 
00355     nLines = CSLCount(papszStrList);
00356 
00357     if (nLines == 0)
00358         return NULL;
00359 
00360     papszNewList = (char **)CPLMalloc((nLines+1)*sizeof(char*));
00361     papszSrc = papszStrList;
00362     papszDst = papszNewList;
00363 
00364     while(*papszSrc != NULL)
00365     {
00366         *papszDst = CPLStrdup(*papszSrc);
00367 
00368         papszSrc++;
00369         papszDst++;
00370     }
00371     *papszDst = NULL;
00372 
00373     return papszNewList;
00374 }
00375 
00376 /**********************************************************************
00377  *                       CSLTokenizeString()
00378  *
00379  * Tokenizes a string and returns a StringList with one string for
00380  * each token.
00381  **********************************************************************/
00382 char    **CSLTokenizeString( const char *pszString )
00383 {
00384     return CSLTokenizeStringComplex( pszString, " ", TRUE, FALSE );
00385 }
00386 
00387 /************************************************************************/
00388 /*                      CSLTokenizeStringComplex()                      */
00389 /*                                                                      */
00390 /*      The ultimate tokenizer?                                         */
00391 /************************************************************************/
00392 
00393 char ** CSLTokenizeStringComplex( const char * pszString,
00394                                   const char * pszDelimiters,
00395                                   int bHonourStrings, int bAllowEmptyTokens )
00396 
00397 {
00398     char        **papszRetList = NULL;
00399     char        *pszToken;
00400     int         nTokenMax, nTokenLen;
00401 
00402     pszToken = (char *) CPLCalloc(10,1);
00403     nTokenMax = 10;
00404     
00405     while( pszString != NULL && *pszString != '\0' )
00406     {
00407         int     bInString = FALSE;
00408 
00409         nTokenLen = 0;
00410         
00411         /* Try to find the next delimeter, marking end of token */
00412         for( ; *pszString != '\0'; pszString++ )
00413         {
00414 
00415             /* End if this is a delimeter skip it and break. */
00416             if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
00417             {
00418                 pszString++;
00419                 break;
00420             }
00421             
00422             /* If this is a quote, and we are honouring constant
00423                strings, then process the constant strings, with out delim
00424                but don't copy over the quotes */
00425             if( bHonourStrings && *pszString == '"' )
00426             {
00427                 if( bInString )
00428                 {
00429                     bInString = FALSE;
00430                     continue;
00431                 }
00432                 else
00433                 {
00434                     bInString = TRUE;
00435                     continue;
00436                 }
00437             }
00438 
00439             /* Within string constants we allow for escaped quotes, but
00440                in processing them we will unescape the quotes */
00441             if( bInString && pszString[0] == '\\' && pszString[1] == '"' )
00442             {
00443                 pszString++;
00444             }
00445 
00446             /* Within string constants a \\ sequence reduces to \ */
00447             else if( bInString
00448                      && pszString[0] == '\\' && pszString[1] == '\\' )
00449             {
00450                 pszString++;
00451             }
00452 
00453             if( nTokenLen >= nTokenMax-1 )
00454             {
00455                 nTokenMax = nTokenMax * 2 + 10;
00456                 pszToken = (char *) CPLRealloc( pszToken, nTokenMax );
00457             }
00458 
00459             pszToken[nTokenLen] = *pszString;
00460             nTokenLen++;
00461         }
00462 
00463         pszToken[nTokenLen] = '\0';
00464 
00465         if( pszToken[0] != '\0' || bAllowEmptyTokens )
00466         {
00467             papszRetList = CSLAddString( papszRetList, pszToken );
00468         }
00469     }
00470 
00471     if( papszRetList == NULL )
00472         papszRetList = (char **) CPLCalloc(sizeof(char *),1);
00473 
00474     CPLFree( pszToken );
00475 
00476     return papszRetList;
00477 }
00478 
00479 /* static buffer to store the last error message.  We'll assume that error
00480  * messages cannot be longer than 2000 chars... which is quite reasonable
00481  * (that's 25 lines of 80 chars!!!)
00482  */
00483 static char gszCPLLastErrMsg[2000] = "";
00484 static int  gnCPLLastErrNo = 0;
00485 
00486 static void (*gpfnCPLErrorHandler)(CPLErr, int, const char *) = NULL;
00487 
00488 /**********************************************************************
00489  *                          CPLError()
00490  *
00491  * This function records an error code and displays the error message
00492  * to stderr.
00493  *
00494  * The error code can be accessed later using CPLGetLastErrNo()
00495  **********************************************************************/
00496 void    CPLError(CPLErr eErrClass, int err_no, const char *fmt, ...)
00497 {
00498     va_list args;
00499 
00500     /* Expand the error message 
00501      */
00502     va_start(args, fmt);
00503     vsprintf(gszCPLLastErrMsg, fmt, args);
00504     va_end(args);
00505 
00506     /* If the user provided his own error handling function, then call
00507      * it, otherwise print the error to stderr and return.
00508      */
00509     gnCPLLastErrNo = err_no;
00510 
00511     if (gpfnCPLErrorHandler != NULL)
00512     {
00513         gpfnCPLErrorHandler(eErrClass, err_no, gszCPLLastErrMsg);
00514     }
00515     else
00516     {
00517         fprintf(stderr, "ERROR %d: %s\n", gnCPLLastErrNo, gszCPLLastErrMsg);
00518     }
00519 
00520     if( eErrClass == CE_Fatal )
00521         abort();
00522 }
00523 
00524 /**********************************************************************
00525  *                          CPLErrorReset()
00526  *
00527  * Erase any traces of previous errors.
00528  **********************************************************************/
00529 void    CPLErrorReset()
00530 {
00531     gnCPLLastErrNo = 0;
00532     gszCPLLastErrMsg[0] = '\0';
00533 }
00534 
00535 
00536 /**********************************************************************
00537  *                          CPLGetLastErrorNo()
00538  *
00539  **********************************************************************/
00540 int     CPLGetLastErrorNo()
00541 {
00542     return gnCPLLastErrNo;
00543 }
00544 
00545 /**********************************************************************
00546  *                          CPLGetLastErrorMsg()
00547  *
00548  **********************************************************************/
00549 const char* CPLGetLastErrorMsg()
00550 {
00551     return gszCPLLastErrMsg;
00552 }
00553 
00554 /**********************************************************************
00555  *                          CPLSetErrorHandler()
00556  *
00557  * Allow the library's user to specify his own error handler function.
00558  *
00559  * A valid error handler is a C function with the following prototype:
00560  *
00561  *     void MyErrorHandler(int errno, const char *msg)
00562  *
00563  * Pass NULL to come back to the default behavior.
00564  **********************************************************************/
00565 
00566 void     CPLSetErrorHandler(void (*pfnErrorHandler)(CPLErr, int, const char *))
00567 {
00568     gpfnCPLErrorHandler = pfnErrorHandler;
00569 }
00570 
00571 /************************************************************************/
00572 /*                             _CPLAssert()                             */
00573 /*                                                                      */
00574 /*      This function is called only when an assertion fails.           */
00575 /************************************************************************/
00576 
00577 void _CPLAssert( const char * pszExpression, const char * pszFile,
00578                  int iLine )
00579 
00580 {
00581     CPLError( CE_Fatal, CPLE_AssertionFailed,
00582               "Assertion `%s' failed\n"
00583               "in file `%s', line %d\n",
00584               pszExpression, pszFile, iLine );
00585 }

Generated at Sun Mar 4 23:32:44 2001 for libgeotiff by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000