LCOV - code coverage report
Current view: directory - ogr - ogrutils.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 542 386 71.2 %
Date: 2011-12-18 Functions: 20 18 90.0 %

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

Generated by: LCOV version 1.7