LCOV - code coverage report
Current view: directory - ogr - ogrutils.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 556 467 84.0 %
Date: 2013-03-30 Functions: 20 18 90.0 %

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

Generated by: LCOV version 1.7