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 }