LCOV - code coverage report
Current view: directory - ogr - ogrutils.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 548 394 71.9 %
Date: 2012-04-28 Functions: 20 18 90.0 %

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

Generated by: LCOV version 1.7