LCOV - code coverage report
Current view: top level - frmts/sdts - sdtscatd.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 77 100 77.0 %
Date: 2025-01-18 12:42:00 Functions: 7 9 77.8 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SDTS Translator
       4             :  * Purpose:  Implementation of SDTS_CATD and SDTS_CATDEntry classes for
       5             :  *           reading CATD files.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 1999, Frank Warmerdam
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "sdts_al.h"
      15             : 
      16             : #include <set>
      17             : 
      18             : /************************************************************************/
      19             : /* ==================================================================== */
      20             : /*                            SDTS_CATDEntry                            */
      21             : /*                                                                      */
      22             : /*      This class is for internal use of the SDTS_CATD class only,     */
      23             : /*      and represents one entry in the directory ... a reference       */
      24             : /*      to another module file.                                         */
      25             : /* ==================================================================== */
      26             : /************************************************************************/
      27             : 
      28             : class SDTS_CATDEntry
      29             : 
      30             : {
      31             :   public:
      32             :     char *pszModule;
      33             :     char *pszType;
      34             :     char *pszFile;
      35             :     char *pszExternalFlag;
      36             : 
      37             :     char *pszFullPath;
      38             : };
      39             : 
      40             : /************************************************************************/
      41             : /* ==================================================================== */
      42             : /*                             SDTS_CATD                                */
      43             : /* ==================================================================== */
      44             : /************************************************************************/
      45             : 
      46             : /************************************************************************/
      47             : /*                             SDTS_CATD()                              */
      48             : /************************************************************************/
      49             : 
      50          52 : SDTS_CATD::SDTS_CATD()
      51          52 :     : pszPrefixPath(nullptr), nEntries(0), papoEntries(nullptr)
      52             : {
      53          52 : }
      54             : 
      55             : /************************************************************************/
      56             : /*                             ~SDTS_CATD()                             */
      57             : /************************************************************************/
      58             : 
      59         104 : SDTS_CATD::~SDTS_CATD()
      60             : {
      61         112 :     for (int i = 0; i < nEntries; i++)
      62             :     {
      63          60 :         CPLFree(papoEntries[i]->pszModule);
      64          60 :         CPLFree(papoEntries[i]->pszType);
      65          60 :         CPLFree(papoEntries[i]->pszFile);
      66          60 :         CPLFree(papoEntries[i]->pszExternalFlag);
      67          60 :         CPLFree(papoEntries[i]->pszFullPath);
      68          60 :         delete papoEntries[i];
      69             :     }
      70             : 
      71          52 :     CPLFree(papoEntries);
      72          52 :     CPLFree(pszPrefixPath);
      73          52 : }
      74             : 
      75             : /************************************************************************/
      76             : /*                                Read()                                */
      77             : /*                                                                      */
      78             : /*      Read the named file to initialize this structure.               */
      79             : /************************************************************************/
      80             : 
      81          52 : int SDTS_CATD::Read(const char *pszFilename)
      82             : 
      83             : {
      84             :     /* -------------------------------------------------------------------- */
      85             :     /*      Open the file.                                                  */
      86             :     /* -------------------------------------------------------------------- */
      87         104 :     DDFModule oCATDFile;
      88          52 :     if (!oCATDFile.Open(pszFilename))
      89           0 :         return FALSE;
      90             : 
      91          52 :     CPLErrorReset();  // Clear any ADRG "unrecognized data_struct_code" errors.
      92             : 
      93             :     /* -------------------------------------------------------------------- */
      94             :     /*      Does this file have a CATD field?  If not, it isn't an SDTS     */
      95             :     /*      record and we won't even try reading the first record for       */
      96             :     /*      fear it will we a huge honking ADRG data record or something.   */
      97             :     /* -------------------------------------------------------------------- */
      98          52 :     if (oCATDFile.FindFieldDefn("CATD") == nullptr)
      99          49 :         return FALSE;
     100             : 
     101             :     /* -------------------------------------------------------------------- */
     102             :     /*      Strip off the filename, and keep the path prefix.               */
     103             :     /* -------------------------------------------------------------------- */
     104           3 :     pszPrefixPath = CPLStrdup(pszFilename);
     105           3 :     int i = static_cast<int>(strlen(pszPrefixPath)) - 1;
     106          39 :     for (; i > 0; i--)
     107             :     {
     108          39 :         if (pszPrefixPath[i] == '\\' || pszPrefixPath[i] == '/')
     109             :         {
     110           3 :             pszPrefixPath[i] = '\0';
     111           3 :             break;
     112             :         }
     113             :     }
     114             : 
     115           3 :     if (i <= 0)
     116             :     {
     117           0 :         strcpy(pszPrefixPath, ".");
     118             :     }
     119             : 
     120             :     /* ==================================================================== */
     121             :     /*      Loop reading CATD records, and adding to our list of entries    */
     122             :     /*      for each.                                                       */
     123             :     /* ==================================================================== */
     124           3 :     DDFRecord *poRecord = nullptr;
     125           3 :     int nIters = 0;
     126           3 :     std::set<std::string> aoSetFiles;
     127          63 :     while ((poRecord = oCATDFile.ReadRecord()) != nullptr && nIters < 1000)
     128             :     {
     129          60 :         nIters++;
     130             : 
     131             :         /* --------------------------------------------------------------------
     132             :          */
     133             :         /*      Verify that we have a proper CATD record. */
     134             :         /* --------------------------------------------------------------------
     135             :          */
     136          60 :         if (poRecord->GetStringSubfield("CATD", 0, "MODN", 0) == nullptr)
     137           0 :             continue;
     138             : 
     139             :         /* --------------------------------------------------------------------
     140             :          */
     141             :         /*      Create a new entry, and get the module and file name. */
     142             :         /* --------------------------------------------------------------------
     143             :          */
     144          60 :         SDTS_CATDEntry *poEntry = new SDTS_CATDEntry;
     145             : 
     146          60 :         poEntry->pszModule =
     147          60 :             CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "NAME", 0));
     148          60 :         poEntry->pszFile =
     149          60 :             CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "FILE", 0));
     150          60 :         poEntry->pszExternalFlag =
     151          60 :             CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "EXTR", 0));
     152          60 :         poEntry->pszType =
     153          60 :             CPLStrdup(poRecord->GetStringSubfield("CATD", 0, "TYPE", 0));
     154             : 
     155          60 :         if (poEntry->pszModule[0] == '\0' || poEntry->pszFile[0] == '\0' ||
     156             :             // Exclude following one for performance reasons in oss-fuzz
     157         180 :             (poEntry->pszFile[0] == '/' && poEntry->pszFile[1] == '\0') ||
     158         120 :             aoSetFiles.find(poEntry->pszFile) != aoSetFiles.end())
     159             :         {
     160           0 :             CPLFree(poEntry->pszModule);
     161           0 :             CPLFree(poEntry->pszFile);
     162           0 :             CPLFree(poEntry->pszExternalFlag);
     163           0 :             CPLFree(poEntry->pszType);
     164           0 :             delete poEntry;
     165           0 :             continue;
     166             :         }
     167          60 :         aoSetFiles.insert(poEntry->pszFile);
     168             : 
     169             :         /* --------------------------------------------------------------------
     170             :          */
     171             :         /*      Create a full path to the file. */
     172             :         /* --------------------------------------------------------------------
     173             :          */
     174          60 :         poEntry->pszFullPath = CPLStrdup(
     175         120 :             CPLFormCIFilenameSafe(pszPrefixPath, poEntry->pszFile, nullptr)
     176             :                 .c_str());
     177             : 
     178             :         /* --------------------------------------------------------------------
     179             :          */
     180             :         /*      Add the entry to the list. */
     181             :         /* --------------------------------------------------------------------
     182             :          */
     183         120 :         papoEntries = reinterpret_cast<SDTS_CATDEntry **>(
     184          60 :             CPLRealloc(papoEntries, sizeof(void *) * ++nEntries));
     185          60 :         papoEntries[nEntries - 1] = poEntry;
     186             :     }
     187             : 
     188           3 :     return nEntries > 0;
     189             : }
     190             : 
     191             : /************************************************************************/
     192             : /*                         GetModuleFilePath()                          */
     193             : /************************************************************************/
     194             : 
     195          28 : const char *SDTS_CATD::GetModuleFilePath(const char *pszModule) const
     196             : 
     197             : {
     198         188 :     for (int i = 0; i < nEntries; i++)
     199             :     {
     200         188 :         if (EQUAL(papoEntries[i]->pszModule, pszModule))
     201          28 :             return papoEntries[i]->pszFullPath;
     202             :     }
     203             : 
     204           0 :     return nullptr;
     205             : }
     206             : 
     207             : /************************************************************************/
     208             : /*                           GetEntryModule()                           */
     209             : /************************************************************************/
     210             : 
     211          34 : const char *SDTS_CATD::GetEntryModule(int iEntry) const
     212             : 
     213             : {
     214          34 :     if (iEntry < 0 || iEntry >= nEntries)
     215           0 :         return nullptr;
     216             : 
     217          34 :     return papoEntries[iEntry]->pszModule;
     218             : }
     219             : 
     220             : /************************************************************************/
     221             : /*                          GetEntryTypeDesc()                          */
     222             : /************************************************************************/
     223             : 
     224             : /**
     225             :  * Fetch the type description of a module in the catalog.
     226             :  *
     227             :  * @param iEntry The module index within the CATD catalog.  A number from
     228             :  * zero to GetEntryCount()-1.
     229             :  *
     230             :  * @return A pointer to an internal string with the type description for
     231             :  * this module.  This is from the CATD file (subfield TYPE of field CATD),
     232             :  * and will be something like "Attribute Primary        ".
     233             :  */
     234             : 
     235           0 : const char *SDTS_CATD::GetEntryTypeDesc(int iEntry) const
     236             : 
     237             : {
     238           0 :     if (iEntry < 0 || iEntry >= nEntries)
     239           0 :         return nullptr;
     240             : 
     241           0 :     return papoEntries[iEntry]->pszType;
     242             : }
     243             : 
     244             : /************************************************************************/
     245             : /*                            GetEntryType()                            */
     246             : /************************************************************************/
     247             : 
     248             : /**
     249             :  * Fetch the enumerated type of a module in the catalog.
     250             :  *
     251             :  * @param iEntry The module index within the CATD catalog.  A number from
     252             :  * zero to GetEntryCount()-1.
     253             :  *
     254             :  * @return A value from the SDTSLayerType enumeration indicating the type of
     255             :  * the module, and indicating the corresponding type of reader.<p>
     256             :  *
     257             :  * <ul>
     258             :  * <li> SLTPoint: Read with SDTSPointReader, underlying type of
     259             :  * <tt>Point-Node</tt>.
     260             :  * <li> SLTLine: Read with SDTSLineReader, underlying type of
     261             :  * <tt>Line</tt>.
     262             :  * <li> SLTAttr: Read with SDTSAttrReader, underlying type of
     263             :  * <tt>Attribute Primary</tt> or <tt>Attribute Secondary</tt>.
     264             :  * <li> SLTPolygon: Read with SDTSPolygonReader, underlying type of
     265             :  * <tt>Polygon</tt>.
     266             :  * </ul>
     267             :  */
     268             : 
     269        1281 : SDTSLayerType SDTS_CATD::GetEntryType(int iEntry) const
     270             : 
     271             : {
     272        1281 :     if (iEntry < 0 || iEntry >= nEntries)
     273           0 :         return SLTUnknown;
     274             : 
     275        1281 :     else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Attribute Primary"))
     276         600 :         return SLTAttr;
     277             : 
     278         681 :     else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType,
     279             :                             "Attribute Secondary"))
     280           0 :         return SLTAttr;
     281             : 
     282         681 :     else if (EQUAL(papoEntries[iEntry]->pszType, "Line") ||
     283         681 :              STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Line "))
     284          93 :         return SLTLine;
     285             : 
     286         588 :     else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Point-Node"))
     287         411 :         return SLTPoint;
     288             : 
     289         177 :     else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Polygon"))
     290         121 :         return SLTPoly;
     291             : 
     292          56 :     else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Cell"))
     293           6 :         return SLTRaster;
     294             : 
     295             :     else
     296          50 :         return SLTUnknown;
     297             : }
     298             : 
     299             : /************************************************************************/
     300             : /*                       SetEntryTypeUnknown()                          */
     301             : /************************************************************************/
     302             : 
     303           0 : void SDTS_CATD::SetEntryTypeUnknown(int iEntry)
     304             : {
     305           0 :     if (iEntry >= 0 && iEntry < nEntries)
     306             :     {
     307           0 :         CPLFree(papoEntries[iEntry]->pszType);
     308           0 :         papoEntries[iEntry]->pszType = CPLStrdup("Unknown");
     309             :     }
     310           0 : }
     311             : 
     312             : /************************************************************************/
     313             : /*                          GetEntryFilePath()                          */
     314             : /************************************************************************/
     315             : 
     316             : /**
     317             :  * Fetch the full filename of the requested module.
     318             :  *
     319             :  * @param iEntry The module index within the CATD catalog.  A number from
     320             :  * zero to GetEntryCount()-1.
     321             :  *
     322             :  * @return A pointer to an internal string containing the filename.  This
     323             :  * string should not be altered, or freed by the application.
     324             :  */
     325             : 
     326           8 : const char *SDTS_CATD::GetEntryFilePath(int iEntry) const
     327             : 
     328             : {
     329           8 :     if (iEntry < 0 || iEntry >= nEntries)
     330           0 :         return nullptr;
     331             : 
     332           8 :     return papoEntries[iEntry]->pszFullPath;
     333             : }

Generated by: LCOV version 1.14