LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/tiger - ogrtigerdatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 331 253 76.4 %
Date: 2011-12-18 Functions: 23 20 87.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrtigerdatasource.cpp 22622 2011-06-29 21:33:28Z 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 22622 2011-06-29 21:33:28Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                        TigerClassifyVersion()                        */
      39                 : /************************************************************************/
      40                 : 
      41             286 : 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             286 :     nVersion = TIGER_Unknown;
      72             286 :     if( nVersionCode == 0 )
      73               0 :         nVersion = TIGER_1990_Precensus;
      74             286 :     else if( nVersionCode == 2 )
      75               0 :         nVersion = TIGER_1990;
      76             286 :     else if( nVersionCode == 3 )
      77               0 :         nVersion = TIGER_1992;
      78             286 :     else if( nVersionCode == 5 )
      79               0 :         nVersion = TIGER_1994;
      80             286 :     else if( nVersionCode == 21 )
      81               0 :         nVersion = TIGER_1994;
      82             286 :     else if( nVersionCode == 24 )
      83               0 :         nVersion = TIGER_1995;
      84                 : 
      85             286 :     else if( nVersionCode == 9999 )  /* special hack, fme bug 7625 */
      86               0 :         nVersion = TIGER_UA2000;
      87                 : 
      88             286 :     nYear = nVersionCode % 100;
      89             286 :     nMonth = nVersionCode / 100;
      90                 : 
      91             286 :     nVersionCode = nYear * 100 + nMonth;
      92                 : 
      93             286 :     if( nVersion != TIGER_Unknown )
      94                 :         /* do nothing */;
      95             286 :     else if( nVersionCode >= 9706 && nVersionCode <= 9810 )
      96               0 :         nVersion = TIGER_1997;
      97             286 :     else if( nVersionCode >= 9812 && nVersionCode <= 9904 )
      98               0 :         nVersion = TIGER_1998;
      99             286 :     else if( nVersionCode >=    6 /*0006*/ && nVersionCode <=    8 /*0008*/ )
     100               0 :         nVersion = TIGER_1999;
     101             286 :     else if( nVersionCode >=   10 /*0010*/ && nVersionCode <=   11 /*0011*/ )
     102               0 :         nVersion = TIGER_2000_Redistricting;
     103             286 :     else if( nVersionCode >=  103 /*0103*/ && nVersionCode <= 108 /*0108*/ )
     104               0 :         nVersion = TIGER_2000_Census;
     105             286 :     else if( nVersionCode >=  203 /*0302*/ && nVersionCode <= 205 /*0502*/ )
     106               0 :         nVersion = TIGER_UA2000;
     107             286 :     else if( nVersionCode >=  210 /*1002*/ && nVersionCode <= 306 /*0603*/)
     108               0 :         nVersion = TIGER_2002;
     109             286 :     else if( nVersionCode >=  312 /*1203*/ && nVersionCode <= 403 /*0304*/)
     110               0 :         nVersion = TIGER_2003;
     111             286 :     else if( nVersionCode >=  404 )
     112             286 :         nVersion = TIGER_2004;
     113                 : 
     114             286 :     return nVersion;
     115                 : }
     116                 : 
     117                 : /************************************************************************/
     118                 : /*                         TigerVersionString()                         */
     119                 : /************************************************************************/
     120                 : 
     121               6 : const char * TigerVersionString( TigerVersion nVersion )
     122                 : {
     123                 : 
     124               6 :   if (nVersion == TIGER_1990_Precensus) { return "TIGER_1990_Precensus"; }
     125               6 :   if (nVersion == TIGER_1990) { return "TIGER_1990"; }
     126               6 :   if (nVersion == TIGER_1992) { return "TIGER_1992"; }
     127               6 :   if (nVersion == TIGER_1994) { return "TIGER_1994"; }
     128               6 :   if (nVersion == TIGER_1995) { return "TIGER_1995"; }
     129               6 :   if (nVersion == TIGER_1997) { return "TIGER_1997"; }
     130               6 :   if (nVersion == TIGER_1998) { return "TIGER_1998"; }
     131               6 :   if (nVersion == TIGER_1999) { return "TIGER_1999"; }
     132               6 :   if (nVersion == TIGER_2000_Redistricting) { return "TIGER_2000_Redistricting"; }
     133               6 :   if (nVersion == TIGER_UA2000) { return "TIGER_UA2000"; }
     134               6 :   if (nVersion == TIGER_2002) { return "TIGER_2002"; }
     135               6 :   if (nVersion == TIGER_2003) { return "TIGER_2003"; }
     136               6 :   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               6 : TigerVersion OGRTigerDataSource::TigerCheckVersion( TigerVersion nOldVersion, 
     152                 :                                                     const char *pszFilename )
     153                 : 
     154                 : {
     155               6 :     if( nOldVersion != TIGER_2002 )
     156               6 :         return nOldVersion;
     157                 : 
     158               0 :     char *pszRTCFilename = BuildFilename( pszFilename, "C" );
     159               0 :     FILE *fp = VSIFOpen( 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( VSIFRead( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
     168                 :     {
     169               0 :         VSIFClose( fp );
     170               0 :         return nOldVersion;
     171                 :     }
     172                 : 
     173               0 :     VSIFClose( 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             670 : OGRTigerDataSource::OGRTigerDataSource()
     193                 : 
     194                 : {
     195             670 :     bWriteMode = FALSE;
     196                 : 
     197             670 :     nLayers = 0;
     198             670 :     papoLayers = NULL;
     199                 : 
     200             670 :     nModules = 0;
     201             670 :     papszModules = NULL;
     202                 : 
     203             670 :     pszName = NULL;
     204             670 :     pszPath = NULL;
     205                 : 
     206             670 :     papszOptions = NULL;
     207                 : 
     208             670 :     poSpatialRef = new OGRSpatialReference( "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]" );
     209             670 : }
     210                 : 
     211                 : /************************************************************************/
     212                 : /*                        ~OGRTigerDataSource()                         */
     213                 : /************************************************************************/
     214                 : 
     215             670 : OGRTigerDataSource::~OGRTigerDataSource()
     216                 : 
     217                 : {
     218                 :     int         i;
     219                 : 
     220             796 :     for( i = 0; i < nLayers; i++ )
     221             126 :         delete papoLayers[i];
     222                 :     
     223             670 :     CPLFree( papoLayers );
     224                 : 
     225             670 :     CPLFree( pszName );
     226             670 :     CPLFree( pszPath );
     227                 : 
     228             670 :     CSLDestroy( papszOptions );
     229                 : 
     230             670 :     CSLDestroy( papszModules );
     231                 : 
     232             670 :     delete poSpatialRef;
     233             670 : }
     234                 : 
     235                 : /************************************************************************/
     236                 : /*                              AddLayer()                              */
     237                 : /************************************************************************/
     238                 : 
     239             126 : void OGRTigerDataSource::AddLayer( OGRTigerLayer * poNewLayer )
     240                 : 
     241                 : {
     242                 :     papoLayers = (OGRTigerLayer **)
     243             126 :         CPLRealloc( papoLayers, sizeof(void*) * ++nLayers );
     244                 :     
     245             126 :     papoLayers[nLayers-1] = poNewLayer;
     246             126 : }
     247                 : 
     248                 : /************************************************************************/
     249                 : /*                              GetLayer()                              */
     250                 : /************************************************************************/
     251                 : 
     252             861 : OGRLayer *OGRTigerDataSource::GetLayer( int iLayer )
     253                 : 
     254                 : {
     255             861 :     if( iLayer < 0 || iLayer >= nLayers )
     256               0 :         return NULL;
     257                 :     else
     258             861 :         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             876 : int OGRTigerDataSource::GetLayerCount()
     282                 : 
     283                 : {
     284             876 :     return nLayers;
     285                 : }
     286                 : 
     287                 : /************************************************************************/
     288                 : /*                                Open()                                */
     289                 : /************************************************************************/
     290                 : 
     291             669 : int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
     292                 :                               char ** papszLimitedFileList )
     293                 : 
     294                 : {
     295                 :     VSIStatBuf      stat;
     296             669 :     char            **papszFileList = NULL;
     297                 :     int             i;
     298                 : 
     299             669 :     pszName = CPLStrdup( pszFilename );
     300                 : 
     301                 : /* -------------------------------------------------------------------- */
     302                 : /*      Is the given path a directory or a regular file?                */
     303                 : /* -------------------------------------------------------------------- */
     304             669 :     if( CPLStat( pszFilename, &stat ) != 0 
     305                 :         || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) )
     306                 :     {
     307             248 :         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             248 :         return FALSE;
     313                 :     }
     314                 :     
     315                 : /* -------------------------------------------------------------------- */
     316                 : /*      Build a list of filenames we figure are Tiger files.            */
     317                 : /* -------------------------------------------------------------------- */
     318             421 :     if( VSI_ISREG(stat.st_mode) )
     319                 :     {
     320                 :         char       szModule[128];
     321                 : 
     322             400 :         pszPath = CPLStrdup( CPLGetPath(pszFilename) );
     323                 : 
     324             400 :         strncpy( szModule, CPLGetFilename(pszFilename), sizeof(szModule)-1 );
     325             400 :         szModule[sizeof(szModule)-1] = '\0';
     326                 : 
     327             400 :         papszFileList = CSLAddString( papszFileList, szModule );
     328                 :     }
     329                 :     else
     330                 :     {
     331              21 :         char      **candidateFileList = CPLReadDir( pszFilename );
     332                 :         int         i;
     333                 : 
     334              21 :         pszPath = CPLStrdup( pszFilename );
     335                 : 
     336            1542 :         for( i = 0; 
     337             771 :              candidateFileList != NULL && candidateFileList[i] != NULL; 
     338                 :              i++ ) 
     339                 :         {
     340             750 :             int nCandidateLen = strlen(candidateFileList[i]);
     341                 : 
     342             750 :             if( papszLimitedFileList != NULL 
     343                 :                 && CSLFindString(papszLimitedFileList,
     344               0 :                                  CPLGetBasename(candidateFileList[i])) == -1 )
     345                 :             {
     346               0 :                 continue;
     347                 :             }
     348                 : 
     349            2818 :             if( nCandidateLen > 4 
     350            1398 :                 && candidateFileList[i][nCandidateLen-4] == '.'
     351             670 :                 && candidateFileList[i][nCandidateLen-1] == '1')
     352                 :             {
     353                 :                 char       szModule[128];
     354                 : 
     355               6 :                 strncpy( szModule, candidateFileList[i],
     356              12 :                          strlen(candidateFileList[i])-1 );
     357                 : 
     358               6 :                 szModule[strlen(candidateFileList[i])-1] = '\0';
     359                 : 
     360               6 :                 papszFileList = CSLAddString(papszFileList, szModule);
     361                 :             }
     362                 :         }
     363                 : 
     364              21 :         CSLDestroy( candidateFileList );
     365                 : 
     366              21 :         if( CSLCount(papszFileList) == 0 )
     367                 :         {
     368              15 :             if( !bTestOpen )
     369                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     370                 :                           "No candidate Tiger files (TGR*.RT1) found in\n"
     371                 :                           "directory: %s",
     372               0 :                           pszFilename );
     373                 : 
     374              15 :             return FALSE;
     375                 :         }
     376                 :     }
     377                 : 
     378                 : /* -------------------------------------------------------------------- */
     379                 : /*      Loop over all these files trying to open them.  In testopen     */
     380                 : /*      mode we first read the first 80 characters, to verify that      */
     381                 : /*      it looks like an Tiger file.  Note that we don't keep the file  */
     382                 : /*      open ... we don't want to occupy alot of file handles when      */
     383                 : /*      handling a whole directory.                                     */
     384                 : /* -------------------------------------------------------------------- */
     385             406 :     papszModules = NULL;
     386                 :     
     387             812 :     for( i = 0; papszFileList[i] != NULL; i++ )
     388                 :     {
     389             406 :         if( bTestOpen || i == 0 )
     390                 :         {
     391                 :             char        szHeader[500];
     392                 :             FILE        *fp;
     393             406 :             char        *pszRecStart = NULL;
     394             406 :             int         bIsGDT = FALSE;
     395                 :             char       *pszFilename;
     396                 : 
     397             406 :             pszFilename = BuildFilename( papszFileList[i], "1" );
     398                 : 
     399             406 :             fp = VSIFOpen( pszFilename, "rb" );
     400             406 :             CPLFree( pszFilename );
     401                 : 
     402             406 :             if( fp == NULL )
     403             400 :                 continue;
     404                 :             
     405               6 :             if( VSIFRead( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
     406                 :             {
     407               0 :                 VSIFClose( fp );
     408               0 :                 continue;
     409                 :             }
     410                 : 
     411               6 :             VSIFClose( fp );
     412                 : 
     413               6 :             pszRecStart = szHeader;
     414               6 :             szHeader[sizeof(szHeader)-1] = '\0';
     415                 : 
     416               6 :             if( EQUALN(pszRecStart,"Copyright (C)",13) 
     417                 :                 && strstr(pszRecStart,"Geographic Data Tech") != NULL )
     418                 :             {
     419               0 :                 bIsGDT = TRUE;
     420                 : 
     421               0 :                 while( *pszRecStart != '\0' 
     422                 :                        && *pszRecStart != 10 
     423                 :                        && *pszRecStart != 13 )
     424               0 :                     pszRecStart++;
     425                 : 
     426               0 :                 while( *pszRecStart == 10 || *pszRecStart == 13 )
     427               0 :                     pszRecStart++;
     428                 :             }
     429                 :             
     430               6 :             if( pszRecStart[0] != '1' )
     431               0 :                 continue;
     432                 : 
     433              18 :             if( !isdigit(pszRecStart[1]) || !isdigit(pszRecStart[2])
     434              12 :                 || !isdigit(pszRecStart[3]) || !isdigit(pszRecStart[4]) )
     435               0 :                 continue;
     436                 : 
     437               6 :             nVersionCode = atoi(TigerFileBase::GetField( pszRecStart, 2, 5 ));
     438               6 :             nVersion = TigerClassifyVersion( nVersionCode );
     439               6 :             nVersion = TigerCheckVersion( nVersion, papszFileList[i] );
     440                 : 
     441                 :             CPLDebug( "OGR", "Tiger Version Code=%d, Classified as %s ", 
     442               6 :                       nVersionCode, TigerVersionString(nVersion) );
     443                 : 
     444              18 :             if(    nVersionCode !=  0
     445                 :                 && nVersionCode !=  2
     446                 :                 && nVersionCode !=  3
     447                 :                 && nVersionCode !=  5
     448                 :                 && nVersionCode != 21 
     449                 :                 && nVersionCode != 24
     450               6 :                 && pszRecStart[3]  != '9'
     451               6 :                 && pszRecStart[3]  != '0'
     452                 :                 && !bIsGDT )
     453               0 :                 continue;
     454                 : 
     455                 :             // we could (and should) add a bunch more validation here.
     456                 :         }
     457                 : 
     458               6 :         papszModules = CSLAddString( papszModules, papszFileList[i] );
     459                 :     }
     460                 : 
     461             406 :     CSLDestroy( papszFileList );
     462                 : 
     463             406 :     nModules = CSLCount( papszModules );
     464                 : 
     465             406 :     if( nModules == 0 )
     466                 :     {
     467             400 :         if( !bTestOpen )
     468                 :         {
     469               0 :             if( VSI_ISREG(stat.st_mode) )
     470                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     471                 :                           "No TIGER/Line files (TGR*.RT1) found in\n"
     472                 :                           "directory: %s",
     473               0 :                           pszFilename );
     474                 :             else
     475                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     476                 :                           "File %s does not appear to be a TIGER/Line .RT1 file.",
     477               0 :                           pszFilename );
     478                 :         }
     479                 : 
     480             400 :         return FALSE;
     481                 :     }
     482                 : 
     483                 : /* -------------------------------------------------------------------- */
     484                 : /*      Do we have a user provided version override?                    */
     485                 : /* -------------------------------------------------------------------- */
     486               6 :     if( CPLGetConfigOption( "TIGER_VERSION", NULL ) != NULL )
     487                 :     {
     488                 :         const char *pszRequestedVersion = 
     489               0 :             CPLGetConfigOption( "TIGER_VERSION", NULL );
     490                 : 
     491               0 :         if( EQUALN(pszRequestedVersion,"TIGER_",6) )
     492                 :         {
     493                 :             int iCode;
     494                 : 
     495               0 :             for( iCode = 1; iCode < TIGER_Unknown; iCode++ )
     496                 :             {
     497               0 :                 if( EQUAL(TigerVersionString((TigerVersion)iCode),
     498                 :                           pszRequestedVersion) )
     499                 :                 {
     500               0 :                     nVersion = (TigerVersion) iCode;
     501               0 :                     break;
     502                 :                 }
     503                 :             }
     504                 : 
     505               0 :             if( iCode == TIGER_Unknown )
     506                 :             {
     507                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     508                 :                           "Failed to recognise TIGER_VERSION setting: %s", 
     509               0 :                           pszRequestedVersion );
     510               0 :                 return FALSE;
     511                 :             }                          
     512                 : 
     513                 :             CPLDebug( "OGR", "OVERRIDE Tiger Version %s ", 
     514               0 :                       TigerVersionString(nVersion) );
     515                 :         }
     516                 :         else
     517                 :         {
     518               0 :             nVersionCode = atoi(pszRequestedVersion);
     519               0 :             nVersion = TigerClassifyVersion( nVersionCode );
     520                 : 
     521                 :             CPLDebug( "OGR", 
     522                 :                       "OVERRIDE Tiger Version Code=%d, Classified as %s ", 
     523               0 :                       nVersionCode, TigerVersionString(nVersion) );
     524                 :         }
     525                 :     }
     526                 : 
     527                 : /* -------------------------------------------------------------------- */
     528                 : /*      Create the layers which appear to exist.                        */
     529                 : /* -------------------------------------------------------------------- */
     530                 :     // RT1, RT2, RT3
     531                 :     AddLayer( new OGRTigerLayer( this,
     532                 :                                  new TigerCompleteChain( this,
     533               6 :                                                          papszModules[0]) ));
     534                 : 
     535                 :     /* should we have kept track of whether we encountered an RT4 file? */
     536                 :     // RT4
     537                 :     AddLayer( new OGRTigerLayer( this,
     538                 :                                  new TigerAltName( this,
     539              12 :                                                    papszModules[0]) ));
     540                 : 
     541                 :     // RT5
     542                 :     AddLayer( new OGRTigerLayer( this,
     543                 :                                  new TigerFeatureIds( this,
     544              12 :                                                       papszModules[0]) ));
     545                 : 
     546                 :     // RT6
     547                 :     AddLayer( new OGRTigerLayer( this,
     548                 :                                  new TigerZipCodes( this,
     549              12 :                                                     papszModules[0]) ));
     550                 :     // RT7
     551                 :     AddLayer( new OGRTigerLayer( this,
     552                 :                                  new TigerLandmarks( this,
     553              12 :                                                      papszModules[0]) ));
     554                 :     
     555                 :     // RT8
     556                 :     AddLayer( new OGRTigerLayer( this,
     557                 :                                  new TigerAreaLandmarks( this,
     558              12 :                                                      papszModules[0]) ));
     559                 : 
     560                 :     // RT9
     561               6 :     if (nVersion < TIGER_2002) {
     562                 :       AddLayer( new OGRTigerLayer( this,
     563                 :                                    new TigerKeyFeatures( this,
     564               0 :                                                          papszModules[0]) ));
     565                 :     }
     566                 :     
     567                 :     // RTA, RTS
     568                 :     AddLayer( new OGRTigerLayer( this,
     569                 :                                  new TigerPolygon( this,
     570               6 :                                                    papszModules[0]) ));
     571                 : 
     572                 :     // RTB
     573               6 :     if (nVersion >= TIGER_2002) {
     574                 :       AddLayer( new OGRTigerLayer( this,
     575                 :                                    new TigerPolygonCorrections( this,
     576               6 :                                                                 papszModules[0]) ));
     577                 :     }
     578                 :     
     579                 :     // RTC
     580                 :     AddLayer( new OGRTigerLayer( this,
     581                 :                                  new TigerEntityNames( this,
     582               6 :                                                        papszModules[0]) ));
     583                 : 
     584                 :     // RTE
     585               6 :     if (nVersion >= TIGER_2002) {
     586                 :       AddLayer( new OGRTigerLayer( this,
     587                 :                                    new TigerPolygonEconomic( this,
     588               6 :                                                              papszModules[0]) ));
     589                 :     }
     590                 : 
     591                 :     // RTH
     592                 :     AddLayer( new OGRTigerLayer( this,
     593                 :                                  new TigerIDHistory( this,
     594               6 :                                                      papszModules[0]) ));
     595                 :     
     596                 :     // RTI
     597                 :     AddLayer( new OGRTigerLayer( this,
     598                 :                                  new TigerPolyChainLink( this,
     599              12 :                                                        papszModules[0]) ));
     600                 :     
     601                 :     // RTM
     602                 :     AddLayer( new OGRTigerLayer( this,
     603                 :                                  new TigerSpatialMetadata( this,
     604              12 :                                                            papszModules[0] ) ) );
     605                 :     
     606                 :     // RTP
     607                 :     AddLayer( new OGRTigerLayer( this,
     608                 :                                  new TigerPIP( this,
     609              12 :                                                papszModules[0]) ));
     610                 :     
     611                 :     // RTR
     612                 :     AddLayer( new OGRTigerLayer( this,
     613                 :                                  new TigerTLIDRange( this,
     614              12 :                                                      papszModules[0]) ));
     615                 :     
     616                 :     // RTT
     617               6 :     if (nVersion >= TIGER_2002) {
     618                 :       AddLayer( new OGRTigerLayer( this,
     619                 :                                    new TigerZeroCellID( this,
     620               6 :                                                         papszModules[0]) ));
     621                 :     }
     622                 : 
     623                 :     // RTU
     624               6 :     if (nVersion >= TIGER_2002) {
     625                 :       AddLayer( new OGRTigerLayer( this,
     626                 :                                    new TigerOverUnder( this,
     627               6 :                                                        papszModules[0]) ));
     628                 :     }
     629                 : 
     630                 :     // RTZ
     631                 :     AddLayer( new OGRTigerLayer( this,
     632                 :                                  new TigerZipPlus4( this,
     633               6 :                                                      papszModules[0]) ));
     634                 :     
     635               6 :     return TRUE;
     636                 : }
     637                 : 
     638                 : /************************************************************************/
     639                 : /*                             SetOptions()                             */
     640                 : /************************************************************************/
     641                 : 
     642               1 : void OGRTigerDataSource::SetOptionList( char ** papszNewOptions )
     643                 : 
     644                 : {
     645               1 :     CSLDestroy( papszOptions );
     646               1 :     papszOptions = CSLDuplicate( papszNewOptions );
     647               1 : }
     648                 : 
     649                 : /************************************************************************/
     650                 : /*                             GetOption()                              */
     651                 : /************************************************************************/
     652                 : 
     653               2 : const char *OGRTigerDataSource::GetOption( const char * pszOption )
     654                 : 
     655                 : {
     656               2 :     return CSLFetchNameValue( papszOptions, pszOption );
     657                 : }
     658                 : 
     659                 : /************************************************************************/
     660                 : /*                             GetModule()                              */
     661                 : /************************************************************************/
     662                 : 
     663             291 : const char *OGRTigerDataSource::GetModule( int iModule )
     664                 : 
     665                 : {
     666             291 :     if( iModule < 0 || iModule >= nModules )
     667               0 :         return NULL;
     668                 :     else
     669             291 :         return papszModules[iModule];
     670                 : }
     671                 : 
     672                 : /************************************************************************/
     673                 : /*                            CheckModule()                             */
     674                 : /*                                                                      */
     675                 : /*      This is used by the writer to check if this module has been     */
     676                 : /*      written to before.                                              */
     677                 : /************************************************************************/
     678                 : 
     679              17 : int OGRTigerDataSource::CheckModule( const char *pszModule )
     680                 : 
     681                 : {
     682                 :     int         i;
     683                 : 
     684              17 :     for( i = 0; i < nModules; i++ )
     685                 :     {
     686              15 :         if( EQUAL(pszModule,papszModules[i]) )
     687              15 :             return TRUE;
     688                 :     }
     689               2 :     return FALSE;
     690                 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                             AddModule()                              */
     694                 : /************************************************************************/
     695                 : 
     696               1 : void OGRTigerDataSource::AddModule( const char *pszModule )
     697                 : 
     698                 : {
     699               1 :     if( CheckModule( pszModule ) )
     700               0 :         return;
     701                 : 
     702               1 :     papszModules = CSLAddString( papszModules, pszModule );
     703               1 :     nModules++;
     704                 : }
     705                 : 
     706                 : /************************************************************************/
     707                 : /*                           BuildFilename()                            */
     708                 : /************************************************************************/
     709                 : 
     710           24486 : char *OGRTigerDataSource::BuildFilename( const char *pszModuleName,
     711                 :                                     const char *pszExtension )
     712                 : 
     713                 : {
     714                 :     char        *pszFilename;
     715                 :     char        szLCExtension[3];
     716                 : 
     717                 : /* -------------------------------------------------------------------- */
     718                 : /*      Force the record type to lower case if the filename appears     */
     719                 : /*      to be in lower case.                                            */
     720                 : /* -------------------------------------------------------------------- */
     721           24486 :     if( *pszExtension >= 'A' && *pszExtension <= 'Z' && *pszModuleName == 't' )
     722                 :     {
     723               0 :         szLCExtension[0] = (*pszExtension) + 'a' - 'A';
     724               0 :         szLCExtension[1] = '\0';
     725               0 :         pszExtension = szLCExtension;
     726                 :     }
     727                 : 
     728                 : /* -------------------------------------------------------------------- */
     729                 : /*      Build the filename.                                             */
     730                 : /* -------------------------------------------------------------------- */
     731                 :     pszFilename = (char *) CPLMalloc(strlen(GetDirPath())
     732                 :                                      + strlen(pszModuleName)
     733           24486 :                                      + strlen(pszExtension) + 10);
     734                 : 
     735           24486 :     if( strlen(GetDirPath()) == 0 )
     736                 :         sprintf( pszFilename, "%s%s",
     737               0 :                  pszModuleName, pszExtension );
     738                 :     else
     739                 :         sprintf( pszFilename, "%s/%s%s",
     740           24486 :                  GetDirPath(), pszModuleName, pszExtension );
     741                 : 
     742           24486 :     return pszFilename;
     743                 : }
     744                 : 
     745                 : /************************************************************************/
     746                 : /*                           TestCapability()                           */
     747                 : /************************************************************************/
     748                 : 
     749              18 : int OGRTigerDataSource::TestCapability( const char *pszCap )
     750                 : 
     751                 : {
     752              18 :     if( EQUAL(pszCap,ODsCCreateLayer) )
     753              18 :         return GetWriteMode();
     754                 :     else
     755               0 :         return FALSE;
     756                 : }
     757                 : 
     758                 : /************************************************************************/
     759                 : /*                               Create()                               */
     760                 : /************************************************************************/
     761                 : 
     762               1 : int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptions )
     763                 : 
     764                 : {
     765                 :     VSIStatBuf      stat;
     766                 :     
     767                 : /* -------------------------------------------------------------------- */
     768                 : /*      Try to create directory if it doesn't already exist.            */
     769                 : /* -------------------------------------------------------------------- */
     770               1 :     if( CPLStat( pszNameIn, &stat ) != 0 )
     771                 :     {
     772               0 :         VSIMkdir( pszNameIn, 0755 );
     773                 :     }
     774                 : 
     775               1 :     if( CPLStat( pszNameIn, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
     776                 :     {
     777                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     778                 :                   "%s is not a directory, nor can be directly created as one.",
     779               0 :                   pszName );
     780               0 :         return FALSE;
     781                 :     }
     782                 : 
     783                 : /* -------------------------------------------------------------------- */
     784                 : /*      Store various information.                                      */
     785                 : /* -------------------------------------------------------------------- */
     786               1 :     pszPath = CPLStrdup( pszNameIn );
     787               1 :     pszName = CPLStrdup( pszNameIn );
     788               1 :     bWriteMode = TRUE;
     789                 : 
     790               1 :     SetOptionList( papszOptions );
     791                 : 
     792                 : /* -------------------------------------------------------------------- */
     793                 : /*      Work out the version.                                           */
     794                 : /* -------------------------------------------------------------------- */
     795                 : //    nVersionCode = 1000; /* census 2000 */
     796                 : 
     797               1 :     nVersionCode = 1002; /* census 2002 */
     798               1 :     if( GetOption("VERSION") != NULL )
     799                 :     {
     800               1 :         nVersionCode = atoi(GetOption("VERSION"));
     801               1 :         nVersionCode = MAX(0,MIN(9999,nVersionCode));
     802                 :     }
     803               1 :     nVersion = TigerClassifyVersion(nVersionCode);
     804                 : 
     805               1 :     return TRUE;
     806                 : }
     807                 : 
     808                 : /************************************************************************/
     809                 : /*                            CreateLayer()                             */
     810                 : /************************************************************************/
     811                 : 
     812              18 : OGRLayer *OGRTigerDataSource::CreateLayer( const char *pszLayerName, 
     813                 :                                            OGRSpatialReference *poSpatRef, 
     814                 :                                            OGRwkbGeometryType eGType, 
     815                 :                                            char **papszOptions )
     816                 : 
     817                 : {
     818              18 :     OGRTigerLayer       *poLayer = NULL;
     819                 : 
     820              18 :     if( GetLayer( pszLayerName ) != NULL )
     821               0 :         return GetLayer( pszLayerName );
     822                 : 
     823              18 :     if( poSpatRef != NULL && 
     824                 :         (!poSpatRef->IsGeographic() 
     825                 :          || !EQUAL(poSpatRef->GetAttrValue("DATUM"),
     826                 :                    "North_American_Datum_1983")) )
     827                 :     {
     828                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     829                 :                   "Requested coordinate system wrong for Tiger, " 
     830               0 :                   "forcing to GEOGCS NAD83." );
     831                 :     }
     832                 : 
     833              18 :     if( EQUAL(pszLayerName,"PIP") )
     834                 :     {
     835                 :         poLayer = new OGRTigerLayer( this,
     836               1 :                                      new TigerPIP( this, NULL ) );
     837                 :     }
     838              17 :     else if( EQUAL(pszLayerName,"ZipPlus4") )
     839                 :     {
     840                 :         poLayer = new OGRTigerLayer( this,
     841               1 :                                      new TigerZipPlus4( this, NULL ) );
     842                 :     }
     843              16 :     else if( EQUAL(pszLayerName,"TLIDRange") )
     844                 :     {
     845                 :         poLayer = new OGRTigerLayer( this,
     846               1 :                                      new TigerTLIDRange( this, NULL ) );
     847                 :     }
     848              15 :     else if( EQUAL(pszLayerName,"PolyChainLink") )
     849                 :     {
     850                 :         poLayer = new OGRTigerLayer( this,
     851               1 :                                      new TigerPolyChainLink( this, NULL ) );
     852                 :     }
     853              14 :     else if( EQUAL(pszLayerName,"CompleteChain") )
     854                 :     {
     855                 :         poLayer = new OGRTigerLayer( this,
     856               1 :                                      new TigerCompleteChain( this, NULL ) );
     857                 :     }
     858              13 :     else if( EQUAL(pszLayerName,"AltName") )
     859                 :     {
     860                 :         poLayer = new OGRTigerLayer( this,
     861               1 :                                      new TigerAltName( this, NULL ) );
     862                 :     }
     863              12 :     else if( EQUAL(pszLayerName,"FeatureIds") )
     864                 :     {
     865                 :         poLayer = new OGRTigerLayer( this,
     866               1 :                                      new TigerFeatureIds( this, NULL ) );
     867                 :     }
     868              11 :     else if( EQUAL(pszLayerName,"ZipCodes") )
     869                 :     {
     870                 :         poLayer = new OGRTigerLayer( this,
     871               1 :                                      new TigerZipCodes( this, NULL ) );
     872                 :     }
     873              10 :     else if( EQUAL(pszLayerName,"Landmarks") )
     874                 :     {
     875                 :         poLayer = new OGRTigerLayer( this,
     876               1 :                                      new TigerLandmarks( this, NULL ) );
     877                 :     }
     878               9 :     else if( EQUAL(pszLayerName,"AreaLandmarks") )
     879                 :     {
     880                 :         poLayer = new OGRTigerLayer( this,
     881               1 :                                      new TigerAreaLandmarks( this, NULL ) );
     882                 :     }
     883               8 :     else if( EQUAL(pszLayerName,"KeyFeatures") )
     884                 :     {
     885                 :         poLayer = new OGRTigerLayer( this,
     886               0 :                                      new TigerKeyFeatures( this, NULL ) );
     887                 :     }
     888               8 :     else if( EQUAL(pszLayerName,"EntityNames") )
     889                 :     {
     890                 :         poLayer = new OGRTigerLayer( this,
     891               1 :                                      new TigerEntityNames( this, NULL ) );
     892                 :     }
     893               7 :     else if( EQUAL(pszLayerName,"IDHistory") )
     894                 :     {
     895                 :         poLayer = new OGRTigerLayer( this,
     896               1 :                                      new TigerIDHistory( this, NULL ) );
     897                 :     }
     898               6 :     else if( EQUAL(pszLayerName,"Polygon") )
     899                 :     {
     900                 :         poLayer = new OGRTigerLayer( this,
     901               1 :                                      new TigerPolygon( this, NULL ) );
     902                 :     }
     903                 : 
     904               5 :     else if( EQUAL(pszLayerName,"PolygonCorrections") )
     905                 :     {
     906                 :         poLayer = new OGRTigerLayer( this,
     907               1 :                                      new TigerPolygonCorrections( this, NULL ) );
     908                 :     }
     909                 : 
     910               4 :     else if( EQUAL(pszLayerName,"PolygonEconomic") )
     911                 :     {
     912                 :         poLayer = new OGRTigerLayer( this,
     913               1 :                                      new TigerPolygonEconomic( this, NULL ) );
     914                 :     }
     915                 : 
     916               3 :     else if( EQUAL(pszLayerName,"SpatialMetadata") )
     917                 :     {
     918                 :         poLayer = new OGRTigerLayer( this,
     919               1 :                                      new TigerSpatialMetadata( this, NULL ) );
     920                 :     }
     921                 : 
     922               2 :     else if( EQUAL(pszLayerName,"ZeroCellID") )
     923                 :     {
     924                 :         poLayer = new OGRTigerLayer( this,
     925               1 :                                      new TigerZeroCellID( this, NULL ) );
     926                 :     }
     927                 : 
     928               1 :     else if( EQUAL(pszLayerName,"OverUnder") )
     929                 :     {
     930                 :         poLayer = new OGRTigerLayer( this,
     931               1 :                                      new TigerOverUnder( this, NULL ) );
     932                 :     }
     933                 : 
     934              18 :     if( poLayer == NULL )
     935                 :     {
     936                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     937                 :                   "Unable to create layer %s, not a known TIGER/Line layer.",
     938               0 :                   pszLayerName );
     939                 :     }
     940                 :     else
     941              18 :         AddLayer( poLayer );
     942                 : 
     943              18 :     return poLayer;
     944                 : }
     945                 : 
     946                 : /************************************************************************/
     947                 : /*                         DeleteModuleFiles()                          */
     948                 : /************************************************************************/
     949                 : 
     950               1 : void OGRTigerDataSource::DeleteModuleFiles( const char *pszModule )
     951                 : 
     952                 : {
     953               1 :     char        **papszDirFiles = CPLReadDir( GetDirPath() );
     954               1 :     int         i, nCount = CSLCount(papszDirFiles);
     955                 :     
     956              21 :     for( i = 0; i < nCount; i++ )
     957                 :     {
     958              20 :         if( EQUALN(pszModule,papszDirFiles[i],strlen(pszModule)) )
     959                 :         {
     960                 :             const char  *pszFilename;
     961                 : 
     962                 :             pszFilename = CPLFormFilename( GetDirPath(), 
     963              18 :                                            papszDirFiles[i], 
     964              36 :                                            NULL );
     965              18 :             if( VSIUnlink( pszFilename ) != 0 )
     966                 :             {
     967               0 :                 CPLDebug( "OGR_TIGER", "Failed to unlink %s", pszFilename );
     968                 :             }
     969                 :         }
     970                 :     }
     971                 : 
     972               1 :     CSLDestroy( papszDirFiles );
     973               1 : }

Generated by: LCOV version 1.7