LCOV - code coverage report
Current view: directory - ogr - ogrutils.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 549 393 71.6 %
Date: 2012-12-26 Functions: 20 18 90.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrutils.cpp 25340 2012-12-21 20:30:21Z 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 25340 2012-12-21 20:30:21Z rouault $");
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                        OGRFormatDouble()                             */
      44                 : /************************************************************************/
      45                 : 
      46            9133 : void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal, char chDecimalSep, int nPrecision )
      47                 : {
      48                 :     int i;
      49            9133 :     int nTruncations = 0;
      50                 :     char szFormat[16];
      51            9133 :     sprintf(szFormat, "%%.%df", nPrecision);
      52                 : 
      53            9133 :     int ret = snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
      54                 :     /* Windows CRT doesn't conform with C99 and return -1 when buffer is truncated */
      55            9133 :     if (ret >= nBufferLen || ret == -1)
      56                 :     {
      57               2 :         snprintf(pszBuffer, nBufferLen, "%s", "too_big");
      58               2 :         return;
      59                 :     }
      60                 : 
      61             158 :     while(TRUE)
      62                 :     {
      63            9289 :         i = 0;
      64            9289 :         int nCountBeforeDot = 0;
      65            9289 :         int iDotPos = -1;
      66          211572 :         while( pszBuffer[i] != '\0' )
      67                 :         {
      68          202283 :             if ((pszBuffer[i] == '.' || pszBuffer[i] == ',') && chDecimalSep != '\0')
      69                 :             {
      70            9289 :                 iDotPos = i;
      71            9289 :                 pszBuffer[i] = chDecimalSep;
      72                 :             }
      73          183705 :             else if (iDotPos < 0 && pszBuffer[i] != '-')
      74           49988 :                 nCountBeforeDot ++;
      75          192994 :             i++;
      76                 :         }
      77                 : 
      78                 :     /* -------------------------------------------------------------------- */
      79                 :     /*      Trim trailing 00000x's as they are likely roundoff error.       */
      80                 :     /* -------------------------------------------------------------------- */
      81            9289 :         if( i > 10 && iDotPos >=0 )
      82                 :         {
      83           57427 :             if (/* && pszBuffer[i-1] == '1' &&*/
      84            8913 :                 pszBuffer[i-2] == '0' 
      85            8049 :                 && pszBuffer[i-3] == '0' 
      86            7964 :                 && pszBuffer[i-4] == '0' 
      87            7960 :                 && pszBuffer[i-5] == '0' 
      88            7960 :                 && pszBuffer[i-6] == '0' )
      89                 :             {
      90            7668 :                 pszBuffer[--i] = '\0';
      91                 :             }
      92            3446 :             else if( i - 8 > iDotPos && /* pszBuffer[i-1] == '1' */
      93                 :                   /* && pszBuffer[i-2] == '0' && */
      94            1036 :                     (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0') 
      95             331 :                     && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0') 
      96             299 :                     && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0') 
      97             421 :                     && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '0')
      98              92 :                     && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '0')
      99              12 :                     && pszBuffer[i-8] == '0'
     100              10 :                     && pszBuffer[i-9] == '0')
     101                 :             {
     102              10 :                 i -= 8;
     103              10 :                 pszBuffer[i] = '\0';
     104                 :             }
     105                 :         }
     106                 : 
     107                 :     /* -------------------------------------------------------------------- */
     108                 :     /*      Trim trailing zeros.                                            */
     109                 :     /* -------------------------------------------------------------------- */
     110          105590 :         while( i > 2 && pszBuffer[i-1] == '0' && pszBuffer[i-2] != '.' )
     111                 :         {
     112           87012 :             pszBuffer[--i] = '\0';
     113                 :         }
     114                 : 
     115                 :     /* -------------------------------------------------------------------- */
     116                 :     /*      Detect trailing 99999X's as they are likely roundoff error.     */
     117                 :     /* -------------------------------------------------------------------- */
     118            9289 :         if( i > 10 &&
     119                 :             iDotPos >= 0 &&
     120                 :             nPrecision + nTruncations >= 15)
     121                 :         {
     122            8544 :             if (/*pszBuffer[i-1] == '9' && */
     123            3958 :                  pszBuffer[i-2] == '9' 
     124             240 :                 && pszBuffer[i-3] == '9' 
     125             140 :                 && pszBuffer[i-4] == '9' 
     126             124 :                 && pszBuffer[i-5] == '9' 
     127             124 :                 && pszBuffer[i-6] == '9' )
     128                 :             {
     129             102 :                 nPrecision --;
     130             102 :                 nTruncations ++;
     131             102 :                 sprintf(szFormat, "%%.%df", nPrecision);
     132             102 :                 snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
     133             102 :                 continue;
     134                 :             }
     135            5342 :             else if (i - 9 > iDotPos && /*pszBuffer[i-1] == '9' && */
     136                 :                      /*pszBuffer[i-2] == '9' && */
     137             959 :                     (nCountBeforeDot >= 4 || pszBuffer[i-3] == '9') 
     138             138 :                     && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9') 
     139              23 :                     && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9') 
     140             120 :                     && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '9')
     141             134 :                     && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '9')
     142              56 :                     && pszBuffer[i-8] == '9'
     143              56 :                     && pszBuffer[i-9] == '9')
     144                 :             {
     145              56 :                 nPrecision --;
     146              56 :                 nTruncations ++;
     147              56 :                 sprintf(szFormat, "%%.%df", nPrecision);
     148              56 :                 snprintf(pszBuffer, nBufferLen, szFormat, dfVal);
     149              56 :                 continue;
     150                 :             }
     151                 :         }
     152                 : 
     153            9131 :         break;
     154                 :     }
     155                 : 
     156                 : }
     157                 : 
     158                 : /************************************************************************/
     159                 : /*                        OGRMakeWktCoordinate()                        */
     160                 : /*                                                                      */
     161                 : /*      Format a well known text coordinate, trying to keep the         */
     162                 : /*      ASCII representation compact, but accurate.  These rules        */
     163                 : /*      will have to tighten up in the future.                          */
     164                 : /*                                                                      */
     165                 : /*      Currently a new point should require no more than 64            */
     166                 : /*      characters barring the X or Y value being extremely large.      */
     167                 : /************************************************************************/
     168                 : 
     169            8010 : void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z, 
     170                 :                            int nDimension )
     171                 : 
     172                 : {
     173            8010 :     const size_t bufSize = 75;
     174            8010 :     const size_t maxTargetSize = 75; /* Assumed max length of the target buffer. */
     175                 : 
     176                 :     char szX[bufSize];
     177                 :     char szY[bufSize];
     178                 :     char szZ[bufSize];
     179                 : 
     180            8010 :     szZ[0] = '\0';
     181                 : 
     182                 :     int nLenX, nLenY;
     183                 : 
     184           11762 :     if( x == (int) x && y == (int) y )
     185                 :     {
     186            3752 :         snprintf( szX, bufSize, "%d", (int) x );
     187            3752 :         snprintf( szY, bufSize, "%d", (int) y );
     188                 :     }
     189                 :     else
     190                 :     {
     191            4258 :         OGRFormatDouble( szX, bufSize, x, '.' );
     192            4258 :         OGRFormatDouble( szY, bufSize, y, '.' );
     193                 :     }
     194                 : 
     195            8010 :     nLenX = strlen(szX);
     196            8010 :     nLenY = strlen(szY);
     197                 : 
     198            8010 :     if( nDimension == 3 )
     199                 :     {
     200            1124 :         if( z == (int) z )
     201                 :         {
     202            1117 :             snprintf( szZ, bufSize, "%d", (int) z );
     203                 :         }
     204                 :         else
     205                 :         {
     206               7 :             OGRFormatDouble( szZ, bufSize, z, '.' );
     207                 :         }
     208                 :     }
     209                 : 
     210            8010 :     if( nLenX + 1 + nLenY + ((nDimension == 3) ? (1 + strlen(szZ)) : 0) >= maxTargetSize )
     211                 :     {
     212                 : #ifdef DEBUG
     213                 :         CPLDebug( "OGR", 
     214                 :                   "Yow!  Got this big result in OGRMakeWktCoordinate()\n"
     215                 :                   "%s %s %s", 
     216               0 :                   szX, szY, szZ );
     217                 : #endif
     218               0 :         if( nDimension == 3 )
     219               0 :             strcpy( pszTarget, "0 0 0");
     220                 :         else
     221               0 :             strcpy( pszTarget, "0 0");
     222                 :     }
     223                 :     else
     224                 :     {
     225            8010 :         memcpy( pszTarget, szX, nLenX );
     226            8010 :         pszTarget[nLenX] = ' ';
     227            8010 :         memcpy( pszTarget + nLenX + 1, szY, nLenY );
     228            8010 :         if (nDimension == 3)
     229                 :         {
     230            1124 :             pszTarget[nLenX + 1 + nLenY] = ' ';
     231            1124 :             strcpy( pszTarget + nLenX + 1 + nLenY + 1, szZ );
     232                 :         }
     233                 :         else
     234                 :         {
     235            6886 :             pszTarget[nLenX + 1 + nLenY] = '\0';
     236                 :         }
     237                 :     }
     238            8010 : }
     239                 : 
     240                 : /************************************************************************/
     241                 : /*                          OGRWktReadToken()                           */
     242                 : /*                                                                      */
     243                 : /*      Read one token or delimeter and put into token buffer.  Pre     */
     244                 : /*      and post white space is swallowed.                              */
     245                 : /************************************************************************/
     246                 : 
     247          437075 : const char *OGRWktReadToken( const char * pszInput, char * pszToken )
     248                 : 
     249                 : {
     250          437075 :     if( pszInput == NULL )
     251               0 :         return NULL;
     252                 :     
     253                 : /* -------------------------------------------------------------------- */
     254                 : /*      Swallow pre-white space.                                        */
     255                 : /* -------------------------------------------------------------------- */
     256          874150 :     while( *pszInput == ' ' || *pszInput == '\t' )
     257               0 :         pszInput++;
     258                 : 
     259                 : /* -------------------------------------------------------------------- */
     260                 : /*      If this is a delimeter, read just one character.                */
     261                 : /* -------------------------------------------------------------------- */
     262          606262 :     if( *pszInput == '(' || *pszInput == ')' || *pszInput == ',' )
     263                 :     {
     264          169187 :         pszToken[0] = *pszInput;
     265          169187 :         pszToken[1] = '\0';
     266                 :         
     267          169187 :         pszInput++;
     268                 :     }
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Or if it alpha numeric read till we reach non-alpha numeric     */
     272                 : /*      text.                                                           */
     273                 : /* -------------------------------------------------------------------- */
     274                 :     else
     275                 :     {
     276          267888 :         int             iChar = 0;
     277                 :         
     278         2622783 :         while( iChar < OGR_WKT_TOKEN_MAX-1
     279                 :                && ((*pszInput >= 'a' && *pszInput <= 'z')
     280                 :                    || (*pszInput >= 'A' && *pszInput <= 'Z')
     281                 :                    || (*pszInput >= '0' && *pszInput <= '9')
     282                 :                    || *pszInput == '.' 
     283                 :                    || *pszInput == '+' 
     284                 :                    || *pszInput == '-') )
     285                 :         {
     286         2087007 :             pszToken[iChar++] = *(pszInput++);
     287                 :         }
     288                 : 
     289          267888 :         pszToken[iChar++] = '\0';
     290                 :     }
     291                 : 
     292                 : /* -------------------------------------------------------------------- */
     293                 : /*      Eat any trailing white space.                                   */
     294                 : /* -------------------------------------------------------------------- */
     295          997132 :     while( *pszInput == ' ' || *pszInput == '\t' )
     296          122982 :         pszInput++;
     297                 : 
     298          437075 :     return( pszInput );
     299                 : }
     300                 : 
     301                 : /************************************************************************/
     302                 : /*                          OGRWktReadPoints()                          */
     303                 : /*                                                                      */
     304                 : /*      Read a point string.  The point list must be contained in       */
     305                 : /*      brackets and each point pair separated by a comma.              */
     306                 : /************************************************************************/
     307                 : 
     308           30599 : const char * OGRWktReadPoints( const char * pszInput,
     309                 :                                OGRRawPoint ** ppaoPoints, double **ppadfZ,
     310                 :                                int * pnMaxPoints,
     311                 :                                int * pnPointsRead )
     312                 : 
     313                 : {
     314           30599 :     const char *pszOrigInput = pszInput;
     315           30599 :     *pnPointsRead = 0;
     316                 : 
     317           30599 :     if( pszInput == NULL )
     318               0 :         return NULL;
     319                 :     
     320                 : /* -------------------------------------------------------------------- */
     321                 : /*      Eat any leading white space.                                    */
     322                 : /* -------------------------------------------------------------------- */
     323           61198 :     while( *pszInput == ' ' || *pszInput == '\t' )
     324               0 :         pszInput++;
     325                 : 
     326                 : /* -------------------------------------------------------------------- */
     327                 : /*      If this isn't an opening bracket then we have a problem!        */
     328                 : /* -------------------------------------------------------------------- */
     329           30599 :     if( *pszInput != '(' )
     330                 :     {
     331                 :         CPLDebug( "OGR",
     332                 :                   "Expected '(', but got %s in OGRWktReadPoints().\n",
     333              39 :                   pszInput );
     334                 :                   
     335              39 :         return pszInput;
     336                 :     }
     337                 : 
     338           30560 :     pszInput++;
     339                 : 
     340                 : /* ==================================================================== */
     341                 : /*      This loop reads a single point.  It will continue till we       */
     342                 : /*      run out of well formed points, or a closing bracket is          */
     343                 : /*      encountered.                                                    */
     344                 : /* ==================================================================== */
     345                 :     char        szDelim[OGR_WKT_TOKEN_MAX];
     346                 :     
     347           85271 :     do {
     348                 : /* -------------------------------------------------------------------- */
     349                 : /*      Read the X and Y values, verify they are numeric.               */
     350                 : /* -------------------------------------------------------------------- */
     351                 :         char    szTokenX[OGR_WKT_TOKEN_MAX];
     352                 :         char    szTokenY[OGR_WKT_TOKEN_MAX];
     353                 : 
     354           85319 :         pszInput = OGRWktReadToken( pszInput, szTokenX );
     355           85319 :         pszInput = OGRWktReadToken( pszInput, szTokenY );
     356                 : 
     357          172264 :         if( (!isdigit(szTokenX[0]) && szTokenX[0] != '-' && szTokenX[0] != '.' )
     358           86945 :             || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' && szTokenY[0] != '.') )
     359              38 :             return NULL;
     360                 : 
     361                 : /* -------------------------------------------------------------------- */
     362                 : /*      Do we need to grow the point list to hold this point?           */
     363                 : /* -------------------------------------------------------------------- */
     364           85281 :         if( *pnPointsRead == *pnMaxPoints )
     365                 :         {
     366           30280 :             *pnMaxPoints = *pnMaxPoints * 2 + 10;
     367                 :             *ppaoPoints = (OGRRawPoint *)
     368           30280 :                 CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints);
     369                 : 
     370           30280 :             if( *ppadfZ != NULL )
     371                 :             {
     372                 :                 *ppadfZ = (double *)
     373              21 :                     CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints);
     374                 :             }
     375                 :         }
     376                 : 
     377                 : /* -------------------------------------------------------------------- */
     378                 : /*      Add point to list.                                              */
     379                 : /* -------------------------------------------------------------------- */
     380           85281 :         (*ppaoPoints)[*pnPointsRead].x = CPLAtof(szTokenX);
     381           85281 :         (*ppaoPoints)[*pnPointsRead].y = CPLAtof(szTokenY);
     382                 : 
     383                 : /* -------------------------------------------------------------------- */
     384                 : /*      Do we have a Z coordinate?                                      */
     385                 : /* -------------------------------------------------------------------- */
     386           85281 :         pszInput = OGRWktReadToken( pszInput, szDelim );
     387                 : 
     388          101348 :         if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
     389                 :         {
     390           16067 :             if( *ppadfZ == NULL )
     391                 :             {
     392           14969 :                 *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
     393                 :             }
     394                 : 
     395           16067 :             (*ppadfZ)[*pnPointsRead] = CPLAtof(szDelim);
     396                 : 
     397           16067 :             pszInput = OGRWktReadToken( pszInput, szDelim );
     398                 :         }
     399           69214 :         else if ( *ppadfZ != NULL )
     400             114 :             (*ppadfZ)[*pnPointsRead] = 0.0;
     401                 :         
     402           85281 :         (*pnPointsRead)++;
     403                 : 
     404                 : /* -------------------------------------------------------------------- */
     405                 : /*      Do we have a M coordinate?                                      */
     406                 : /*      If we do, just skip it.                                         */
     407                 : /* -------------------------------------------------------------------- */
     408           85281 :         if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
     409                 :         {
     410              54 :             pszInput = OGRWktReadToken( pszInput, szDelim );
     411                 :         }
     412                 :         
     413                 : /* -------------------------------------------------------------------- */
     414                 : /*      Read next delimeter ... it should be a comma if there are       */
     415                 : /*      more points.                                                    */
     416                 : /* -------------------------------------------------------------------- */
     417           85281 :         if( szDelim[0] != ')' && szDelim[0] != ',' )
     418                 :         {
     419                 :             CPLDebug( "OGR",
     420                 :                       "Corrupt input in OGRWktReadPoints()\n"
     421                 :                       "Got `%s' when expecting `,' or `)', near `%s' in %s.\n",
     422              10 :                       szDelim, pszInput, pszOrigInput );
     423              10 :             return NULL;
     424                 :         }
     425                 :         
     426           85271 :     } while( szDelim[0] == ',' );
     427                 : 
     428           30512 :     return pszInput;
     429                 : }
     430                 : 
     431                 : /************************************************************************/
     432                 : /*                             OGRMalloc()                              */
     433                 : /*                                                                      */
     434                 : /*      Cover for CPLMalloc()                                           */
     435                 : /************************************************************************/
     436                 : 
     437               0 : void *OGRMalloc( size_t size )
     438                 : 
     439                 : {
     440               0 :     return CPLMalloc( size );
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                             OGRCalloc()                              */
     445                 : /*                                                                      */
     446                 : /*      Cover for CPLCalloc()                                           */
     447                 : /************************************************************************/
     448                 : 
     449          341024 : void * OGRCalloc( size_t count, size_t size )
     450                 : 
     451                 : {
     452          341024 :     return CPLCalloc( count, size );
     453                 : }
     454                 : 
     455                 : /************************************************************************/
     456                 : /*                             OGRRealloc()                             */
     457                 : /*                                                                      */
     458                 : /*      Cover for CPLRealloc()                                          */
     459                 : /************************************************************************/
     460                 : 
     461          137750 : void *OGRRealloc( void * pOld, size_t size )
     462                 : 
     463                 : {
     464          137750 :     return CPLRealloc( pOld, size );
     465                 : }
     466                 : 
     467                 : /************************************************************************/
     468                 : /*                              OGRFree()                               */
     469                 : /*                                                                      */
     470                 : /*      Cover for CPLFree().                                            */
     471                 : /************************************************************************/
     472                 : 
     473         1291210 : void OGRFree( void * pMemory )
     474                 : 
     475                 : {
     476         1291210 :     CPLFree( pMemory );
     477         1291210 : }
     478                 : 
     479                 : /**
     480                 :  * General utility option processing.
     481                 :  *
     482                 :  * This function is intended to provide a variety of generic commandline 
     483                 :  * options for all OGR commandline utilities.  It takes care of the following
     484                 :  * commandline options:
     485                 :  *  
     486                 :  *  --version: report version of GDAL in use. 
     487                 :  *  --license: report GDAL license info.
     488                 :  *  --formats: report all format drivers configured.
     489                 :  *  --optfile filename: expand an option file into the argument list. 
     490                 :  *  --config key value: set system configuration option. 
     491                 :  *  --debug [on/off/value]: set debug level.
     492                 :  *  --pause: Pause for user input (allows time to attach debugger)
     493                 :  *  --locale [locale]: Install a locale using setlocale() (debugging)
     494                 :  *  --help-general: report detailed help on general options. 
     495                 :  *
     496                 :  * The argument array is replaced "in place" and should be freed with 
     497                 :  * CSLDestroy() when no longer needed.  The typical usage looks something
     498                 :  * like the following.  Note that the formats should be registered so that
     499                 :  * the --formats option will work properly.
     500                 :  *
     501                 :  *  int main( int argc, char ** argv )
     502                 :  *  { 
     503                 :  *    OGRAllRegister();
     504                 :  *
     505                 :  *    argc = OGRGeneralCmdLineProcessor( argc, &argv, 0 );
     506                 :  *    if( argc < 1 )
     507                 :  *        exit( -argc );
     508                 :  *
     509                 :  * @param nArgc number of values in the argument list.
     510                 :  * @param ppapszArgv pointer to the argument list array (will be updated in place). 
     511                 :  * @param nOptions unused.
     512                 :  *
     513                 :  * @return updated nArgc argument count.  Return of 0 requests terminate 
     514                 :  * without error, return of -1 requests exit with error code.
     515                 :  */
     516                 : 
     517             203 : int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
     518                 : 
     519                 : {
     520             203 :     char **papszReturn = NULL;
     521                 :     int  iArg;
     522             203 :     char **papszArgv = *ppapszArgv;
     523                 : 
     524                 :     (void) nOptions;
     525                 :     
     526                 : /* -------------------------------------------------------------------- */
     527                 : /*      Preserve the program name.                                      */
     528                 : /* -------------------------------------------------------------------- */
     529             203 :     papszReturn = CSLAddString( papszReturn, papszArgv[0] );
     530                 : 
     531                 : /* ==================================================================== */
     532                 : /*      Loop over all arguments.                                        */
     533                 : /* ==================================================================== */
     534            1080 :     for( iArg = 1; iArg < nArgc; iArg++ )
     535                 :     {
     536                 : /* -------------------------------------------------------------------- */
     537                 : /*      --version                                                       */
     538                 : /* -------------------------------------------------------------------- */
     539             877 :         if( EQUAL(papszArgv[iArg],"--version") )
     540                 :         {
     541               0 :             printf( "%s\n", GDALVersionInfo( "--version" ) );
     542               0 :             CSLDestroy( papszReturn );
     543               0 :             return 0;
     544                 :         }
     545                 : 
     546                 : /* -------------------------------------------------------------------- */
     547                 : /*      --license                                                       */
     548                 : /* -------------------------------------------------------------------- */
     549             877 :         else if( EQUAL(papszArgv[iArg],"--license") )
     550                 :         {
     551               0 :             printf( "%s\n", GDALVersionInfo( "LICENSE" ) );
     552               0 :             CSLDestroy( papszReturn );
     553               0 :             return 0;
     554                 :         }
     555                 : 
     556                 : /* -------------------------------------------------------------------- */
     557                 : /*      --config                                                        */
     558                 : /* -------------------------------------------------------------------- */
     559             877 :         else if( EQUAL(papszArgv[iArg],"--config") )
     560                 :         {
     561               8 :             if( iArg + 2 >= nArgc )
     562                 :             {
     563                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     564               0 :                           "--config option given without a key and value argument." );
     565               0 :                 CSLDestroy( papszReturn );
     566               0 :                 return -1;
     567                 :             }
     568                 : 
     569               8 :             CPLSetConfigOption( papszArgv[iArg+1], papszArgv[iArg+2] );
     570                 : 
     571               8 :             iArg += 2;
     572                 :         }
     573                 : 
     574                 : /* -------------------------------------------------------------------- */
     575                 : /*      --mempreload                                                    */
     576                 : /* -------------------------------------------------------------------- */
     577             869 :         else if( EQUAL(papszArgv[iArg],"--mempreload") )
     578                 :         {
     579                 :             int i;
     580                 : 
     581               0 :             if( iArg + 1 >= nArgc )
     582                 :             {
     583                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     584               0 :                           "--mempreload option given without directory path.");
     585               0 :                 CSLDestroy( papszReturn );
     586               0 :                 return -1;
     587                 :             }
     588                 :             
     589               0 :             char **papszFiles = CPLReadDir( papszArgv[iArg+1] );
     590               0 :             if( CSLCount(papszFiles) == 0 )
     591                 :             {
     592                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     593               0 :                           "--mempreload given invalid or empty directory.");
     594               0 :                 CSLDestroy( papszReturn );
     595               0 :                 return -1;
     596                 :             }
     597                 :                 
     598               0 :             for( i = 0; papszFiles[i] != NULL; i++ )
     599                 :             {
     600               0 :                 CPLString osOldPath, osNewPath;
     601                 :                 
     602               0 :                 if( EQUAL(papszFiles[i],".") || EQUAL(papszFiles[i],"..") )
     603               0 :                     continue;
     604                 : 
     605               0 :                 osOldPath = CPLFormFilename( papszArgv[iArg+1], 
     606               0 :                                              papszFiles[i], NULL );
     607               0 :                 osNewPath.Printf( "/vsimem/%s", papszFiles[i] );
     608                 : 
     609                 :                 CPLDebug( "VSI", "Preloading %s to %s.", 
     610               0 :                           osOldPath.c_str(), osNewPath.c_str() );
     611                 : 
     612               0 :                 if( CPLCopyFile( osNewPath, osOldPath ) != 0 )
     613               0 :                     return -1;
     614                 :             }
     615                 :             
     616               0 :             CSLDestroy( papszFiles );
     617               0 :             iArg += 1;
     618                 :         }
     619                 : 
     620                 : /* -------------------------------------------------------------------- */
     621                 : /*      --debug                                                         */
     622                 : /* -------------------------------------------------------------------- */
     623             869 :         else if( EQUAL(papszArgv[iArg],"--debug") )
     624                 :         {
     625               0 :             if( iArg + 1 >= nArgc )
     626                 :             {
     627                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     628               0 :                           "--debug option given without debug level." );
     629               0 :                 CSLDestroy( papszReturn );
     630               0 :                 return -1;
     631                 :             }
     632                 : 
     633               0 :             CPLSetConfigOption( "CPL_DEBUG", papszArgv[iArg+1] );
     634               0 :             iArg += 1;
     635                 :         }
     636                 : 
     637                 : /* -------------------------------------------------------------------- */
     638                 : /*      --optfile                                                       */
     639                 : /*                                                                      */
     640                 : /*      Annoyingly the options inserted by --optfile will *not* be      */
     641                 : /*      processed properly if they are general options.                 */
     642                 : /* -------------------------------------------------------------------- */
     643             869 :         else if( EQUAL(papszArgv[iArg],"--optfile") )
     644                 :         {
     645                 :             const char *pszLine;
     646                 :             FILE *fpOptFile;
     647                 : 
     648               0 :             if( iArg + 1 >= nArgc )
     649                 :             {
     650                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     651               0 :                           "--optfile option given without filename." );
     652               0 :                 CSLDestroy( papszReturn );
     653               0 :                 return -1;
     654                 :             }
     655                 : 
     656               0 :             fpOptFile = VSIFOpen( papszArgv[iArg+1], "rb" );
     657                 : 
     658               0 :             if( fpOptFile == NULL )
     659                 :             {
     660                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     661                 :                           "Unable to open optfile '%s'.\n%s",
     662               0 :                           papszArgv[iArg+1], VSIStrerror( errno ) );
     663               0 :                 CSLDestroy( papszReturn );
     664               0 :                 return -1;
     665                 :             }
     666                 :             
     667               0 :             while( (pszLine = CPLReadLine( fpOptFile )) != NULL )
     668                 :             {
     669                 :                 char **papszTokens;
     670                 :                 int i;
     671                 : 
     672               0 :                 if( pszLine[0] == '#' || strlen(pszLine) == 0 )
     673               0 :                     continue;
     674                 : 
     675               0 :                 papszTokens = CSLTokenizeString( pszLine );
     676               0 :                 for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++)
     677               0 :                     papszReturn = CSLAddString( papszReturn, papszTokens[i] );
     678               0 :                 CSLDestroy( papszTokens );
     679                 :             }
     680                 : 
     681               0 :             VSIFClose( fpOptFile );
     682                 :                 
     683               0 :             iArg += 1;
     684                 :         }
     685                 : 
     686                 : /* -------------------------------------------------------------------- */
     687                 : /*      --formats                                                       */
     688                 : /* -------------------------------------------------------------------- */
     689                 : #ifdef OGR_ENABLED
     690             869 :         else if( EQUAL(papszArgv[iArg], "--formats") )
     691                 :         {
     692                 :             int iDr;
     693                 : 
     694               0 :             printf( "Supported Formats:\n" );
     695                 : 
     696               0 :             OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
     697                 :         
     698               0 :             for( iDr = 0; iDr < poR->GetDriverCount(); iDr++ )
     699                 :             {
     700               0 :                 OGRSFDriver *poDriver = poR->GetDriver(iDr);
     701                 : 
     702               0 :                 if( poDriver->TestCapability( ODrCCreateDataSource ) )
     703                 :                     printf( "  -> \"%s\" (read/write)\n", 
     704               0 :                             poDriver->GetName() );
     705                 :                 else
     706                 :                     printf( "  -> \"%s\" (readonly)\n", 
     707               0 :                             poDriver->GetName() );
     708                 :             }
     709                 : 
     710               0 :             CSLDestroy( papszReturn );
     711               0 :             return 0;
     712                 :         }
     713                 : #endif /* OGR_ENABLED */
     714                 : 
     715                 : /* -------------------------------------------------------------------- */
     716                 : /*      --locale                                                        */
     717                 : /* -------------------------------------------------------------------- */
     718             869 :         else if( EQUAL(papszArgv[iArg],"--locale") && iArg < nArgc-1 )
     719                 :         {
     720               0 :             setlocale( LC_ALL, papszArgv[++iArg] );
     721                 :         }
     722                 : 
     723                 : /* -------------------------------------------------------------------- */
     724                 : /*      --pause - "hit enter" pause useful to connect a debugger.       */
     725                 : /* -------------------------------------------------------------------- */
     726             869 :         else if( EQUAL(papszArgv[iArg],"--pause") )
     727                 :         {
     728               0 :             printf( "Hit <ENTER> to Continue.\n" );
     729               0 :             CPLReadLine( stdin );
     730                 :         }
     731                 : 
     732                 : /* -------------------------------------------------------------------- */
     733                 : /*      --help-general                                                  */
     734                 : /* -------------------------------------------------------------------- */
     735             869 :         else if( EQUAL(papszArgv[iArg],"--help-general") )
     736                 :         {
     737               0 :             printf( "Generic GDAL/OGR utility command options:\n" );
     738               0 :             printf( "  --version: report version of GDAL/OGR in use.\n" );
     739               0 :             printf( "  --license: report GDAL/OGR license info.\n" );
     740                 : #ifdef OGR_ENABLED
     741               0 :             printf( "  --formats: report all configured format drivers.\n" );
     742                 : #endif /* OGR_ENABLED */
     743               0 :             printf( "  --optfile filename: expand an option file into the argument list.\n" );
     744               0 :             printf( "  --config key value: set system configuration option.\n" );
     745               0 :             printf( "  --debug [on/off/value]: set debug level.\n" );
     746               0 :             printf( "  --pause: wait for user input, time to attach debugger\n" );
     747               0 :             printf( "  --locale [locale]: install locale for debugging (ie. en_US.UTF-8)\n" );
     748               0 :             printf( "  --help-general: report detailed help on general options.\n" );
     749               0 :             CSLDestroy( papszReturn );
     750               0 :             return 0;
     751                 :         }
     752                 : 
     753                 : /* -------------------------------------------------------------------- */
     754                 : /*      carry through unrecognised options.                             */
     755                 : /* -------------------------------------------------------------------- */
     756                 :         else
     757                 :         {
     758             869 :             papszReturn = CSLAddString( papszReturn, papszArgv[iArg] );
     759                 :         }
     760                 :     }
     761                 : 
     762             203 :     *ppapszArgv = papszReturn;
     763                 : 
     764             203 :     return CSLCount( *ppapszArgv );
     765                 : }
     766                 : 
     767                 : /************************************************************************/
     768                 : /*                            OGRParseDate()                            */
     769                 : /*                                                                      */
     770                 : /*      Parse a variety of text date formats into an OGRField.          */
     771                 : /************************************************************************/
     772                 : 
     773                 : /**
     774                 :  * Parse date string.
     775                 :  *
     776                 :  * This function attempts to parse a date string in a variety of formats
     777                 :  * into the OGRField.Date format suitable for use with OGR.  Generally 
     778                 :  * speaking this function is expecting values like:
     779                 :  * 
     780                 :  *   YYYY-MM-DD HH:MM:SS+nn
     781                 :  *
     782                 :  * The seconds may also have a decimal portion (which is ignored).  And
     783                 :  * just dates (YYYY-MM-DD) or just times (HH:MM:SS) are also supported. 
     784                 :  * The date may also be in YYYY/MM/DD format.  If the year is less than 100
     785                 :  * and greater than 30 a "1900" century value will be set.  If it is less than
     786                 :  * 30 and greater than -1 then a "2000" century value will be set.  In 
     787                 :  * the future this function may be generalized, and additional control 
     788                 :  * provided through nOptions, but an nOptions value of "0" should always do
     789                 :  * a reasonable default form of processing.
     790                 :  *
     791                 :  * The value of psField will be indeterminate if the function fails (returns
     792                 :  * FALSE).  
     793                 :  *
     794                 :  * @param pszInput the input date string.
     795                 :  * @param psField the OGRField that will be updated with the parsed result.
     796                 :  * @param nOptions parsing options, for now always 0. 
     797                 :  *
     798                 :  * @return TRUE if apparently successful or FALSE on failure.
     799                 :  */
     800                 : 
     801             282 : int OGRParseDate( const char *pszInput, OGRField *psField, int nOptions )
     802                 : 
     803                 : {
     804             282 :     int bGotSomething = FALSE;
     805                 : 
     806             282 :     psField->Date.Year = 0;
     807             282 :     psField->Date.Month = 0;
     808             282 :     psField->Date.Day = 0;
     809             282 :     psField->Date.Hour = 0;
     810             282 :     psField->Date.Minute = 0;
     811             282 :     psField->Date.Second = 0;
     812             282 :     psField->Date.TZFlag = 0;
     813                 :     
     814                 : /* -------------------------------------------------------------------- */
     815                 : /*      Do we have a date?                                              */
     816                 : /* -------------------------------------------------------------------- */
     817             564 :     while( *pszInput == ' ' )
     818               0 :         pszInput++;
     819                 :     
     820             282 :     if( strstr(pszInput,"-") != NULL || strstr(pszInput,"/") != NULL )
     821                 :     {
     822             216 :         psField->Date.Year = (GInt16)atoi(pszInput);
     823             216 :         if( psField->Date.Year < 100 && psField->Date.Year >= 30 )
     824               0 :             psField->Date.Year += 1900;
     825             216 :         else if( psField->Date.Year < 30 && psField->Date.Year >= 0 )
     826               0 :             psField->Date.Year += 2000;
     827                 : 
     828            1296 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     829             864 :             pszInput++;
     830             216 :         if( *pszInput != '-' && *pszInput != '/' )
     831               0 :             return FALSE;
     832                 :         else 
     833             216 :             pszInput++;
     834                 : 
     835             216 :         psField->Date.Month = (GByte)atoi(pszInput);
     836             216 :         if( psField->Date.Month > 12 )
     837               0 :             return FALSE;
     838                 : 
     839             864 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     840             432 :             pszInput++;
     841             216 :         if( *pszInput != '-' && *pszInput != '/' )
     842               0 :             return FALSE;
     843                 :         else 
     844             216 :             pszInput++;
     845                 : 
     846             216 :         psField->Date.Day = (GByte)atoi(pszInput);
     847             216 :         if( psField->Date.Day > 31 )
     848               0 :             return FALSE;
     849                 : 
     850             864 :         while( *pszInput >= '0' && *pszInput <= '9' )
     851             432 :             pszInput++;
     852                 : 
     853             216 :         bGotSomething = TRUE;
     854                 :     }
     855                 : 
     856                 : /* -------------------------------------------------------------------- */
     857                 : /*      Do we have a time?                                              */
     858                 : /* -------------------------------------------------------------------- */
     859             699 :     while( *pszInput == ' ' )
     860             135 :         pszInput++;
     861                 :     
     862             282 :     if( strstr(pszInput,":") != NULL )
     863                 :     {
     864             188 :         psField->Date.Hour = (GByte)atoi(pszInput);
     865             188 :         if( psField->Date.Hour > 23 )
     866               0 :             return FALSE;
     867                 : 
     868             749 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     869             373 :             pszInput++;
     870             188 :         if( *pszInput != ':' )
     871               0 :             return FALSE;
     872                 :         else 
     873             188 :             pszInput++;
     874                 : 
     875             188 :         psField->Date.Minute = (GByte)atoi(pszInput);
     876             188 :         if( psField->Date.Minute > 59 )
     877               0 :             return FALSE;
     878                 : 
     879             752 :         while( *pszInput >= '0' && *pszInput <= '9' ) 
     880             376 :             pszInput++;
     881             188 :         if( *pszInput != ':' )
     882               0 :             return FALSE;
     883                 :         else 
     884             188 :             pszInput++;
     885                 : 
     886             188 :         psField->Date.Second = (GByte)atoi(pszInput);
     887             188 :         if( psField->Date.Second > 59 )
     888               0 :             return FALSE;
     889                 : 
     890             752 :         while( (*pszInput >= '0' && *pszInput <= '9')
     891                 :                || *pszInput == '.' )
     892             376 :             pszInput++;
     893                 : 
     894             188 :         bGotSomething = TRUE;
     895                 :     }
     896                 : 
     897                 :     // No date or time!
     898             282 :     if( !bGotSomething )
     899               3 :         return FALSE;
     900                 : 
     901                 : /* -------------------------------------------------------------------- */
     902                 : /*      Do we have a timezone?                                          */
     903                 : /* -------------------------------------------------------------------- */
     904             566 :     while( *pszInput == ' ' )
     905               8 :         pszInput++;
     906                 :     
     907             279 :     if( *pszInput == '-' || *pszInput == '+' )
     908                 :     {
     909                 :         // +HH integral offset
     910              51 :         if( strlen(pszInput) <= 3 )
     911              44 :             psField->Date.TZFlag = (GByte)(100 + atoi(pszInput) * 4);
     912                 : 
     913              14 :         else if( pszInput[3] == ':'  // +HH:MM offset
     914                 :                  && atoi(pszInput+4) % 15 == 0 )
     915                 :         {
     916                 :             psField->Date.TZFlag = (GByte)(100 
     917                 :                 + atoi(pszInput+1) * 4
     918               7 :                 + (atoi(pszInput+4) / 15));
     919                 : 
     920               7 :             if( pszInput[0] == '-' )
     921               4 :                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
     922                 :         }
     923               0 :         else if( isdigit(pszInput[3]) && isdigit(pszInput[4])  // +HHMM offset
     924                 :                  && atoi(pszInput+3) % 15 == 0 )
     925                 :         {
     926                 :             psField->Date.TZFlag = (GByte)(100 
     927                 :                 + static_cast<GByte>(CPLScanLong(pszInput+1,2)) * 4
     928               0 :                 + (atoi(pszInput+3) / 15));
     929                 : 
     930               0 :             if( pszInput[0] == '-' )
     931               0 :                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
     932                 :         }
     933               0 :         else if( isdigit(pszInput[3]) && pszInput[4] == '\0'  // +HMM offset
     934                 :                  && atoi(pszInput+2) % 15 == 0 )
     935                 :         {
     936                 :             psField->Date.TZFlag = (GByte)(100 
     937                 :                 + static_cast<GByte>(CPLScanLong(pszInput+1,1)) * 4
     938               0 :                 + (atoi(pszInput+2) / 15));
     939                 : 
     940               0 :             if( pszInput[0] == '-' )
     941               0 :                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
     942                 :         }
     943                 :         // otherwise ignore any timezone info.
     944                 :     }
     945                 : 
     946             279 :     return TRUE;
     947                 : }
     948                 : 
     949                 : 
     950                 : /************************************************************************/
     951                 : /*                           OGRParseXMLDateTime()                      */
     952                 : /************************************************************************/
     953                 : 
     954              82 : int OGRParseXMLDateTime( const char* pszXMLDateTime,
     955                 :                                int *pnYear, int *pnMonth, int *pnDay,
     956                 :                                int *pnHour, int *pnMinute, float* pfSecond, int *pnTZ)
     957                 : {
     958              82 :     int year = 0, month = 0, day = 0, hour = 0, minute = 0, TZHour, TZMinute;
     959              82 :     float second = 0;
     960                 :     char c;
     961              82 :     int TZ = 0;
     962              82 :     int bRet = FALSE;
     963                 : 
     964                 :     /* Date is expressed as a UTC date */
     965              82 :     if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c",
     966                 :                 &year, &month, &day, &hour, &minute, &second, &c) == 7 && c == 'Z')
     967                 :     {
     968               4 :         TZ = 100;
     969               4 :         bRet = TRUE;
     970                 :     }
     971                 :     /* Date is expressed as a UTC date, with a timezone */
     972              78 :     else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c%02d:%02d",
     973                 :                 &year, &month, &day, &hour, &minute, &second, &c, &TZHour, &TZMinute) == 9 &&
     974                 :                 (c == '+' || c == '-'))
     975                 :     {
     976              23 :         TZ = 100 + ((c == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
     977              23 :         bRet = TRUE;
     978                 :     }
     979                 :     /* Date is expressed into an unknown timezone */
     980              55 :     else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f",
     981                 :                     &year, &month, &day, &hour, &minute, &second) == 6)
     982                 :     {
     983              30 :         TZ = 0;
     984              30 :         bRet = TRUE;
     985                 :     }
     986                 :     /* Date is expressed as a UTC date with only year:month:day */
     987              25 :     else if (sscanf(pszXMLDateTime, "%04d-%02d-%02d", &year, &month, &day) == 3)
     988                 :     {
     989              25 :         TZ = 0;
     990              25 :         bRet = TRUE;
     991                 :     }
     992                 : 
     993              82 :     if (bRet)
     994                 :     {
     995              82 :         if (pnYear) *pnYear = year;
     996              82 :         if (pnMonth) *pnMonth = month;
     997              82 :         if (pnDay) *pnDay = day;
     998              82 :         if (pnHour) *pnHour = hour;
     999              82 :         if (pnMinute) *pnMinute = minute;
    1000              82 :         if (pfSecond) *pfSecond = second;
    1001              82 :         if (pnTZ) *pnTZ = TZ;
    1002                 :     }
    1003                 : 
    1004              82 :     return bRet;
    1005                 : }
    1006                 : 
    1007                 : /************************************************************************/
    1008                 : /*                      OGRParseRFC822DateTime()                        */
    1009                 : /************************************************************************/
    1010                 : 
    1011                 : static const char* aszMonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    1012                 :                                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
    1013                 : 
    1014              25 : int OGRParseRFC822DateTime( const char* pszRFC822DateTime,
    1015                 :                                   int *pnYear, int *pnMonth, int *pnDay,
    1016                 :                                   int *pnHour, int *pnMinute, int *pnSecond, int *pnTZ)
    1017                 : {
    1018                 :     /* Following http://asg.web.cmu.edu/rfc/rfc822.html#sec-5 : [Fri,] 28 Dec 2007 05:24[:17] GMT */
    1019              25 :     char** papszTokens = CSLTokenizeStringComplex( pszRFC822DateTime, " ,:", TRUE, FALSE );
    1020              25 :     char** papszVal = papszTokens;
    1021              25 :     int bRet = FALSE;
    1022              25 :     int nTokens = CSLCount(papszTokens);
    1023              25 :     if (nTokens >= 6)
    1024                 :     {
    1025              21 :         if ( ! ((*papszVal)[0] >= '0' && (*papszVal)[0] <= '9') )
    1026                 :         {
    1027                 :             /* Ignore day of week */
    1028              21 :             papszVal ++;
    1029                 :         }
    1030                 : 
    1031              21 :         int day = atoi(*papszVal);
    1032              21 :         papszVal ++;
    1033                 : 
    1034              21 :         int month = 0;
    1035                 : 
    1036             273 :         for(int i = 0; i < 12; i++)
    1037                 :         {
    1038             252 :             if (EQUAL(*papszVal, aszMonthStr[i]))
    1039              21 :                 month = i + 1;
    1040                 :         }
    1041              21 :         papszVal ++;
    1042                 : 
    1043              21 :         int year = atoi(*papszVal);
    1044              21 :         papszVal ++;
    1045              21 :         if( year < 100 && year >= 30 )
    1046               0 :             year += 1900;
    1047              21 :         else if( year < 30 && year >= 0 )
    1048               0 :             year += 2000;
    1049                 : 
    1050              21 :         int hour = atoi(*papszVal);
    1051              21 :         papszVal ++;
    1052                 : 
    1053              21 :         int minute = atoi(*papszVal);
    1054              21 :         papszVal ++;
    1055                 : 
    1056              21 :         int second = 0;
    1057              21 :         if (*papszVal != NULL && (*papszVal)[0] >= '0' && (*papszVal)[0] <= '9')
    1058                 :         {
    1059              21 :             second = atoi(*papszVal);
    1060              21 :             papszVal ++;
    1061                 :         }
    1062                 : 
    1063              21 :         if (month != 0)
    1064                 :         {
    1065              21 :             bRet = TRUE;
    1066              21 :             int TZ = 0;
    1067                 : 
    1068              21 :             if (*papszVal == NULL)
    1069                 :             {
    1070                 :             }
    1071              63 :             else if (strlen(*papszVal) == 5 &&
    1072              21 :                      ((*papszVal)[0] == '+' || (*papszVal)[0] == '-'))
    1073                 :             {
    1074                 :                 char szBuf[3];
    1075              21 :                 szBuf[0] = (*papszVal)[1];
    1076              21 :                 szBuf[1] = (*papszVal)[2];
    1077              21 :                 szBuf[2] = 0;
    1078              21 :                 int TZHour = atoi(szBuf);
    1079              21 :                 szBuf[0] = (*papszVal)[3];
    1080              21 :                 szBuf[1] = (*papszVal)[4];
    1081              21 :                 szBuf[2] = 0;
    1082              21 :                 int TZMinute = atoi(szBuf);
    1083              21 :                 TZ = 100 + (((*papszVal)[0] == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
    1084                 :             }
    1085                 :             else
    1086                 :             {
    1087               0 :                 const char* aszTZStr[] = { "GMT", "UT", "Z", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", "PDT" };
    1088               0 :                 int anTZVal[] = { 0, 0, 0, -5, -4, -6, -5, -7, -6, -8, -7 };
    1089               0 :                 for(int i = 0; i < 11; i++)
    1090                 :                 {
    1091               0 :                     if (EQUAL(*papszVal, aszTZStr[i]))
    1092                 :                     {
    1093               0 :                         TZ =  100 + anTZVal[i] * 4;
    1094               0 :                         break;
    1095                 :                     }
    1096                 :                 }
    1097                 :             }
    1098                 : 
    1099              21 :             if (pnYear) *pnYear = year;
    1100              21 :             if (pnMonth) *pnMonth = month;
    1101              21 :             if (pnDay) *pnDay = day;
    1102              21 :             if (pnHour) *pnHour = hour;
    1103              21 :             if (pnMinute) *pnMinute = minute;
    1104              21 :             if (pnSecond) *pnSecond = second;
    1105              21 :             if (pnTZ) *pnTZ = TZ;
    1106                 :         }
    1107                 :     }
    1108              25 :     CSLDestroy(papszTokens);
    1109              25 :     return bRet;
    1110                 : }
    1111                 : 
    1112                 : 
    1113                 : /**
    1114                 :   * Returns the day of the week in Gregorian calendar
    1115                 :   *
    1116                 :   * @param day : day of the month, between 1 and 31
    1117                 :   * @param month : month of the year, between 1 (Jan) and 12 (Dec)
    1118                 :   * @param year : year
    1119                 : 
    1120                 :   * @return day of the week : 0 for Monday, ... 6 for Sunday
    1121                 :   */
    1122                 : 
    1123              12 : int OGRGetDayOfWeek(int day, int month, int year)
    1124                 : {
    1125                 :     /* Reference: Zeller's congruence */
    1126              12 :     int q = day;
    1127                 :     int m;
    1128              12 :     if (month >=3)
    1129              12 :         m = month;
    1130                 :     else
    1131                 :     {
    1132               0 :         m = month + 12;
    1133               0 :         year --;
    1134                 :     }
    1135              12 :     int K = year % 100;
    1136              12 :     int J = year / 100;
    1137              12 :     int h = ( q + (((m+1)*26)/10) + K + K/4 + J/4 + 5 * J) % 7;
    1138              12 :     return ( h + 5 ) % 7;
    1139                 : }
    1140                 : 
    1141                 : 
    1142                 : /************************************************************************/
    1143                 : /*                         OGRGetRFC822DateTime()                       */
    1144                 : /************************************************************************/
    1145                 : 
    1146              12 : char* OGRGetRFC822DateTime(int year, int month, int day, int hour, int minute, int second, int TZFlag)
    1147                 : {
    1148              12 :     char* pszTZ = NULL;
    1149              12 :     const char* aszDayOfWeek[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
    1150                 : 
    1151              12 :     int dayofweek = OGRGetDayOfWeek(day, month, year);
    1152                 : 
    1153              12 :     if (month < 1 || month > 12)
    1154               0 :         month = 1;
    1155                 : 
    1156              12 :     if (TZFlag == 0 || TZFlag == 100)
    1157                 :     {
    1158               0 :         pszTZ = CPLStrdup("GMT");
    1159                 :     }
    1160                 :     else
    1161                 :     {
    1162              12 :         int TZOffset = ABS(TZFlag - 100) * 15;
    1163              12 :         int TZHour = TZOffset / 60;
    1164              12 :         int TZMinute = TZOffset - TZHour * 60;
    1165                 :         pszTZ = CPLStrdup(CPLSPrintf("%c%02d%02d", TZFlag > 100 ? '+' : '-',
    1166              12 :                                         TZHour, TZMinute));
    1167                 :     }
    1168                 :     char* pszRet = CPLStrdup(CPLSPrintf("%s, %02d %s %04d %02d:%02d:%02d %s",
    1169              12 :                      aszDayOfWeek[dayofweek], day, aszMonthStr[month - 1], year, hour, minute, second, pszTZ));
    1170              12 :     CPLFree(pszTZ);
    1171              12 :     return pszRet;
    1172                 : }
    1173                 : 
    1174                 : /************************************************************************/
    1175                 : /*                            OGRGetXMLDateTime()                       */
    1176                 : /************************************************************************/
    1177                 : 
    1178               4 : char* OGRGetXMLDateTime(int year, int month, int day, int hour, int minute, int second, int TZFlag)
    1179                 : {
    1180                 :     char* pszRet;
    1181               6 :     if (TZFlag == 0 || TZFlag == 100)
    1182                 :     {
    1183                 :         pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
    1184               2 :                            year, month, day, hour, minute, second));
    1185                 :     }
    1186                 :     else
    1187                 :     {
    1188               2 :         int TZOffset = ABS(TZFlag - 100) * 15;
    1189               2 :         int TZHour = TZOffset / 60;
    1190               2 :         int TZMinute = TZOffset - TZHour * 60;
    1191                 :         pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
    1192                 :                            year, month, day, hour, minute, second,
    1193               2 :                            (TZFlag > 100) ? '+' : '-', TZHour, TZMinute));
    1194                 :     }
    1195               4 :     return pszRet;
    1196                 : }
    1197                 : 
    1198                 : /************************************************************************/
    1199                 : /*                 OGRGetXML_UTF8_EscapedString()                       */
    1200                 : /************************************************************************/
    1201                 : 
    1202             462 : char* OGRGetXML_UTF8_EscapedString(const char* pszString)
    1203                 : {
    1204                 :     char *pszEscaped;
    1205             462 :     if (!CPLIsUTF8(pszString, -1) &&
    1206                 :          CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
    1207                 :     {
    1208                 :         static int bFirstTime = TRUE;
    1209               1 :         if (bFirstTime)
    1210                 :         {
    1211               1 :             bFirstTime = FALSE;
    1212                 :             CPLError(CE_Warning, CPLE_AppDefined,
    1213                 :                     "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
    1214                 :                     "If you still want the original string and change the XML file encoding\n"
    1215                 :                     "afterwards, you can define OGR_FORCE_ASCII=NO as configuration option.\n"
    1216               1 :                     "This warning won't be issued anymore", pszString);
    1217                 :         }
    1218                 :         else
    1219                 :         {
    1220                 :             CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
    1221               0 :                     pszString);
    1222                 :         }
    1223               1 :         char* pszTemp = CPLForceToASCII(pszString, -1, '?');
    1224               1 :         pszEscaped = CPLEscapeString( pszTemp, -1, CPLES_XML );
    1225               1 :         CPLFree(pszTemp);
    1226                 :     }
    1227                 :     else
    1228             461 :         pszEscaped = CPLEscapeString( pszString, -1, CPLES_XML );
    1229             462 :     return pszEscaped;
    1230                 : }
    1231                 : 
    1232                 : /************************************************************************/
    1233                 : /*                        OGRCompareDate()                              */
    1234                 : /************************************************************************/
    1235                 : 
    1236               1 : int OGRCompareDate(   OGRField *psFirstTuple,
    1237                 :                       OGRField *psSecondTuple )
    1238                 : {
    1239                 :     /* FIXME? : We ignore TZFlag */
    1240                 : 
    1241               1 :     if (psFirstTuple->Date.Year < psSecondTuple->Date.Year)
    1242               0 :         return -1;
    1243               1 :     else if (psFirstTuple->Date.Year > psSecondTuple->Date.Year)
    1244               0 :         return 1;
    1245                 : 
    1246               1 :     if (psFirstTuple->Date.Month < psSecondTuple->Date.Month)
    1247               1 :         return -1;
    1248               0 :     else if (psFirstTuple->Date.Month > psSecondTuple->Date.Month)
    1249               0 :         return 1;
    1250                 : 
    1251               0 :     if (psFirstTuple->Date.Day < psSecondTuple->Date.Day)
    1252               0 :         return -1;
    1253               0 :     else if (psFirstTuple->Date.Day > psSecondTuple->Date.Day)
    1254               0 :         return 1;
    1255                 : 
    1256               0 :     if (psFirstTuple->Date.Hour < psSecondTuple->Date.Hour)
    1257               0 :         return -1;
    1258               0 :     else if (psFirstTuple->Date.Hour > psSecondTuple->Date.Hour)
    1259               0 :         return 1;
    1260                 : 
    1261               0 :     if (psFirstTuple->Date.Minute < psSecondTuple->Date.Minute)
    1262               0 :         return -1;
    1263               0 :     else if (psFirstTuple->Date.Minute > psSecondTuple->Date.Minute)
    1264               0 :         return 1;
    1265                 : 
    1266               0 :     if (psFirstTuple->Date.Second < psSecondTuple->Date.Second)
    1267               0 :         return -1;
    1268               0 :     else if (psFirstTuple->Date.Second > psSecondTuple->Date.Second)
    1269               0 :         return 1;
    1270                 : 
    1271               0 :     return 0;
    1272                 : }
    1273                 : 
    1274                 : /************************************************************************/
    1275                 : /*                        OGRFastAtof()                                 */
    1276                 : /************************************************************************/
    1277                 : 
    1278                 : /* On Windows, atof() is very slow if the number */
    1279                 : /* is followed by other long content. */
    1280                 : /* So we just extract the number into a short string */
    1281                 : /* before calling atof() on it */
    1282                 : static
    1283               0 : double OGRCallAtofOnShortString(const char* pszStr)
    1284                 : {
    1285                 :     char szTemp[128];
    1286               0 :     int nCounter = 0;
    1287               0 :     const char* p = pszStr;
    1288               0 :     while(*p == ' ' || *p == '\t')
    1289               0 :         p++;
    1290               0 :     while(*p == '+'  ||
    1291                 :           *p == '-'  ||
    1292                 :           (*p >= '0' && *p <= '9') ||
    1293                 :           *p == '.'  ||
    1294                 :           (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D'))
    1295                 :     {
    1296               0 :         szTemp[nCounter++] = *(p++);
    1297               0 :         if (nCounter == 127)
    1298               0 :             return atof(pszStr);
    1299                 :     }
    1300               0 :     szTemp[nCounter] = '\0';
    1301               0 :     return atof(szTemp);
    1302                 : }
    1303                 : 
    1304                 : /** Same contract as CPLAtof, except than it doesn't always call the
    1305                 :  *  system atof() that may be slow on some platforms. For simple but
    1306                 :  *  common strings, it'll use a faster implementation (up to 20x faster
    1307                 :  *  than atof() on MS runtime libraries) that has no garanty to return
    1308                 :  *  exactly the same floating point number.
    1309                 :  */
    1310                 :  
    1311          286019 : double OGRFastAtof(const char* pszStr)
    1312                 : {
    1313          286019 :     double dfVal = 0;
    1314          286019 :     double dfSign = 1.0;
    1315          286019 :     const char* p = pszStr;
    1316                 :     
    1317                 :     static const double adfTenPower[] =
    1318                 :     {
    1319                 :         1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
    1320                 :         1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20,
    1321                 :         1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31
    1322                 :     };
    1323                 :         
    1324          572040 :     while(*p == ' ' || *p == '\t')
    1325               2 :         p++;
    1326                 : 
    1327          286019 :     if (*p == '+')
    1328               9 :         p++;
    1329          286010 :     else if (*p == '-')
    1330                 :     {
    1331            1165 :         dfSign = -1.0;
    1332            1165 :         p++;
    1333                 :     }
    1334                 :     
    1335         1814703 :     while(TRUE)
    1336                 :     {
    1337         2100722 :         if (*p >= '0' && *p <= '9')
    1338                 :         {
    1339         1814703 :             dfVal = dfVal * 10.0 + (*p - '0');
    1340         1814703 :             p++;
    1341                 :         }
    1342          286019 :         else if (*p == '.')
    1343                 :         {
    1344          282248 :             p++;
    1345                 :             break;
    1346                 :         }
    1347            3771 :         else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
    1348               0 :             return OGRCallAtofOnShortString(pszStr);
    1349                 :         else
    1350            3771 :             return dfSign * dfVal;
    1351                 :     }
    1352                 :     
    1353          282248 :     unsigned int countFractionnal = 0;
    1354          849711 :     while(TRUE)
    1355                 :     {
    1356         1131959 :         if (*p >= '0' && *p <= '9')
    1357                 :         {
    1358          849711 :             dfVal = dfVal * 10.0 + (*p - '0');
    1359          849711 :             countFractionnal ++;
    1360          849711 :             p++;
    1361                 :         }
    1362          282248 :         else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
    1363               0 :             return OGRCallAtofOnShortString(pszStr);
    1364                 :         else
    1365                 :         {
    1366          282248 :             if (countFractionnal < sizeof(adfTenPower) / sizeof(adfTenPower[0]))
    1367          282248 :                 return dfSign * (dfVal / adfTenPower[countFractionnal]);
    1368                 :             else
    1369               0 :                 return OGRCallAtofOnShortString(pszStr);
    1370                 :         }
    1371                 :     }
    1372                 : }
    1373                 : 
    1374                 : /**
    1375                 :  * Check that panPermutation is a permutation of [0,nSize-1].
    1376                 :  * @param panPermutation an array of nSize elements.
    1377                 :  * @param nSize size of the array.
    1378                 :  * @return OGRERR_NONE if panPermutation is a permutation of [0,nSize-1].
    1379                 :  * @since OGR 1.9.0
    1380                 :  */
    1381              64 : OGRErr OGRCheckPermutation(int* panPermutation, int nSize)
    1382                 : {
    1383              64 :     OGRErr eErr = OGRERR_NONE;
    1384              64 :     int* panCheck = (int*)CPLCalloc(nSize, sizeof(int));
    1385                 :     int i;
    1386             319 :     for(i=0;i<nSize;i++)
    1387                 :     {
    1388             259 :         if (panPermutation[i] < 0 || panPermutation[i] >= nSize)
    1389                 :         {
    1390                 :             CPLError(CE_Failure, CPLE_IllegalArg,
    1391               1 :                      "Bad value for element %d", i);
    1392               1 :             eErr = OGRERR_FAILURE;
    1393               1 :             break;
    1394                 :         }
    1395             258 :         if (panCheck[panPermutation[i]] != 0)
    1396                 :         {
    1397                 :             CPLError(CE_Failure, CPLE_IllegalArg,
    1398                 :                      "Array is not a permutation of [0,%d]",
    1399               3 :                      nSize - 1);
    1400               3 :             eErr = OGRERR_FAILURE;
    1401               3 :             break;
    1402                 :         }
    1403             255 :         panCheck[panPermutation[i]] = 1;
    1404                 :     }
    1405              64 :     CPLFree(panCheck);
    1406              64 :     return eErr;
    1407                 : }

Generated by: LCOV version 1.7