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 }
1.2.3-20001105 written by Dimitri van Heesch,
© 1997-2000