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

cpl_conv.cpp

00001 /******************************************************************************
00002  * $Id: cpl_conv_cpp-source.html,v 1.13 2002/12/21 19:13:12 warmerda Exp $
00003  *
00004  * Project:  CPL - Common Portability Library
00005  * Purpose:  Convenience functions.
00006  * Author:   Frank Warmerdam, warmerda@home.com
00007  *
00008  ******************************************************************************
00009  * Copyright (c) 1998, Frank Warmerdam
00010  *
00011  * Permission is hereby granted, free of charge, to any person obtaining a
00012  * copy of this software and associated documentation files (the "Software"),
00013  * to deal in the Software without restriction, including without limitation
00014  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00015  * and/or sell copies of the Software, and to permit persons to whom the
00016  * Software is furnished to do so, subject to the following conditions:
00017  *
00018  * The above copyright notice and this permission notice shall be included
00019  * in all copies or substantial portions of the Software.
00020  *
00021  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00022  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00024  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00026  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00027  * DEALINGS IN THE SOFTWARE.
00028  ******************************************************************************
00029  *
00030  * $Log: cpl_conv_cpp-source.html,v $
00030  * Revision 1.13  2002/12/21 19:13:12  warmerda
00030  * updated
00030  *
00031  * Revision 1.18  2002/12/18 20:22:53  warmerda
00032  * fiddle with roundoff issues in DecToDMS
00033  *
00034  * Revision 1.17  2002/12/10 19:46:04  warmerda
00035  * modified CPLReadLine() to seek back if it overreads past a CR or LF
00036  *
00037  * Revision 1.16  2002/12/09 18:52:51  warmerda
00038  * added DMS conversion
00039  *
00040  * Revision 1.15  2002/03/05 14:26:57  warmerda
00041  * expanded tabs
00042  *
00043  * Revision 1.14  2001/12/12 17:06:57  warmerda
00044  * added CPLStat
00045  *
00046  * Revision 1.13  2001/07/18 04:00:49  warmerda
00047  * added CPL_CVSID
00048  *
00049  * Revision 1.12  2001/03/09 03:19:24  danmo
00050  * Set pszRLBuffer=NULL after freeing it to avoid reallocating an invalid ptr
00051  *
00052  * Revision 1.11  2001/03/05 03:37:19  warmerda
00053  * Improve support for recovering CPLReadLine() working buffer.
00054  *
00055  * Revision 1.10  2001/01/19 21:16:41  warmerda
00056  * expanded tabs
00057  *
00058  * Revision 1.9  2000/04/17 15:56:11  warmerda
00059  * make configuration tests always happen
00060  *
00061  * Revision 1.8  2000/04/05 21:02:47  warmerda
00062  * Added CPLVerifyConfiguration()
00063  *
00064  * Revision 1.7  1999/08/27 12:55:39  danmo
00065  * Support 0 bytes allocations in CPLRealloc()
00066  *
00067  * Revision 1.6  1999/06/25 04:38:03  warmerda
00068  * Fixed CPLReadLine() to work for long lines.
00069  *
00070  * Revision 1.5  1999/05/20 02:54:37  warmerda
00071  * Added API documentation
00072  *
00073  * Revision 1.4  1999/01/02 20:29:53  warmerda
00074  * Allow zero length allocations
00075  *
00076  * Revision 1.3  1998/12/15 19:01:07  warmerda
00077  * Added CPLReadLine().
00078  *
00079  * Revision 1.2  1998/12/03 18:30:04  warmerda
00080  * Use CPLError() instead of GPSError().
00081  *
00082  * Revision 1.1  1998/12/02 19:33:23  warmerda
00083  * New
00084  *
00085  */
00086 
00087 #include "cpl_conv.h"
00088 
00089 CPL_CVSID("$Id: cpl_conv_cpp-source.html,v 1.13 2002/12/21 19:13:12 warmerda Exp $");
00090 
00091 /************************************************************************/
00092 /*                             CPLCalloc()                              */
00093 /************************************************************************/
00094 
00112 void *CPLCalloc( size_t nCount, size_t nSize )
00113 
00114 {
00115     void        *pReturn;
00116 
00117     if( nSize * nCount == 0 )
00118         return NULL;
00119     
00120     pReturn = VSICalloc( nCount, nSize );
00121     if( pReturn == NULL )
00122     {
00123         CPLError( CE_Fatal, CPLE_OutOfMemory,
00124                   "CPLCalloc(): Out of memory allocating %d bytes.\n",
00125                   nSize * nCount );
00126     }
00127 
00128     return pReturn;
00129 }
00130 
00131 /************************************************************************/
00132 /*                             CPLMalloc()                              */
00133 /************************************************************************/
00134 
00150 void *CPLMalloc( size_t nSize )
00151 
00152 {
00153     void        *pReturn;
00154 
00155     CPLVerifyConfiguration();
00156 
00157     if( nSize == 0 )
00158         return NULL;
00159     
00160     pReturn = VSIMalloc( nSize );
00161     if( pReturn == NULL )
00162     {
00163         CPLError( CE_Fatal, CPLE_OutOfMemory,
00164                   "CPLMalloc(): Out of memory allocating %d bytes.\n",
00165                   nSize );
00166     }
00167 
00168     return pReturn;
00169 }
00170 
00171 /************************************************************************/
00172 /*                             CPLRealloc()                             */
00173 /************************************************************************/
00174 
00195 void * CPLRealloc( void * pData, size_t nNewSize )
00196 
00197 {
00198     void        *pReturn;
00199 
00200     if ( nNewSize == 0 )
00201     {
00202         VSIFree(pData);
00203         return NULL;
00204     }
00205 
00206     if( pData == NULL )
00207         pReturn = VSIMalloc( nNewSize );
00208     else
00209         pReturn = VSIRealloc( pData, nNewSize );
00210     
00211     if( pReturn == NULL )
00212     {
00213         CPLError( CE_Fatal, CPLE_OutOfMemory,
00214                   "CPLRealloc(): Out of memory allocating %d bytes.\n",
00215                   nNewSize );
00216     }
00217 
00218     return pReturn;
00219 }
00220 
00221 /************************************************************************/
00222 /*                             CPLStrdup()                              */
00223 /************************************************************************/
00224 
00243 char *CPLStrdup( const char * pszString )
00244 
00245 {
00246     char        *pszReturn;
00247 
00248     if( pszString == NULL )
00249         pszString = "";
00250 
00251     pszReturn = VSIStrdup( pszString );
00252         
00253     if( pszReturn == NULL )
00254     {
00255         CPLError( CE_Fatal, CPLE_OutOfMemory,
00256                   "CPLStrdup(): Out of memory allocating %d bytes.\n",
00257                   strlen(pszString) );
00258         
00259     }
00260     
00261     return( pszReturn );
00262 }
00263 
00264 /************************************************************************/
00265 /*                            CPLReadLine()                             */
00266 /************************************************************************/
00267 
00289 const char *CPLReadLine( FILE * fp )
00290 
00291 {
00292     static char *pszRLBuffer = NULL;
00293     static int  nRLBufferSize = 0;
00294     int         nLength, nReadSoFar = 0, nStripped = 0, i;
00295 
00296 /* -------------------------------------------------------------------- */
00297 /*      Cleanup case.                                                   */
00298 /* -------------------------------------------------------------------- */
00299     if( fp == NULL )
00300     {
00301         CPLFree( pszRLBuffer );
00302         pszRLBuffer = NULL;
00303         nRLBufferSize = 0;
00304         return NULL;
00305     }
00306 
00307 /* -------------------------------------------------------------------- */
00308 /*      Loop reading chunks of the line till we get to the end of       */
00309 /*      the line.                                                       */
00310 /* -------------------------------------------------------------------- */
00311     do {
00312 /* -------------------------------------------------------------------- */
00313 /*      Grow the working buffer if we have it nearly full.  Fail out    */
00314 /*      of read line if we can't reallocate it big enough (for          */
00315 /*      instance for a _very large_ file with no newlines).             */
00316 /* -------------------------------------------------------------------- */
00317         if( nRLBufferSize-nReadSoFar < 128 )
00318         {
00319             nRLBufferSize = nRLBufferSize*2 + 128;
00320             pszRLBuffer = (char *) VSIRealloc(pszRLBuffer, nRLBufferSize);
00321             if( pszRLBuffer == NULL )
00322             {
00323                 nRLBufferSize = 0;
00324                 return NULL;
00325             }
00326         }
00327 
00328 /* -------------------------------------------------------------------- */
00329 /*      Do the actual read.                                             */
00330 /* -------------------------------------------------------------------- */
00331         if( VSIFGets( pszRLBuffer+nReadSoFar, nRLBufferSize-nReadSoFar, fp )
00332             == NULL )
00333         {
00334             CPLFree( pszRLBuffer );
00335             pszRLBuffer = NULL;
00336             nRLBufferSize = 0;
00337 
00338             return NULL;
00339         }
00340 
00341         nReadSoFar = strlen(pszRLBuffer);
00342 
00343     } while( nReadSoFar == nRLBufferSize - 1
00344              && pszRLBuffer[nRLBufferSize-2] != 13
00345              && pszRLBuffer[nRLBufferSize-2] != 10 );
00346 
00347 /* -------------------------------------------------------------------- */
00348 /*      Clear CR and LF off the end.                                    */
00349 /* -------------------------------------------------------------------- */
00350     nLength = strlen(pszRLBuffer);
00351     if( nLength > 0
00352         && (pszRLBuffer[nLength-1] == 10 || pszRLBuffer[nLength-1] == 13) )
00353     {
00354         pszRLBuffer[--nLength] = '\0';
00355         nStripped++;
00356     }
00357     
00358     if( nLength > 0
00359         && (pszRLBuffer[nLength-1] == 10 || pszRLBuffer[nLength-1] == 13) )
00360     {
00361         pszRLBuffer[--nLength] = '\0';
00362         nStripped++;
00363     }
00364 
00365 /* -------------------------------------------------------------------- */
00366 /*      Check that there aren't any extra CR or LF characters           */
00367 /*      embedded in what is left.  I have encountered files with        */
00368 /*      embedded CR (13) characters that should have acted as line      */
00369 /*      terminators but got sucked up by VSIFGetc().                    */
00370 /* -------------------------------------------------------------------- */
00371     for( i = 0; i < nLength; i++ )
00372     {
00373         if( pszRLBuffer[i] == 10 || pszRLBuffer[i] == 13 )
00374         {
00375             /* we need to chop off the buffer here, and seek the input back
00376                to after the character that should have been the line
00377                terminator. */
00378             VSIFSeek( fp, (i+1) - (nLength+nStripped), SEEK_CUR );
00379             pszRLBuffer[i] = '\0';
00380         }
00381     }
00382 
00383     return( pszRLBuffer );
00384 }
00385 
00386 /************************************************************************/
00387 /*                       CPLVerifyConfiguration()                       */
00388 /************************************************************************/
00389 
00390 void CPLVerifyConfiguration()
00391 
00392 {
00393 /* -------------------------------------------------------------------- */
00394 /*      Verify data types.                                              */
00395 /* -------------------------------------------------------------------- */
00396     CPLAssert( sizeof(GInt32) == 4 );
00397     CPLAssert( sizeof(GInt16) == 2 );
00398     CPLAssert( sizeof(GByte) == 1 );
00399 
00400     if( sizeof(GInt32) != 4 )
00401         CPLError( CE_Fatal, CPLE_AppDefined, 
00402                   "sizeof(GInt32) == %d ... yow!\n", 
00403                   sizeof(GInt32) );
00404 
00405 /* -------------------------------------------------------------------- */
00406 /*      Verify byte order                                               */
00407 /* -------------------------------------------------------------------- */
00408     GInt32   nTest;
00409 
00410     nTest = 1;
00411 
00412 #ifdef CPL_LSB
00413     if( ((GByte *) &nTest)[0] != 1 )
00414 #endif
00415 #ifdef CPL_MSB
00416     if( ((GByte *) &nTest)[3] != 1 )
00417 #endif    
00418         CPLError( CE_Fatal, CPLE_AppDefined, 
00419                   "CPLVerifyConfiguration(): byte order set wrong.\n" );
00420 }
00421 
00422 /************************************************************************/
00423 /*                              CPLStat()                               */
00424 /*                                                                      */
00425 /*      Same as VSIStat() except it works on "C:" as if it were         */
00426 /*      "C:\".                                                          */
00427 /************************************************************************/
00428 
00429 int CPLStat( const char *pszPath, VSIStatBuf *psStatBuf )
00430 
00431 {
00432     if( strlen(pszPath) == 2 && pszPath[1] == ':' )
00433     {
00434         char    szAltPath[10];
00435         
00436         strcpy( szAltPath, pszPath );
00437         strcat( szAltPath, "\\" );
00438         return VSIStat( szAltPath, psStatBuf );
00439     }
00440     else
00441         return VSIStat( pszPath, psStatBuf );
00442 }
00443 
00444 /************************************************************************/
00445 /*                            proj_strtod()                             */
00446 /************************************************************************/
00447 static double
00448 proj_strtod(char *nptr, char **endptr) 
00449 
00450 {
00451     char c, *cp = nptr;
00452     double result;
00453 
00454     /*
00455      * Scan for characters which cause problems with VC++ strtod()
00456      */
00457     while ((c = *cp) != '\0') {
00458         if (c == 'd' || c == 'D') {
00459 
00460             /*
00461              * Found one, so NUL it out, call strtod(),
00462              * then restore it and return
00463              */
00464             *cp = '\0';
00465             result = strtod(nptr, endptr);
00466             *cp = c;
00467             return result;
00468         }
00469         ++cp;
00470     }
00471 
00472     /* no offending characters, just handle normally */
00473 
00474     return strtod(nptr, endptr);
00475 }
00476 
00477 /************************************************************************/
00478 /*                            CPLDMSToDec()                             */
00479 /************************************************************************/
00480 
00481 static const char*sym = "NnEeSsWw";
00482 static const double vm[] = { 1.0, 0.0166666666667, 0.00027777778 };
00483 
00484 double CPLDMSToDec( const char *is )
00485 
00486 {
00487     int sign, n, nl;
00488     char *p, *s, work[64];
00489     double v, tv;
00490 
00491     /* copy sting into work space */
00492     while (isspace(sign = *is)) ++is;
00493     for (n = sizeof(work), s = work, p = (char *)is; isgraph(*p) && --n ; )
00494         *s++ = *p++;
00495     *s = '\0';
00496     /* it is possible that a really odd input (like lots of leading
00497        zeros) could be truncated in copying into work.  But ... */
00498     sign = *(s = work);
00499     if (sign == '+' || sign == '-') s++;
00500     else sign = '+';
00501     for (v = 0., nl = 0 ; nl < 3 ; nl = n + 1 ) {
00502         if (!(isdigit(*s) || *s == '.')) break;
00503         if ((tv = proj_strtod(s, &s)) == HUGE_VAL)
00504             return tv;
00505         switch (*s) {
00506           case 'D': case 'd':
00507             n = 0; break;
00508           case '\'':
00509             n = 1; break;
00510           case '"':
00511             n = 2; break;
00512           case 'r': case 'R':
00513             if (nl) {
00514                 return 0.0;
00515             }
00516             ++s;
00517             v = tv;
00518             goto skip;
00519           default:
00520             v += tv * vm[nl];
00521           skip: n = 4;
00522             continue;
00523         }
00524         if (n < nl) {
00525             return 0.0;
00526         }
00527         v += tv * vm[n];
00528         ++s;
00529     }
00530     /* postfix sign */
00531     if (*s && (p = strchr(sym, *s))) {
00532         sign = (p - sym) >= 4 ? '-' : '+';
00533         ++s;
00534     }
00535     if (sign == '-')
00536         v = -v;
00537 
00538     return v;
00539 }
00540 
00541 
00542 /************************************************************************/
00543 /*                            CPLDecToDMS()                             */
00544 /*                                                                      */
00545 /*      Translate a decimal degrees value to a DMS string with          */
00546 /*      hemisphere.                                                     */
00547 /************************************************************************/
00548 
00549 const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
00550                           int nPrecision )
00551 
00552 {
00553     int         nDegrees, nMinutes;
00554     double      dfSeconds, dfABSAngle, dfEpsilon;
00555     char        szFormat[30];
00556     static char szBuffer[50];
00557     const char  *pszHemisphere;
00558     
00559     dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
00560 
00561     dfABSAngle = ABS(dfAngle) + dfEpsilon;
00562 
00563     nDegrees = (int) dfABSAngle;
00564     nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
00565     dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
00566 
00567     if( dfSeconds > dfEpsilon * 3600.0 )
00568         dfSeconds -= dfEpsilon * 3600.0;
00569 
00570     if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
00571         pszHemisphere = "W";
00572     else if( EQUAL(pszAxis,"Long") )
00573         pszHemisphere = "E";
00574     else if( dfAngle < 0.0 )
00575         pszHemisphere = "S";
00576     else
00577         pszHemisphere = "N";
00578 
00579     sprintf( szFormat, "%%3dd%%2d\'%%.%df\"%s", nPrecision, pszHemisphere );
00580     sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
00581 
00582     return( szBuffer );
00583 }
00584 

Generated at Sat Dec 21 14:01:56 2002 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000