LCOV - code coverage report
Current view: directory - ogr - ogrutils.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 448 310 69.2 %
Date: 2010-01-09 Functions: 18 16 88.9 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrutils.cpp 17696 2009-09-26 15:56:39Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Utility functions for OGR classes, including some related to
       6                 :  *           parsing well known text format vectors.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 1999, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include <ctype.h>
      32                 : 
      33                 : #include "ogr_geometry.h"
      34                 : #include "ogr_p.h"
      35                 : 
      36                 : #ifdef OGR_ENABLED
      37                 : # include "ogrsf_frmts.h"
      38                 : #endif /* OGR_ENABLED */
      39                 : 
      40                 : CPL_CVSID("$Id: ogrutils.cpp 17696 2009-09-26 15:56:39Z rouault $");
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                         OGRTrimExtraZeros()                          */
      44                 : /************************************************************************/
      45                 : 
      46            6505 : static void OGRTrimExtraZeros( char *pszTarget )
      47                 : 
      48                 : {
      49            6505 :     int i = 0;
      50                 : 
      51          156280 :     while( pszTarget[i] != '\0' ) 
      52          143270 :         i++;
      53                 : 
      54                 : /* -------------------------------------------------------------------- */
      55                 : /*      Trim trailing 000001's as they are likely roundoff error.       */
      56                 : /* -------------------------------------------------------------------- */
      57           13610 :     if( i > 10
      58            6505 :         && pszTarget[i-1] == '1' 
      59             208 :         && pszTarget[i-2] == '0' 
      60              98 :         && pszTarget[i-3] == '0' 
      61              98 :         && pszTarget[i-4] == '0' 
      62              98 :         && pszTarget[i-5] == '0' 
      63              98 :         && pszTarget[i-6] == '0' )
      64                 :     {
      65              54 :         pszTarget[--i] = '\0';
      66                 :     }
      67                 : 
      68                 : /* -------------------------------------------------------------------- */
      69                 : /*      Trim trailing zeros.                                            */
      70                 : /* -------------------------------------------------------------------- */
      71           81584 :     while( i > 2 && pszTarget[i-1] == '0' && pszTarget[i-2] != '.' )
      72                 :     {
      73           68574 :         pszTarget[--i] = '\0';
      74                 :     }
      75            6505 : }
      76                 : 
      77                 : /************************************************************************/
      78                 : /*                        OGRMakeWktCoordinate()                        */
      79                 : /*                                                                      */
      80                 : /*      Format a well known text coordinate, trying to keep the         */
      81                 : /*      ASCII representation compact, but accurate.  These rules        */
      82                 : /*      will have to tighten up in the future.                          */
      83                 : /*                                                                      */
      84                 : /*      Currently a new point should require no more than 64            */
      85                 : /*      characters barring the X or Y value being extremely large.      */
      86                 : /************************************************************************/
      87                 : 
      88            4089 : void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z, 
      89                 :                            int nDimension )
      90                 : 
      91                 : {
      92            4089 :     const size_t bufSize = 400;
      93            4089 :     const size_t maxTargetSize= 75; /* Assumed max length of the target buffer. */
      94                 : 
      95                 :     char szX[bufSize];
      96                 :     char szY[bufSize];
      97                 :     char szZ[bufSize];
      98                 : 
      99            4089 :     memset( szX, '\0', bufSize );
     100            4089 :     memset( szY, '\0', bufSize );
     101            4089 :     memset( szZ, '\0', bufSize );
     102                 : 
     103            4929 :     if( x == (int) x && y == (int) y && z == (int) z )
     104                 :     {
     105             840 :         snprintf( szX, bufSize, "%d", (int) x );
     106             840 :         snprintf( szY, bufSize, " %d", (int) y );
     107                 :     }
     108                 :     else
     109                 :     {
     110            3249 :         snprintf( szX, bufSize, "%.15f", x );
     111            3249 :         OGRTrimExtraZeros( szX );
     112                 : 
     113            3249 :         snprintf( szY, bufSize, " %.15f", y );
     114            3249 :         OGRTrimExtraZeros( szY );
     115                 :     }
     116                 : 
     117            4089 :     if( nDimension == 3 )
     118                 :     {
     119             558 :         if( z == (int) z )
     120                 :         {
     121             551 :             snprintf( szZ, bufSize, " %d", (int) z );
     122                 :         }
     123                 :         else
     124                 :         {
     125               7 :             snprintf( szZ, bufSize, " %.15f", z );
     126               7 :             OGRTrimExtraZeros( szZ );
     127                 :         }
     128                 :     }
     129                 : 
     130            4089 :     if( strlen(szX) + strlen(szY) + strlen(szZ) > maxTargetSize )
     131                 :     {
     132               1 :         strcpy( szX, "0" );
     133               1 :         strcpy( szY, " 0" );
     134               1 :         if( nDimension == 3 )
     135               1 :             strcpy( szZ, " 0" );
     136                 : 
     137                 : #ifdef DEBUG
     138                 :         CPLDebug( "OGR", 
     139                 :                   "Yow!  Got this big result in OGRMakeWktCoordinate()\n"
     140                 :                   "%s %s %s", 
     141                 :                   szX, szY, szZ );
     142                 : #endif
     143                 :     }
     144                 : 
     145            4089 :     strcpy( pszTarget, szX );
     146            4089 :     strcat( pszTarget, szY );
     147            4089 :     strcat( pszTarget, szZ );
     148            4089 : }
     149                 : 
     150                 : /************************************************************************/
     151                 : /*                          OGRWktReadToken()                           */
     152                 : /*                                                                      */
     153                 : /*      Read one token or delimeter and put into token buffer.  Pre     */
     154                 : /*      and post white space is swallowed.                              */
     155                 : /************************************************************************/
     156                 : 
     157          133729 : const char *OGRWktReadToken( const char * pszInput, char * pszToken )
     158                 : 
     159                 : {
     160          133729 :     if( pszInput == NULL )
     161               0 :         return NULL;
     162                 :     
     163                 : /* -------------------------------------------------------------------- */
     164                 : /*      Swallow pre-white space.                                        */
     165                 : /* -------------------------------------------------------------------- */
     166          267459 :     while( *pszInput == ' ' || *pszInput == '\t' )
     167               1 :         pszInput++;
     168                 : 
     169                 : /* -------------------------------------------------------------------- */
     170                 : /*      If this is a delimeter, read just one character.                */
     171                 : /* -------------------------------------------------------------------- */
     172          168141 :     if( *pszInput == '(' || *pszInput == ')' || *pszInput == ',' )
     173                 :     {
     174           34412 :         pszToken[0] = *pszInput;
     175           34412 :         pszToken[1] = '\0';
     176                 :         
     177           34412 :         pszInput++;
     178                 :     }
     179                 : 
     180                 : /* -------------------------------------------------------------------- */
     181                 : /*      Or if it alpha numeric read till we reach non-alpha numeric     */
     182                 : /*      text.                                                           */
     183                 : /* -------------------------------------------------------------------- */
     184                 :     else
     185                 :     {
     186           99317 :         int             iChar = 0;
     187                 :         
     188          878186 :         while( iChar < OGR_WKT_TOKEN_MAX-1
     189                 :                && ((*pszInput >= 'a' && *pszInput <= 'z')
     190                 :                    || (*pszInput >= 'A' && *pszInput <= 'Z')
     191                 :                    || (*pszInput >= '0' && *pszInput <= '9')
     192                 :                    || *pszInput == '.' 
     193                 :                    || *pszInput == '+' 
     194                 :                    || *pszInput == '-') )
     195                 :         {
     196          679552 :             pszToken[iChar++] = *(pszInput++);
     197                 :         }
     198                 : 
     199           99317 :         pszToken[iChar++] = '\0';
     200                 :     }
     201                 : 
     202                 : /* -------------------------------------------------------------------- */
     203                 : /*      Eat any trailing white space.                                   */
     204                 : /* -------------------------------------------------------------------- */
     205          317726 :     while( *pszInput == ' ' || *pszInput == '\t' )
     206           50268 :         pszInput++;
     207                 : 
     208          133729 :     return( pszInput );
     209                 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /*                          OGRWktReadPoints()                          */
     213                 : /*                                                                      */
     214                 : /*      Read a point string.  The point list must be contained in       */
     215                 : /*      brackets and each point pair separated by a comma.              */
     216                 : /************************************************************************/
     217                 : 
     218           15453 : const char * OGRWktReadPoints( const char * pszInput,
     219                 :                                OGRRawPoint ** ppaoPoints, double **ppadfZ,
     220                 :                                int * pnMaxPoints,
     221                 :                                int * pnPointsRead )
     222                 : 
     223                 : {
     224           15453 :     const char *pszOrigInput = pszInput;
     225           15453 :     *pnPointsRead = 0;
     226                 : 
     227           15453 :     if( pszInput == NULL )
     228               0 :         return NULL;
     229                 :     
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Eat any leading white space.                                    */
     232                 : /* -------------------------------------------------------------------- */
     233           30906 :     while( *pszInput == ' ' || *pszInput == '\t' )
     234               0 :         pszInput++;
     235                 : 
     236                 : /* -------------------------------------------------------------------- */
     237                 : /*      If this isn't an opening bracket then we have a problem!        */
     238                 : /* -------------------------------------------------------------------- */
     239           15453 :     if( *pszInput != '(' )
     240                 :     {
     241                 :         CPLDebug( "OGR",
     242                 :                   "Expected '(', but got %s in OGRWktReadPoints().\n",
     243               0 :                   pszInput );
     244                 :                   
     245               0 :         return pszInput;
     246                 :     }
     247                 : 
     248           15453 :     pszInput++;
     249                 : 
     250                 : /* ==================================================================== */
     251                 : /*      This loop reads a single point.  It will continue till we       */
     252                 : /*      run out of well formed points, or a closing bracket is          */
     253                 : /*      encountered.                                                    */
     254                 : /* ==================================================================== */
     255                 :     char        szDelim[OGR_WKT_TOKEN_MAX];
     256                 :     
     257           18191 :     do {
     258                 : /* -------------------------------------------------------------------- */
     259                 : /*      Read the X and Y values, verify they are numeric.               */
     260                 : /* -------------------------------------------------------------------- */
     261                 :         char    szTokenX[OGR_WKT_TOKEN_MAX];
     262                 :         char    szTokenY[OGR_WKT_TOKEN_MAX];
     263                 : 
     264           18191 :         pszInput = OGRWktReadToken( pszInput, szTokenX );
     265           18191 :         pszInput = OGRWktReadToken( pszInput, szTokenY );
     266                 : 
     267           36572 :         if( (!isdigit(szTokenX[0]) && szTokenX[0] != '-' && szTokenX[0] != '.' )
     268           18381 :             || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' && szTokenY[0] != '.') )
     269               0 :             return NULL;
     270                 : 
     271                 : /* -------------------------------------------------------------------- */
     272                 : /*      Do we need to grow the point list to hold this point?           */
     273                 : /* -------------------------------------------------------------------- */
     274           18191 :         if( *pnPointsRead == *pnMaxPoints )
     275                 :         {
     276           15343 :             *pnMaxPoints = *pnMaxPoints * 2 + 10;
     277                 :             *ppaoPoints = (OGRRawPoint *)
     278           15343 :                 CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints);
     279                 : 
     280           15343 :             if( *ppadfZ != NULL )
     281                 :             {
     282                 :                 *ppadfZ = (double *)
     283              48 :                     CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints);
     284                 :             }
     285                 :         }
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Add point to list.                                              */
     289                 : /* -------------------------------------------------------------------- */
     290           18191 :         (*ppaoPoints)[*pnPointsRead].x = atof(szTokenX);
     291           18191 :         (*ppaoPoints)[*pnPointsRead].y = atof(szTokenY);
     292                 : 
     293                 : /* -------------------------------------------------------------------- */
     294                 : /*      Do we have a Z coordinate?                                      */
     295                 : /* -------------------------------------------------------------------- */
     296           18191 :         pszInput = OGRWktReadToken( pszInput, szDelim );
     297                 : 
     298           18191 :         if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
     299                 :         {
     300           16122 :             if( *ppadfZ == NULL )
     301                 :             {
     302           14814 :                 *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
     303                 :             }
     304                 : 
     305           16122 :             (*ppadfZ)[*pnPointsRead] = atof(szDelim);
     306                 :             
     307           16122 :             pszInput = OGRWktReadToken( pszInput, szDelim );
     308                 :         }
     309                 :         
     310           18191 :         (*pnPointsRead)++;
     311                 : 
     312                 : /* -------------------------------------------------------------------- */
     313                 : /*      Do we have a M coordinate?                                      */
     314                 : /*      If we do, just skip it.                                         */
     315                 : /* -------------------------------------------------------------------- */
     316           18191 :         if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
     317                 :         {
     318              34 :             pszInput = OGRWktReadToken( pszInput, szDelim );
     319                 :         }
     320                 :         
     321                 : /* -------------------------------------------------------------------- */
     322                 : /*      Read next delimeter ... it should be a comma if there are       */
     323                 : /*      more points.                                                    */
     324                 : /* -------------------------------------------------------------------- */
     325           18191 :         if( szDelim[0] != ')' && szDelim[0] != ',' )
     326                 :         {
     327                 :             CPLDebug( "OGR",
     328                 :                       "Corrupt input in OGRWktReadPoints()\n"
     329                 :                       "Got `%s' when expecting `,' or `)', near `%s' in %s.\n",
     330               0 :                       szDelim, pszInput, pszOrigInput );
     331               0 :             return NULL;
     332                 :         }
     333                 :         
     334           18191 :     } while( szDelim[0] == ',' );
     335                 : 
     336           15453 :     return pszInput;
     337                 : }
     338                 : 
     339                 : /************************************************************************/
     340                 : /*                             OGRMalloc()                              */
     341                 : /*                                                                      */
     342                 : /*      Cover for CPLMalloc()                                           */
     343                 : /************************************************************************/
     344                 : 
     345               0 : void *OGRMalloc( size_t size )
     346                 : 
     347                 : {
     348               0 :     return CPLMalloc( size );
     349                 : }
     350                 : 
     351                 : /************************************************************************/
     352                 : /*                             OGRCalloc()                              */
     353                 : /*                                                                      */
     354                 : /*      Cover for CPLCalloc()                                           */
     355                 : /************************************************************************/
     356                 : 
     357            1543 : void * OGRCalloc( size_t count, size_t size )
     358                 : 
     359                 : {
     360            1543 :     return CPLCalloc( count, size );
     361                 : }
     362                 : 
     363                 : /************************************************************************/
     364                 : /*                             OGRRealloc()                             */
     365                 : /*                                                                      */
     366                 : /*      Cover for CPLRealloc()                                          */
     367                 : /************************************************************************/
     368                 : 
     369           33810 : void *OGRRealloc( void * pOld, size_t size )
     370                 : 
     371                 : {
     372           33810 :     return CPLRealloc( pOld, size );
     373                 : }
     374                 : 
     375                 : /************************************************************************/
     376                 : /*                              OGRFree()                               */
     377                 : /*                                                                      */
     378                 : /*      Cover for CPLFree().                                            */
     379                 : /************************************************************************/
     380                 : 
     381           20414 : void OGRFree( void * pMemory )
     382                 : 
     383                 : {
     384           20414 :     CPLFree( pMemory );
     385           20414 : }
     386                 : 
     387                 : /**
     388                 :  * General utility option processing.
     389                 :  *
     390                 :  * This function is intended to provide a variety of generic commandline 
     391                 :  * options for all OGR commandline utilities.  It takes care of the following
     392                 :  * commandline options:
     393                 :  *  
     394                 :  *  --formats: report all format drivers configured.
     395                 :  *  --optfile filename: expand an option file into the argument list. 
     396                 :  *  --config key value: set system configuration option. 
     397                 :  *  --debug [on/off/value]: set debug level.
     398                 :  *  --help-general: report detailed help on general options. 
     399                 :  *
     400                 :  * The argument array is replaced "in place" and should be freed with 
     401                 :  * CSLDestroy() when no longer needed.  The typical usage looks something
     402                 :  * like the following.  Note that the formats should be registered so that
     403                 :  * the --formats option will work properly.
     404                 :  *
     405                 :  *  int main( int argc, char ** argv )
     406                 :  *  { 
     407                 :  *    OGRAllRegister();
     408                 :  *
     409                 :  *    argc = OGRGeneralCmdLineProcessor( argc, &argv, 0 );
     410                 :  *    if( argc < 1 )
     411                 :  *        exit( -argc );
     412                 :  *
     413                 :  * @param nArgc number of values in the argument list.
     414                 :  * @param Pointer to the argument list array (will be updated in place). 
     415                 :  *
     416                 :  * @return updated nArgc argument count.  Return of 0 requests terminate 
     417                 :  * without error, return of -1 requests exit with error code.
     418                 :  */
     419                 : 
     420              40 : int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
     421                 : 
     422                 : {
     423              40 :     char **papszReturn = NULL;
     424                 :     int  iArg;
     425              40 :     char **papszArgv = *ppapszArgv;
     426                 : 
     427                 :     (void) nOptions;
     428                 :     
     429                 : /* -------------------------------------------------------------------- */
     430                 : /*      Preserve the program name.                                      */
     431                 : /* -------------------------------------------------------------------- */
     432              40 :     papszReturn = CSLAddString( papszReturn, papszArgv[0] );
     433                 : 
     434                 : /* ==================================================================== */
     435                 : /*      Loop over all arguments.                                        */
     436                 : /* ==================================================================== */
     437             194 :     for( iArg = 1; iArg < nArgc; iArg++ )
     438                 :     {
     439                 : /* -------------------------------------------------------------------- */
     440                 : /*      --version                                                       */
     441                 : /* -------------------------------------------------------------------- */
     442             154 :         if( EQUAL(papszArgv[iArg],"--version") )
     443                 :         {
     444               0 :             printf( "%s\n", GDALVersionInfo( "--version" ) );
     445               0 :             CSLDestroy( papszReturn );
     446               0 :             return 0;
     447                 :         }
     448                 : 
     449                 : /* -------------------------------------------------------------------- */
     450                 : /*      --license                                                       */
     451                 : /* -------------------------------------------------------------------- */
     452             154 :         else if( EQUAL(papszArgv[iArg],"--license") )
     453                 :         {
     454               0 :             printf( "%s\n", GDALVersionInfo( "LICENSE" ) );
     455               0 :             CSLDestroy( papszReturn );
     456               0 :             return 0;
     457                 :         }
     458                 : 
     459                 : /* -------------------------------------------------------------------- */
     460                 : /*      --config                                                        */
     461                 : /* -------------------------------------------------------------------- */
     462             154 :         else if( EQUAL(papszArgv[iArg],"--config") )
     463                 :         {
     464               0 :             if( iArg + 2 >= nArgc )
     465                 :             {
     466                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     467               0 :                           "--config option given without a key and value argument." );
     468               0 :                 CSLDestroy( papszReturn );
     469               0 :                 return -1;
     470                 :             }
     471                 : 
     472               0 :             CPLSetConfigOption( papszArgv[iArg+1], papszArgv[iArg+2] );
     473                 : 
     474               0 :             iArg += 2;
     475                 :         }
     476                 : 
     477                 : /* -------------------------------------------------------------------- */
     478                 : /*      --mempreload                                                    */
     479                 : /* -------------------------------------------------------------------- */
     480             154 :         else if( EQUAL(papszArgv[iArg],"--mempreload") )
     481                 :         {
     482                 :             int i;
     483                 : 
     484               0 :             if( iArg + 1 >= nArgc )
     485                 :             {
     486                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     487               0 :                           "--mempreload option given without directory path.");
     488               0 :                 CSLDestroy( papszReturn );
     489               0 :                 return -1;
     490                 :             }
     491                 :             
     492               0 :             char **papszFiles = CPLReadDir( papszArgv[iArg+1] );
     493               0 :             if( CSLCount(papszFiles) == 0 )
     494                 :             {
     495                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     496               0 :                           "--mempreload given invalid or empty directory.");
     497               0 :                 CSLDestroy( papszReturn );
     498               0 :                 return -1;
     499                 :             }
     500                 :                 
     501               0 :             for( i = 0; papszFiles[i] != NULL; i++ )
     502                 :             {
     503               0 :                 CPLString osOldPath, osNewPath;
     504                 :                 
     505               0 :                 if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
     506               0 :                     continue;
     507                 : 
     508               0 :                 osOldPath = CPLFormFilename( papszArgv[iArg+1], 
     509               0 :                                              papszFiles[i], NULL );
     510               0 :                 osNewPath.Printf( "/vsimem/%s", papszFiles[i] );
     511                 : 
     512                 :                 CPLDebug( "VSI", "Preloading %s to %s.", 
     513               0 :                           osOldPath.c_str(), osNewPath.c_str() );
     514                 : 
     515               0 :                 if( CPLCopyFile( osNewPath, osOldPath ) != 0 )
     516               0 :                     return -1;
     517                 :             }
     518                 :             
     519               0 :             CSLDestroy( papszFiles );
     520               0 :             iArg += 1;
     521                 :         }
     522                 : 
     523                 : /* -------------------------------------------------------------------- */
     524                 : /*      --debug                                                         */
     525                 : /* -------------------------------------------------------------------- */
     526             154 :         else if( EQUAL(papszArgv[iArg],"--debug") )
     527                 :         {
     528               0 :             if( iArg + 1 >= nArgc )
     529                 :             {
     530                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     531               0 :                           "--debug option given without debug level." );
     532               0 :                 CSLDestroy( papszReturn );
     533               0 :                 return -1;
     534                 :             }
     535                 : 
     536               0 :             CPLSetConfigOption( "CPL_DEBUG", papszArgv[iArg+1] );
     537               0 :             iArg += 1;
     538                 :         }
     539                 : 
     540                 : /* -------------------------------------------------------------------- */
     541                 : /*      --optfile                                                       */
     542                 : /*                                                                      */
     543                 : /*      Annoyingly the options inserted by --optfile will *not* be      */
     544                 : /*      processed properly if they are general options.                 */
     545                 : /* -------------------------------------------------------------------- */
     546             154 :         else if( EQUAL(papszArgv[iArg],"--optfile") )
     547                 :         {
     548                 :             const char *pszLine;
     549                 :             FILE *fpOptFile;
     550                 : 
     551               0 :             if( iArg + 1 >= nArgc )
     552                 :             {
     553                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     554               0 :                           "--optfile option given without filename." );
     555               0 :                 CSLDestroy( papszReturn );
     556               0 :                 return -1;
     557                 :             }
     558                 : 
     559               0 :             fpOptFile = VSIFOpen( papszArgv[iArg+1], "rb" );
     560                 : 
     561               0 :             if( fpOptFile == NULL )
     562                 :             {
     563                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     564                 :                           "Unable to open optfile '%s'.\n%s",
     565               0 :                           papszArgv[iArg+1], VSIStrerror( errno ) );
     566               0 :                 CSLDestroy( papszReturn );
     567               0 :                 return -1;
     568                 :             }
     569                 :             
     570               0 :             while( (pszLine = CPLReadLine( fpOptFile )) != NULL )
     571                 :             {
     572                 :                 char **papszTokens;
     573                 :                 int i;
     574                 : 
     575               0 :                 if( pszLine[0] == '#' || strlen(pszLine) == 0 )
     576               0 :                     continue;
     577                 : 
     578               0 :                 papszTokens = CSLTokenizeString( pszLine );
     579               0 :                 for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++)
     580               0 :                     papszReturn = CSLAddString( papszReturn, papszTokens[i] );
     581               0 :                 CSLDestroy( papszTokens );
     582                 :             }
     583                 : 
     584               0 :             VSIFClose( fpOptFile );
     585                 :                 
     586               0 :             iArg += 1;
     587                 :         }
     588                 : 
     589                 : /* -------------------------------------------------------------------- */
     590                 : /*      --formats                                                       */
     591                 : /* -------------------------------------------------------------------- */
     592                 : #ifdef OGR_ENABLED
     593             154 :         else if( EQUAL(papszArgv[iArg], "--formats") )
     594                 :         {
     595                 :             int iDr;
     596                 : 
     597               0 :             printf( "Supported Formats:\n" );
     598                 : 
     599               0 :             OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
     600                 :         
     601               0 :             for( iDr = 0; iDr < poR->GetDriverCount(); iDr++ )
     602                 :             {
     603               0 :                 OGRSFDriver *poDriver = poR->GetDriver(iDr);
     604                 : 
     605               0 :                 if( poDriver->TestCapability( ODrCCreateDataSource ) )
     606                 :                     printf( "  -> \"%s\" (read/write)\n", 
     607               0 :                             poDriver->GetName() );
     608                 :                 else
     609                 :                     printf( "  -> \"%s\" (readonly)\n", 
     610               0 :                             poDriver->GetName() );
     611                 :             }
     612                 : 
     613               0 :             CSLDestroy( papszReturn );
     614               0 :             return 0;
     615                 :         }
     616                 : #endif /* OGR_ENABLED */
     617                 : 
     618                 : /* -------------------------------------------------------------------- */
     619                 : /*      --locale                                                        */
     620                 : /* -------------------------------------------------------------------- */
     621             154 :         else if( EQUAL(papszArgv[iArg],"--locale") && iArg < nArgc-1 )
     622                 :         {
     623               0 :             setlocale( LC_ALL, papszArgv[++iArg] );
     624                 :         }
     625                 : 
     626                 : /* -------------------------------------------------------------------- */
     627                 : /*      --help-general                                                  */
     628                 : /* -------------------------------------------------------------------- */
     629             154 :         else if( EQUAL(papszArgv[iArg],"--help-general") )
     630                 :         {
     631               0 :             printf( "Generic GDAL/OGR utility command options:\n" );
     632               0 :             printf( "  --version: report version of GDAL/OGR in use.\n" );
     633               0 :             printf( "  --license: report GDAL/OGR license info.\n" );
     634                 : #ifdef OGR_ENABLED
     635               0 :             printf( "  --formats: report all configured format drivers.\n" );
     636                 : #endif /* OGR_ENABLED */
     637               0 :             printf( "  --optfile filename: expand an option file into the argument list.\n" );
     638               0 :             printf( "  --config key value: set system configuration option.\n" );
     639               0 :             printf( "  --debug [on/off/value]: set debug level.\n" );
     640               0 :             printf( "  --help-general: report detailed help on general options.\n" );
     641               0 :             CSLDestroy( papszReturn );
     642               0 :             return 0;
     643                 :         }
     644                 : 
     645                 : /* -------------------------------------------------------------------- */
     646                 : /*      carry through unrecognised options.                             */
     647                 : /* -------------------------------------------------------------------- */
     648                 :         else
     649                 :         {
     650             154 :             papszReturn = CSLAddString( papszReturn, papszArgv[iArg] );
     651                 :         }
     652                 :     }
     653                 : 
     654              40 :     *ppapszArgv = papszReturn;
     655                 : 
     656              40 :     return CSLCount( *ppapszArgv );
     657                 : }
     658                 : 
     659                 : /************************************************************************/
     660                 : /*                            OGRParseDate()                            */
     661                 : /*                                                                      */
     662                 : /*      Parse a variety of text date formats into an OGRField.          */
     663                 : /************************************************************************/
     664                 : 
     665                 : /**
     666                 :  * Parse date string.
     667                 :  *
     668                 :  * This function attempts to parse a date string in a variety of formats
     669                 :  * into the OGRField.Date format suitable for use with OGR.  Generally 
     670                 :  * speaking this function is expecting values like:
     671                 :  * 
     672                 :  *   YYYY-MM-DD HH:MM:SS+nn
     673                 :  *
     674                 :  * The seconds may also have a decimal portion (which is ignored).  And
     675                 :  * just dates (YYYY-MM-DD) or just times (HH:MM:SS) are also supported. 
     676                 :  * The date may also be in YYYY/MM/DD format.  If the year is less than 100
     677                 :  * and greater than 30 a "1900" century value will be set.  If it is less than
     678                 :  * 30 and greater than -1 then a "2000" century value will be set.  In 
     679                 :  * the future this function may be generalized, and additional control 
     680                 :  * provided through nOptions, but an nOptions value of "0" should always do
     681                 :  * a reasonable default form of processing.
     682                 :  *
     683                 :  * The value of psField will be indeterminate if the function fails (returns
     684                 :  * FALSE).  
     685                 :  *
     686                 :  * @param pszInput the input date string.
     687                 :  * @param psField the OGRField that will be updated with the parsed result.
     688                 :  * @param nOptions parsing options, for now always 0. 
     689                 :  *
     690                 :  * @return TRUE if apparently successful or FALSE on failure.
     691                 :  */
     692                 : 
     693             161 : int OGRParseDate( const char *pszInput, OGRField *psField, int nOptions )
     694                 : 
     695                 : {
     696             161 :     int bGotSomething = FALSE;
     697                 : 
     698             161 :     psField->Date.Year = 0;
     699             161 :     psField->Date.Month = 0;
     700             161 :     psField->Date.Day = 0;
     701             161 :     psField->Date.Hour = 0;
     702             161 :     psField->Date.Minute = 0;
     703             161 :     psField->Date.Second = 0;
     704             161 :     psField->Date.TZFlag = 0;
     705                 :     
     706                 : /* -------------------------------------------------------------------- */
     707                 : /*      Do we have a date?                                              */
     708                 : /* -------------------------------------------------------------------- */
     709             322 :     while( *pszInput == ' ' )
     710               0 :         pszInput++;
     711                 :     
     712             161 :     if( strstr(pszInput,"-") != NULL || strstr(pszInput,"/") != NULL )
     713                 :     {
     714             119 :         psField->Date.Year = (GInt16)atoi(pszInput);
     715             119 :         if( psField->Date.Year < 100 && psField->Date.Year >= 30 )
     716               0 :             psField->Date.Year += 1900;
     717             119 :         else if( psField->Date.Year < 30 && psField->Date.Year >= 0 )
     718               0 :             psField->Date.Year += 2000;
     719                 : 
     720             714 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     721             476 :             pszInput++;
     722             119 :         if( *pszInput != '-' && *pszInput != '/' )
     723               0 :             return FALSE;
     724                 :         else 
     725             119 :             pszInput++;
     726                 : 
     727             119 :         psField->Date.Month = (GByte)atoi(pszInput);
     728             119 :         if( psField->Date.Month > 12 )
     729               0 :             return FALSE;
     730                 : 
     731             476 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     732             238 :             pszInput++;
     733             119 :         if( *pszInput != '-' && *pszInput != '/' )
     734               0 :             return FALSE;
     735                 :         else 
     736             119 :             pszInput++;
     737                 : 
     738             119 :         psField->Date.Day = (GByte)atoi(pszInput);
     739             119 :         if( psField->Date.Day > 31 )
     740               0 :             return FALSE;
     741                 : 
     742             476 :         while( *pszInput >= '0' && *pszInput <= '9' )
     743             238 :             pszInput++;
     744                 : 
     745             119 :         bGotSomething = TRUE;
     746                 :     }
     747                 : 
     748                 : /* -------------------------------------------------------------------- */
     749                 : /*      Do we have a time?                                              */
     750                 : /* -------------------------------------------------------------------- */
     751             401 :     while( *pszInput == ' ' )
     752              79 :         pszInput++;
     753                 :     
     754             161 :     if( strstr(pszInput,":") != NULL )
     755                 :     {
     756             120 :         psField->Date.Hour = (GByte)atoi(pszInput);
     757             120 :         if( psField->Date.Hour > 23 )
     758               0 :             return FALSE;
     759                 : 
     760             479 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     761             239 :             pszInput++;
     762             120 :         if( *pszInput != ':' )
     763               1 :             return FALSE;
     764                 :         else 
     765             119 :             pszInput++;
     766                 : 
     767             119 :         psField->Date.Minute = (GByte)atoi(pszInput);
     768             119 :         if( psField->Date.Minute > 59 )
     769               0 :             return FALSE;
     770                 : 
     771             476 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     772             238 :             pszInput++;
     773             119 :         if( *pszInput != ':' )
     774               0 :             return FALSE;
     775                 :         else 
     776             119 :             pszInput++;
     777                 : 
     778             119 :         psField->Date.Second = (GByte)atoi(pszInput);
     779             119 :         if( psField->Date.Second > 59 )
     780               0 :             return FALSE;
     781                 : 
     782             476 :         while( (*pszInput >= '0' && *pszInput <= '9')
     783                 :                || *pszInput == '.' )
     784             238 :             pszInput++;
     785                 : 
     786             119 :         bGotSomething = TRUE;
     787                 :     }
     788                 : 
     789                 :     // No date or time!
     790             160 :     if( !bGotSomething )
     791               0 :         return FALSE;
     792                 : 
     793                 : /* -------------------------------------------------------------------- */
     794                 : /*      Do we have a timezone?                                          */
     795                 : /* -------------------------------------------------------------------- */
     796             320 :     while( *pszInput == ' ' )
     797               0 :         pszInput++;
     798                 :     
     799             160 :     if( *pszInput == '-' || *pszInput == '+' )
     800                 :     {
     801                 :         // +HH integral offset
     802              46 :         if( strlen(pszInput) <= 3 )
     803              42 :             psField->Date.TZFlag = (GByte)(100 + atoi(pszInput) * 4);
     804                 : 
     805               8 :         else if( pszInput[3] == ':'  // +HH:MM offset
     806                 :                  && atoi(pszInput+4) % 15 == 0 )
     807                 :         {
     808                 :             psField->Date.TZFlag = (GByte)(100 
     809                 :                 + atoi(pszInput+1) * 4
     810               4 :                 + (atoi(pszInput+4) / 15));
     811                 : 
     812               4 :             if( pszInput[0] == '-' )
     813               4 :                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
     814                 :         }
     815               0 :         else if( isdigit(pszInput[3]) && isdigit(pszInput[4])  // +HHMM offset
     816                 :                  && atoi(pszInput+3) % 15 == 0 )
     817                 :         {
     818                 :             psField->Date.TZFlag = (GByte)(100 
     819                 :                 + static_cast<GByte>(CPLScanLong(pszInput+1,2)) * 4
     820               0 :                 + (atoi(pszInput+3) / 15));
     821                 : 
     822               0 :             if( pszInput[0] == '-' )
     823               0 :                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
     824                 :         }
     825               0 :         else if( isdigit(pszInput[3]) && pszInput[4] == '\0'  // +HMM offset
     826                 :                  && atoi(pszInput+2) % 15 == 0 )
     827                 :         {
     828                 :             psField->Date.TZFlag = (GByte)(100 
     829                 :                 + static_cast<GByte>(CPLScanLong(pszInput+1,1)) * 4
     830               0 :                 + (atoi(pszInput+2) / 15));
     831                 : 
     832               0 :             if( pszInput[0] == '-' )
     833               0 :                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
     834                 :         }
     835                 :         // otherwise ignore any timezone info.
     836                 :     }
     837                 : 
     838             160 :     return TRUE;
     839                 : }
     840                 : 
     841                 : 
     842                 : /************************************************************************/
     843                 : /*                           OGRParseXMLDateTime()                      */
     844                 : /************************************************************************/
     845                 : 
     846              27 : int OGRParseXMLDateTime( const char* pszXMLDateTime,
     847                 :                                int *pnYear, int *pnMonth, int *pnDay,
     848                 :                                int *pnHour, int *pnMinute, float* pfSecond, int *pnTZ)
     849                 : {
     850              27 :     int year = 0, month = 0, day = 0, hour = 0, minute = 0, TZHour, TZMinute;
     851              27 :     float second = 0;
     852                 :     char c;
     853              27 :     int TZ = 0;
     854              27 :     int bRet = FALSE;
     855                 : 
     856                 :     /* Date is expressed as a UTC date */
     857              27 :     if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c",
     858                 :                 &year, &month, &day, &hour, &minute, &second, &c) == 7 && c == 'Z')
     859                 :     {
     860               4 :         TZ = 100;
     861               4 :         bRet = TRUE;
     862                 :     }
     863                 :     /* Date is expressed as a UTC date, with a timezone */
     864              23 :     else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c%02d:%02d",
     865                 :                 &year, &month, &day, &hour, &minute, &second, &c, &TZHour, &TZMinute) == 9 &&
     866                 :                 (c == '+' || c == '-'))
     867                 :     {
     868              23 :         TZ = 100 + ((c == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
     869              23 :         bRet = TRUE;
     870                 :     }
     871                 :     /* Date is expressed into an unknown timezone */
     872               0 :     else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f",
     873                 :                     &year, &month, &day, &hour, &minute, &second) == 6)
     874                 :     {
     875               0 :         TZ = 0;
     876               0 :         bRet = TRUE;
     877                 :     }
     878              27 :     if (bRet)
     879                 :     {
     880              27 :         if (pnYear) *pnYear = year;
     881              27 :         if (pnMonth) *pnMonth = month;
     882              27 :         if (pnDay) *pnDay = day;
     883              27 :         if (pnHour) *pnHour = hour;
     884              27 :         if (pnMinute) *pnMinute = minute;
     885              27 :         if (pfSecond) *pfSecond = second;
     886              27 :         if (pnTZ) *pnTZ = TZ;
     887                 :     }
     888                 : 
     889              27 :     return bRet;
     890                 : }
     891                 : 
     892                 : /************************************************************************/
     893                 : /*                      OGRParseRFC822DateTime()                        */
     894                 : /************************************************************************/
     895                 : 
     896                 : static const char* aszMonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
     897                 :                                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
     898                 : 
     899              25 : int OGRParseRFC822DateTime( const char* pszRFC822DateTime,
     900                 :                                   int *pnYear, int *pnMonth, int *pnDay,
     901                 :                                   int *pnHour, int *pnMinute, int *pnSecond, int *pnTZ)
     902                 : {
     903                 :     /* Following http://asg.web.cmu.edu/rfc/rfc822.html#sec-5 : [Fri,] 28 Dec 2007 05:24[:17] GMT */
     904              25 :     char** papszTokens = CSLTokenizeStringComplex( pszRFC822DateTime, " ,:", TRUE, FALSE );
     905              25 :     char** papszVal = papszTokens;
     906              25 :     int bRet = FALSE;
     907              25 :     int nTokens = CSLCount(papszTokens);
     908              25 :     if (nTokens >= 6)
     909                 :     {
     910              21 :         if ( ! ((*papszVal)[0] >= '0' && (*papszVal)[0] <= '9') )
     911                 :         {
     912                 :             /* Ignore day of week */
     913              21 :             papszVal ++;
     914                 :         }
     915                 : 
     916              21 :         int day = atoi(*papszVal);
     917              21 :         papszVal ++;
     918                 : 
     919              21 :         int month = 0;
     920                 : 
     921             273 :         for(int i = 0; i < 12; i++)
     922                 :         {
     923             252 :             if (EQUAL(*papszVal, aszMonthStr[i]))
     924              21 :                 month = i + 1;
     925                 :         }
     926              21 :         papszVal ++;
     927                 : 
     928              21 :         int year = atoi(*papszVal);
     929              21 :         papszVal ++;
     930              21 :         if( year < 100 && year >= 30 )
     931               0 :             year += 1900;
     932              21 :         else if( year < 30 && year >= 0 )
     933               0 :             year += 2000;
     934                 : 
     935              21 :         int hour = atoi(*papszVal);
     936              21 :         papszVal ++;
     937                 : 
     938              21 :         int minute = atoi(*papszVal);
     939              21 :         papszVal ++;
     940                 : 
     941              21 :         int second = 0;
     942              21 :         if (*papszVal != NULL && (*papszVal)[0] >= '0' && (*papszVal)[0] <= '9')
     943                 :         {
     944              21 :             second = atoi(*papszVal);
     945              21 :             papszVal ++;
     946                 :         }
     947                 : 
     948              21 :         if (month != 0)
     949                 :         {
     950              21 :             bRet = TRUE;
     951              21 :             int TZ = 0;
     952                 : 
     953              21 :             if (*papszVal == NULL)
     954                 :             {
     955                 :             }
     956              63 :             else if (strlen(*papszVal) == 5 &&
     957              21 :                      ((*papszVal)[0] == '+' || (*papszVal)[0] == '-'))
     958                 :             {
     959                 :                 char szBuf[3];
     960              21 :                 szBuf[0] = (*papszVal)[1];
     961              21 :                 szBuf[1] = (*papszVal)[2];
     962              21 :                 szBuf[2] = 0;
     963              21 :                 int TZHour = atoi(szBuf);
     964              21 :                 szBuf[0] = (*papszVal)[3];
     965              21 :                 szBuf[1] = (*papszVal)[4];
     966              21 :                 szBuf[2] = 0;
     967              21 :                 int TZMinute = atoi(szBuf);
     968              21 :                 TZ = 100 + (((*papszVal)[0] == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
     969                 :             }
     970                 :             else
     971                 :             {
     972               0 :                 const char* aszTZStr[] = { "GMT", "UT", "Z", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", "PDT" };
     973               0 :                 int anTZVal[] = { 0, 0, 0, -5, -4, -6, -5, -7, -6, -8, -7 };
     974               0 :                 for(int i = 0; i < 11; i++)
     975                 :                 {
     976               0 :                     if (EQUAL(*papszVal, aszTZStr[i]))
     977                 :                     {
     978               0 :                         TZ =  100 + anTZVal[i] * 4;
     979               0 :                         break;
     980                 :                     }
     981                 :                 }
     982                 :             }
     983                 : 
     984              21 :             if (pnYear) *pnYear = year;
     985              21 :             if (pnMonth) *pnMonth = month;
     986              21 :             if (pnDay) *pnDay = day;
     987              21 :             if (pnHour) *pnHour = hour;
     988              21 :             if (pnMinute) *pnMinute = minute;
     989              21 :             if (pnSecond) *pnSecond = second;
     990              21 :             if (pnTZ) *pnTZ = TZ;
     991                 :         }
     992                 :     }
     993              25 :     CSLDestroy(papszTokens);
     994              25 :     return bRet;
     995                 : }
     996                 : 
     997                 : 
     998                 : /**
     999                 :   * Returns the day of the week in Gregorian calendar
    1000                 :   *
    1001                 :   * @param day : day of the month, between 1 and 31
    1002                 :   * @param month : month of the year, between 1 (Jan) and 12 (Dec)
    1003                 :   * @param year : year
    1004                 : 
    1005                 :   * @return day of the week : 0 for Monday, ... 6 for Sunday
    1006                 :   */
    1007                 : 
    1008              12 : int OGRGetDayOfWeek(int day, int month, int year)
    1009                 : {
    1010                 :     /* Reference: Zeller's congruence */
    1011              12 :     int q = day;
    1012                 :     int m;
    1013              12 :     if (month >=3)
    1014              12 :         m = month;
    1015                 :     else
    1016                 :     {
    1017               0 :         m = month + 12;
    1018               0 :         year --;
    1019                 :     }
    1020              12 :     int K = year % 100;
    1021              12 :     int J = year / 100;
    1022              12 :     int h = ( q + (((m+1)*26)/10) + K + K/4 + J/4 + 5 * J) % 7;
    1023              12 :     return ( h + 5 ) % 7;
    1024                 : }
    1025                 : 
    1026                 : 
    1027                 : /************************************************************************/
    1028                 : /*                         OGRGetRFC822DateTime()                       */
    1029                 : /************************************************************************/
    1030                 : 
    1031              12 : char* OGRGetRFC822DateTime(int year, int month, int day, int hour, int minute, int second, int TZFlag)
    1032                 : {
    1033              12 :     char* pszTZ = NULL;
    1034              12 :     const char* aszDayOfWeek[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
    1035                 : 
    1036              12 :     int dayofweek = OGRGetDayOfWeek(day, month, year);
    1037                 : 
    1038              12 :     if (month < 1 || month > 12)
    1039               0 :         month = 1;
    1040                 : 
    1041              12 :     if (TZFlag == 0 || TZFlag == 100)
    1042                 :     {
    1043               0 :         pszTZ = CPLStrdup("GMT");
    1044                 :     }
    1045                 :     else
    1046                 :     {
    1047              12 :         int TZOffset = ABS(TZFlag - 100) * 15;
    1048              12 :         int TZHour = TZOffset / 60;
    1049              12 :         int TZMinute = TZOffset - TZHour * 60;
    1050                 :         pszTZ = CPLStrdup(CPLSPrintf("%c%02d%02d", TZFlag > 100 ? '+' : '-',
    1051              12 :                                         TZHour, TZMinute));
    1052                 :     }
    1053                 :     char* pszRet = CPLStrdup(CPLSPrintf("%s, %02d %s %04d %02d:%02d:%02d %s",
    1054              12 :                      aszDayOfWeek[dayofweek], day, aszMonthStr[month - 1], year, hour, minute, second, pszTZ));
    1055              12 :     CPLFree(pszTZ);
    1056              12 :     return pszRet;
    1057                 : }
    1058                 : 
    1059                 : /************************************************************************/
    1060                 : /*                            OGRGetXMLDateTime()                       */
    1061                 : /************************************************************************/
    1062                 : 
    1063               3 : char* OGRGetXMLDateTime(int year, int month, int day, int hour, int minute, int second, int TZFlag)
    1064                 : {
    1065                 :     char* pszRet;
    1066               4 :     if (TZFlag == 0 || TZFlag == 100)
    1067                 :     {
    1068                 :         pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
    1069               1 :                            year, month, day, hour, minute, second));
    1070                 :     }
    1071                 :     else
    1072                 :     {
    1073               2 :         int TZOffset = ABS(TZFlag - 100) * 15;
    1074               2 :         int TZHour = TZOffset / 60;
    1075               2 :         int TZMinute = TZOffset - TZHour * 60;
    1076                 :         pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
    1077                 :                            year, month, day, hour, minute, second,
    1078               2 :                            (TZFlag > 100) ? '+' : '-', TZHour, TZMinute));
    1079                 :     }
    1080               3 :     return pszRet;
    1081                 : }
    1082                 : 
    1083                 : /************************************************************************/
    1084                 : /*                 OGRGetXML_UTF8_EscapedString()                       */
    1085                 : /************************************************************************/
    1086                 : 
    1087              94 : char* OGRGetXML_UTF8_EscapedString(const char* pszString)
    1088                 : {
    1089                 :     char *pszEscaped;
    1090              94 :     if (!CPLIsUTF8(pszString, -1) &&
    1091                 :          CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
    1092                 :     {
    1093                 :         static int bFirstTime = TRUE;
    1094               1 :         if (bFirstTime)
    1095                 :         {
    1096               1 :             bFirstTime = FALSE;
    1097                 :             CPLError(CE_Warning, CPLE_AppDefined,
    1098                 :                     "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
    1099                 :                     "If you still want the original string and change the XML file encoding\n"
    1100                 :                     "afterwards, you can define OGR_FORCE_ASCII=NO as configuration option.\n"
    1101               1 :                     "This warning won't be issued anymore", pszString);
    1102                 :         }
    1103                 :         else
    1104                 :         {
    1105                 :             CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
    1106               0 :                     pszString);
    1107                 :         }
    1108               1 :         char* pszTemp = CPLForceToASCII(pszString, -1, '?');
    1109               1 :         pszEscaped = CPLEscapeString( pszTemp, -1, CPLES_XML );
    1110               1 :         CPLFree(pszTemp);
    1111                 :     }
    1112                 :     else
    1113              93 :         pszEscaped = CPLEscapeString( pszString, -1, CPLES_XML );
    1114              94 :     return pszEscaped;
    1115                 : }
    1116                 : 
    1117                 : /************************************************************************/
    1118                 : /*                        OGRFastAtof()                                 */
    1119                 : /************************************************************************/
    1120                 : 
    1121                 : /* On Windows, atof() is very slow if the number */
    1122                 : /* is followed by other long content. */
    1123                 : /* So we just extract the number into a short string */
    1124                 : /* before calling atof() on it */
    1125                 : static
    1126               0 : double OGRCallAtofOnShortString(const char* pszStr)
    1127                 : {
    1128                 :     char szTemp[128];
    1129               0 :     int nCounter = 0;
    1130               0 :     const char* p = pszStr;
    1131               0 :     while(*p == ' ' || *p == '\t')
    1132               0 :         p++;
    1133               0 :     while(*p == '+'  ||
    1134                 :           *p == '-'  ||
    1135                 :           (*p >= '0' && *p <= '9') ||
    1136                 :           (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D'))
    1137                 :     {
    1138               0 :         szTemp[nCounter++] = *(p++);
    1139               0 :         if (nCounter == 127)
    1140               0 :             return atof(pszStr);
    1141                 :     }
    1142               0 :     szTemp[nCounter] = '\0';
    1143               0 :     return atof(szTemp);
    1144                 : }
    1145                 : 
    1146                 : /** Same contract as CPLAtof, except than it doesn't always call the
    1147                 :  *  system atof() that may be slow on some platforms. For simple but
    1148                 :  *  common strings, it'll use a faster implementation (up to 20x faster
    1149                 :  *  than atof() on MS runtime libraries) that has no garanty to return
    1150                 :  *  exactly the same floating point number.
    1151                 :  */
    1152                 :  
    1153             744 : double OGRFastAtof(const char* pszStr)
    1154                 : {
    1155             744 :     double dfVal = 0;
    1156             744 :     double dfSign = 1.0;
    1157             744 :     const char* p = pszStr;
    1158                 :     
    1159                 :     static const double adfTenPower[] =
    1160                 :     {
    1161                 :         1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
    1162                 :         1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20,
    1163                 :         1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31
    1164                 :     };
    1165                 :         
    1166            1490 :     while(*p == ' ' || *p == '\t')
    1167               2 :         p++;
    1168                 : 
    1169             744 :     if (*p == '+')
    1170               9 :         p++;
    1171             735 :     else if (*p == '-')
    1172                 :     {
    1173              62 :         dfSign = -1.0;
    1174              62 :         p++;
    1175                 :     }
    1176                 :     
    1177            2446 :     while(TRUE)
    1178                 :     {
    1179            3190 :         if (*p >= '0' && *p <= '9')
    1180                 :         {
    1181            2446 :             dfVal = dfVal * 10.0 + (*p - '0');
    1182            2446 :             p++;
    1183                 :         }
    1184             744 :         else if (*p == '.')
    1185                 :         {
    1186             292 :             p++;
    1187                 :             break;
    1188                 :         }
    1189             452 :         else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
    1190               0 :             return OGRCallAtofOnShortString(pszStr);
    1191                 :         else
    1192             452 :             return dfSign * dfVal;
    1193                 :     }
    1194                 :     
    1195             292 :     unsigned int countFractionnal = 0;
    1196            3697 :     while(TRUE)
    1197                 :     {
    1198            3989 :         if (*p >= '0' && *p <= '9')
    1199                 :         {
    1200            3697 :             dfVal = dfVal * 10.0 + (*p - '0');
    1201            3697 :             countFractionnal ++;
    1202            3697 :             p++;
    1203                 :         }
    1204             292 :         else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
    1205               0 :             return OGRCallAtofOnShortString(pszStr);
    1206                 :         else
    1207                 :         {
    1208             292 :             if (countFractionnal < sizeof(adfTenPower) / sizeof(adfTenPower[0]))
    1209             292 :                 return dfSign * (dfVal / adfTenPower[countFractionnal]);
    1210                 :             else
    1211               0 :                 return OGRCallAtofOnShortString(pszStr);
    1212                 :         }
    1213                 :     }
    1214                 : }

Generated by: LCOV version 1.7