LCOV - code coverage report
Current view: directory - port - cpl_conv.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 590 451 76.4 %
Date: 2012-04-28 Functions: 47 41 87.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: cpl_conv.cpp 23504 2011-12-09 20:43:50Z rouault $
       3                 :  *
       4                 :  * Project:  CPL - Common Portability Library
       5                 :  * Purpose:  Convenience functions.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1998, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : #ifdef MSVC_USE_VLD
      30                 : #include <vld.h>
      31                 : #endif
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : #include "cpl_vsi.h"
      35                 : #include "cpl_multiproc.h"
      36                 : 
      37                 : CPL_CVSID("$Id: cpl_conv.cpp 23504 2011-12-09 20:43:50Z rouault $");
      38                 : 
      39                 : #if defined(WIN32CE)
      40                 : #  include "cpl_wince.h"
      41                 : #endif
      42                 : 
      43                 : static void *hConfigMutex = NULL;
      44                 : static volatile char **papszConfigOptions = NULL;
      45                 : 
      46                 : static void *hSharedFileMutex = NULL;
      47                 : static volatile int nSharedFileCount = 0;
      48                 : static volatile CPLSharedFileInfo *pasSharedFileList = NULL;
      49                 : 
      50                 : 
      51                 : /************************************************************************/
      52                 : /*                             CPLCalloc()                              */
      53                 : /************************************************************************/
      54                 : 
      55                 : /**
      56                 :  * Safe version of calloc().
      57                 :  *
      58                 :  * This function is like the C library calloc(), but raises a CE_Fatal
      59                 :  * error with CPLError() if it fails to allocate the desired memory.  It
      60                 :  * should be used for small memory allocations that are unlikely to fail
      61                 :  * and for which the application is unwilling to test for out of memory
      62                 :  * conditions.  It uses VSICalloc() to get the memory, so any hooking of
      63                 :  * VSICalloc() will apply to CPLCalloc() as well.  CPLFree() or VSIFree()
      64                 :  * can be used free memory allocated by CPLCalloc().
      65                 :  *
      66                 :  * @param nCount number of objects to allocate.
      67                 :  * @param nSize size (in bytes) of object to allocate.
      68                 :  * @return pointer to newly allocated memory, only NULL if nSize * nCount is
      69                 :  * NULL.
      70                 :  */
      71                 : 
      72        18921669 : void *CPLCalloc( size_t nCount, size_t nSize )
      73                 : 
      74                 : {
      75                 :     void        *pReturn;
      76                 : 
      77        18921669 :     if( nSize * nCount == 0 )
      78           66940 :         return NULL;
      79                 :     
      80        18854729 :     pReturn = CPLMalloc( nCount * nSize );
      81        18854729 :     memset( pReturn, 0, nCount * nSize );
      82        18854729 :     return pReturn;
      83                 : }
      84                 : 
      85                 : /************************************************************************/
      86                 : /*                             CPLMalloc()                              */
      87                 : /************************************************************************/
      88                 : 
      89                 : /**
      90                 :  * Safe version of malloc().
      91                 :  *
      92                 :  * This function is like the C library malloc(), but raises a CE_Fatal
      93                 :  * error with CPLError() if it fails to allocate the desired memory.  It
      94                 :  * should be used for small memory allocations that are unlikely to fail
      95                 :  * and for which the application is unwilling to test for out of memory
      96                 :  * conditions.  It uses VSIMalloc() to get the memory, so any hooking of
      97                 :  * VSIMalloc() will apply to CPLMalloc() as well.  CPLFree() or VSIFree()
      98                 :  * can be used free memory allocated by CPLMalloc().
      99                 :  *
     100                 :  * @param nSize size (in bytes) of memory block to allocate.
     101                 :  * @return pointer to newly allocated memory, only NULL if nSize is zero.
     102                 :  */
     103                 : 
     104        70580119 : void *CPLMalloc( size_t nSize )
     105                 : 
     106                 : {
     107                 :     void        *pReturn;
     108                 : 
     109        70580119 :     CPLVerifyConfiguration();
     110                 : 
     111        70580119 :     if( nSize == 0 )
     112            2452 :         return NULL;
     113                 : 
     114        70577667 :     if( long(nSize) < 0 )
     115                 :     {
     116                 :         CPLError( CE_Failure, CPLE_AppDefined,
     117                 :                   "CPLMalloc(%ld): Silly size requested.\n",
     118               0 :                   (long) nSize );
     119               0 :         return NULL;
     120                 :     }
     121                 :     
     122        70577667 :     pReturn = VSIMalloc( nSize );
     123        70577667 :     if( pReturn == NULL )
     124                 :     {
     125               0 :         if( nSize > 0 && nSize < 2000 )
     126                 :         {
     127                 :             char szSmallMsg[60];
     128                 : 
     129                 :             sprintf( szSmallMsg, 
     130                 :                      "CPLMalloc(): Out of memory allocating %ld bytes.", 
     131               0 :                      (long) nSize );
     132               0 :             CPLEmergencyError( szSmallMsg ); 
     133                 :         }
     134                 :         else
     135                 :             CPLError( CE_Fatal, CPLE_OutOfMemory,
     136                 :                       "CPLMalloc(): Out of memory allocating %ld bytes.\n",
     137               0 :                       (long) nSize );
     138                 :     }
     139                 : 
     140        70577667 :     return pReturn;
     141                 : }
     142                 : 
     143                 : /************************************************************************/
     144                 : /*                             CPLRealloc()                             */
     145                 : /************************************************************************/
     146                 : 
     147                 : /**
     148                 :  * Safe version of realloc().
     149                 :  *
     150                 :  * This function is like the C library realloc(), but raises a CE_Fatal
     151                 :  * error with CPLError() if it fails to allocate the desired memory.  It
     152                 :  * should be used for small memory allocations that are unlikely to fail
     153                 :  * and for which the application is unwilling to test for out of memory
     154                 :  * conditions.  It uses VSIRealloc() to get the memory, so any hooking of
     155                 :  * VSIRealloc() will apply to CPLRealloc() as well.  CPLFree() or VSIFree()
     156                 :  * can be used free memory allocated by CPLRealloc().
     157                 :  *
     158                 :  * It is also safe to pass NULL in as the existing memory block for
     159                 :  * CPLRealloc(), in which case it uses VSIMalloc() to allocate a new block.
     160                 :  *
     161                 :  * @param pData existing memory block which should be copied to the new block.
     162                 :  * @param nNewSize new size (in bytes) of memory block to allocate.
     163                 :  * @return pointer to allocated memory, only NULL if nNewSize is zero.
     164                 :  */
     165                 : 
     166                 : 
     167        23342200 : void * CPLRealloc( void * pData, size_t nNewSize )
     168                 : 
     169                 : {
     170                 :     void        *pReturn;
     171                 : 
     172        23342200 :     if ( nNewSize == 0 )
     173                 :     {
     174               0 :         VSIFree(pData);
     175               0 :         return NULL;
     176                 :     }
     177                 : 
     178        23342200 :     if( long(nNewSize) < 0 )
     179                 :     {
     180                 :         CPLError( CE_Failure, CPLE_AppDefined,
     181                 :                   "CPLRealloc(%ld): Silly size requested.\n",
     182               0 :                   (long) nNewSize );
     183               0 :         return NULL;
     184                 :     }
     185                 :     
     186        23342200 :     if( pData == NULL )
     187         2785996 :         pReturn = VSIMalloc( nNewSize );
     188                 :     else
     189        20556204 :         pReturn = VSIRealloc( pData, nNewSize );
     190                 :     
     191        23342200 :     if( pReturn == NULL )
     192                 :     {
     193               0 :         if( nNewSize > 0 && nNewSize < 2000 )
     194                 :         {
     195                 :             char szSmallMsg[60];
     196                 : 
     197                 :             sprintf( szSmallMsg, 
     198                 :                      "CPLRealloc(): Out of memory allocating %ld bytes.", 
     199               0 :                      (long) nNewSize );
     200               0 :             CPLEmergencyError( szSmallMsg ); 
     201                 :         }
     202                 :         else
     203                 :             CPLError( CE_Fatal, CPLE_OutOfMemory,
     204                 :                       "CPLRealloc(): Out of memory allocating %ld bytes.\n",
     205               0 :                       (long) nNewSize );
     206                 :     }
     207                 : 
     208        23342200 :     return pReturn;
     209                 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /*                             CPLStrdup()                              */
     213                 : /************************************************************************/
     214                 : 
     215                 : /**
     216                 :  * Safe version of strdup() function.
     217                 :  *
     218                 :  * This function is similar to the C library strdup() function, but if
     219                 :  * the memory allocation fails it will issue a CE_Fatal error with
     220                 :  * CPLError() instead of returning NULL.  It uses VSIStrdup(), so any
     221                 :  * hooking of that function will apply to CPLStrdup() as well.  Memory
     222                 :  * allocated with CPLStrdup() can be freed with CPLFree() or VSIFree().
     223                 :  *
     224                 :  * It is also safe to pass a NULL string into CPLStrdup().  CPLStrdup()
     225                 :  * will allocate and return a zero length string (as opposed to a NULL
     226                 :  * string).
     227                 :  *
     228                 :  * @param pszString input string to be duplicated.  May be NULL.
     229                 :  * @return pointer to a newly allocated copy of the string.  Free with
     230                 :  * CPLFree() or VSIFree().
     231                 :  */
     232                 : 
     233        42616970 : char *CPLStrdup( const char * pszString )
     234                 : 
     235                 : {
     236                 :     char        *pszReturn;
     237                 : 
     238        42616970 :     if( pszString == NULL )
     239          826743 :         pszString = "";
     240                 : 
     241        42616970 :     pszReturn = (char *) CPLMalloc(strlen(pszString)+1);
     242        42616970 :     if( pszReturn == NULL )
     243                 :     {
     244                 :         CPLError( CE_Fatal, CPLE_OutOfMemory,
     245                 :                   "CPLStrdup(): Out of memory allocating %ld bytes.\n",
     246               0 :                   (long) strlen(pszString) );
     247                 :         
     248                 :     }
     249                 : 
     250        42616970 :     strcpy( pszReturn, pszString );
     251        42616970 :     return( pszReturn );
     252                 : }
     253                 : 
     254                 : /************************************************************************/
     255                 : /*                             CPLStrlwr()                              */
     256                 : /************************************************************************/
     257                 : 
     258                 : /**
     259                 :  * Convert each characters of the string to lower case.
     260                 :  *
     261                 :  * For example, "ABcdE" will be converted to "abcde".
     262                 :  * This function is locale dependent.
     263                 :  *
     264                 :  * @param pszString input string to be converted.
     265                 :  * @return pointer to the same string, pszString.
     266                 :  */
     267                 : 
     268              20 : char *CPLStrlwr( char *pszString )
     269                 : 
     270                 : {
     271              20 :     if (pszString)
     272                 :     {
     273              20 :         char *pszTemp = pszString;
     274                 : 
     275             124 :         while (*pszTemp)
     276                 :         {
     277              84 :             *pszTemp = (char) tolower (*pszTemp);
     278              84 :             pszTemp++;
     279                 :         }
     280                 :     }
     281                 : 
     282              20 :     return pszString;
     283                 : }
     284                 : 
     285                 : /************************************************************************/
     286                 : /*                              CPLFGets()                              */
     287                 : /*                                                                      */
     288                 : /*      Note: CR = \r = ASCII 13                                        */
     289                 : /*            LF = \n = ASCII 10                                        */
     290                 : /************************************************************************/
     291                 : 
     292                 : /**
     293                 :  * Reads in at most one less than nBufferSize characters from the fp
     294                 :  * stream and stores them into the buffer pointed to by pszBuffer.
     295                 :  * Reading stops after an EOF or a newline. If a newline is read, it
     296                 :  * is _not_ stored into the buffer. A '\\0' is stored after the last
     297                 :  * character in the buffer. All three types of newline terminators
     298                 :  * recognized by the CPLFGets(): single '\\r' and '\\n' and '\\r\\n'
     299                 :  * combination.
     300                 :  *
     301                 :  * @param pszBuffer pointer to the targeting character buffer.
     302                 :  * @param nBufferSize maximum size of the string to read (not including
     303                 :  * termonating '\\0').
     304                 :  * @param fp file pointer to read from.
     305                 :  * @return pointer to the pszBuffer containing a string read
     306                 :  * from the file or NULL if the error or end of file was encountered.
     307                 :  */
     308                 : 
     309         2746705 : char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
     310                 : 
     311                 : {
     312                 :     int nActuallyRead, nOriginalOffset;
     313                 : 
     314         2746705 :     if ( nBufferSize == 0 || pszBuffer == NULL || fp == NULL )
     315               0 :         return NULL;
     316                 : 
     317                 : /* -------------------------------------------------------------------- */
     318                 : /*      Let the OS level call read what it things is one line.  This    */
     319                 : /*      will include the newline.  On windows, if the file happens      */
     320                 : /*      to be in text mode, the CRLF will have been converted to        */
     321                 : /*      just the newline (LF).  If it is in binary mode it may well     */
     322                 : /*      have both.                                                      */
     323                 : /* -------------------------------------------------------------------- */
     324         2746705 :     nOriginalOffset = VSIFTell( fp );
     325         2746705 :     if( VSIFGets( pszBuffer, nBufferSize, fp ) == NULL )
     326            2758 :         return NULL;
     327                 :     
     328         2743947 :     nActuallyRead = strlen(pszBuffer);
     329         2743947 :     if ( nActuallyRead == 0 )
     330               0 :         return NULL;
     331                 : 
     332                 : /* -------------------------------------------------------------------- */
     333                 : /*      If we found \r and out buffer is full, it is possible there     */
     334                 : /*      is also a pending \n.  Check for it.                            */
     335                 : /* -------------------------------------------------------------------- */
     336         4554822 :     if( nBufferSize == nActuallyRead+1
     337         1810875 :         && pszBuffer[nActuallyRead-1] == 13 )
     338                 :     {
     339                 :         int chCheck;
     340              57 :         chCheck = fgetc( fp );
     341              57 :         if( chCheck != 10 )
     342                 :         {
     343                 :             // unget the character.
     344               0 :             VSIFSeek( fp, nOriginalOffset+nActuallyRead, SEEK_SET );
     345                 :         }
     346                 :     }
     347                 : 
     348                 : /* -------------------------------------------------------------------- */
     349                 : /*      Trim off \n, \r or \r\n if it appears at the end.  We don't     */
     350                 : /*      need to do any "seeking" since we want the newline eaten.       */
     351                 : /* -------------------------------------------------------------------- */
     352         6565796 :     if( nActuallyRead > 1 
     353         2734593 :         && pszBuffer[nActuallyRead-1] == 10 
     354          927859 :         && pszBuffer[nActuallyRead-2] == 13 )
     355                 :     {
     356          159397 :         pszBuffer[nActuallyRead-2] = '\0';
     357                 :     }
     358         4391284 :     else if( pszBuffer[nActuallyRead-1] == 10 
     359         1806734 :              || pszBuffer[nActuallyRead-1] == 13 )
     360                 :     {
     361          777873 :         pszBuffer[nActuallyRead-1] = '\0';
     362                 :     }
     363                 : 
     364                 : /* -------------------------------------------------------------------- */
     365                 : /*      Search within the string for a \r (MacOS convention             */
     366                 : /*      apparently), and if we find it we need to trim the string,      */
     367                 : /*      and seek back.                                                  */
     368                 : /* -------------------------------------------------------------------- */
     369         2743947 :     char *pszExtraNewline = strchr( pszBuffer, 13 );
     370                 :     
     371         2743947 :     if( pszExtraNewline != NULL )
     372                 :     {
     373                 :         int chCheck;
     374                 : 
     375               0 :         nActuallyRead = pszExtraNewline - pszBuffer + 1;
     376                 :         
     377               0 :         *pszExtraNewline = '\0';
     378               0 :         VSIFSeek( fp, nOriginalOffset + nActuallyRead - 1, SEEK_SET );
     379                 : 
     380                 :         /* 
     381                 :          * This hackery is necessary to try and find our correct
     382                 :          * spot on win32 systems with text mode line translation going 
     383                 :          * on.  Sometimes the fseek back overshoots, but it doesn't
     384                 :          * "realize it" till a character has been read. Try to read till
     385                 :          * we get to the right spot and get our CR. 
     386                 :          */ 
     387               0 :         chCheck = fgetc( fp );
     388               0 :         while( (chCheck != 13 && chCheck != EOF)
     389                 :                || VSIFTell(fp) < nOriginalOffset + nActuallyRead )
     390                 :         {
     391                 :             static volatile int bWarned = FALSE;
     392                 : 
     393               0 :             if( !bWarned )
     394                 :             {
     395               0 :                 bWarned = TRUE;
     396               0 :                 CPLDebug( "CPL", "CPLFGets() correcting for DOS text mode translation seek problem." );
     397                 :             }
     398               0 :             chCheck = fgetc( fp );
     399                 :         }
     400                 :     }
     401                 : 
     402         2743947 :     return pszBuffer;
     403                 : }
     404                 : 
     405                 : /************************************************************************/
     406                 : /*                         CPLReadLineBuffer()                          */
     407                 : /*                                                                      */
     408                 : /*      Fetch readline buffer, and ensure it is the desired size,       */
     409                 : /*      reallocating if needed.  Manages TLS (thread local storage)     */
     410                 : /*      issues for the buffer.                                          */
     411                 : /*      We use a special trick to track the actual size of the buffer   */
     412                 : /*      The first 4 bytes are reserved to store it as a int, hence the  */
     413                 : /*      -4 / +4 hacks with the size and pointer.                        */
     414                 : /************************************************************************/
     415         4400595 : static char *CPLReadLineBuffer( int nRequiredSize )
     416                 : 
     417                 : {
     418                 :     
     419                 : /* -------------------------------------------------------------------- */
     420                 : /*      A required size of -1 means the buffer should be freed.         */
     421                 : /* -------------------------------------------------------------------- */
     422         4400595 :     if( nRequiredSize == -1 )
     423                 :     {
     424            1456 :         if( CPLGetTLS( CTLS_RLBUFFERINFO ) != NULL )
     425                 :         {
     426            1456 :             CPLFree( CPLGetTLS( CTLS_RLBUFFERINFO ) );
     427            1456 :             CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
     428                 :         }
     429            1456 :         return NULL;
     430                 :     }
     431                 : 
     432                 : /* -------------------------------------------------------------------- */
     433                 : /*      If the buffer doesn't exist yet, create it.                     */
     434                 : /* -------------------------------------------------------------------- */
     435         4399139 :     GUInt32 *pnAlloc = (GUInt32 *) CPLGetTLS( CTLS_RLBUFFERINFO );
     436                 : 
     437         4399139 :     if( pnAlloc == NULL )
     438                 :     {
     439            1682 :         pnAlloc = (GUInt32 *) CPLMalloc(200);
     440            1682 :         *pnAlloc = 196;
     441            1682 :         CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
     442                 :     }
     443                 : 
     444                 : /* -------------------------------------------------------------------- */
     445                 : /*      If it is too small, grow it bigger.                             */
     446                 : /* -------------------------------------------------------------------- */
     447         4399139 :     if( ((int) *pnAlloc) -1 < nRequiredSize )
     448                 :     {
     449             918 :         int nNewSize = nRequiredSize + 4 + 500;
     450             918 :         if (nNewSize <= 0)
     451                 :         {
     452               0 :             VSIFree( pnAlloc );
     453               0 :             CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
     454                 :             CPLError( CE_Failure, CPLE_OutOfMemory,
     455               0 :                       "CPLReadLineBuffer(): Trying to allocate more than 2 GB." );
     456               0 :             return NULL;
     457                 :         }
     458                 : 
     459             918 :         GUInt32* pnAllocNew = (GUInt32 *) VSIRealloc(pnAlloc,nNewSize);
     460             918 :         if( pnAllocNew == NULL )
     461                 :         {
     462               0 :             VSIFree( pnAlloc );
     463               0 :             CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
     464                 :             CPLError( CE_Failure, CPLE_OutOfMemory,
     465                 :                       "CPLReadLineBuffer(): Out of memory allocating %ld bytes.",
     466               0 :                       (long) nNewSize );
     467               0 :             return NULL;
     468                 :         }
     469             918 :         pnAlloc = pnAllocNew;
     470                 :             
     471             918 :         *pnAlloc = nNewSize - 4;
     472             918 :         CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
     473                 :     }
     474                 : 
     475         4399139 :     return (char *) (pnAlloc+1);
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                            CPLReadLine()                             */
     480                 : /************************************************************************/
     481                 : 
     482                 : /**
     483                 :  * Simplified line reading from text file.
     484                 :  * 
     485                 :  * Read a line of text from the given file handle, taking care
     486                 :  * to capture CR and/or LF and strip off ... equivelent of
     487                 :  * DKReadLine().  Pointer to an internal buffer is returned.
     488                 :  * The application shouldn't free it, or depend on it's value
     489                 :  * past the next call to CPLReadLine().
     490                 :  * 
     491                 :  * Note that CPLReadLine() uses VSIFGets(), so any hooking of VSI file
     492                 :  * services should apply to CPLReadLine() as well.
     493                 :  *
     494                 :  * CPLReadLine() maintains an internal buffer, which will appear as a 
     495                 :  * single block memory leak in some circumstances.  CPLReadLine() may 
     496                 :  * be called with a NULL FILE * at any time to free this working buffer.
     497                 :  *
     498                 :  * @param fp file pointer opened with VSIFOpen().
     499                 :  *
     500                 :  * @return pointer to an internal buffer containing a line of text read
     501                 :  * from the file or NULL if the end of file was encountered.
     502                 :  */
     503                 : 
     504          940602 : const char *CPLReadLine( FILE * fp )
     505                 : 
     506                 : {
     507          940602 :     char *pszRLBuffer = CPLReadLineBuffer(1);
     508          940602 :     int         nReadSoFar = 0;
     509                 : 
     510                 : /* -------------------------------------------------------------------- */
     511                 : /*      Cleanup case.                                                   */
     512                 : /* -------------------------------------------------------------------- */
     513          940602 :     if( fp == NULL )
     514                 :     {
     515             564 :         CPLReadLineBuffer( -1 );
     516             564 :         return NULL;
     517                 :     }
     518                 : 
     519                 : /* -------------------------------------------------------------------- */
     520                 : /*      Loop reading chunks of the line till we get to the end of       */
     521                 : /*      the line.                                                       */
     522                 : /* -------------------------------------------------------------------- */
     523                 :     int nBytesReadThisTime;
     524                 : 
     525         6357281 :     do {
     526                 : /* -------------------------------------------------------------------- */
     527                 : /*      Grow the working buffer if we have it nearly full.  Fail out    */
     528                 : /*      of read line if we can't reallocate it big enough (for          */
     529                 : /*      instance for a _very large_ file with no newlines).             */
     530                 : /* -------------------------------------------------------------------- */
     531         2746705 :         pszRLBuffer = CPLReadLineBuffer( nReadSoFar + 129 );
     532         2746705 :         if( pszRLBuffer == NULL )
     533               0 :             return NULL;
     534                 : 
     535                 : /* -------------------------------------------------------------------- */
     536                 : /*      Do the actual read.                                             */
     537                 : /* -------------------------------------------------------------------- */
     538         2746705 :         if( CPLFGets( pszRLBuffer+nReadSoFar, 128, fp ) == NULL 
     539                 :             && nReadSoFar == 0 )
     540            2758 :             return NULL;
     541                 : 
     542         2743947 :         nBytesReadThisTime = strlen(pszRLBuffer+nReadSoFar);
     543         2743947 :         nReadSoFar += nBytesReadThisTime;
     544                 : 
     545                 :     } while( nBytesReadThisTime >= 127
     546         1806667 :              && pszRLBuffer[nReadSoFar-1] != 13
     547         1806667 :              && pszRLBuffer[nReadSoFar-1] != 10 );
     548                 : 
     549          937280 :     return( pszRLBuffer );
     550                 : }
     551                 : 
     552                 : /************************************************************************/
     553                 : /*                            CPLReadLineL()                            */
     554                 : /************************************************************************/
     555                 : 
     556                 : /**
     557                 :  * Simplified line reading from text file.
     558                 :  * 
     559                 :  * Similar to CPLReadLine(), but reading from a large file API handle.
     560                 :  *
     561                 :  * @param fp file pointer opened with VSIFOpenL().
     562                 :  *
     563                 :  * @return pointer to an internal buffer containing a line of text read
     564                 :  * from the file or NULL if the end of file was encountered.
     565                 :  */
     566                 : 
     567           78596 : const char *CPLReadLineL( VSILFILE * fp )
     568                 : {
     569           78596 :     return CPLReadLine2L( fp, -1, NULL );
     570                 : }
     571                 : 
     572                 : /************************************************************************/
     573                 : /*                           CPLReadLine2L()                            */
     574                 : /************************************************************************/
     575                 : 
     576                 : /**
     577                 :  * Simplified line reading from text file.
     578                 :  * 
     579                 :  * Similar to CPLReadLine(), but reading from a large file API handle.
     580                 :  *
     581                 :  * @param fp file pointer opened with VSIFOpenL().
     582                 :  * @param nMaxCars  maximum number of characters allowed, or -1 for no limit.
     583                 :  * @param papszOptions NULL-terminated array of options. Unused for now.
     584                 : 
     585                 :  * @return pointer to an internal buffer containing a line of text read
     586                 :  * from the file or NULL if the end of file was encountered or the maximum
     587                 :  * number of characters allowed readched.
     588                 :  *
     589                 :  * @since GDAL 1.7.0
     590                 :  */
     591                 : 
     592          679982 : const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars, char** papszOptions )
     593                 : 
     594                 : {
     595                 :     (void) papszOptions;
     596                 : 
     597                 : /* -------------------------------------------------------------------- */
     598                 : /*      Cleanup case.                                                   */
     599                 : /* -------------------------------------------------------------------- */
     600          679982 :     if( fp == NULL )
     601                 :     {
     602             892 :         CPLReadLineBuffer( -1 );
     603             892 :         return NULL;
     604                 :     }
     605                 : 
     606                 : /* -------------------------------------------------------------------- */
     607                 : /*      Loop reading chunks of the line till we get to the end of       */
     608                 : /*      the line.                                                       */
     609                 : /* -------------------------------------------------------------------- */
     610                 :     char *pszRLBuffer;
     611          679090 :     const size_t nChunkSize = 40;
     612                 :     char szChunk[nChunkSize];
     613          679090 :     size_t nChunkBytesRead = 0;
     614          679090 :     int nBufLength = 0;
     615          679090 :     size_t nChunkBytesConsumed = 0;
     616                 : 
     617           32742 :     while( TRUE )
     618                 :     {
     619                 : /* -------------------------------------------------------------------- */
     620                 : /*      Read a chunk from the input file.                               */
     621                 : /* -------------------------------------------------------------------- */
     622          711832 :         if ( nBufLength > INT_MAX - nChunkSize - 1 )
     623                 :         {
     624                 :             CPLError( CE_Failure, CPLE_AppDefined,
     625               0 :                       "Too big line : more than 2 billion characters!." );
     626               0 :             CPLReadLineBuffer( -1 );
     627               0 :             return NULL;
     628                 :         }
     629                 : 
     630          711832 :         pszRLBuffer = CPLReadLineBuffer( nBufLength + nChunkSize + 1 );
     631          711832 :         if( pszRLBuffer == NULL )
     632               0 :             return NULL;
     633                 : 
     634          711832 :         if( nChunkBytesRead == nChunkBytesConsumed + 1 )
     635                 :         {
     636                 : 
     637                 :             // case where one character is left over from last read.
     638           32742 :             szChunk[0] = szChunk[nChunkBytesConsumed];
     639                 : 
     640           32742 :             nChunkBytesConsumed = 0;
     641           32742 :             nChunkBytesRead = VSIFReadL( szChunk+1, 1, nChunkSize-1, fp ) + 1;
     642                 :         }
     643                 :         else
     644                 :         {
     645          679090 :             nChunkBytesConsumed = 0;
     646                 : 
     647                 :             // fresh read.
     648          679090 :             nChunkBytesRead = VSIFReadL( szChunk, 1, nChunkSize, fp );
     649          679090 :             if( nChunkBytesRead == 0 )
     650                 :             {
     651            1050 :                 if( nBufLength == 0 )
     652            1050 :                     return NULL;
     653                 :                 else
     654               0 :                     break;
     655                 :             }
     656                 :         }
     657                 :         
     658                 : /* -------------------------------------------------------------------- */
     659                 : /*      copy over characters watching for end-of-line.                  */
     660                 : /* -------------------------------------------------------------------- */
     661          710782 :         int bBreak = FALSE;
     662        20569946 :         while( nChunkBytesConsumed < nChunkBytesRead-1 && !bBreak )
     663                 :         {
     664        38972876 :             if( (szChunk[nChunkBytesConsumed] == 13
     665          224142 :                  && szChunk[nChunkBytesConsumed+1] == 10)
     666        18924302 :                 || (szChunk[nChunkBytesConsumed] == 10
     667          451850 :                     && szChunk[nChunkBytesConsumed+1] == 13) )
     668                 :             {
     669          224140 :                 nChunkBytesConsumed += 2;
     670          224140 :                 bBreak = TRUE;
     671                 :             }
     672        37848606 :             else if( szChunk[nChunkBytesConsumed] == 10
     673        18472452 :                      || szChunk[nChunkBytesConsumed] == 13 )
     674                 :             {
     675          451852 :                 nChunkBytesConsumed += 1;
     676          451852 :                 bBreak = TRUE;
     677                 :             }
     678                 :             else
     679                 :             {
     680        18472450 :                 pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
     681        18472450 :                 if (nMaxCars >= 0 && nBufLength == nMaxCars)
     682                 :                 {
     683                 :                     CPLError( CE_Failure, CPLE_AppDefined,
     684              60 :                              "Maximum number of characters allowed reached.");
     685              60 :                     return NULL;
     686                 :                 }
     687                 :             }
     688                 :         }
     689                 : 
     690          710722 :         if( bBreak )
     691          675992 :             break;
     692                 : 
     693                 : /* -------------------------------------------------------------------- */
     694                 : /*      If there is a remaining character and it is not a newline       */
     695                 : /*      consume it.  If it is a newline, but we are clearly at the      */
     696                 : /*      end of the file then consume it.                                */
     697                 : /* -------------------------------------------------------------------- */
     698           34730 :         if( nChunkBytesConsumed == nChunkBytesRead-1 
     699                 :             && nChunkBytesRead < nChunkSize )
     700                 :         {
     701            2564 :             if( szChunk[nChunkBytesConsumed] == 10
     702             576 :                 || szChunk[nChunkBytesConsumed] == 13 )
     703                 :             {
     704            1412 :                 nChunkBytesConsumed++;
     705            1412 :                 break;
     706                 :             }
     707                 : 
     708             576 :             pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
     709             576 :             break;
     710                 :         }
     711                 :     }
     712                 : 
     713                 : /* -------------------------------------------------------------------- */
     714                 : /*      If we have left over bytes after breaking out, seek back to     */
     715                 : /*      ensure they remain to be read next time.                        */
     716                 : /* -------------------------------------------------------------------- */
     717          677980 :     if( nChunkBytesConsumed < nChunkBytesRead )
     718                 :     {
     719          671702 :         size_t nBytesToPush = nChunkBytesRead - nChunkBytesConsumed;
     720                 :         
     721          671702 :         VSIFSeekL( fp, VSIFTellL( fp ) - nBytesToPush, SEEK_SET );
     722                 :     }
     723                 : 
     724          677980 :     pszRLBuffer[nBufLength] = '\0';
     725                 : 
     726          677980 :     return( pszRLBuffer );
     727                 : }
     728                 : 
     729                 : /************************************************************************/
     730                 : /*                            CPLScanString()                           */
     731                 : /************************************************************************/
     732                 : 
     733                 : /**
     734                 :  * Scan up to a maximum number of characters from a given string,
     735                 :  * allocate a buffer for a new string and fill it with scanned characters.
     736                 :  *
     737                 :  * @param pszString String containing characters to be scanned. It may be
     738                 :  * terminated with a null character.
     739                 :  *
     740                 :  * @param nMaxLength The maximum number of character to read. Less
     741                 :  * characters will be read if a null character is encountered.
     742                 :  *
     743                 :  * @param bTrimSpaces If TRUE, trim ending spaces from the input string.
     744                 :  * Character considered as empty using isspace(3) function.
     745                 :  *
     746                 :  * @param bNormalize If TRUE, replace ':' symbol with the '_'. It is needed if
     747                 :  * resulting string will be used in CPL dictionaries.
     748                 :  * 
     749                 :  * @return Pointer to the resulting string buffer. Caller responsible to free
     750                 :  * this buffer with CPLFree().
     751                 :  */
     752                 : 
     753            8572 : char *CPLScanString( const char *pszString, int nMaxLength,
     754                 :                      int bTrimSpaces, int bNormalize )
     755                 : {
     756                 :     char    *pszBuffer;
     757                 : 
     758            8572 :     if ( !pszString )
     759               0 :         return NULL;
     760                 : 
     761            8572 :     if ( !nMaxLength )
     762               4 :         return CPLStrdup( "" );
     763                 : 
     764            8568 :     pszBuffer = (char *)CPLMalloc( nMaxLength + 1 );
     765            8568 :     if ( !pszBuffer )
     766               0 :         return NULL;
     767                 : 
     768            8568 :     strncpy( pszBuffer, pszString,  nMaxLength );
     769            8568 :     pszBuffer[nMaxLength] = '\0';
     770                 : 
     771            8568 :     if ( bTrimSpaces )
     772                 :     {
     773            8568 :         size_t  i = strlen( pszBuffer );
     774           18270 :         while ( i-- > 0 && isspace((unsigned char)pszBuffer[i]) )
     775            1134 :             pszBuffer[i] = '\0';
     776                 :     }
     777                 : 
     778            8568 :     if ( bNormalize )
     779                 :     {
     780            8446 :         size_t  i = strlen( pszBuffer );
     781           73728 :         while ( i-- > 0 )
     782                 :         {
     783           56836 :             if ( pszBuffer[i] == ':' )
     784               0 :                 pszBuffer[i] = '_';
     785                 :         }
     786                 :     }
     787                 : 
     788            8568 :     return pszBuffer;
     789                 : }
     790                 : 
     791                 : /************************************************************************/
     792                 : /*                             CPLScanLong()                            */
     793                 : /************************************************************************/
     794                 : 
     795                 : /**
     796                 :  * Scan up to a maximum number of characters from a string and convert
     797                 :  * the result to a long.
     798                 :  *
     799                 :  * @param pszString String containing characters to be scanned. It may be
     800                 :  * terminated with a null character.
     801                 :  *
     802                 :  * @param nMaxLength The maximum number of character to consider as part
     803                 :  * of the number. Less characters will be considered if a null character
     804                 :  * is encountered.
     805                 :  * 
     806                 :  * @return Long value, converted from its ASCII form.
     807                 :  */
     808                 : 
     809              18 : long CPLScanLong( const char *pszString, int nMaxLength )
     810                 : {
     811                 :     long    iValue;
     812              18 :     char    *pszValue = (char *)CPLMalloc( nMaxLength + 1);
     813                 : 
     814                 : /* -------------------------------------------------------------------- */
     815                 : /*      Compute string into local buffer, and terminate it.             */
     816                 : /* -------------------------------------------------------------------- */
     817              18 :     strncpy( pszValue, pszString, nMaxLength );
     818              18 :     pszValue[nMaxLength] = '\0';
     819                 : 
     820                 : /* -------------------------------------------------------------------- */
     821                 : /*      Use atol() to fetch out the result                              */
     822                 : /* -------------------------------------------------------------------- */
     823              18 :     iValue = atol( pszValue );
     824                 : 
     825              18 :     CPLFree( pszValue );
     826              18 :     return iValue;
     827                 : }
     828                 : 
     829                 : 
     830                 : /************************************************************************/
     831                 : /*                            CPLScanULong()                            */
     832                 : /************************************************************************/
     833                 : 
     834                 : /**
     835                 :  * Scan up to a maximum number of characters from a string and convert
     836                 :  * the result to a unsigned long.
     837                 :  *
     838                 :  * @param pszString String containing characters to be scanned. It may be
     839                 :  * terminated with a null character.
     840                 :  *
     841                 :  * @param nMaxLength The maximum number of character to consider as part
     842                 :  * of the number. Less characters will be considered if a null character
     843                 :  * is encountered.
     844                 :  * 
     845                 :  * @return Unsigned long value, converted from its ASCII form.
     846                 :  */
     847                 : 
     848               0 : unsigned long CPLScanULong( const char *pszString, int nMaxLength )
     849                 : {
     850                 :     unsigned long    uValue;
     851               0 :     char    *pszValue = (char *)CPLMalloc( nMaxLength + 1);
     852                 : 
     853                 : /* -------------------------------------------------------------------- */
     854                 : /*      Compute string into local buffer, and terminate it.             */
     855                 : /* -------------------------------------------------------------------- */
     856               0 :     strncpy( pszValue, pszString, nMaxLength );
     857               0 :     pszValue[nMaxLength] = '\0';
     858                 : 
     859                 : /* -------------------------------------------------------------------- */
     860                 : /*      Use strtoul() to fetch out the result                           */
     861                 : /* -------------------------------------------------------------------- */
     862               0 :     uValue = strtoul( pszValue, NULL, 10 );
     863                 : 
     864               0 :     CPLFree( pszValue );
     865               0 :     return uValue;
     866                 : }
     867                 : 
     868                 : /************************************************************************/
     869                 : /*                           CPLScanUIntBig()                           */
     870                 : /************************************************************************/
     871                 : 
     872                 : /**
     873                 :  * Extract big integer from string.
     874                 :  *
     875                 :  * Scan up to a maximum number of characters from a string and convert
     876                 :  * the result to a GUIntBig. 
     877                 :  *
     878                 :  * @param pszString String containing characters to be scanned. It may be
     879                 :  * terminated with a null character.
     880                 :  *
     881                 :  * @param nMaxLength The maximum number of character to consider as part
     882                 :  * of the number. Less characters will be considered if a null character
     883                 :  * is encountered.
     884                 :  * 
     885                 :  * @return GUIntBig value, converted from its ASCII form.
     886                 :  */
     887                 : 
     888           14730 : GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
     889                 : {
     890                 :     GUIntBig    iValue;
     891           14730 :     char        *pszValue = (char *)CPLMalloc( nMaxLength + 1);
     892                 : 
     893                 : /* -------------------------------------------------------------------- */
     894                 : /*      Compute string into local buffer, and terminate it.             */
     895                 : /* -------------------------------------------------------------------- */
     896           14730 :     strncpy( pszValue, pszString, nMaxLength );
     897           14730 :     pszValue[nMaxLength] = '\0';
     898                 : 
     899                 : /* -------------------------------------------------------------------- */
     900                 : /*      Fetch out the result                                            */
     901                 : /* -------------------------------------------------------------------- */
     902                 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
     903                 :     iValue = (GUIntBig)_atoi64( pszValue );
     904                 : # elif HAVE_ATOLL
     905           14730 :     iValue = atoll( pszValue );
     906                 : #else
     907                 :     iValue = atol( pszValue );
     908                 : #endif
     909                 : 
     910           14730 :     CPLFree( pszValue );
     911           14730 :     return iValue;
     912                 : }
     913                 : 
     914                 : /************************************************************************/
     915                 : /*                           CPLScanPointer()                           */
     916                 : /************************************************************************/
     917                 : 
     918                 : /**
     919                 :  * Extract pointer from string.
     920                 :  *
     921                 :  * Scan up to a maximum number of characters from a string and convert
     922                 :  * the result to a pointer. 
     923                 :  *
     924                 :  * @param pszString String containing characters to be scanned. It may be
     925                 :  * terminated with a null character.
     926                 :  *
     927                 :  * @param nMaxLength The maximum number of character to consider as part
     928                 :  * of the number. Less characters will be considered if a null character
     929                 :  * is encountered.
     930                 :  * 
     931                 :  * @return pointer value, converted from its ASCII form.
     932                 :  */
     933                 : 
     934             172 : void *CPLScanPointer( const char *pszString, int nMaxLength )
     935                 : {
     936                 :     void  *pResult;
     937                 :     char  szTemp[128];
     938                 : 
     939                 : /* -------------------------------------------------------------------- */
     940                 : /*      Compute string into local buffer, and terminate it.             */
     941                 : /* -------------------------------------------------------------------- */
     942             172 :     if( nMaxLength > (int) sizeof(szTemp)-1 )
     943               0 :         nMaxLength = sizeof(szTemp)-1;
     944                 : 
     945             172 :     strncpy( szTemp, pszString, nMaxLength );
     946             172 :     szTemp[nMaxLength] = '\0';
     947                 : 
     948                 : /* -------------------------------------------------------------------- */
     949                 : /*      On MSVC we have to scanf pointer values without the 0x          */
     950                 : /*      prefix.                                                         */
     951                 : /* -------------------------------------------------------------------- */
     952             172 :     if( EQUALN(szTemp,"0x",2) )
     953                 :     {
     954             172 :         pResult = NULL;
     955                 : 
     956                 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
     957                 :         sscanf( szTemp+2, "%p", &pResult );
     958                 : #else
     959             172 :         sscanf( szTemp, "%p", &pResult );
     960                 : 
     961                 :         /* Solaris actually behaves like MSVCRT... */
     962             172 :         if (pResult == NULL)
     963                 :         {
     964               0 :             sscanf( szTemp+2, "%p", &pResult );
     965                 :         }
     966                 : #endif
     967                 :     }
     968                 :     
     969                 :     else
     970                 :     {
     971                 : #if SIZEOF_VOIDP == 8
     972               0 :         pResult = (void *) CPLScanUIntBig( szTemp, nMaxLength );
     973                 : #else
     974                 :         pResult = (void *) CPLScanULong( szTemp, nMaxLength );
     975                 : #endif
     976                 :     }
     977                 : 
     978             172 :     return pResult;
     979                 : }
     980                 : 
     981                 : /************************************************************************/
     982                 : /*                             CPLScanDouble()                          */
     983                 : /************************************************************************/
     984                 : 
     985                 : /**
     986                 :  * Extract double from string.
     987                 :  *
     988                 :  * Scan up to a maximum number of characters from a string and convert the
     989                 :  * result to a double. This function uses CPLAtof() to convert string to
     990                 :  * double value, so it uses a comma as a decimal delimiter.
     991                 :  *
     992                 :  * @param pszString String containing characters to be scanned. It may be
     993                 :  * terminated with a null character.
     994                 :  *
     995                 :  * @param nMaxLength The maximum number of character to consider as part
     996                 :  * of the number. Less characters will be considered if a null character
     997                 :  * is encountered.
     998                 :  * 
     999                 :  * @return Double value, converted from its ASCII form.
    1000                 :  */
    1001                 : 
    1002             322 : double CPLScanDouble( const char *pszString, int nMaxLength )
    1003                 : {
    1004                 :     int     i;
    1005                 :     double  dfValue;
    1006             322 :     char    *pszValue = (char *)CPLMalloc( nMaxLength + 1);
    1007                 : 
    1008                 : /* -------------------------------------------------------------------- */
    1009                 : /*      Compute string into local buffer, and terminate it.             */
    1010                 : /* -------------------------------------------------------------------- */
    1011             322 :     strncpy( pszValue, pszString, nMaxLength );
    1012             322 :     pszValue[nMaxLength] = '\0';
    1013                 : 
    1014                 : /* -------------------------------------------------------------------- */
    1015                 : /*      Make a pass through converting 'D's to 'E's.                    */
    1016                 : /* -------------------------------------------------------------------- */
    1017            6818 :     for( i = 0; i < nMaxLength; i++ )
    1018            6496 :         if ( pszValue[i] == 'd' || pszValue[i] == 'D' )
    1019              60 :             pszValue[i] = 'E';
    1020                 : 
    1021                 : /* -------------------------------------------------------------------- */
    1022                 : /*      The conversion itself.                                          */
    1023                 : /* -------------------------------------------------------------------- */
    1024             322 :     dfValue = CPLAtof( pszValue );
    1025                 : 
    1026             322 :     CPLFree( pszValue );
    1027             322 :     return dfValue;
    1028                 : }
    1029                 : 
    1030                 : /************************************************************************/
    1031                 : /*                      CPLPrintString()                                */
    1032                 : /************************************************************************/
    1033                 : 
    1034                 : /**
    1035                 :  * Copy the string pointed to by pszSrc, NOT including the terminating
    1036                 :  * `\\0' character, to the array pointed to by pszDest.
    1037                 :  *
    1038                 :  * @param pszDest Pointer to the destination string buffer. Should be
    1039                 :  * large enough to hold the resulting string.
    1040                 :  *
    1041                 :  * @param pszSrc Pointer to the source buffer.
    1042                 :  * 
    1043                 :  * @param nMaxLen Maximum length of the resulting string. If string length
    1044                 :  * is greater than nMaxLen, it will be truncated.
    1045                 :  * 
    1046                 :  * @return Number of characters printed.
    1047                 :  */
    1048                 : 
    1049            2946 : int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
    1050                 : {
    1051            2946 :     char    *pszTemp = pszDest;
    1052            2946 :     int     nChars = 0;
    1053                 : 
    1054            2946 :     if ( !pszDest )
    1055               0 :         return 0;
    1056                 : 
    1057            2946 :     if ( !pszSrc )
    1058                 :     {
    1059               0 :         *pszDest = '\0';
    1060               0 :         return 1;
    1061                 :     }
    1062                 : 
    1063           85865 :     while ( nChars < nMaxLen && *pszSrc )
    1064                 :     {
    1065           79973 :         *pszTemp++ = *pszSrc++;
    1066           79973 :         nChars++;
    1067                 :     }
    1068                 : 
    1069            2946 :     return nChars;
    1070                 : }
    1071                 : 
    1072                 : /************************************************************************/
    1073                 : /*                         CPLPrintStringFill()                         */
    1074                 : /************************************************************************/
    1075                 : 
    1076                 : /**
    1077                 :  * Copy the string pointed to by pszSrc, NOT including the terminating
    1078                 :  * `\\0' character, to the array pointed to by pszDest. Remainder of the
    1079                 :  * destination string will be filled with space characters. This is only
    1080                 :  * difference from the PrintString().
    1081                 :  *
    1082                 :  * @param pszDest Pointer to the destination string buffer. Should be
    1083                 :  * large enough to hold the resulting string.
    1084                 :  *
    1085                 :  * @param pszSrc Pointer to the source buffer.
    1086                 :  * 
    1087                 :  * @param nMaxLen Maximum length of the resulting string. If string length
    1088                 :  * is greater than nMaxLen, it will be truncated.
    1089                 :  * 
    1090                 :  * @return Number of characters printed.
    1091                 :  */
    1092                 : 
    1093             308 : int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
    1094                 : {
    1095             308 :     char    *pszTemp = pszDest;
    1096                 : 
    1097             308 :     if ( !pszDest )
    1098               0 :         return 0;
    1099                 : 
    1100             308 :     if ( !pszSrc )
    1101                 :     {
    1102               0 :         memset( pszDest, ' ', nMaxLen );
    1103               0 :         return nMaxLen;
    1104                 :     }
    1105                 : 
    1106            2202 :     while ( nMaxLen && *pszSrc )
    1107                 :     {
    1108            1586 :         *pszTemp++ = *pszSrc++;
    1109            1586 :         nMaxLen--;
    1110                 :     }
    1111                 : 
    1112             308 :     if ( nMaxLen )
    1113             104 :         memset( pszTemp, ' ', nMaxLen );
    1114                 : 
    1115             308 :     return nMaxLen;
    1116                 : }
    1117                 : 
    1118                 : /************************************************************************/
    1119                 : /*                          CPLPrintInt32()                             */
    1120                 : /************************************************************************/
    1121                 : 
    1122                 : /**
    1123                 :  * Print GInt32 value into specified string buffer. This string will not
    1124                 :  * be NULL-terminated.
    1125                 :  *
    1126                 :  * @param pszBuffer Pointer to the destination string buffer. Should be
    1127                 :  * large enough to hold the resulting string. Note, that the string will
    1128                 :  * not be NULL-terminated, so user should do this himself, if needed.
    1129                 :  *
    1130                 :  * @param iValue Numerical value to print.
    1131                 :  * 
    1132                 :  * @param nMaxLen Maximum length of the resulting string. If string length
    1133                 :  * is greater than nMaxLen, it will be truncated.
    1134                 :  * 
    1135                 :  * @return Number of characters printed.
    1136                 :  */
    1137                 : 
    1138               8 : int CPLPrintInt32( char *pszBuffer, GInt32 iValue, int nMaxLen )
    1139                 : {
    1140                 :     char    szTemp[64];
    1141                 : 
    1142               8 :     if ( !pszBuffer )
    1143               0 :         return 0;
    1144                 : 
    1145               8 :     if ( nMaxLen >= 64 )
    1146               0 :         nMaxLen = 63;
    1147                 : 
    1148                 : #if UINT_MAX == 65535
    1149                 :     sprintf( szTemp, "%*ld", nMaxLen, iValue );
    1150                 : #else
    1151               8 :     sprintf( szTemp, "%*d", nMaxLen, iValue );
    1152                 : #endif
    1153                 : 
    1154               8 :     return CPLPrintString( pszBuffer, szTemp, nMaxLen );
    1155                 : }
    1156                 : 
    1157                 : /************************************************************************/
    1158                 : /*                          CPLPrintUIntBig()                           */
    1159                 : /************************************************************************/
    1160                 : 
    1161                 : /**
    1162                 :  * Print GUIntBig value into specified string buffer. This string will not
    1163                 :  * be NULL-terminated.
    1164                 :  *
    1165                 :  * @param pszBuffer Pointer to the destination string buffer. Should be
    1166                 :  * large enough to hold the resulting string. Note, that the string will
    1167                 :  * not be NULL-terminated, so user should do this himself, if needed.
    1168                 :  *
    1169                 :  * @param iValue Numerical value to print.
    1170                 :  * 
    1171                 :  * @param nMaxLen Maximum length of the resulting string. If string length
    1172                 :  * is greater than nMaxLen, it will be truncated.
    1173                 :  * 
    1174                 :  * @return Number of characters printed.
    1175                 :  */
    1176                 : 
    1177              20 : int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
    1178                 : {
    1179                 :     char    szTemp[64];
    1180                 : 
    1181              20 :     if ( !pszBuffer )
    1182               0 :         return 0;
    1183                 : 
    1184              20 :     if ( nMaxLen >= 64 )
    1185               0 :         nMaxLen = 63;
    1186                 : 
    1187                 : #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
    1188                 :     sprintf( szTemp, "%*I64d", nMaxLen, iValue );
    1189                 : # elif HAVE_LONG_LONG
    1190              20 :     sprintf( szTemp, "%*lld", nMaxLen, (long long) iValue );
    1191                 : //    sprintf( szTemp, "%*Ld", nMaxLen, (long long) iValue );
    1192                 : #else
    1193                 :     sprintf( szTemp, "%*ld", nMaxLen, iValue );
    1194                 : #endif
    1195                 : 
    1196              20 :     return CPLPrintString( pszBuffer, szTemp, nMaxLen );
    1197                 : }
    1198                 : 
    1199                 : /************************************************************************/
    1200                 : /*                          CPLPrintPointer()                           */
    1201                 : /************************************************************************/
    1202                 : 
    1203                 : /**
    1204                 :  * Print pointer value into specified string buffer. This string will not
    1205                 :  * be NULL-terminated.
    1206                 :  *
    1207                 :  * @param pszBuffer Pointer to the destination string buffer. Should be
    1208                 :  * large enough to hold the resulting string. Note, that the string will
    1209                 :  * not be NULL-terminated, so user should do this himself, if needed.
    1210                 :  *
    1211                 :  * @param pValue Pointer to ASCII encode.
    1212                 :  * 
    1213                 :  * @param nMaxLen Maximum length of the resulting string. If string length
    1214                 :  * is greater than nMaxLen, it will be truncated.
    1215                 :  * 
    1216                 :  * @return Number of characters printed.
    1217                 :  */
    1218                 : 
    1219             172 : int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
    1220                 : {
    1221                 :     char    szTemp[64];
    1222                 : 
    1223             172 :     if ( !pszBuffer )
    1224               0 :         return 0;
    1225                 : 
    1226             172 :     if ( nMaxLen >= 64 )
    1227             170 :         nMaxLen = 63;
    1228                 : 
    1229             172 :     sprintf( szTemp, "%p", pValue );
    1230                 : 
    1231                 :     // On windows, and possibly some other platforms the sprintf("%p")
    1232                 :     // does not prefix things with 0x so it is hard to know later if the
    1233                 :     // value is hex encoded.  Fix this up here. 
    1234                 : 
    1235             172 :     if( !EQUALN(szTemp,"0x",2) )
    1236               0 :         sprintf( szTemp, "0x%p", pValue );
    1237                 : 
    1238             172 :     return CPLPrintString( pszBuffer, szTemp, nMaxLen );
    1239                 : }
    1240                 : 
    1241                 : /************************************************************************/
    1242                 : /*                          CPLPrintDouble()                            */
    1243                 : /************************************************************************/
    1244                 : 
    1245                 : /**
    1246                 :  * Print double value into specified string buffer. Exponential character
    1247                 :  * flag 'E' (or 'e') will be replaced with 'D', as in Fortran. Resulting
    1248                 :  * string will not to be NULL-terminated.
    1249                 :  *
    1250                 :  * @param pszBuffer Pointer to the destination string buffer. Should be
    1251                 :  * large enough to hold the resulting string. Note, that the string will
    1252                 :  * not be NULL-terminated, so user should do this himself, if needed.
    1253                 :  *
    1254                 :  * @param pszFormat Format specifier (for example, "%16.9E").
    1255                 :  *
    1256                 :  * @param dfValue Numerical value to print.
    1257                 :  * 
    1258                 :  * @param pszLocale Pointer to a character string containing locale name
    1259                 :  * ("C", "POSIX", "us_US", "ru_RU.KOI8-R" etc.). If NULL we will not
    1260                 :  * manipulate with locale settings and current process locale will be used for
    1261                 :  * printing. With the pszLocale option we can control what exact locale
    1262                 :  * will be used for printing a numeric value to the string (in most cases
    1263                 :  * it should be C/POSIX).
    1264                 :  *
    1265                 :  * @return Number of characters printed.
    1266                 :  */
    1267                 : 
    1268               0 : int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
    1269                 :                     double dfValue, const char *pszLocale )
    1270                 : {
    1271                 : 
    1272                 : #define DOUBLE_BUFFER_SIZE 64
    1273                 : 
    1274                 :     char    szTemp[DOUBLE_BUFFER_SIZE];
    1275                 :     int     i;
    1276                 : 
    1277               0 :     if ( !pszBuffer )
    1278               0 :         return 0;
    1279                 : 
    1280                 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
    1281                 :     char        *pszCurLocale = NULL;
    1282                 : 
    1283                 :     if ( pszLocale || EQUAL( pszLocale, "" ) )
    1284                 :     {
    1285                 :         // Save the current locale
    1286                 :         pszCurLocale = setlocale(LC_ALL, NULL );
    1287                 :         // Set locale to the specified value
    1288                 :         setlocale( LC_ALL, pszLocale );
    1289                 :     }
    1290                 : #else
    1291                 :     (void) pszLocale;
    1292                 : #endif
    1293                 : 
    1294                 : #if defined(HAVE_SNPRINTF)
    1295               0 :     snprintf( szTemp, DOUBLE_BUFFER_SIZE, pszFormat, dfValue );
    1296                 : #else
    1297                 :     sprintf( szTemp, pszFormat, dfValue );
    1298                 : #endif
    1299               0 :     szTemp[DOUBLE_BUFFER_SIZE - 1] = '\0';
    1300                 : 
    1301               0 :     for( i = 0; szTemp[i] != '\0'; i++ )
    1302                 :     {
    1303               0 :         if( szTemp[i] == 'E' || szTemp[i] == 'e' )
    1304               0 :             szTemp[i] = 'D';
    1305                 :     }
    1306                 : 
    1307                 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
    1308                 :     // Restore stored locale back
    1309                 :     if ( pszCurLocale )
    1310                 :         setlocale( LC_ALL, pszCurLocale );
    1311                 : #endif
    1312                 : 
    1313               0 :     return CPLPrintString( pszBuffer, szTemp, 64 );
    1314                 : 
    1315                 : #undef DOUBLE_BUFFER_SIZE
    1316                 : 
    1317                 : }
    1318                 : 
    1319                 : /************************************************************************/
    1320                 : /*                            CPLPrintTime()                            */
    1321                 : /************************************************************************/
    1322                 : 
    1323                 : /**
    1324                 :  * Print specified time value accordingly to the format options and
    1325                 :  * specified locale name. This function does following:
    1326                 :  * 
    1327                 :  *  - if locale parameter is not NULL, the current locale setting will be
    1328                 :  *  stored and replaced with the specified one;
    1329                 :  *  - format time value with the strftime(3) function;
    1330                 :  *  - restore back current locale, if was saved.
    1331                 :  * 
    1332                 :  * @param pszBuffer Pointer to the destination string buffer. Should be
    1333                 :  * large enough to hold the resulting string. Note, that the string will
    1334                 :  * not be NULL-terminated, so user should do this himself, if needed.
    1335                 :  *
    1336                 :  * @param nMaxLen Maximum length of the resulting string. If string length is
    1337                 :  * greater than nMaxLen, it will be truncated.
    1338                 :  * 
    1339                 :  * @param pszFormat Controls the output format. Options are the same as
    1340                 :  * for strftime(3) function.
    1341                 :  *
    1342                 :  * @param poBrokenTime Pointer to the broken-down time structure. May be
    1343                 :  * requested with the VSIGMTime() and VSILocalTime() functions.
    1344                 :  *
    1345                 :  * @param pszLocale Pointer to a character string containing locale name
    1346                 :  * ("C", "POSIX", "us_US", "ru_RU.KOI8-R" etc.). If NULL we will not
    1347                 :  * manipulate with locale settings and current process locale will be used for
    1348                 :  * printing. Be aware that it may be unsuitable to use current locale for
    1349                 :  * printing time, because all names will be printed in your native language,
    1350                 :  * as well as time format settings also may be ajusted differently from the
    1351                 :  * C/POSIX defaults. To solve these problems this option was introdiced.
    1352                 :  *
    1353                 :  * @return Number of characters printed.
    1354                 :  */
    1355                 : 
    1356                 : #ifndef WIN32CE /* XXX - mloskot - strftime is not available yet. */
    1357                 : 
    1358               0 : int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
    1359                 :                   const struct tm *poBrokenTime, const char *pszLocale )
    1360                 : {
    1361               0 :     char    *pszTemp = (char *)CPLMalloc( (nMaxLen + 1) * sizeof(char) );
    1362                 :     int     nChars;
    1363                 : 
    1364                 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
    1365                 :     char        *pszCurLocale = NULL;
    1366                 : 
    1367                 :     if ( pszLocale || EQUAL( pszLocale, "" ) )
    1368                 :     {
    1369                 :         // Save the current locale
    1370                 :         pszCurLocale = setlocale(LC_ALL, NULL );
    1371                 :         // Set locale to the specified value
    1372                 :         setlocale( LC_ALL, pszLocale );
    1373                 :     }
    1374                 : #else
    1375                 :     (void) pszLocale;
    1376                 : #endif
    1377                 :     
    1378               0 :     if ( !strftime( pszTemp, nMaxLen + 1, pszFormat, poBrokenTime ) )
    1379               0 :         memset( pszTemp, 0, nMaxLen + 1);
    1380                 : 
    1381                 : #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
    1382                 :     // Restore stored locale back
    1383                 :     if ( pszCurLocale )
    1384                 :         setlocale( LC_ALL, pszCurLocale );
    1385                 : #endif
    1386                 : 
    1387               0 :     nChars = CPLPrintString( pszBuffer, pszTemp, nMaxLen );
    1388                 : 
    1389               0 :     CPLFree( pszTemp );
    1390                 : 
    1391               0 :     return nChars;
    1392                 : }
    1393                 : 
    1394                 : #endif
    1395                 : 
    1396                 : /************************************************************************/
    1397                 : /*                       CPLVerifyConfiguration()                       */
    1398                 : /************************************************************************/
    1399                 : 
    1400        70580119 : void CPLVerifyConfiguration()
    1401                 : 
    1402                 : {
    1403                 : /* -------------------------------------------------------------------- */
    1404                 : /*      Verify data types.                                              */
    1405                 : /* -------------------------------------------------------------------- */
    1406                 :     CPLAssert( sizeof(GInt32) == 4 );
    1407                 :     CPLAssert( sizeof(GInt16) == 2 );
    1408                 :     CPLAssert( sizeof(GByte) == 1 );
    1409                 : 
    1410                 :     if( sizeof(GInt32) != 4 )
    1411                 :         CPLError( CE_Fatal, CPLE_AppDefined, 
    1412                 :                   "sizeof(GInt32) == %d ... yow!\n", 
    1413                 :                   (int) sizeof(GInt32) );
    1414                 : 
    1415                 : /* -------------------------------------------------------------------- */
    1416                 : /*      Verify byte order                                               */
    1417                 : /* -------------------------------------------------------------------- */
    1418                 :     GInt32   nTest;
    1419                 : 
    1420        70580119 :     nTest = 1;
    1421                 : 
    1422                 : #ifdef CPL_LSB
    1423        70580119 :     if( ((GByte *) &nTest)[0] != 1 )
    1424                 : #endif
    1425                 : #ifdef CPL_MSB
    1426                 :     if( ((GByte *) &nTest)[3] != 1 )
    1427                 : #endif    
    1428                 :         CPLError( CE_Fatal, CPLE_AppDefined, 
    1429               0 :                   "CPLVerifyConfiguration(): byte order set wrong.\n" );
    1430        70580119 : }
    1431                 : 
    1432                 : /* Uncomment to get list of options that have been fetched and set */
    1433                 : //#define DEBUG_CONFIG_OPTIONS
    1434                 : 
    1435                 : #ifdef DEBUG_CONFIG_OPTIONS
    1436                 : 
    1437                 : #include <set>
    1438                 : #include "cpl_multiproc.h"
    1439                 : 
    1440                 : static void* hRegisterConfigurationOptionMutex = 0;
    1441                 : static std::set<CPLString>* paoGetKeys = NULL;
    1442                 : static std::set<CPLString>* paoSetKeys = NULL;
    1443                 : 
    1444                 : /************************************************************************/
    1445                 : /*                      CPLShowAccessedOptions()                        */
    1446                 : /************************************************************************/
    1447                 : 
    1448                 : static void CPLShowAccessedOptions()
    1449                 : {
    1450                 :     std::set<CPLString>::iterator aoIter;
    1451                 : 
    1452                 :     printf("Configuration options accessed in reading : "),
    1453                 :     aoIter = paoGetKeys->begin();
    1454                 :     while(aoIter != paoGetKeys->end())
    1455                 :     {
    1456                 :         printf("%s, ", (*aoIter).c_str());
    1457                 :         aoIter ++;
    1458                 :     }
    1459                 :     printf("\n");
    1460                 : 
    1461                 :     printf("Configuration options accessed in writing : "),
    1462                 :     aoIter = paoSetKeys->begin();
    1463                 :     while(aoIter != paoSetKeys->end())
    1464                 :     {
    1465                 :         printf("%s, ", (*aoIter).c_str());
    1466                 :         aoIter ++;
    1467                 :     }
    1468                 :     printf("\n");
    1469                 : 
    1470                 :     delete paoGetKeys;
    1471                 :     delete paoSetKeys;
    1472                 :     paoGetKeys = paoSetKeys = NULL;
    1473                 : }
    1474                 : 
    1475                 : /************************************************************************/
    1476                 : /*                       CPLAccessConfigOption()                        */
    1477                 : /************************************************************************/
    1478                 : 
    1479                 : static void CPLAccessConfigOption(const char* pszKey, int bGet)
    1480                 : {
    1481                 :     CPLMutexHolderD(&hRegisterConfigurationOptionMutex);
    1482                 :     if (paoGetKeys == NULL)
    1483                 :     {
    1484                 :         paoGetKeys = new std::set<CPLString>;
    1485                 :         paoSetKeys = new std::set<CPLString>;
    1486                 :         atexit(CPLShowAccessedOptions);
    1487                 :     }
    1488                 :     if (bGet)
    1489                 :         paoGetKeys->insert(pszKey);
    1490                 :     else
    1491                 :         paoSetKeys->insert(pszKey);
    1492                 : }
    1493                 : #endif
    1494                 : 
    1495                 : /************************************************************************/
    1496                 : /*                         CPLGetConfigOption()                         */
    1497                 : /************************************************************************/
    1498                 : 
    1499                 : /**
    1500                 :   * Get the value of a configuration option.
    1501                 :   * 
    1502                 :   * The value is the value of a (key, value) option set with CPLSetConfigOption().
    1503                 :   * If the given option was no defined with CPLSetConfigOption(), it tries to find
    1504                 :   * it in environment variables.
    1505                 :   *
    1506                 :   * @param pszKey the key of the option to retrieve
    1507                 :   * @param pszDefault a default value if the key does not match existing defined options (may be NULL)
    1508                 :   * @return the value associated to the key, or the default value if not found
    1509                 :   *
    1510                 :   * @see CPLSetConfigOption(), http://trac.osgeo.org/gdal/wiki/ConfigOptions
    1511                 :   */
    1512                 : const char * CPL_STDCALL
    1513         2063906 : CPLGetConfigOption( const char *pszKey, const char *pszDefault )
    1514                 : 
    1515                 : {
    1516                 : #ifdef DEBUG_CONFIG_OPTIONS
    1517                 :     CPLAccessConfigOption(pszKey, TRUE);
    1518                 : #endif
    1519                 : 
    1520         2063906 :     const char *pszResult = NULL;
    1521                 : 
    1522         2063906 :     char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
    1523         2063906 :     if( papszTLConfigOptions != NULL )
    1524         1623155 :         pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
    1525                 : 
    1526         2063906 :     if( pszResult == NULL )
    1527                 :     {
    1528         2063534 :         CPLMutexHolderD( &hConfigMutex );
    1529                 : 
    1530         2063534 :         pszResult = CSLFetchNameValue( (char **) papszConfigOptions, pszKey );
    1531                 :     }
    1532                 : 
    1533                 : #if !defined(WIN32CE) 
    1534         2063906 :     if( pszResult == NULL )
    1535          719838 :         pszResult = getenv( pszKey );
    1536                 : #endif
    1537                 :     
    1538         2063906 :     if( pszResult == NULL )
    1539          717079 :         return pszDefault;
    1540                 :     else
    1541         1346827 :         return pszResult;
    1542                 : }
    1543                 : 
    1544                 : /************************************************************************/
    1545                 : /*                         CPLSetConfigOption()                         */
    1546                 : /************************************************************************/
    1547                 : 
    1548                 : /**
    1549                 :   * Set a configuration option for GDAL/OGR use.
    1550                 :   *
    1551                 :   * Those options are defined as a (key, value) couple. The value corresponding
    1552                 :   * to a key can be got later with the CPLGetConfigOption() method.
    1553                 :   *
    1554                 :   * This mechanism is similar to environment variables, but options set with
    1555                 :   * CPLSetConfigOption() overrides, for CPLGetConfigOption() point of view,
    1556                 :   * values defined in the environment.
    1557                 :   *
    1558                 :   * If CPLSetConfigOption() is called several times with the same key, the
    1559                 :   * value provided during the last call will be used.
    1560                 :   *
    1561                 :   * Options can also be passed on the command line of most GDAL utilities
    1562                 :   * with the with '--config KEY VALUE'. For example,
    1563                 :   * ogrinfo --config CPL_DEBUG ON ~/data/test/point.shp
    1564                 :   *
    1565                 :   * @param pszKey the key of the option
    1566                 :   * @param pszValue the value of the option, or NULL to clear a setting.
    1567                 :   * 
    1568                 :   * @see http://trac.osgeo.org/gdal/wiki/ConfigOptions
    1569                 :   */
    1570                 : void CPL_STDCALL 
    1571             862 : CPLSetConfigOption( const char *pszKey, const char *pszValue )
    1572                 : 
    1573                 : {
    1574                 : #ifdef DEBUG_CONFIG_OPTIONS
    1575                 :     CPLAccessConfigOption(pszKey, FALSE);
    1576                 : #endif
    1577             862 :     CPLMutexHolderD( &hConfigMutex );
    1578                 : 
    1579                 :     papszConfigOptions = (volatile char **) 
    1580             862 :         CSLSetNameValue( (char **) papszConfigOptions, pszKey, pszValue );
    1581             862 : }
    1582                 : 
    1583                 : /************************************************************************/
    1584                 : /*                   CPLSetThreadLocalConfigOption()                    */
    1585                 : /************************************************************************/
    1586                 : 
    1587                 : /**
    1588                 :   * Set a configuration option for GDAL/OGR use.
    1589                 :   *
    1590                 :   * Those options are defined as a (key, value) couple. The value corresponding
    1591                 :   * to a key can be got later with the CPLGetConfigOption() method.  
    1592                 :   *
    1593                 :   * This function sets the configuration option that only applies in the
    1594                 :   * current thread, as opposed to CPLSetConfigOption() which sets an option
    1595                 :   * that applies on all threads.
    1596                 :   *
    1597                 :   * @param pszKey the key of the option
    1598                 :   * @param pszValue the value of the option, or NULL to clear a setting.
    1599                 :   */
    1600                 : 
    1601                 : void CPL_STDCALL 
    1602             368 : CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
    1603                 : 
    1604                 : {
    1605                 : #ifdef DEBUG_CONFIG_OPTIONS
    1606                 :     CPLAccessConfigOption(pszKey, FALSE);
    1607                 : #endif
    1608                 : 
    1609             368 :     char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
    1610                 : 
    1611                 :     papszTLConfigOptions = 
    1612             368 :         CSLSetNameValue( papszTLConfigOptions, pszKey, pszValue );
    1613                 : 
    1614             368 :     CPLSetTLSWithFreeFunc( CTLS_CONFIGOPTIONS, papszTLConfigOptions, (CPLTLSFreeFunc)CSLDestroy );
    1615             368 : }
    1616                 : 
    1617                 : /************************************************************************/
    1618                 : /*                           CPLFreeConfig()                            */
    1619                 : /************************************************************************/
    1620                 : 
    1621            1974 : void CPL_STDCALL CPLFreeConfig()
    1622                 : 
    1623                 : {
    1624                 :     {
    1625            1974 :         CPLMutexHolderD( &hConfigMutex );
    1626                 : 
    1627            1974 :         CSLDestroy( (char **) papszConfigOptions);
    1628            1974 :         papszConfigOptions = NULL;
    1629                 :         
    1630            1974 :         char **papszTLConfigOptions = (char **) CPLGetTLS( CTLS_CONFIGOPTIONS );
    1631            1974 :         if( papszTLConfigOptions != NULL )
    1632                 :         {
    1633               4 :             CSLDestroy( papszTLConfigOptions );
    1634               4 :             CPLSetTLS( CTLS_CONFIGOPTIONS, NULL, FALSE );
    1635            1974 :         }
    1636                 :     }
    1637            1974 :     CPLDestroyMutex( hConfigMutex );
    1638            1974 :     hConfigMutex = NULL;
    1639            1974 : }
    1640                 : 
    1641                 : /************************************************************************/
    1642                 : /*                              CPLStat()                               */
    1643                 : /*                                                                      */
    1644                 : /*      Same as VSIStat() except it works on "C:" as if it were         */
    1645                 : /*      "C:\".                                                          */
    1646                 : /************************************************************************/
    1647                 : 
    1648            1862 : int CPLStat( const char *pszPath, VSIStatBuf *psStatBuf )
    1649                 : 
    1650                 : {
    1651            1862 :     if( strlen(pszPath) == 2 && pszPath[1] == ':' )
    1652                 :     {
    1653                 :         char    szAltPath[4];
    1654                 :         
    1655               0 :         szAltPath[0] = pszPath[0];
    1656               0 :         szAltPath[1] = pszPath[1];
    1657               0 :         szAltPath[2] = '\\';
    1658               0 :         szAltPath[3] = '\0';
    1659               0 :         return VSIStat( szAltPath, psStatBuf );
    1660                 :     }
    1661                 :     else
    1662            1862 :         return VSIStat( pszPath, psStatBuf );
    1663                 : }
    1664                 : 
    1665                 : /************************************************************************/
    1666                 : /*                            proj_strtod()                             */
    1667                 : /************************************************************************/
    1668                 : static double
    1669            1052 : proj_strtod(char *nptr, char **endptr) 
    1670                 : 
    1671                 : {
    1672            1052 :     char c, *cp = nptr;
    1673                 :     double result;
    1674                 : 
    1675                 :     /*
    1676                 :      * Scan for characters which cause problems with VC++ strtod()
    1677                 :      */
    1678            5678 :     while ((c = *cp) != '\0') {
    1679            3604 :         if (c == 'd' || c == 'D') {
    1680                 : 
    1681                 :             /*
    1682                 :              * Found one, so NUL it out, call strtod(),
    1683                 :              * then restore it and return
    1684                 :              */
    1685              30 :             *cp = '\0';
    1686              30 :             result = strtod(nptr, endptr);
    1687              30 :             *cp = c;
    1688              30 :             return result;
    1689                 :         }
    1690            3574 :         ++cp;
    1691                 :     }
    1692                 : 
    1693                 :     /* no offending characters, just handle normally */
    1694                 : 
    1695            1022 :     return strtod(nptr, endptr);
    1696                 : }
    1697                 : 
    1698                 : /************************************************************************/
    1699                 : /*                            CPLDMSToDec()                             */
    1700                 : /************************************************************************/
    1701                 : 
    1702                 : static const char*sym = "NnEeSsWw";
    1703                 : static const double vm[] = { 1.0, 0.0166666666667, 0.00027777778 };
    1704                 : 
    1705            1028 : double CPLDMSToDec( const char *is )
    1706                 : 
    1707                 : {
    1708                 :     int sign, n, nl;
    1709                 :     char *p, *s, work[64];
    1710                 :     double v, tv;
    1711                 : 
    1712                 :     /* copy sting into work space */
    1713            1028 :     while (isspace((unsigned char)(sign = *is))) ++is;
    1714            5710 :     for (n = sizeof(work), s = work, p = (char *)is; isgraph(*p) && --n ; )
    1715            3654 :         *s++ = *p++;
    1716            1028 :     *s = '\0';
    1717                 :     /* it is possible that a really odd input (like lots of leading
    1718                 :        zeros) could be truncated in copying into work.  But ... */
    1719            1028 :     sign = *(s = work);
    1720            1028 :     if (sign == '+' || sign == '-') s++;
    1721             918 :     else sign = '+';
    1722            2080 :     for (v = 0., nl = 0 ; nl < 3 ; nl = n + 1 ) {
    1723            1080 :         if (!(isdigit(*s) || *s == '.')) break;
    1724            1052 :         if ((tv = proj_strtod(s, &s)) == HUGE_VAL)
    1725               0 :             return tv;
    1726            1052 :         switch (*s) {
    1727                 :           case 'D': case 'd':
    1728              30 :             n = 0; break;
    1729                 :           case '\'':
    1730              22 :             n = 1; break;
    1731                 :           case '"':
    1732              14 :             n = 2; break;
    1733                 :           case 'r': case 'R':
    1734               0 :             if (nl) {
    1735               0 :                 return 0.0;
    1736                 :             }
    1737               0 :             ++s;
    1738               0 :             v = tv;
    1739               0 :             goto skip;
    1740                 :           default:
    1741             986 :             v += tv * vm[nl];
    1742             986 :           skip: n = 4;
    1743             986 :             continue;
    1744                 :         }
    1745              66 :         if (n < nl) {
    1746               0 :             return 0.0;
    1747                 :         }
    1748              66 :         v += tv * vm[n];
    1749              66 :         ++s;
    1750                 :     }
    1751                 :     /* postfix sign */
    1752            1028 :     if (*s && ((p = (char *) strchr(sym, *s))) != NULL) {
    1753              34 :         sign = (p - sym) >= 4 ? '-' : '+';
    1754              34 :         ++s;
    1755                 :     }
    1756            1028 :     if (sign == '-')
    1757             122 :         v = -v;
    1758                 : 
    1759            1028 :     return v;
    1760                 : }
    1761                 : 
    1762                 : 
    1763                 : /************************************************************************/
    1764                 : /*                            CPLDecToDMS()                             */
    1765                 : /*                                                                      */
    1766                 : /*      Translate a decimal degrees value to a DMS string with          */
    1767                 : /*      hemisphere.                                                     */
    1768                 : /************************************************************************/
    1769                 : 
    1770             520 : const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
    1771                 :                          int nPrecision )
    1772                 : 
    1773                 : {
    1774             520 :     VALIDATE_POINTER1( pszAxis, "CPLDecToDMS", "" );
    1775                 : 
    1776                 :     int         nDegrees, nMinutes;
    1777                 :     double      dfSeconds, dfABSAngle, dfEpsilon;
    1778                 :     char        szFormat[30];
    1779                 :     const char  *pszHemisphere;
    1780                 :     static CPL_THREADLOCAL char szBuffer[50] = { 0 };
    1781                 :     
    1782                 :     
    1783             520 :     dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
    1784                 : 
    1785             520 :     dfABSAngle = ABS(dfAngle) + dfEpsilon;
    1786             520 :     if (dfABSAngle > 361)
    1787                 :     {
    1788               0 :         return "Invalid angle";
    1789                 :     }
    1790                 : 
    1791             520 :     nDegrees = (int) dfABSAngle;
    1792             520 :     nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
    1793             520 :     dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
    1794                 : 
    1795             520 :     if( dfSeconds > dfEpsilon * 3600.0 )
    1796             520 :         dfSeconds -= dfEpsilon * 3600.0;
    1797                 : 
    1798             720 :     if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
    1799             200 :         pszHemisphere = "W";
    1800             320 :     else if( EQUAL(pszAxis,"Long") )
    1801              60 :         pszHemisphere = "E";
    1802             260 :     else if( dfAngle < 0.0 )
    1803              20 :         pszHemisphere = "S";
    1804                 :     else
    1805             240 :         pszHemisphere = "N";
    1806                 : 
    1807             520 :     sprintf( szFormat, "%%3dd%%2d\'%%%d.%df\"%s", nPrecision+3, nPrecision, pszHemisphere );
    1808             520 :     sprintf( szBuffer, szFormat, nDegrees, nMinutes, dfSeconds );
    1809                 : 
    1810             520 :     return( szBuffer );
    1811                 : }
    1812                 : 
    1813                 : /************************************************************************/
    1814                 : /*                         CPLPackedDMSToDec()                          */
    1815                 : /************************************************************************/
    1816                 : 
    1817                 : /**
    1818                 :  * Convert a packed DMS value (DDDMMMSSS.SS) into decimal degrees.
    1819                 :  * 
    1820                 :  * This function converts a packed DMS angle to seconds. The standard
    1821                 :  * packed DMS format is:
    1822                 :  *
    1823                 :  *  degrees * 1000000 + minutes * 1000 + seconds
    1824                 :  *
    1825                 :  * Example:     ang = 120025045.25 yields
    1826                 :  *              deg = 120
    1827                 :  *              min = 25
    1828                 :  *              sec = 45.25
    1829                 :  * 
    1830                 :  * The algorithm used for the conversion is as follows:
    1831                 :  *
    1832                 :  * 1.  The absolute value of the angle is used.
    1833                 :  *
    1834                 :  * 2.  The degrees are separated out:
    1835                 :  *     deg = ang/1000000                    (fractional portion truncated)
    1836                 :  *
    1837                 :  * 3.  The minutes are separated out:
    1838                 :  *     min = (ang - deg * 1000000) / 1000   (fractional portion truncated)
    1839                 :  *
    1840                 :  * 4.  The seconds are then computed:
    1841                 :  *     sec = ang - deg * 1000000 - min * 1000
    1842                 :  *
    1843                 :  * 5.  The total angle in seconds is computed:
    1844                 :  *     sec = deg * 3600.0 + min * 60.0 + sec
    1845                 :  *
    1846                 :  * 6.  The sign of sec is set to that of the input angle.
    1847                 :  *
    1848                 :  * Packed DMS values used by the USGS GCTP package and probably by other
    1849                 :  * software.
    1850                 :  *
    1851                 :  * NOTE: This code does not validate input value. If you give the wrong
    1852                 :  * value, you will get the wrong result.
    1853                 :  *
    1854                 :  * @param dfPacked Angle in packed DMS format.
    1855                 :  *
    1856                 :  * @return Angle in decimal degrees.
    1857                 :  * 
    1858                 :  */
    1859                 : 
    1860              64 : double CPLPackedDMSToDec( double dfPacked )
    1861                 : {
    1862                 :     double  dfDegrees, dfMinutes, dfSeconds, dfSign;
    1863                 : 
    1864              64 :     dfSign = ( dfPacked < 0.0 )? -1 : 1;
    1865                 :         
    1866              64 :     dfSeconds = ABS( dfPacked );
    1867              64 :     dfDegrees = floor(dfSeconds / 1000000.0);
    1868              64 :     dfSeconds = dfSeconds - dfDegrees * 1000000.0;
    1869              64 :     dfMinutes = floor(dfSeconds / 1000.0);
    1870              64 :     dfSeconds = dfSeconds - dfMinutes * 1000.0;
    1871              64 :     dfSeconds = dfSign * ( dfDegrees * 3600.0 + dfMinutes * 60.0 + dfSeconds);
    1872              64 :     dfDegrees = dfSeconds / 3600.0;
    1873                 : 
    1874              64 :     return dfDegrees;
    1875                 : }
    1876                 : 
    1877                 : /************************************************************************/
    1878                 : /*                         CPLDecToPackedDMS()                          */
    1879                 : /************************************************************************/
    1880                 : /**
    1881                 :  * Convert decimal degrees into packed DMS value (DDDMMMSSS.SS).
    1882                 :  * 
    1883                 :  * This function converts a value, specified in decimal degrees into
    1884                 :  * packed DMS angle. The standard packed DMS format is:
    1885                 :  *
    1886                 :  *  degrees * 1000000 + minutes * 1000 + seconds
    1887                 :  *
    1888                 :  * See also CPLPackedDMSToDec().
    1889                 :  *
    1890                 :  * @param dfDec Angle in decimal degrees.
    1891                 :  *
    1892                 :  * @return Angle in packed DMS format.
    1893                 :  * 
    1894                 :  */
    1895                 : 
    1896              16 : double CPLDecToPackedDMS( double dfDec )
    1897                 : {
    1898                 :     double  dfDegrees, dfMinutes, dfSeconds, dfSign;
    1899                 : 
    1900              16 :     dfSign = ( dfDec < 0.0 )? -1 : 1;
    1901                 : 
    1902              16 :     dfDec = ABS( dfDec );
    1903              16 :     dfDegrees = floor( dfDec );
    1904              16 :     dfMinutes = floor( ( dfDec - dfDegrees ) * 60.0 );
    1905              16 :     dfSeconds = ( dfDec - dfDegrees ) * 3600.0 - dfMinutes * 60.0;
    1906                 : 
    1907              16 :     return dfSign * (dfDegrees * 1000000.0 + dfMinutes * 1000.0 + dfSeconds);
    1908                 : }
    1909                 : 
    1910                 : /************************************************************************/
    1911                 : /*                         CPLStringToComplex()                         */
    1912                 : /************************************************************************/
    1913                 : 
    1914            1226 : void CPL_DLL CPLStringToComplex( const char *pszString, 
    1915                 :                                  double *pdfReal, double *pdfImag )
    1916                 : 
    1917                 : {
    1918                 :     int  i;
    1919            1226 :     int  iPlus = -1, iImagEnd = -1;
    1920                 : 
    1921            2452 :     while( *pszString == ' ' )
    1922               0 :         pszString++;
    1923                 : 
    1924            1226 :     *pdfReal = CPLAtof(pszString);
    1925            1226 :     *pdfImag = 0.0;
    1926                 : 
    1927            2464 :     for( i = 0; pszString[i] != '\0' && pszString[i] != ' ' && i < 100; i++ )
    1928                 :     {
    1929            1238 :         if( pszString[i] == '+' && i > 0 )
    1930               0 :             iPlus = i;
    1931            1238 :         if( pszString[i] == '-' && i > 0 )
    1932               0 :             iPlus = i;
    1933            1238 :         if( pszString[i] == 'i' )
    1934               0 :             iImagEnd = i;
    1935                 :     }
    1936                 : 
    1937            1226 :     if( iPlus > -1 && iImagEnd > -1 && iPlus < iImagEnd )
    1938                 :     {
    1939               0 :         *pdfImag = CPLAtof(pszString + iPlus);
    1940                 :     }
    1941                 : 
    1942                 :     return;
    1943                 : }
    1944                 : 
    1945                 : /************************************************************************/
    1946                 : /*                           CPLOpenShared()                            */
    1947                 : /************************************************************************/
    1948                 : 
    1949                 : /**
    1950                 :  * Open a shared file handle. 
    1951                 :  *
    1952                 :  * Some operating systems have limits on the number of file handles that can
    1953                 :  * be open at one time.  This function attempts to maintain a registry of
    1954                 :  * already open file handles, and reuse existing ones if the same file
    1955                 :  * is requested by another part of the application. 
    1956                 :  *
    1957                 :  * Note that access is only shared for access types "r", "rb", "r+" and 
    1958                 :  * "rb+".  All others will just result in direct VSIOpen() calls.  Keep in
    1959                 :  * mind that a file is only reused if the file name is exactly the same. 
    1960                 :  * Different names referring to the same file will result in different 
    1961                 :  * handles.  
    1962                 :  *
    1963                 :  * The VSIFOpen() or VSIFOpenL() function is used to actually open the file, 
    1964                 :  * when an existing file handle can't be shared. 
    1965                 :  *
    1966                 :  * @param pszFilename the name of the file to open.
    1967                 :  * @param pszAccess the normal fopen()/VSIFOpen() style access string.
    1968                 :  * @param bLarge If TRUE VSIFOpenL() (for large files) will be used instead of
    1969                 :  * VSIFOpen(). 
    1970                 :  *
    1971                 :  * @return a file handle or NULL if opening fails. 
    1972                 :  */
    1973                 : 
    1974              26 : FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
    1975                 :                      int bLarge )
    1976                 : 
    1977                 : {
    1978                 :     int i;
    1979                 :     int bReuse;
    1980              26 :     CPLMutexHolderD( &hSharedFileMutex );
    1981                 : 
    1982                 : /* -------------------------------------------------------------------- */
    1983                 : /*      Is there an existing file we can use?                           */
    1984                 : /* -------------------------------------------------------------------- */
    1985              26 :     bReuse = EQUAL(pszAccess,"rb") || EQUAL(pszAccess, "rb+");
    1986                 : 
    1987              30 :     for( i = 0; bReuse && i < nSharedFileCount; i++ )
    1988                 :     {
    1989              34 :         if( strcmp(pasSharedFileList[i].pszFilename,pszFilename) == 0 
    1990              10 :             && !bLarge == !pasSharedFileList[i].bLarge
    1991              10 :             && EQUAL(pasSharedFileList[i].pszAccess,pszAccess) )
    1992                 :         {
    1993              10 :             pasSharedFileList[i].nRefCount++;
    1994              10 :             return pasSharedFileList[i].fp;
    1995                 :         }
    1996                 :     }
    1997                 : 
    1998                 : /* -------------------------------------------------------------------- */
    1999                 : /*      Open the file.                                                  */
    2000                 : /* -------------------------------------------------------------------- */
    2001                 :     FILE *fp;
    2002                 : 
    2003              16 :     if( bLarge )
    2004              16 :         fp = (FILE*) VSIFOpenL( pszFilename, pszAccess );
    2005                 :     else
    2006               0 :         fp = VSIFOpen( pszFilename, pszAccess );
    2007                 : 
    2008              16 :     if( fp == NULL )
    2009               0 :         return NULL;
    2010                 : 
    2011                 : /* -------------------------------------------------------------------- */
    2012                 : /*      Add an entry to the list.                                       */
    2013                 : /* -------------------------------------------------------------------- */
    2014              16 :     nSharedFileCount++;
    2015                 : 
    2016                 :     pasSharedFileList = (CPLSharedFileInfo *)
    2017                 :         CPLRealloc( (void *) pasSharedFileList, 
    2018              16 :                     sizeof(CPLSharedFileInfo) * nSharedFileCount );
    2019                 : 
    2020              16 :     pasSharedFileList[nSharedFileCount-1].fp = fp;
    2021              16 :     pasSharedFileList[nSharedFileCount-1].nRefCount = 1;
    2022              16 :     pasSharedFileList[nSharedFileCount-1].bLarge = bLarge;
    2023              16 :     pasSharedFileList[nSharedFileCount-1].pszFilename =CPLStrdup(pszFilename);
    2024              16 :     pasSharedFileList[nSharedFileCount-1].pszAccess = CPLStrdup(pszAccess);
    2025                 : 
    2026              16 :     return fp;
    2027                 : }
    2028                 : 
    2029                 : /************************************************************************/
    2030                 : /*                           CPLCloseShared()                           */
    2031                 : /************************************************************************/
    2032                 : 
    2033                 : /**
    2034                 :  * Close shared file.
    2035                 :  *
    2036                 :  * Dereferences the indicated file handle, and closes it if the reference
    2037                 :  * count has dropped to zero.  A CPLError() is issued if the file is not
    2038                 :  * in the shared file list.
    2039                 :  *
    2040                 :  * @param fp file handle from CPLOpenShared() to deaccess.
    2041                 :  */
    2042                 : 
    2043              26 : void CPLCloseShared( FILE * fp )
    2044                 : 
    2045                 : {
    2046              26 :     CPLMutexHolderD( &hSharedFileMutex );
    2047                 :     int i;
    2048                 : 
    2049                 : /* -------------------------------------------------------------------- */
    2050                 : /*      Search for matching information.                                */
    2051                 : /* -------------------------------------------------------------------- */
    2052              26 :     for( i = 0; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ){}
    2053                 : 
    2054              26 :     if( i == nSharedFileCount )
    2055                 :     {
    2056                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2057                 :                   "Unable to find file handle %p in CPLCloseShared().",
    2058               0 :                   fp );
    2059                 :         return;
    2060                 :     }
    2061                 : 
    2062                 : /* -------------------------------------------------------------------- */
    2063                 : /*      Dereference and return if there are still some references.      */
    2064                 : /* -------------------------------------------------------------------- */
    2065              26 :     if( --pasSharedFileList[i].nRefCount > 0 )
    2066                 :         return;
    2067                 : 
    2068                 : /* -------------------------------------------------------------------- */
    2069                 : /*      Close the file, and remove the information.                     */
    2070                 : /* -------------------------------------------------------------------- */
    2071              16 :     if( pasSharedFileList[i].bLarge )
    2072              16 :         VSIFCloseL( (VSILFILE*) pasSharedFileList[i].fp );
    2073                 :     else
    2074               0 :         VSIFClose( pasSharedFileList[i].fp );
    2075                 : 
    2076              16 :     CPLFree( pasSharedFileList[i].pszFilename );
    2077              16 :     CPLFree( pasSharedFileList[i].pszAccess );
    2078                 : 
    2079                 : //    pasSharedFileList[i] = pasSharedFileList[--nSharedFileCount];
    2080                 :     memmove( (void *) (pasSharedFileList + i), 
    2081                 :              (void *) (pasSharedFileList + --nSharedFileCount), 
    2082              16 :              sizeof(CPLSharedFileInfo) );
    2083                 : 
    2084              16 :     if( nSharedFileCount == 0 )
    2085                 :     {
    2086              14 :         CPLFree( (void *) pasSharedFileList );
    2087              14 :         pasSharedFileList = NULL;
    2088               0 :     }
    2089                 : }
    2090                 : 
    2091                 : /************************************************************************/
    2092                 : /*                          CPLGetSharedList()                          */
    2093                 : /************************************************************************/
    2094                 : 
    2095                 : /**
    2096                 :  * Fetch list of open shared files.
    2097                 :  *
    2098                 :  * @param pnCount place to put the count of entries. 
    2099                 :  *
    2100                 :  * @return the pointer to the first in the array of shared file info 
    2101                 :  * structures.
    2102                 :  */
    2103                 : 
    2104               0 : CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
    2105                 : 
    2106                 : {
    2107               0 :     if( pnCount != NULL )
    2108               0 :         *pnCount = nSharedFileCount;
    2109                 :         
    2110               0 :     return (CPLSharedFileInfo *) pasSharedFileList;
    2111                 : }
    2112                 : 
    2113                 : /************************************************************************/
    2114                 : /*                         CPLDumpSharedList()                          */
    2115                 : /************************************************************************/
    2116                 : 
    2117                 : /**
    2118                 :  * Report open shared files.
    2119                 :  *
    2120                 :  * Dumps all open shared files to the indicated file handle.  If the
    2121                 :  * file handle is NULL information is sent via the CPLDebug() call. 
    2122                 :  *
    2123                 :  * @param fp File handle to write to.
    2124                 :  */
    2125                 : 
    2126              36 : void CPLDumpSharedList( FILE *fp )
    2127                 : 
    2128                 : {
    2129                 :     int i;
    2130                 : 
    2131              36 :     if( nSharedFileCount > 0 )
    2132                 :     {
    2133               0 :         if( fp == NULL )
    2134               0 :             CPLDebug( "CPL", "%d Shared files open.", nSharedFileCount );
    2135                 :         else
    2136               0 :             fprintf( fp, "%d Shared files open.", nSharedFileCount );
    2137                 :     }
    2138                 : 
    2139              36 :     for( i = 0; i < nSharedFileCount; i++ )
    2140                 :     {
    2141               0 :         if( fp == NULL )
    2142                 :             CPLDebug( "CPL", 
    2143                 :                       "%2d %d %4s %s", 
    2144               0 :                       pasSharedFileList[i].nRefCount, 
    2145               0 :                       pasSharedFileList[i].bLarge,
    2146               0 :                       pasSharedFileList[i].pszAccess,
    2147               0 :                       pasSharedFileList[i].pszFilename );
    2148                 :         else
    2149                 :             fprintf( fp, "%2d %d %4s %s", 
    2150               0 :                      pasSharedFileList[i].nRefCount, 
    2151               0 :                      pasSharedFileList[i].bLarge,
    2152               0 :                      pasSharedFileList[i].pszAccess,
    2153               0 :                      pasSharedFileList[i].pszFilename );
    2154                 :     }
    2155              36 : }
    2156                 : 
    2157                 : /************************************************************************/
    2158                 : /*                           CPLUnlinkTree()                            */
    2159                 : /************************************************************************/
    2160                 : 
    2161                 : /**
    2162                 :  * @return 0 on successful completion, -1 if function fails.
    2163                 :  */
    2164                 : 
    2165              32 : int CPLUnlinkTree( const char *pszPath )
    2166                 : 
    2167                 : {
    2168                 : /* -------------------------------------------------------------------- */
    2169                 : /*      First, ensure there isn't any such file yet.                    */
    2170                 : /* -------------------------------------------------------------------- */
    2171                 :     VSIStatBuf sStatBuf;
    2172                 : 
    2173              32 :     if( VSIStat( pszPath, &sStatBuf ) != 0 )
    2174                 :     {
    2175                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2176                 :                   "It seems no file system object called '%s' exists.",
    2177               4 :                   pszPath );
    2178                 : 
    2179               4 :         return -1;
    2180                 :     }
    2181                 : 
    2182                 : /* -------------------------------------------------------------------- */
    2183                 : /*      If it's a simple file, just delete it.                          */
    2184                 : /* -------------------------------------------------------------------- */
    2185              28 :     if( VSI_ISREG( sStatBuf.st_mode ) )
    2186                 :     {
    2187              26 :         if( VSIUnlink( pszPath ) != 0 )
    2188                 :         {
    2189                 :             CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.", 
    2190               0 :                       pszPath );
    2191                 : 
    2192               0 :             return -1;
    2193                 :         }
    2194                 :         else
    2195              26 :             return 0;
    2196                 :     }
    2197                 : 
    2198                 : /* -------------------------------------------------------------------- */
    2199                 : /*      If it is a directory recurse then unlink the directory.         */
    2200                 : /* -------------------------------------------------------------------- */
    2201               2 :     else if( VSI_ISDIR( sStatBuf.st_mode ) )
    2202                 :     {
    2203               2 :         char **papszItems = CPLReadDir( pszPath );
    2204                 :         int  i;
    2205                 : 
    2206              28 :         for( i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
    2207                 :         {
    2208                 :             char *pszSubPath;
    2209                 :             int nErr;
    2210                 : 
    2211              26 :             if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
    2212               4 :                 continue;
    2213                 : 
    2214                 :             pszSubPath = CPLStrdup(
    2215              22 :                 CPLFormFilename( pszPath, papszItems[i], NULL ) );
    2216                 : 
    2217              22 :             nErr = CPLUnlinkTree( pszSubPath );
    2218              22 :             CPLFree( pszSubPath );
    2219                 : 
    2220              22 :             if( nErr != 0 )
    2221                 :             {
    2222               0 :                 CSLDestroy( papszItems );
    2223               0 :                 return nErr;
    2224                 :             }
    2225                 :         }
    2226                 :         
    2227               2 :         CSLDestroy( papszItems );
    2228                 : 
    2229               2 :         if( VSIRmdir( pszPath ) != 0 )
    2230                 :         {
    2231                 :             CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.", 
    2232               0 :                       pszPath );
    2233                 : 
    2234               0 :             return -1;
    2235                 :         }
    2236                 :         else
    2237               2 :             return 0;
    2238                 :     }
    2239                 : 
    2240                 : /* -------------------------------------------------------------------- */
    2241                 : /*      otherwise report an error.                                      */
    2242                 : /* -------------------------------------------------------------------- */
    2243                 :     else
    2244                 :     {
    2245                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    2246                 :                   "Failed to unlink %s.\nUnrecognised filesystem object.",
    2247               0 :                   pszPath );
    2248               0 :         return 1000;
    2249                 :     }
    2250                 : }
    2251                 : 
    2252                 : /************************************************************************/
    2253                 : /*                            CPLCopyFile()                             */
    2254                 : /************************************************************************/
    2255                 : 
    2256              18 : int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
    2257                 : 
    2258                 : {
    2259                 :     VSILFILE *fpOld, *fpNew;
    2260                 :     GByte *pabyBuffer;
    2261                 :     size_t nBufferSize;
    2262                 :     size_t nBytesRead;
    2263              18 :     int nRet = 0;
    2264                 : 
    2265                 : /* -------------------------------------------------------------------- */
    2266                 : /*      Open old and new file.                                          */
    2267                 : /* -------------------------------------------------------------------- */
    2268              18 :     fpOld = VSIFOpenL( pszOldPath, "rb" );
    2269              18 :     if( fpOld == NULL )
    2270               0 :         return -1;
    2271                 : 
    2272              18 :     fpNew = VSIFOpenL( pszNewPath, "wb" );
    2273              18 :     if( fpNew == NULL )
    2274                 :     {
    2275               4 :         VSIFCloseL( fpOld );
    2276               4 :         return -1;
    2277                 :     }
    2278                 : 
    2279                 : /* -------------------------------------------------------------------- */
    2280                 : /*      Prepare buffer.                                                 */
    2281                 : /* -------------------------------------------------------------------- */
    2282              14 :     nBufferSize = 1024 * 1024;
    2283              14 :     pabyBuffer = (GByte *) CPLMalloc(nBufferSize);
    2284                 : 
    2285                 : /* -------------------------------------------------------------------- */
    2286                 : /*      Copy file over till we run out of stuff.                        */
    2287                 : /* -------------------------------------------------------------------- */
    2288              14 :     do { 
    2289              14 :         nBytesRead = VSIFReadL( pabyBuffer, 1, nBufferSize, fpOld );
    2290              14 :         if( long(nBytesRead) < 0 )
    2291               0 :             nRet = -1;
    2292                 : 
    2293              14 :         if( nRet == 0
    2294                 :             && VSIFWriteL( pabyBuffer, 1, nBytesRead, fpNew ) < nBytesRead )
    2295               0 :             nRet = -1;
    2296                 :     } while( nRet == 0 && nBytesRead == nBufferSize );
    2297                 : 
    2298                 : /* -------------------------------------------------------------------- */
    2299                 : /*      Cleanup                                                         */
    2300                 : /* -------------------------------------------------------------------- */
    2301              14 :     VSIFCloseL( fpNew );
    2302              14 :     VSIFCloseL( fpOld );
    2303                 : 
    2304              14 :     CPLFree( pabyBuffer );
    2305                 : 
    2306              14 :     return nRet;
    2307                 : }
    2308                 : 
    2309                 : /************************************************************************/
    2310                 : /*                            CPLMoveFile()                             */
    2311                 : /************************************************************************/
    2312                 : 
    2313               8 : int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
    2314                 : 
    2315                 : {
    2316               8 :     if( VSIRename( pszOldPath, pszNewPath ) == 0 )
    2317               8 :         return 0;
    2318                 : 
    2319               0 :     int nRet = CPLCopyFile( pszNewPath, pszOldPath );
    2320                 : 
    2321               0 :     if( nRet == 0 )
    2322               0 :         VSIUnlink( pszOldPath );
    2323                 :     
    2324               0 :     return nRet;
    2325                 : }
    2326                 : 
    2327                 : /************************************************************************/
    2328                 : /* ==================================================================== */
    2329                 : /*                              CPLLocaleC                              */
    2330                 : /* ==================================================================== */
    2331                 : /************************************************************************/
    2332                 : 
    2333                 : #include <locale.h>
    2334                 : 
    2335                 : /************************************************************************/
    2336                 : /*                             CPLLocaleC()                             */
    2337                 : /************************************************************************/
    2338                 : 
    2339          153926 : CPLLocaleC::CPLLocaleC() : pszOldLocale(CPLStrdup(setlocale(LC_NUMERIC,NULL)))
    2340                 : 
    2341                 : {
    2342          153926 :     if( CSLTestBoolean(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC","NO"))
    2343                 :         || EQUAL(pszOldLocale,"C")
    2344                 :         || EQUAL(pszOldLocale,"POSIX")
    2345                 :         || setlocale(LC_NUMERIC,"C") == NULL )
    2346                 :     {
    2347          153926 :         CPLFree( pszOldLocale );
    2348          153926 :         pszOldLocale = NULL;
    2349                 :     }
    2350          153926 : }
    2351                 : 
    2352                 : /************************************************************************/
    2353                 : /*                            ~CPLLocaleC()                             */
    2354                 : /************************************************************************/
    2355                 : 
    2356          153926 : CPLLocaleC::~CPLLocaleC()
    2357                 : 
    2358                 : {
    2359          153926 :     if( pszOldLocale != NULL )
    2360                 :     {
    2361               0 :         setlocale( LC_NUMERIC, pszOldLocale );
    2362               0 :         CPLFree( pszOldLocale );
    2363                 :     }
    2364          153926 : }
    2365                 : 
    2366                 : /************************************************************************/
    2367                 : /*                          CPLCheckForFile()                           */
    2368                 : /************************************************************************/
    2369                 : 
    2370                 : /**
    2371                 :  * Check for file existance.
    2372                 :  *
    2373                 :  * The function checks if a named file exists in the filesystem, hopefully
    2374                 :  * in an efficient fashion if a sibling file list is available.   It exists
    2375                 :  * primarily to do faster file checking for functions like GDAL open methods
    2376                 :  * that get a list of files from the target directory. 
    2377                 :  *
    2378                 :  * If the sibling file list exists (is not NULL) it is assumed to be a list
    2379                 :  * of files in the same directory as the target file, and it will be checked
    2380                 :  * (case insensitively) for a match.  If a match is found, pszFilename is
    2381                 :  * updated with the correct case and TRUE is returned. 
    2382                 :  *
    2383                 :  * If papszSiblingFiles is NULL, a VSIStatL() is used to test for the files
    2384                 :  * existance, and no case insensitive testing is done. 
    2385                 :  *
    2386                 :  * @param pszFilename name of file to check for - filename case updated in some cases.
    2387                 :  * @param papszSiblingFiles a list of files in the same directory as 
    2388                 :  * pszFilename if available, or NULL. This list should have no path components.
    2389                 :  *
    2390                 :  * @return TRUE if a match is found, or FALSE if not.
    2391                 :  */
    2392                 : 
    2393           12914 : int CPLCheckForFile( char *pszFilename, char **papszSiblingFiles )
    2394                 : 
    2395                 : {
    2396                 : /* -------------------------------------------------------------------- */
    2397                 : /*      Fallback case if we don't have a sibling file list.             */
    2398                 : /* -------------------------------------------------------------------- */
    2399           12914 :     if( papszSiblingFiles == NULL )
    2400                 :     {
    2401                 :         VSIStatBufL sStatBuf;
    2402                 : 
    2403            5600 :         return VSIStatL( pszFilename, &sStatBuf ) == 0;
    2404                 :     }
    2405                 : 
    2406                 : /* -------------------------------------------------------------------- */
    2407                 : /*      We have sibling files, compare the non-path filename portion    */
    2408                 : /*      of pszFilename too all entries.                                 */
    2409                 : /* -------------------------------------------------------------------- */
    2410            7314 :     CPLString osFileOnly = CPLGetFilename( pszFilename );
    2411                 :     int i;
    2412                 : 
    2413          360832 :     for( i = 0; papszSiblingFiles[i] != NULL; i++ )
    2414                 :     {
    2415          353718 :         if( EQUAL(papszSiblingFiles[i],osFileOnly) )
    2416                 :         {
    2417                 :             strcpy( pszFilename + strlen(pszFilename) - strlen(osFileOnly), 
    2418             200 :                     papszSiblingFiles[i] );
    2419             200 :             return TRUE;
    2420                 :         }
    2421                 :     }
    2422                 : 
    2423            7114 :     return FALSE;
    2424                 : }
    2425                 : 
    2426                 : /************************************************************************/
    2427                 : /*      Stub implementation of zip services if we don't have libz.      */
    2428                 : /************************************************************************/
    2429                 : 
    2430                 : #if !defined(HAVE_LIBZ)
    2431                 : 
    2432                 : void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
    2433                 : 
    2434                 : {
    2435                 :     CPLError( CE_Failure, CPLE_NotSupported,
    2436                 :               "This GDAL/OGR build does not include zlib and zip services." );
    2437                 :     return NULL;
    2438                 : }
    2439                 : 
    2440                 : CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename, 
    2441                 :                            char **papszOptions )
    2442                 : 
    2443                 : {
    2444                 :     return CE_Failure;
    2445                 : }
    2446                 : 
    2447                 : CPLErr CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize )
    2448                 : 
    2449                 : {
    2450                 :     return CE_Failure;
    2451                 : }
    2452                 : 
    2453                 : CPLErr CPLCloseFileInZip( void *hZip )
    2454                 : 
    2455                 : {
    2456                 :     return CE_Failure;
    2457                 : }
    2458                 : 
    2459                 : CPLErr CPLCloseZip( void *hZip )
    2460                 : 
    2461                 : {
    2462                 :     return CE_Failure;
    2463                 : }
    2464                 : 
    2465                 : #endif /* !defined(HAVE_LIBZ) */

Generated by: LCOV version 1.7