LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/tiger - ogrtigerdatasource.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 64 293 21.8 %
Date: 2024-04-29 17:29:47 Functions: 5 17 29.4 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  TIGER/Line Translator
       4             :  * Purpose:  Implements OGRTigerDataSource class
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, Frank Warmerdam <warmerdam@pobox.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_conv.h"
      30             : #include "cpl_string.h"
      31             : #include "ogr_tiger.h"
      32             : 
      33             : #include <cctype>
      34             : #include <algorithm>
      35             : 
      36             : #define DIGIT_ZERO '0'
      37             : 
      38             : /************************************************************************/
      39             : /*                        TigerClassifyVersion()                        */
      40             : /************************************************************************/
      41             : 
      42           0 : TigerVersion TigerClassifyVersion(int nVersionCode)
      43             : 
      44             : {
      45             :     TigerVersion nVersion;
      46             :     int nYear, nMonth;
      47             : 
      48             :     /*
      49             :     ** TIGER Versions
      50             :     **
      51             :     ** 0000           TIGER/Line Precensus Files, 1990
      52             :     ** 0002           TIGER/Line Initial Voting District Codes Files, 1990
      53             :     ** 0003           TIGER/Line Files, 1990
      54             :     ** 0005           TIGER/Line Files, 1992
      55             :     ** 0021           TIGER/Line Files, 1994
      56             :     ** 0024           TIGER/Line Files, 1995
      57             :     ** 9706 to 9810   TIGER/Line Files, 1997
      58             :     ** 9812 to 9904   TIGER/Line Files, 1998
      59             :     ** 0006 to 0008   TIGER/Line Files, 1999
      60             :     ** 0010 to 0011   TIGER/Line Files, Redistricting Census 2000
      61             :     ** 0103 to 0108   TIGER/Line Files, Census 2000
      62             :     **
      63             :     ** 0203 to 0205   TIGER/Line Files, UA 2000
      64             :     ** ????    ????
      65             :     **
      66             :     ** 0206 to 0299   TIGER/Line Files, 2002
      67             :     ** 0300 to 0399   TIGER/Line Files, 2003
      68             :     ** 0400+          TIGER/Line Files, 2004 - one sample is 0405
      69             :     ** ????
      70             :     */
      71             : 
      72           0 :     nVersion = TIGER_Unknown;
      73           0 :     if (nVersionCode == 0)
      74           0 :         nVersion = TIGER_1990_Precensus;
      75           0 :     else if (nVersionCode == 2)
      76           0 :         nVersion = TIGER_1990;
      77           0 :     else if (nVersionCode == 3)
      78           0 :         nVersion = TIGER_1992;
      79           0 :     else if (nVersionCode == 5)
      80           0 :         nVersion = TIGER_1994;
      81           0 :     else if (nVersionCode == 21)
      82           0 :         nVersion = TIGER_1994;
      83           0 :     else if (nVersionCode == 24)
      84           0 :         nVersion = TIGER_1995;
      85             : 
      86           0 :     else if (nVersionCode == 9999) /* special hack, fme bug 7625 */
      87           0 :         nVersion = TIGER_UA2000;
      88             : 
      89           0 :     nYear = nVersionCode % 100;
      90           0 :     nMonth = nVersionCode / 100;
      91             : 
      92           0 :     nVersionCode = nYear * 100 + nMonth;
      93             : 
      94           0 :     if (nVersion != TIGER_Unknown)
      95             :         /* do nothing */;
      96           0 :     else if (nVersionCode >= 9706 && nVersionCode <= 9810)
      97           0 :         nVersion = TIGER_1997;
      98           0 :     else if (nVersionCode >= 9812 && nVersionCode <= 9904)
      99           0 :         nVersion = TIGER_1998;
     100           0 :     else if (nVersionCode >= 6 /*0006*/ && nVersionCode <= 8 /*0008*/)
     101           0 :         nVersion = TIGER_1999;
     102           0 :     else if (nVersionCode >= 10 /*0010*/ && nVersionCode <= 11 /*0011*/)
     103           0 :         nVersion = TIGER_2000_Redistricting;
     104           0 :     else if (nVersionCode >= 103 /*0103*/ && nVersionCode <= 108 /*0108*/)
     105           0 :         nVersion = TIGER_2000_Census;
     106           0 :     else if (nVersionCode >= 203 /*0302*/ && nVersionCode <= 205 /*0502*/)
     107           0 :         nVersion = TIGER_UA2000;
     108           0 :     else if (nVersionCode >= 210 /*1002*/ && nVersionCode <= 306 /*0603*/)
     109           0 :         nVersion = TIGER_2002;
     110           0 :     else if (nVersionCode >= 312 /*1203*/ && nVersionCode <= 403 /*0304*/)
     111           0 :         nVersion = TIGER_2003;
     112           0 :     else if (nVersionCode >= 404)
     113           0 :         nVersion = TIGER_2004;
     114             : 
     115           0 :     return nVersion;
     116             : }
     117             : 
     118             : /************************************************************************/
     119             : /*                         TigerVersionString()                         */
     120             : /************************************************************************/
     121             : 
     122           0 : const char *TigerVersionString(TigerVersion nVersion)
     123             : {
     124             : 
     125           0 :     if (nVersion == TIGER_1990_Precensus)
     126             :     {
     127           0 :         return "TIGER_1990_Precensus";
     128             :     }
     129           0 :     if (nVersion == TIGER_1990)
     130             :     {
     131           0 :         return "TIGER_1990";
     132             :     }
     133           0 :     if (nVersion == TIGER_1992)
     134             :     {
     135           0 :         return "TIGER_1992";
     136             :     }
     137           0 :     if (nVersion == TIGER_1994)
     138             :     {
     139           0 :         return "TIGER_1994";
     140             :     }
     141           0 :     if (nVersion == TIGER_1995)
     142             :     {
     143           0 :         return "TIGER_1995";
     144             :     }
     145           0 :     if (nVersion == TIGER_1997)
     146             :     {
     147           0 :         return "TIGER_1997";
     148             :     }
     149           0 :     if (nVersion == TIGER_1998)
     150             :     {
     151           0 :         return "TIGER_1998";
     152             :     }
     153           0 :     if (nVersion == TIGER_1999)
     154             :     {
     155           0 :         return "TIGER_1999";
     156             :     }
     157           0 :     if (nVersion == TIGER_2000_Redistricting)
     158             :     {
     159           0 :         return "TIGER_2000_Redistricting";
     160             :     }
     161           0 :     if (nVersion == TIGER_UA2000)
     162             :     {
     163           0 :         return "TIGER_UA2000";
     164             :     }
     165           0 :     if (nVersion == TIGER_2002)
     166             :     {
     167           0 :         return "TIGER_2002";
     168             :     }
     169           0 :     if (nVersion == TIGER_2003)
     170             :     {
     171           0 :         return "TIGER_2003";
     172             :     }
     173           0 :     if (nVersion == TIGER_2004)
     174             :     {
     175           0 :         return "TIGER_2004";
     176             :     }
     177           0 :     if (nVersion == TIGER_Unknown)
     178             :     {
     179           0 :         return "TIGER_Unknown";
     180             :     }
     181           0 :     return "???";
     182             : }
     183             : 
     184             : /************************************************************************/
     185             : /*                         TigerCheckVersion()                          */
     186             : /*                                                                      */
     187             : /*      Some tiger products seem to be generated with version info      */
     188             : /*      that doesn't match the tiger specs.  We can sometimes           */
     189             : /*      recognise the wrongness by checking the record length of        */
     190             : /*      some well known changing files and adjusting the version        */
     191             : /*      based on this.                                                  */
     192             : /************************************************************************/
     193             : 
     194           0 : TigerVersion OGRTigerDataSource::TigerCheckVersion(TigerVersion nOldVersion,
     195             :                                                    const char *pszFilename)
     196             : 
     197             : {
     198           0 :     if (nOldVersion != TIGER_2002)
     199           0 :         return nOldVersion;
     200             : 
     201           0 :     char *pszRTCFilename = BuildFilename(pszFilename, "C");
     202           0 :     VSILFILE *fp = VSIFOpenL(pszRTCFilename, "rb");
     203           0 :     CPLFree(pszRTCFilename);
     204             : 
     205           0 :     if (fp == nullptr)
     206           0 :         return nOldVersion;
     207             : 
     208             :     char szHeader[115];
     209             : 
     210           0 :     if (VSIFReadL(szHeader, sizeof(szHeader) - 1, 1, fp) < 1)
     211             :     {
     212           0 :         VSIFCloseL(fp);
     213           0 :         return nOldVersion;
     214             :     }
     215             : 
     216           0 :     VSIFCloseL(fp);
     217             : 
     218             :     /* -------------------------------------------------------------------- */
     219             :     /*      Is the record length 112?  If so, it is an older version        */
     220             :     /*      than 2002.                                                      */
     221             :     /* -------------------------------------------------------------------- */
     222           0 :     if (szHeader[112] == 10 || szHeader[112] == 13)
     223             :     {
     224           0 :         CPLDebug("TIGER",
     225             :                  "Forcing version back to UA2000 since RTC records are short.");
     226           0 :         return TIGER_UA2000;
     227             :     }
     228             : 
     229           0 :     return nOldVersion;
     230             : }
     231             : 
     232             : /************************************************************************/
     233             : /*                         OGRTigerDataSource()                         */
     234             : /************************************************************************/
     235             : 
     236         470 : OGRTigerDataSource::OGRTigerDataSource()
     237             :     : pszName(nullptr), nLayers(0), papoLayers(nullptr),
     238         470 :       poSpatialRef(new OGRSpatialReference()), papszOptions(nullptr),
     239             :       pszPath(nullptr), nModules(0), papszModules(nullptr), nVersionCode(0),
     240         470 :       nVersion(TIGER_Unknown)
     241             : {
     242         470 :     poSpatialRef->SetWellKnownGeogCS("NAD83");
     243         470 :     poSpatialRef->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     244         470 : }
     245             : 
     246             : /************************************************************************/
     247             : /*                        ~OGRTigerDataSource()                         */
     248             : /************************************************************************/
     249             : 
     250         940 : OGRTigerDataSource::~OGRTigerDataSource()
     251             : 
     252             : {
     253         470 :     for (int i = 0; i < nLayers; i++)
     254           0 :         delete papoLayers[i];
     255             : 
     256         470 :     CPLFree(papoLayers);
     257             : 
     258         470 :     CPLFree(pszName);
     259         470 :     CPLFree(pszPath);
     260             : 
     261         470 :     CSLDestroy(papszOptions);
     262             : 
     263         470 :     CSLDestroy(papszModules);
     264             : 
     265         470 :     delete poSpatialRef;
     266         940 : }
     267             : 
     268             : /************************************************************************/
     269             : /*                              AddLayer()                              */
     270             : /************************************************************************/
     271             : 
     272           0 : void OGRTigerDataSource::AddLayer(OGRTigerLayer *poNewLayer)
     273             : 
     274             : {
     275           0 :     poNewLayer->SetDescription(poNewLayer->GetName());
     276           0 :     papoLayers = static_cast<OGRTigerLayer **>(
     277           0 :         CPLRealloc(papoLayers, sizeof(void *) * ++nLayers));
     278             : 
     279           0 :     papoLayers[nLayers - 1] = poNewLayer;
     280           0 : }
     281             : 
     282             : /************************************************************************/
     283             : /*                              GetLayer()                              */
     284             : /************************************************************************/
     285             : 
     286           0 : OGRLayer *OGRTigerDataSource::GetLayer(int iLayer)
     287             : 
     288             : {
     289           0 :     if (iLayer < 0 || iLayer >= nLayers)
     290           0 :         return nullptr;
     291             : 
     292           0 :     return papoLayers[iLayer];
     293             : }
     294             : 
     295             : /************************************************************************/
     296             : /*                              GetLayer()                              */
     297             : /************************************************************************/
     298             : 
     299           0 : OGRLayer *OGRTigerDataSource::GetLayer(const char *pszLayerName)
     300             : 
     301             : {
     302           0 :     for (int iLayer = 0; iLayer < nLayers; iLayer++)
     303             :     {
     304           0 :         if (EQUAL(papoLayers[iLayer]->GetLayerDefn()->GetName(), pszLayerName))
     305           0 :             return papoLayers[iLayer];
     306             :     }
     307             : 
     308           0 :     return nullptr;
     309             : }
     310             : 
     311             : /************************************************************************/
     312             : /*                           GetLayerCount()                            */
     313             : /************************************************************************/
     314             : 
     315           0 : int OGRTigerDataSource::GetLayerCount()
     316             : 
     317             : {
     318           0 :     return nLayers;
     319             : }
     320             : 
     321             : /************************************************************************/
     322             : /*                                Open()                                */
     323             : /************************************************************************/
     324             : 
     325         470 : int OGRTigerDataSource::Open(const char *pszFilename, int bTestOpen,
     326             :                              char **papszLimitedFileList)
     327             : 
     328             : {
     329         470 :     pszName = CPLStrdup(pszFilename);
     330             : 
     331             :     /* -------------------------------------------------------------------- */
     332             :     /*      Is the given path a directory or a regular file?                */
     333             :     /* -------------------------------------------------------------------- */
     334             :     VSIStatBufL stat;
     335             : 
     336         470 :     if (VSIStatExL(pszFilename, &stat,
     337         940 :                    VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) != 0 ||
     338         470 :         (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)))
     339             :     {
     340           0 :         if (!bTestOpen)
     341           0 :             CPLError(
     342             :                 CE_Failure, CPLE_AppDefined,
     343             :                 "%s is neither a file or directory, Tiger access failed.\n",
     344             :                 pszFilename);
     345             : 
     346           0 :         return FALSE;
     347             :     }
     348             : 
     349             :     /* -------------------------------------------------------------------- */
     350             :     /*      Build a list of filenames we figure are Tiger files.            */
     351             :     /* -------------------------------------------------------------------- */
     352         470 :     char **papszFileList = nullptr;
     353         470 :     if (VSI_ISREG(stat.st_mode))
     354             :     {
     355             :         char szModule[128];
     356             : 
     357          21 :         if (strlen(CPLGetFilename(pszFilename)) == 0)
     358             :         {
     359           0 :             return FALSE;
     360             :         }
     361             : 
     362          21 :         pszPath = CPLStrdup(CPLGetPath(pszFilename));
     363             : 
     364          21 :         strncpy(szModule, CPLGetFilename(pszFilename), sizeof(szModule) - 1);
     365             :         /* Make sure the buffer is 0 terminated */
     366          21 :         szModule[sizeof(szModule) - 1] = '\0';
     367             : 
     368             :         /* And now remove last character of filename */
     369          21 :         szModule[strlen(szModule) - 1] = '\0';
     370             : 
     371          21 :         papszFileList = CSLAddString(papszFileList, szModule);
     372             :     }
     373             :     else
     374             :     {
     375         449 :         char **candidateFileList = VSIReadDir(pszFilename);
     376             : 
     377         449 :         pszPath = CPLStrdup(pszFilename);
     378             : 
     379       23378 :         for (int i = 0;
     380       23378 :              candidateFileList != nullptr && candidateFileList[i] != nullptr;
     381             :              i++)
     382             :         {
     383       22929 :             size_t nCandidateLen = strlen(candidateFileList[i]);
     384             : 
     385       22929 :             if (papszLimitedFileList != nullptr &&
     386           0 :                 CSLFindString(papszLimitedFileList,
     387           0 :                               CPLGetBasename(candidateFileList[i])) == -1)
     388             :             {
     389           0 :                 continue;
     390             :             }
     391             : 
     392       22929 :             if (nCandidateLen > 4 &&
     393       22166 :                 candidateFileList[i][nCandidateLen - 4] == '.' &&
     394        6231 :                 candidateFileList[i][nCandidateLen - 1] == '1')
     395             :             {
     396             :                 char szModule[128];
     397             : 
     398           0 :                 snprintf(szModule, sizeof(szModule), "%s",
     399           0 :                          candidateFileList[i]);
     400           0 :                 const size_t nLen = strlen(szModule);
     401           0 :                 if (nLen)
     402           0 :                     szModule[nLen - 1] = '\0';
     403             : 
     404           0 :                 papszFileList = CSLAddString(papszFileList, szModule);
     405             :             }
     406             :         }
     407             : 
     408         449 :         CSLDestroy(candidateFileList);
     409             : 
     410         449 :         if (CSLCount(papszFileList) == 0)
     411             :         {
     412         449 :             if (!bTestOpen)
     413           0 :                 CPLError(CE_Failure, CPLE_OpenFailed,
     414             :                          "No candidate Tiger files (TGR*.RT1) found in\n"
     415             :                          "directory: %s",
     416             :                          pszFilename);
     417         449 :             CSLDestroy(papszFileList);
     418         449 :             return FALSE;
     419             :         }
     420             :     }
     421             : 
     422             :     /* -------------------------------------------------------------------- */
     423             :     /*      Loop over all these files trying to open them.  In testopen     */
     424             :     /*      mode we first read the first 80 characters, to verify that      */
     425             :     /*      it looks like an Tiger file.  Note that we don't keep the file  */
     426             :     /*      open ... we don't want to occupy a lot of file handles when      */
     427             :     /*      handling a whole directory.                                     */
     428             :     /* -------------------------------------------------------------------- */
     429          21 :     papszModules = nullptr;
     430             : 
     431          42 :     for (int i = 0; papszFileList && papszFileList[i] != nullptr; i++)
     432             :     {
     433          21 :         if (bTestOpen || i == 0)
     434             :         {
     435          21 :             char *l_pszFilename = BuildFilename(papszFileList[i], "1");
     436             : 
     437          21 :             VSILFILE *fp = VSIFOpenL(l_pszFilename, "rb");
     438          21 :             CPLFree(l_pszFilename);
     439             : 
     440          21 :             if (fp == nullptr)
     441          21 :                 continue;
     442             : 
     443           0 :             char szHeader[500] = {};
     444           0 :             if (VSIFReadL(szHeader, sizeof(szHeader) - 1, 1, fp) < 1)
     445             :             {
     446           0 :                 VSIFCloseL(fp);
     447           0 :                 continue;
     448             :             }
     449             : 
     450           0 :             VSIFCloseL(fp);
     451             : 
     452           0 :             char *pszRecStart = szHeader;
     453           0 :             szHeader[sizeof(szHeader) - 1] = '\0';
     454             : 
     455           0 :             bool bIsGDT = false;
     456             : 
     457           0 :             if (STARTS_WITH_CI(pszRecStart, "Copyright (C)") &&
     458           0 :                 strstr(pszRecStart, "Geographic Data Tech") != nullptr)
     459             :             {
     460           0 :                 bIsGDT = true;
     461             : 
     462           0 :                 while (*pszRecStart != '\0' && *pszRecStart != 10 &&
     463           0 :                        *pszRecStart != 13)
     464           0 :                     pszRecStart++;
     465             : 
     466           0 :                 while (*pszRecStart == 10 || *pszRecStart == 13)
     467           0 :                     pszRecStart++;
     468             :             }
     469             : 
     470           0 :             if (pszRecStart[0] != '1')
     471           0 :                 continue;
     472             : 
     473           0 :             if (!isdigit(static_cast<unsigned char>(pszRecStart[1])) ||
     474           0 :                 !isdigit(static_cast<unsigned char>(pszRecStart[2])) ||
     475           0 :                 !isdigit(static_cast<unsigned char>(pszRecStart[3])) ||
     476           0 :                 !isdigit(static_cast<unsigned char>(pszRecStart[4])))
     477           0 :                 continue;
     478             : 
     479           0 :             nVersionCode = atoi(TigerFileBase::GetField(pszRecStart, 2, 5));
     480           0 :             nVersion = TigerClassifyVersion(nVersionCode);
     481           0 :             nVersion = TigerCheckVersion(nVersion, papszFileList[i]);
     482             : 
     483           0 :             CPLDebug("OGR", "Tiger Version Code=%d, Classified as %s ",
     484             :                      nVersionCode, TigerVersionString(nVersion));
     485             : 
     486           0 :             if (nVersionCode != 0 && nVersionCode != 2 && nVersionCode != 3 &&
     487           0 :                 nVersionCode != 5 && nVersionCode != 21 && nVersionCode != 24 &&
     488           0 :                 pszRecStart[3] != '9' && pszRecStart[3] != DIGIT_ZERO &&
     489           0 :                 !bIsGDT)
     490           0 :                 continue;
     491             : 
     492             :             // we could (and should) add a bunch more validation here.
     493             :         }
     494             : 
     495           0 :         papszModules = CSLAddString(papszModules, papszFileList[i]);
     496             :     }
     497             : 
     498          21 :     CSLDestroy(papszFileList);
     499             : 
     500          21 :     nModules = CSLCount(papszModules);
     501             : 
     502          21 :     if (nModules == 0 || papszModules == nullptr)
     503             :     {
     504          21 :         if (!bTestOpen)
     505             :         {
     506           0 :             if (VSI_ISREG(stat.st_mode))
     507           0 :                 CPLError(CE_Failure, CPLE_OpenFailed,
     508             :                          "No TIGER/Line files (TGR*.RT1) found in\n"
     509             :                          "directory: %s",
     510             :                          pszFilename);
     511             :             else
     512           0 :                 CPLError(
     513             :                     CE_Failure, CPLE_OpenFailed,
     514             :                     "File %s does not appear to be a TIGER/Line .RT1 file.",
     515             :                     pszFilename);
     516             :         }
     517             : 
     518          21 :         return FALSE;
     519             :     }
     520             : 
     521             :     /* -------------------------------------------------------------------- */
     522             :     /*      Do we have a user provided version override?                    */
     523             :     /* -------------------------------------------------------------------- */
     524             :     const char *pszRequestedVersion =
     525           0 :         CPLGetConfigOption("TIGER_VERSION", nullptr);
     526           0 :     if (pszRequestedVersion != nullptr)
     527             :     {
     528             : 
     529           0 :         if (STARTS_WITH_CI(pszRequestedVersion, "TIGER_"))
     530             :         {
     531           0 :             int iCode = 1;  // Used after for.
     532             : 
     533           0 :             for (; iCode < TIGER_Unknown; iCode++)
     534             :             {
     535           0 :                 if (EQUAL(TigerVersionString((TigerVersion)iCode),
     536             :                           pszRequestedVersion))
     537             :                 {
     538           0 :                     nVersion = (TigerVersion)iCode;
     539           0 :                     break;
     540             :                 }
     541             :             }
     542             : 
     543           0 :             if (iCode == TIGER_Unknown)
     544             :             {
     545           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     546             :                          "Failed to recognise TIGER_VERSION setting: %s",
     547             :                          pszRequestedVersion);
     548           0 :                 return FALSE;
     549             :             }
     550             : 
     551           0 :             CPLDebug("OGR", "OVERRIDE Tiger Version %s ",
     552             :                      TigerVersionString(nVersion));
     553             :         }
     554             :         else
     555             :         {
     556           0 :             nVersionCode = atoi(pszRequestedVersion);
     557           0 :             nVersion = TigerClassifyVersion(nVersionCode);
     558             : 
     559           0 :             CPLDebug("OGR", "OVERRIDE Tiger Version Code=%d, Classified as %s ",
     560             :                      nVersionCode, TigerVersionString(nVersion));
     561             :         }
     562             :     }
     563             : 
     564             :     /* -------------------------------------------------------------------- */
     565             :     /*      Create the layers which appear to exist.                        */
     566             :     /* -------------------------------------------------------------------- */
     567             :     // RT1, RT2, RT3
     568           0 :     AddLayer(
     569           0 :         new OGRTigerLayer(this, new TigerCompleteChain(this, papszModules[0])));
     570             : 
     571             :     /* should we have kept track of whether we encountered an RT4 file? */
     572             :     // RT4
     573           0 :     AddLayer(new OGRTigerLayer(this, new TigerAltName(this, papszModules[0])));
     574             : 
     575             :     // RT5
     576           0 :     AddLayer(
     577           0 :         new OGRTigerLayer(this, new TigerFeatureIds(this, papszModules[0])));
     578             : 
     579             :     // RT6
     580           0 :     AddLayer(new OGRTigerLayer(this, new TigerZipCodes(this, papszModules[0])));
     581             :     // RT7
     582           0 :     AddLayer(
     583           0 :         new OGRTigerLayer(this, new TigerLandmarks(this, papszModules[0])));
     584             : 
     585             :     // RT8
     586           0 :     AddLayer(
     587           0 :         new OGRTigerLayer(this, new TigerAreaLandmarks(this, papszModules[0])));
     588             : 
     589             :     // RT9
     590           0 :     if (nVersion < TIGER_2002)
     591             :     {
     592           0 :         AddLayer(new OGRTigerLayer(
     593           0 :             this, new TigerKeyFeatures(this, papszModules[0])));
     594             :     }
     595             : 
     596             :     // RTA, RTS
     597           0 :     AddLayer(new OGRTigerLayer(this, new TigerPolygon(this, papszModules[0])));
     598             : 
     599             :     // RTB
     600           0 :     if (nVersion >= TIGER_2002)
     601             :     {
     602           0 :         AddLayer(new OGRTigerLayer(
     603           0 :             this, new TigerPolygonCorrections(this, papszModules[0])));
     604             :     }
     605             : 
     606             :     // RTC
     607           0 :     AddLayer(
     608           0 :         new OGRTigerLayer(this, new TigerEntityNames(this, papszModules[0])));
     609             : 
     610             :     // RTE
     611           0 :     if (nVersion >= TIGER_2002)
     612             :     {
     613           0 :         AddLayer(new OGRTigerLayer(
     614           0 :             this, new TigerPolygonEconomic(this, papszModules[0])));
     615             :     }
     616             : 
     617             :     // RTH
     618           0 :     AddLayer(
     619           0 :         new OGRTigerLayer(this, new TigerIDHistory(this, papszModules[0])));
     620             : 
     621             :     // RTI
     622           0 :     AddLayer(
     623           0 :         new OGRTigerLayer(this, new TigerPolyChainLink(this, papszModules[0])));
     624             : 
     625             :     // RTM
     626           0 :     AddLayer(new OGRTigerLayer(
     627           0 :         this, new TigerSpatialMetadata(this, papszModules[0])));
     628             : 
     629             :     // RTP
     630           0 :     AddLayer(new OGRTigerLayer(this, new TigerPIP(this, papszModules[0])));
     631             : 
     632             :     // RTR
     633           0 :     AddLayer(
     634           0 :         new OGRTigerLayer(this, new TigerTLIDRange(this, papszModules[0])));
     635             : 
     636             :     // RTT
     637           0 :     if (nVersion >= TIGER_2002)
     638             :     {
     639           0 :         AddLayer(new OGRTigerLayer(this,
     640           0 :                                    new TigerZeroCellID(this, papszModules[0])));
     641             :     }
     642             : 
     643             :     // RTU
     644           0 :     if (nVersion >= TIGER_2002)
     645             :     {
     646           0 :         AddLayer(
     647           0 :             new OGRTigerLayer(this, new TigerOverUnder(this, papszModules[0])));
     648             :     }
     649             : 
     650             :     // RTZ
     651           0 :     AddLayer(new OGRTigerLayer(this, new TigerZipPlus4(this, papszModules[0])));
     652             : 
     653           0 :     return TRUE;
     654             : }
     655             : 
     656             : /************************************************************************/
     657             : /*                             GetOption()                              */
     658             : /************************************************************************/
     659             : 
     660           0 : const char *OGRTigerDataSource::GetOption(const char *pszOption)
     661             : 
     662             : {
     663           0 :     return CSLFetchNameValue(papszOptions, pszOption);
     664             : }
     665             : 
     666             : /************************************************************************/
     667             : /*                             GetModule()                              */
     668             : /************************************************************************/
     669             : 
     670           0 : const char *OGRTigerDataSource::GetModule(int iModule)
     671             : 
     672             : {
     673           0 :     if (iModule < 0 || iModule >= nModules)
     674           0 :         return nullptr;
     675             :     else
     676           0 :         return papszModules[iModule];
     677             : }
     678             : 
     679             : /************************************************************************/
     680             : /*                            CheckModule()                             */
     681             : /*                                                                      */
     682             : /*      This is used by the writer to check if this module has been     */
     683             : /*      written to before.                                              */
     684             : /************************************************************************/
     685             : 
     686           0 : bool OGRTigerDataSource::CheckModule(const char *pszModule)
     687             : 
     688             : {
     689           0 :     for (int i = 0; i < nModules; i++)
     690             :     {
     691           0 :         if (EQUAL(pszModule, papszModules[i]))
     692           0 :             return true;
     693             :     }
     694           0 :     return false;
     695             : }
     696             : 
     697             : /************************************************************************/
     698             : /*                             AddModule()                              */
     699             : /************************************************************************/
     700             : 
     701           0 : void OGRTigerDataSource::AddModule(const char *pszModule)
     702             : 
     703             : {
     704           0 :     if (CheckModule(pszModule))
     705           0 :         return;
     706             : 
     707           0 :     papszModules = CSLAddString(papszModules, pszModule);
     708           0 :     nModules++;
     709             : }
     710             : 
     711             : /************************************************************************/
     712             : /*                           BuildFilename()                            */
     713             : /************************************************************************/
     714             : 
     715          21 : char *OGRTigerDataSource::BuildFilename(const char *pszModuleName,
     716             :                                         const char *pszExtension)
     717             : 
     718             : {
     719             :     /* -------------------------------------------------------------------- */
     720             :     /*      Force the record type to lower case if the filename appears     */
     721             :     /*      to be in lower case.                                            */
     722             :     /* -------------------------------------------------------------------- */
     723          21 :     char szLCExtension[3] = {};
     724          21 :     if (*pszExtension >= 'A' && *pszExtension <= 'Z' && *pszModuleName == 't')
     725             :     {
     726           0 :         szLCExtension[0] = (*pszExtension) + 'a' - 'A';
     727           0 :         szLCExtension[1] = '\0';
     728           0 :         pszExtension = szLCExtension;
     729             :     }
     730             : 
     731             :     /* -------------------------------------------------------------------- */
     732             :     /*      Build the filename.                                             */
     733             :     /* -------------------------------------------------------------------- */
     734          21 :     const size_t nFilenameLen = strlen(GetDirPath()) + strlen(pszModuleName) +
     735          21 :                                 strlen(pszExtension) + 10;
     736          21 :     char *pszFilename = (char *)CPLMalloc(nFilenameLen);
     737             : 
     738          21 :     if (strlen(GetDirPath()) == 0)
     739           0 :         snprintf(pszFilename, nFilenameLen, "%s%s", pszModuleName,
     740             :                  pszExtension);
     741             :     else
     742          21 :         snprintf(pszFilename, nFilenameLen, "%s/%s%s", GetDirPath(),
     743             :                  pszModuleName, pszExtension);
     744             : 
     745          21 :     return pszFilename;
     746             : }
     747             : 
     748             : /************************************************************************/
     749             : /*                           TestCapability()                           */
     750             : /************************************************************************/
     751             : 
     752           0 : int OGRTigerDataSource::TestCapability(const char *)
     753             : 
     754             : {
     755           0 :     return FALSE;
     756             : }

Generated by: LCOV version 1.14