LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/tiger - ogrtigerdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 332 259 78.0 %
Date: 2012-12-26 Functions: 23 20 87.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrtigerdatasource.cpp 24433 2012-05-17 16:21:43Z rouault $
       3                 :  *
       4                 :  * Project:  TIGER/Line Translator
       5                 :  * Purpose:  Implements OGRTigerDataSource class
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_tiger.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include <ctype.h>
      34                 : 
      35                 : CPL_CVSID("$Id: ogrtigerdatasource.cpp 24433 2012-05-17 16:21:43Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                        TigerClassifyVersion()                        */
      39                 : /************************************************************************/
      40                 : 
      41             373 : TigerVersion TigerClassifyVersion( int nVersionCode )
      42                 : 
      43                 : {
      44                 :     TigerVersion        nVersion;
      45                 :     int                 nYear, nMonth;
      46                 : 
      47                 : /*
      48                 : ** TIGER Versions
      49                 : **
      50                 : ** 0000           TIGER/Line Precensus Files, 1990 
      51                 : ** 0002           TIGER/Line Initial Voting District Codes Files, 1990 
      52                 : ** 0003           TIGER/Line Files, 1990 
      53                 : ** 0005           TIGER/Line Files, 1992 
      54                 : ** 0021           TIGER/Line Files, 1994 
      55                 : ** 0024           TIGER/Line Files, 1995 
      56                 : ** 9706 to 9810   TIGER/Line Files, 1997 
      57                 : ** 9812 to 9904   TIGER/Line Files, 1998 
      58                 : ** 0006 to 0008   TIGER/Line Files, 1999 
      59                 : ** 0010 to 0011   TIGER/Line Files, Redistricting Census 2000
      60                 : ** 0103 to 0108   TIGER/Line Files, Census 2000
      61                 : **
      62                 : ** 0203 to 0205   TIGER/Line Files, UA 2000
      63                 : ** ????    ????
      64                 : **
      65                 : ** 0206 to 0299   TIGER/Line Files, 2002
      66                 : ** 0300 to 0399   TIGER/Line Files, 2003
      67                 : ** 0400+          TIGER/Line Files, 2004 - one sample is 0405
      68                 : ** ????
      69                 : */
      70                 : 
      71             373 :     nVersion = TIGER_Unknown;
      72             373 :     if( nVersionCode == 0 )
      73               0 :         nVersion = TIGER_1990_Precensus;
      74             373 :     else if( nVersionCode == 2 )
      75               0 :         nVersion = TIGER_1990;
      76             373 :     else if( nVersionCode == 3 )
      77               0 :         nVersion = TIGER_1992;
      78             373 :     else if( nVersionCode == 5 )
      79               0 :         nVersion = TIGER_1994;
      80             373 :     else if( nVersionCode == 21 )
      81               0 :         nVersion = TIGER_1994;
      82             373 :     else if( nVersionCode == 24 )
      83               0 :         nVersion = TIGER_1995;
      84                 : 
      85             373 :     else if( nVersionCode == 9999 )  /* special hack, fme bug 7625 */
      86               0 :         nVersion = TIGER_UA2000;
      87                 : 
      88             373 :     nYear = nVersionCode % 100;
      89             373 :     nMonth = nVersionCode / 100;
      90                 : 
      91             373 :     nVersionCode = nYear * 100 + nMonth;
      92                 : 
      93             373 :     if( nVersion != TIGER_Unknown )
      94                 :         /* do nothing */;
      95             373 :     else if( nVersionCode >= 9706 && nVersionCode <= 9810 )
      96               0 :         nVersion = TIGER_1997;
      97             373 :     else if( nVersionCode >= 9812 && nVersionCode <= 9904 )
      98               0 :         nVersion = TIGER_1998;
      99             373 :     else if( nVersionCode >=    6 /*0006*/ && nVersionCode <=    8 /*0008*/ )
     100               0 :         nVersion = TIGER_1999;
     101             373 :     else if( nVersionCode >=   10 /*0010*/ && nVersionCode <=   11 /*0011*/ )
     102               0 :         nVersion = TIGER_2000_Redistricting;
     103             373 :     else if( nVersionCode >=  103 /*0103*/ && nVersionCode <= 108 /*0108*/ )
     104               0 :         nVersion = TIGER_2000_Census;
     105             373 :     else if( nVersionCode >=  203 /*0302*/ && nVersionCode <= 205 /*0502*/ )
     106               0 :         nVersion = TIGER_UA2000;
     107             373 :     else if( nVersionCode >=  210 /*1002*/ && nVersionCode <= 306 /*0603*/)
     108               0 :         nVersion = TIGER_2002;
     109             373 :     else if( nVersionCode >=  312 /*1203*/ && nVersionCode <= 403 /*0304*/)
     110               0 :         nVersion = TIGER_2003;
     111             373 :     else if( nVersionCode >=  404 )
     112             373 :         nVersion = TIGER_2004;
     113                 : 
     114             373 :     return nVersion;
     115                 : }
     116                 : 
     117                 : /************************************************************************/
     118                 : /*                         TigerVersionString()                         */
     119                 : /************************************************************************/
     120                 : 
     121               9 : const char * TigerVersionString( TigerVersion nVersion )
     122                 : {
     123                 : 
     124               9 :   if (nVersion == TIGER_1990_Precensus) { return "TIGER_1990_Precensus"; }
     125               9 :   if (nVersion == TIGER_1990) { return "TIGER_1990"; }
     126               9 :   if (nVersion == TIGER_1992) { return "TIGER_1992"; }
     127               9 :   if (nVersion == TIGER_1994) { return "TIGER_1994"; }
     128               9 :   if (nVersion == TIGER_1995) { return "TIGER_1995"; }
     129               9 :   if (nVersion == TIGER_1997) { return "TIGER_1997"; }
     130               9 :   if (nVersion == TIGER_1998) { return "TIGER_1998"; }
     131               9 :   if (nVersion == TIGER_1999) { return "TIGER_1999"; }
     132               9 :   if (nVersion == TIGER_2000_Redistricting) { return "TIGER_2000_Redistricting"; }
     133               9 :   if (nVersion == TIGER_UA2000) { return "TIGER_UA2000"; }
     134               9 :   if (nVersion == TIGER_2002) { return "TIGER_2002"; }
     135               9 :   if (nVersion == TIGER_2003) { return "TIGER_2003"; }
     136               9 :   if (nVersion == TIGER_2004) { return "TIGER_2004"; }
     137               0 :   if (nVersion == TIGER_Unknown) { return "TIGER_Unknown"; }
     138               0 :   return "???";
     139                 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                         TigerCheckVersion()                          */
     143                 : /*                                                                      */
     144                 : /*      Some tiger products seem to be generated with version info      */
     145                 : /*      that doesn't match the tiger specs.  We can sometimes           */
     146                 : /*      recognise the wrongness by checking the record length of        */
     147                 : /*      some well known changing files and adjusting the version        */
     148                 : /*      based on this.                                                  */
     149                 : /************************************************************************/
     150                 : 
     151               9 : TigerVersion OGRTigerDataSource::TigerCheckVersion( TigerVersion nOldVersion, 
     152                 :                                                     const char *pszFilename )
     153                 : 
     154                 : {
     155               9 :     if( nOldVersion != TIGER_2002 )
     156               9 :         return nOldVersion;
     157                 : 
     158               0 :     char *pszRTCFilename = BuildFilename( pszFilename, "C" );
     159               0 :     VSILFILE *fp = VSIFOpenL( pszRTCFilename, "rb" );
     160               0 :     CPLFree( pszRTCFilename );
     161                 : 
     162               0 :     if( fp == NULL )
     163               0 :         return nOldVersion;
     164                 :     
     165                 :     char        szHeader[115];
     166                 : 
     167               0 :     if( VSIFReadL( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
     168                 :     {
     169               0 :         VSIFCloseL( fp );
     170               0 :         return nOldVersion;
     171                 :     }
     172                 : 
     173               0 :     VSIFCloseL( fp );
     174                 :     
     175                 : /* -------------------------------------------------------------------- */
     176                 : /*      Is the record length 112?  If so, it is an older version        */
     177                 : /*      than 2002.                                                      */
     178                 : /* -------------------------------------------------------------------- */
     179               0 :     if( szHeader[112] == 10 || szHeader[112] == 13 )
     180                 :     {
     181               0 :         CPLDebug( "TIGER", "Forcing version back to UA2000 since RTC records are short." );
     182               0 :         return TIGER_UA2000;
     183                 :     }
     184                 :     else
     185               0 :         return nOldVersion;
     186                 : }
     187                 : 
     188                 : /************************************************************************/
     189                 : /*                         OGRTigerDataSource()                         */
     190                 : /************************************************************************/
     191                 : 
     192             937 : OGRTigerDataSource::OGRTigerDataSource()
     193                 : 
     194                 : {
     195             937 :     bWriteMode = FALSE;
     196                 : 
     197             937 :     nLayers = 0;
     198             937 :     papoLayers = NULL;
     199                 : 
     200             937 :     nModules = 0;
     201             937 :     papszModules = NULL;
     202                 : 
     203             937 :     pszName = NULL;
     204             937 :     pszPath = NULL;
     205                 : 
     206             937 :     papszOptions = NULL;
     207                 : 
     208             937 :     poSpatialRef = new OGRSpatialReference( "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]" );
     209             937 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /*                        ~OGRTigerDataSource()                         */
     213                 : /************************************************************************/
     214                 : 
     215             937 : OGRTigerDataSource::~OGRTigerDataSource()
     216                 : 
     217                 : {
     218                 :     int         i;
     219                 : 
     220            1117 :     for( i = 0; i < nLayers; i++ )
     221             180 :         delete papoLayers[i];
     222                 :     
     223             937 :     CPLFree( papoLayers );
     224                 : 
     225             937 :     CPLFree( pszName );
     226             937 :     CPLFree( pszPath );
     227                 : 
     228             937 :     CSLDestroy( papszOptions );
     229                 : 
     230             937 :     CSLDestroy( papszModules );
     231                 : 
     232             937 :     delete poSpatialRef;
     233             937 : }
     234                 : 
     235                 : /************************************************************************/
     236                 : /*                              AddLayer()                              */
     237                 : /************************************************************************/
     238                 : 
     239             180 : void OGRTigerDataSource::AddLayer( OGRTigerLayer * poNewLayer )
     240                 : 
     241                 : {
     242                 :     papoLayers = (OGRTigerLayer **)
     243             180 :         CPLRealloc( papoLayers, sizeof(void*) * ++nLayers );
     244                 :     
     245             180 :     papoLayers[nLayers-1] = poNewLayer;
     246             180 : }
     247                 : 
     248                 : /************************************************************************/
     249                 : /*                              GetLayer()                              */
     250                 : /************************************************************************/
     251                 : 
     252            1444 : OGRLayer *OGRTigerDataSource::GetLayer( int iLayer )
     253                 : 
     254                 : {
     255            1444 :     if( iLayer < 0 || iLayer >= nLayers )
     256               2 :         return NULL;
     257                 :     else
     258            1442 :         return papoLayers[iLayer];
     259                 : }
     260                 : 
     261                 : /************************************************************************/
     262                 : /*                              GetLayer()                              */
     263                 : /************************************************************************/
     264                 : 
     265              18 : OGRLayer *OGRTigerDataSource::GetLayer( const char *pszLayerName )
     266                 : 
     267                 : {
     268             171 :     for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     269                 :     {
     270             153 :         if( EQUAL(papoLayers[iLayer]->GetLayerDefn()->GetName(),pszLayerName) )
     271               0 :             return papoLayers[iLayer];
     272                 :     }
     273                 : 
     274              18 :     return NULL;
     275                 : }
     276                 : 
     277                 : /************************************************************************/
     278                 : /*                           GetLayerCount()                            */
     279                 : /************************************************************************/
     280                 : 
     281            1460 : int OGRTigerDataSource::GetLayerCount()
     282                 : 
     283                 : {
     284            1460 :     return nLayers;
     285                 : }
     286                 : 
     287                 : /************************************************************************/
     288                 : /*                                Open()                                */
     289                 : /************************************************************************/
     290                 : 
     291             936 : int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
     292                 :                               char ** papszLimitedFileList )
     293                 : 
     294                 : {
     295                 :     VSIStatBufL     stat;
     296             936 :     char            **papszFileList = NULL;
     297                 :     int             i;
     298                 : 
     299             936 :     pszName = CPLStrdup( pszFilename );
     300                 : 
     301                 : /* -------------------------------------------------------------------- */
     302                 : /*      Is the given path a directory or a regular file?                */
     303                 : /* -------------------------------------------------------------------- */
     304             936 :     if( VSIStatExL( pszFilename, &stat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0
     305                 :         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     306                 :     {
     307             205 :         if( !bTestOpen )
     308                 :             CPLError( CE_Failure, CPLE_AppDefined,
     309                 :                    "%s is neither a file or directory, Tiger access failed.\n",
     310               0 :                       pszFilename );
     311                 : 
     312             205 :         return FALSE;
     313                 :     }
     314                 :     
     315                 : /* -------------------------------------------------------------------- */
     316                 : /*      Build a list of filenames we figure are Tiger files.            */
     317                 : /* -------------------------------------------------------------------- */
     318             731 :     if( VSI_ISREG(stat.st_mode) )
     319                 :     {
     320                 :         char       szModule[128];
     321                 : 
     322             697 :         pszPath = CPLStrdup( CPLGetPath(pszFilename) );
     323                 : 
     324             697 :         strncpy( szModule, CPLGetFilename(pszFilename), sizeof(szModule)-1 );
     325                 :         /* Make sure the buffer is 0 terminated */
     326             697 :         szModule[sizeof(szModule)-1] = '\0';
     327                 : 
     328                 :         /* And now remove last character of filename */
     329             697 :         szModule[strlen(szModule)-1] = '\0';
     330                 : 
     331             697 :         papszFileList = CSLAddString( papszFileList, szModule );
     332                 :     }
     333                 :     else
     334                 :     {
     335              34 :         char      **candidateFileList = CPLReadDir( pszFilename );
     336                 :         int         i;
     337                 : 
     338              34 :         pszPath = CPLStrdup( pszFilename );
     339                 : 
     340            3208 :         for( i = 0; 
     341            1604 :              candidateFileList != NULL && candidateFileList[i] != NULL; 
     342                 :              i++ ) 
     343                 :         {
     344            1570 :             int nCandidateLen = strlen(candidateFileList[i]);
     345                 : 
     346            1570 :             if( papszLimitedFileList != NULL 
     347                 :                 && CSLFindString(papszLimitedFileList,
     348               0 :                                  CPLGetBasename(candidateFileList[i])) == -1 )
     349                 :             {
     350               0 :                 continue;
     351                 :             }
     352                 : 
     353            5724 :             if( nCandidateLen > 4 
     354            2974 :                 && candidateFileList[i][nCandidateLen-4] == '.'
     355            1180 :                 && candidateFileList[i][nCandidateLen-1] == '1')
     356                 :             {
     357                 :                 char       szModule[128];
     358                 : 
     359               6 :                 strncpy( szModule, candidateFileList[i],
     360              12 :                          strlen(candidateFileList[i])-1 );
     361                 : 
     362               6 :                 szModule[strlen(candidateFileList[i])-1] = '\0';
     363                 : 
     364               6 :                 papszFileList = CSLAddString(papszFileList, szModule);
     365                 :             }
     366                 :         }
     367                 : 
     368              34 :         CSLDestroy( candidateFileList );
     369                 : 
     370              34 :         if( CSLCount(papszFileList) == 0 )
     371                 :         {
     372              28 :             if( !bTestOpen )
     373                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     374                 :                           "No candidate Tiger files (TGR*.RT1) found in\n"
     375                 :                           "directory: %s",
     376               0 :                           pszFilename );
     377                 : 
     378              28 :             return FALSE;
     379                 :         }
     380                 :     }
     381                 : 
     382                 : /* -------------------------------------------------------------------- */
     383                 : /*      Loop over all these files trying to open them.  In testopen     */
     384                 : /*      mode we first read the first 80 characters, to verify that      */
     385                 : /*      it looks like an Tiger file.  Note that we don't keep the file  */
     386                 : /*      open ... we don't want to occupy alot of file handles when      */
     387                 : /*      handling a whole directory.                                     */
     388                 : /* -------------------------------------------------------------------- */
     389             703 :     papszModules = NULL;
     390                 :     
     391            1406 :     for( i = 0; papszFileList[i] != NULL; i++ )
     392                 :     {
     393             703 :         if( bTestOpen || i == 0 )
     394                 :         {
     395                 :             char        szHeader[500];
     396                 :             VSILFILE    *fp;
     397             703 :             char        *pszRecStart = NULL;
     398             703 :             int         bIsGDT = FALSE;
     399                 :             char       *pszFilename;
     400                 : 
     401             703 :             pszFilename = BuildFilename( papszFileList[i], "1" );
     402                 : 
     403             703 :             fp = VSIFOpenL( pszFilename, "rb" );
     404             703 :             CPLFree( pszFilename );
     405                 : 
     406             703 :             if( fp == NULL )
     407             691 :                 continue;
     408                 :             
     409              12 :             if( VSIFReadL( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
     410                 :             {
     411               2 :                 VSIFCloseL( fp );
     412               2 :                 continue;
     413                 :             }
     414                 : 
     415              10 :             VSIFCloseL( fp );
     416                 : 
     417              10 :             pszRecStart = szHeader;
     418              10 :             szHeader[sizeof(szHeader)-1] = '\0';
     419                 : 
     420              10 :             if( EQUALN(pszRecStart,"Copyright (C)",13) 
     421                 :                 && strstr(pszRecStart,"Geographic Data Tech") != NULL )
     422                 :             {
     423               0 :                 bIsGDT = TRUE;
     424                 : 
     425               0 :                 while( *pszRecStart != '\0' 
     426                 :                        && *pszRecStart != 10 
     427                 :                        && *pszRecStart != 13 )
     428               0 :                     pszRecStart++;
     429                 : 
     430               0 :                 while( *pszRecStart == 10 || *pszRecStart == 13 )
     431               0 :                     pszRecStart++;
     432                 :             }
     433                 :             
     434              10 :             if( pszRecStart[0] != '1' )
     435               1 :                 continue;
     436                 : 
     437              27 :             if( !isdigit(pszRecStart[1]) || !isdigit(pszRecStart[2])
     438              18 :                 || !isdigit(pszRecStart[3]) || !isdigit(pszRecStart[4]) )
     439               0 :                 continue;
     440                 : 
     441               9 :             nVersionCode = atoi(TigerFileBase::GetField( pszRecStart, 2, 5 ));
     442               9 :             nVersion = TigerClassifyVersion( nVersionCode );
     443               9 :             nVersion = TigerCheckVersion( nVersion, papszFileList[i] );
     444                 : 
     445                 :             CPLDebug( "OGR", "Tiger Version Code=%d, Classified as %s ", 
     446               9 :                       nVersionCode, TigerVersionString(nVersion) );
     447                 : 
     448              27 :             if(    nVersionCode !=  0
     449                 :                 && nVersionCode !=  2
     450                 :                 && nVersionCode !=  3
     451                 :                 && nVersionCode !=  5
     452                 :                 && nVersionCode != 21 
     453                 :                 && nVersionCode != 24
     454               9 :                 && pszRecStart[3]  != '9'
     455               9 :                 && pszRecStart[3]  != '0'
     456                 :                 && !bIsGDT )
     457               0 :                 continue;
     458                 : 
     459                 :             // we could (and should) add a bunch more validation here.
     460                 :         }
     461                 : 
     462               9 :         papszModules = CSLAddString( papszModules, papszFileList[i] );
     463                 :     }
     464                 : 
     465             703 :     CSLDestroy( papszFileList );
     466                 : 
     467             703 :     nModules = CSLCount( papszModules );
     468                 : 
     469             703 :     if( nModules == 0 )
     470                 :     {
     471             694 :         if( !bTestOpen )
     472                 :         {
     473               0 :             if( VSI_ISREG(stat.st_mode) )
     474                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     475                 :                           "No TIGER/Line files (TGR*.RT1) found in\n"
     476                 :                           "directory: %s",
     477               0 :                           pszFilename );
     478                 :             else
     479                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     480                 :                           "File %s does not appear to be a TIGER/Line .RT1 file.",
     481               0 :                           pszFilename );
     482                 :         }
     483                 : 
     484             694 :         return FALSE;
     485                 :     }
     486                 : 
     487                 : /* -------------------------------------------------------------------- */
     488                 : /*      Do we have a user provided version override?                    */
     489                 : /* -------------------------------------------------------------------- */
     490               9 :     if( CPLGetConfigOption( "TIGER_VERSION", NULL ) != NULL )
     491                 :     {
     492                 :         const char *pszRequestedVersion = 
     493               0 :             CPLGetConfigOption( "TIGER_VERSION", NULL );
     494                 : 
     495               0 :         if( EQUALN(pszRequestedVersion,"TIGER_",6) )
     496                 :         {
     497                 :             int iCode;
     498                 : 
     499               0 :             for( iCode = 1; iCode < TIGER_Unknown; iCode++ )
     500                 :             {
     501               0 :                 if( EQUAL(TigerVersionString((TigerVersion)iCode),
     502                 :                           pszRequestedVersion) )
     503                 :                 {
     504               0 :                     nVersion = (TigerVersion) iCode;
     505               0 :                     break;
     506                 :                 }
     507                 :             }
     508                 : 
     509               0 :             if( iCode == TIGER_Unknown )
     510                 :             {
     511                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     512                 :                           "Failed to recognise TIGER_VERSION setting: %s", 
     513               0 :                           pszRequestedVersion );
     514               0 :                 return FALSE;
     515                 :             }                          
     516                 : 
     517                 :             CPLDebug( "OGR", "OVERRIDE Tiger Version %s ", 
     518               0 :                       TigerVersionString(nVersion) );
     519                 :         }
     520                 :         else
     521                 :         {
     522               0 :             nVersionCode = atoi(pszRequestedVersion);
     523               0 :             nVersion = TigerClassifyVersion( nVersionCode );
     524                 : 
     525                 :             CPLDebug( "OGR", 
     526                 :                       "OVERRIDE Tiger Version Code=%d, Classified as %s ", 
     527               0 :                       nVersionCode, TigerVersionString(nVersion) );
     528                 :         }
     529                 :     }
     530                 : 
     531                 : /* -------------------------------------------------------------------- */
     532                 : /*      Create the layers which appear to exist.                        */
     533                 : /* -------------------------------------------------------------------- */
     534                 :     // RT1, RT2, RT3
     535                 :     AddLayer( new OGRTigerLayer( this,
     536                 :                                  new TigerCompleteChain( this,
     537               9 :                                                          papszModules[0]) ));
     538                 : 
     539                 :     /* should we have kept track of whether we encountered an RT4 file? */
     540                 :     // RT4
     541                 :     AddLayer( new OGRTigerLayer( this,
     542                 :                                  new TigerAltName( this,
     543              18 :                                                    papszModules[0]) ));
     544                 : 
     545                 :     // RT5
     546                 :     AddLayer( new OGRTigerLayer( this,
     547                 :                                  new TigerFeatureIds( this,
     548              18 :                                                       papszModules[0]) ));
     549                 : 
     550                 :     // RT6
     551                 :     AddLayer( new OGRTigerLayer( this,
     552                 :                                  new TigerZipCodes( this,
     553              18 :                                                     papszModules[0]) ));
     554                 :     // RT7
     555                 :     AddLayer( new OGRTigerLayer( this,
     556                 :                                  new TigerLandmarks( this,
     557              18 :                                                      papszModules[0]) ));
     558                 :     
     559                 :     // RT8
     560                 :     AddLayer( new OGRTigerLayer( this,
     561                 :                                  new TigerAreaLandmarks( this,
     562              18 :                                                      papszModules[0]) ));
     563                 : 
     564                 :     // RT9
     565               9 :     if (nVersion < TIGER_2002) {
     566                 :       AddLayer( new OGRTigerLayer( this,
     567                 :                                    new TigerKeyFeatures( this,
     568               0 :                                                          papszModules[0]) ));
     569                 :     }
     570                 :     
     571                 :     // RTA, RTS
     572                 :     AddLayer( new OGRTigerLayer( this,
     573                 :                                  new TigerPolygon( this,
     574               9 :                                                    papszModules[0]) ));
     575                 : 
     576                 :     // RTB
     577               9 :     if (nVersion >= TIGER_2002) {
     578                 :       AddLayer( new OGRTigerLayer( this,
     579                 :                                    new TigerPolygonCorrections( this,
     580               9 :                                                                 papszModules[0]) ));
     581                 :     }
     582                 :     
     583                 :     // RTC
     584                 :     AddLayer( new OGRTigerLayer( this,
     585                 :                                  new TigerEntityNames( this,
     586               9 :                                                        papszModules[0]) ));
     587                 : 
     588                 :     // RTE
     589               9 :     if (nVersion >= TIGER_2002) {
     590                 :       AddLayer( new OGRTigerLayer( this,
     591                 :                                    new TigerPolygonEconomic( this,
     592               9 :                                                              papszModules[0]) ));
     593                 :     }
     594                 : 
     595                 :     // RTH
     596                 :     AddLayer( new OGRTigerLayer( this,
     597                 :                                  new TigerIDHistory( this,
     598               9 :                                                      papszModules[0]) ));
     599                 :     
     600                 :     // RTI
     601                 :     AddLayer( new OGRTigerLayer( this,
     602                 :                                  new TigerPolyChainLink( this,
     603              18 :                                                        papszModules[0]) ));
     604                 :     
     605                 :     // RTM
     606                 :     AddLayer( new OGRTigerLayer( this,
     607                 :                                  new TigerSpatialMetadata( this,
     608              18 :                                                            papszModules[0] ) ) );
     609                 :     
     610                 :     // RTP
     611                 :     AddLayer( new OGRTigerLayer( this,
     612                 :                                  new TigerPIP( this,
     613              18 :                                                papszModules[0]) ));
     614                 :     
     615                 :     // RTR
     616                 :     AddLayer( new OGRTigerLayer( this,
     617                 :                                  new TigerTLIDRange( this,
     618              18 :                                                      papszModules[0]) ));
     619                 :     
     620                 :     // RTT
     621               9 :     if (nVersion >= TIGER_2002) {
     622                 :       AddLayer( new OGRTigerLayer( this,
     623                 :                                    new TigerZeroCellID( this,
     624               9 :                                                         papszModules[0]) ));
     625                 :     }
     626                 : 
     627                 :     // RTU
     628               9 :     if (nVersion >= TIGER_2002) {
     629                 :       AddLayer( new OGRTigerLayer( this,
     630                 :                                    new TigerOverUnder( this,
     631               9 :                                                        papszModules[0]) ));
     632                 :     }
     633                 : 
     634                 :     // RTZ
     635                 :     AddLayer( new OGRTigerLayer( this,
     636                 :                                  new TigerZipPlus4( this,
     637               9 :                                                      papszModules[0]) ));
     638                 :     
     639               9 :     return TRUE;
     640                 : }
     641                 : 
     642                 : /************************************************************************/
     643                 : /*                             SetOptions()                             */
     644                 : /************************************************************************/
     645                 : 
     646               1 : void OGRTigerDataSource::SetOptionList( char ** papszNewOptions )
     647                 : 
     648                 : {
     649               1 :     CSLDestroy( papszOptions );
     650               1 :     papszOptions = CSLDuplicate( papszNewOptions );
     651               1 : }
     652                 : 
     653                 : /************************************************************************/
     654                 : /*                             GetOption()                              */
     655                 : /************************************************************************/
     656                 : 
     657               2 : const char *OGRTigerDataSource::GetOption( const char * pszOption )
     658                 : 
     659                 : {
     660               2 :     return CSLFetchNameValue( papszOptions, pszOption );
     661                 : }
     662                 : 
     663                 : /************************************************************************/
     664                 : /*                             GetModule()                              */
     665                 : /************************************************************************/
     666                 : 
     667             381 : const char *OGRTigerDataSource::GetModule( int iModule )
     668                 : 
     669                 : {
     670             381 :     if( iModule < 0 || iModule >= nModules )
     671               0 :         return NULL;
     672                 :     else
     673             381 :         return papszModules[iModule];
     674                 : }
     675                 : 
     676                 : /************************************************************************/
     677                 : /*                            CheckModule()                             */
     678                 : /*                                                                      */
     679                 : /*      This is used by the writer to check if this module has been     */
     680                 : /*      written to before.                                              */
     681                 : /************************************************************************/
     682                 : 
     683              17 : int OGRTigerDataSource::CheckModule( const char *pszModule )
     684                 : 
     685                 : {
     686                 :     int         i;
     687                 : 
     688              17 :     for( i = 0; i < nModules; i++ )
     689                 :     {
     690              15 :         if( EQUAL(pszModule,papszModules[i]) )
     691              15 :             return TRUE;
     692                 :     }
     693               2 :     return FALSE;
     694                 : }
     695                 : 
     696                 : /************************************************************************/
     697                 : /*                             AddModule()                              */
     698                 : /************************************************************************/
     699                 : 
     700               1 : void OGRTigerDataSource::AddModule( const char *pszModule )
     701                 : 
     702                 : {
     703               1 :     if( CheckModule( pszModule ) )
     704               0 :         return;
     705                 : 
     706               1 :     papszModules = CSLAddString( papszModules, pszModule );
     707               1 :     nModules++;
     708                 : }
     709                 : 
     710                 : /************************************************************************/
     711                 : /*                           BuildFilename()                            */
     712                 : /************************************************************************/
     713                 : 
     714           24885 : char *OGRTigerDataSource::BuildFilename( const char *pszModuleName,
     715                 :                                     const char *pszExtension )
     716                 : 
     717                 : {
     718                 :     char        *pszFilename;
     719                 :     char        szLCExtension[3];
     720                 : 
     721                 : /* -------------------------------------------------------------------- */
     722                 : /*      Force the record type to lower case if the filename appears     */
     723                 : /*      to be in lower case.                                            */
     724                 : /* -------------------------------------------------------------------- */
     725           24885 :     if( *pszExtension >= 'A' && *pszExtension <= 'Z' && *pszModuleName == 't' )
     726                 :     {
     727               0 :         szLCExtension[0] = (*pszExtension) + 'a' - 'A';
     728               0 :         szLCExtension[1] = '\0';
     729               0 :         pszExtension = szLCExtension;
     730                 :     }
     731                 : 
     732                 : /* -------------------------------------------------------------------- */
     733                 : /*      Build the filename.                                             */
     734                 : /* -------------------------------------------------------------------- */
     735                 :     pszFilename = (char *) CPLMalloc(strlen(GetDirPath())
     736                 :                                      + strlen(pszModuleName)
     737           24885 :                                      + strlen(pszExtension) + 10);
     738                 : 
     739           24885 :     if( strlen(GetDirPath()) == 0 )
     740                 :         sprintf( pszFilename, "%s%s",
     741               0 :                  pszModuleName, pszExtension );
     742                 :     else
     743                 :         sprintf( pszFilename, "%s/%s%s",
     744           24885 :                  GetDirPath(), pszModuleName, pszExtension );
     745                 : 
     746           24885 :     return pszFilename;
     747                 : }
     748                 : 
     749                 : /************************************************************************/
     750                 : /*                           TestCapability()                           */
     751                 : /************************************************************************/
     752                 : 
     753              19 : int OGRTigerDataSource::TestCapability( const char *pszCap )
     754                 : 
     755                 : {
     756              19 :     if( EQUAL(pszCap,ODsCCreateLayer) )
     757              18 :         return GetWriteMode();
     758                 :     else
     759               1 :         return FALSE;
     760                 : }
     761                 : 
     762                 : /************************************************************************/
     763                 : /*                               Create()                               */
     764                 : /************************************************************************/
     765                 : 
     766               1 : int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptions )
     767                 : 
     768                 : {
     769                 :     VSIStatBufL      stat;
     770                 :     
     771                 : /* -------------------------------------------------------------------- */
     772                 : /*      Try to create directory if it doesn't already exist.            */
     773                 : /* -------------------------------------------------------------------- */
     774               1 :     if( VSIStatL( pszNameIn, &stat ) != 0 )
     775                 :     {
     776               0 :         VSIMkdir( pszNameIn, 0755 );
     777                 :     }
     778                 : 
     779               1 :     if( VSIStatL( pszNameIn, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
     780                 :     {
     781                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     782                 :                   "%s is not a directory, nor can be directly created as one.",
     783               0 :                   pszName );
     784               0 :         return FALSE;
     785                 :     }
     786                 : 
     787                 : /* -------------------------------------------------------------------- */
     788                 : /*      Store various information.                                      */
     789                 : /* -------------------------------------------------------------------- */
     790               1 :     pszPath = CPLStrdup( pszNameIn );
     791               1 :     pszName = CPLStrdup( pszNameIn );
     792               1 :     bWriteMode = TRUE;
     793                 : 
     794               1 :     SetOptionList( papszOptions );
     795                 : 
     796                 : /* -------------------------------------------------------------------- */
     797                 : /*      Work out the version.                                           */
     798                 : /* -------------------------------------------------------------------- */
     799                 : //    nVersionCode = 1000; /* census 2000 */
     800                 : 
     801               1 :     nVersionCode = 1002; /* census 2002 */
     802               1 :     if( GetOption("VERSION") != NULL )
     803                 :     {
     804               1 :         nVersionCode = atoi(GetOption("VERSION"));
     805               1 :         nVersionCode = MAX(0,MIN(9999,nVersionCode));
     806                 :     }
     807               1 :     nVersion = TigerClassifyVersion(nVersionCode);
     808                 : 
     809               1 :     return TRUE;
     810                 : }
     811                 : 
     812                 : /************************************************************************/
     813                 : /*                            CreateLayer()                             */
     814                 : /************************************************************************/
     815                 : 
     816              18 : OGRLayer *OGRTigerDataSource::CreateLayer( const char *pszLayerName, 
     817                 :                                            OGRSpatialReference *poSpatRef, 
     818                 :                                            OGRwkbGeometryType eGType, 
     819                 :                                            char **papszOptions )
     820                 : 
     821                 : {
     822              18 :     OGRTigerLayer       *poLayer = NULL;
     823                 : 
     824              18 :     if( GetLayer( pszLayerName ) != NULL )
     825               0 :         return GetLayer( pszLayerName );
     826                 : 
     827              18 :     if( poSpatRef != NULL && 
     828                 :         (!poSpatRef->IsGeographic() 
     829                 :          || !EQUAL(poSpatRef->GetAttrValue("DATUM"),
     830                 :                    "North_American_Datum_1983")) )
     831                 :     {
     832                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     833                 :                   "Requested coordinate system wrong for Tiger, " 
     834               0 :                   "forcing to GEOGCS NAD83." );
     835                 :     }
     836                 : 
     837              18 :     if( EQUAL(pszLayerName,"PIP") )
     838                 :     {
     839                 :         poLayer = new OGRTigerLayer( this,
     840               1 :                                      new TigerPIP( this, NULL ) );
     841                 :     }
     842              17 :     else if( EQUAL(pszLayerName,"ZipPlus4") )
     843                 :     {
     844                 :         poLayer = new OGRTigerLayer( this,
     845               1 :                                      new TigerZipPlus4( this, NULL ) );
     846                 :     }
     847              16 :     else if( EQUAL(pszLayerName,"TLIDRange") )
     848                 :     {
     849                 :         poLayer = new OGRTigerLayer( this,
     850               1 :                                      new TigerTLIDRange( this, NULL ) );
     851                 :     }
     852              15 :     else if( EQUAL(pszLayerName,"PolyChainLink") )
     853                 :     {
     854                 :         poLayer = new OGRTigerLayer( this,
     855               1 :                                      new TigerPolyChainLink( this, NULL ) );
     856                 :     }
     857              14 :     else if( EQUAL(pszLayerName,"CompleteChain") )
     858                 :     {
     859                 :         poLayer = new OGRTigerLayer( this,
     860               1 :                                      new TigerCompleteChain( this, NULL ) );
     861                 :     }
     862              13 :     else if( EQUAL(pszLayerName,"AltName") )
     863                 :     {
     864                 :         poLayer = new OGRTigerLayer( this,
     865               1 :                                      new TigerAltName( this, NULL ) );
     866                 :     }
     867              12 :     else if( EQUAL(pszLayerName,"FeatureIds") )
     868                 :     {
     869                 :         poLayer = new OGRTigerLayer( this,
     870               1 :                                      new TigerFeatureIds( this, NULL ) );
     871                 :     }
     872              11 :     else if( EQUAL(pszLayerName,"ZipCodes") )
     873                 :     {
     874                 :         poLayer = new OGRTigerLayer( this,
     875               1 :                                      new TigerZipCodes( this, NULL ) );
     876                 :     }
     877              10 :     else if( EQUAL(pszLayerName,"Landmarks") )
     878                 :     {
     879                 :         poLayer = new OGRTigerLayer( this,
     880               1 :                                      new TigerLandmarks( this, NULL ) );
     881                 :     }
     882               9 :     else if( EQUAL(pszLayerName,"AreaLandmarks") )
     883                 :     {
     884                 :         poLayer = new OGRTigerLayer( this,
     885               1 :                                      new TigerAreaLandmarks( this, NULL ) );
     886                 :     }
     887               8 :     else if( EQUAL(pszLayerName,"KeyFeatures") )
     888                 :     {
     889                 :         poLayer = new OGRTigerLayer( this,
     890               0 :                                      new TigerKeyFeatures( this, NULL ) );
     891                 :     }
     892               8 :     else if( EQUAL(pszLayerName,"EntityNames") )
     893                 :     {
     894                 :         poLayer = new OGRTigerLayer( this,
     895               1 :                                      new TigerEntityNames( this, NULL ) );
     896                 :     }
     897               7 :     else if( EQUAL(pszLayerName,"IDHistory") )
     898                 :     {
     899                 :         poLayer = new OGRTigerLayer( this,
     900               1 :                                      new TigerIDHistory( this, NULL ) );
     901                 :     }
     902               6 :     else if( EQUAL(pszLayerName,"Polygon") )
     903                 :     {
     904                 :         poLayer = new OGRTigerLayer( this,
     905               1 :                                      new TigerPolygon( this, NULL ) );
     906                 :     }
     907                 : 
     908               5 :     else if( EQUAL(pszLayerName,"PolygonCorrections") )
     909                 :     {
     910                 :         poLayer = new OGRTigerLayer( this,
     911               1 :                                      new TigerPolygonCorrections( this, NULL ) );
     912                 :     }
     913                 : 
     914               4 :     else if( EQUAL(pszLayerName,"PolygonEconomic") )
     915                 :     {
     916                 :         poLayer = new OGRTigerLayer( this,
     917               1 :                                      new TigerPolygonEconomic( this, NULL ) );
     918                 :     }
     919                 : 
     920               3 :     else if( EQUAL(pszLayerName,"SpatialMetadata") )
     921                 :     {
     922                 :         poLayer = new OGRTigerLayer( this,
     923               1 :                                      new TigerSpatialMetadata( this, NULL ) );
     924                 :     }
     925                 : 
     926               2 :     else if( EQUAL(pszLayerName,"ZeroCellID") )
     927                 :     {
     928                 :         poLayer = new OGRTigerLayer( this,
     929               1 :                                      new TigerZeroCellID( this, NULL ) );
     930                 :     }
     931                 : 
     932               1 :     else if( EQUAL(pszLayerName,"OverUnder") )
     933                 :     {
     934                 :         poLayer = new OGRTigerLayer( this,
     935               1 :                                      new TigerOverUnder( this, NULL ) );
     936                 :     }
     937                 : 
     938              18 :     if( poLayer == NULL )
     939                 :     {
     940                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     941                 :                   "Unable to create layer %s, not a known TIGER/Line layer.",
     942               0 :                   pszLayerName );
     943                 :     }
     944                 :     else
     945              18 :         AddLayer( poLayer );
     946                 : 
     947              18 :     return poLayer;
     948                 : }
     949                 : 
     950                 : /************************************************************************/
     951                 : /*                         DeleteModuleFiles()                          */
     952                 : /************************************************************************/
     953                 : 
     954               1 : void OGRTigerDataSource::DeleteModuleFiles( const char *pszModule )
     955                 : 
     956                 : {
     957               1 :     char        **papszDirFiles = CPLReadDir( GetDirPath() );
     958               1 :     int         i, nCount = CSLCount(papszDirFiles);
     959                 :     
     960              21 :     for( i = 0; i < nCount; i++ )
     961                 :     {
     962              20 :         if( EQUALN(pszModule,papszDirFiles[i],strlen(pszModule)) )
     963                 :         {
     964                 :             const char  *pszFilename;
     965                 : 
     966                 :             pszFilename = CPLFormFilename( GetDirPath(), 
     967              18 :                                            papszDirFiles[i], 
     968              36 :                                            NULL );
     969              18 :             if( VSIUnlink( pszFilename ) != 0 )
     970                 :             {
     971               0 :                 CPLDebug( "OGR_TIGER", "Failed to unlink %s", pszFilename );
     972                 :             }
     973                 :         }
     974                 :     }
     975                 : 
     976               1 :     CSLDestroy( papszDirFiles );
     977               1 : }

Generated by: LCOV version 1.7