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 60 : CPLFormCIFilename(pszPrefixPath, poEntry->pszFile, nullptr)); 176 : 177 : /* -------------------------------------------------------------------- 178 : */ 179 : /* Add the entry to the list. */ 180 : /* -------------------------------------------------------------------- 181 : */ 182 120 : papoEntries = reinterpret_cast<SDTS_CATDEntry **>( 183 60 : CPLRealloc(papoEntries, sizeof(void *) * ++nEntries)); 184 60 : papoEntries[nEntries - 1] = poEntry; 185 : } 186 : 187 3 : return nEntries > 0; 188 : } 189 : 190 : /************************************************************************/ 191 : /* GetModuleFilePath() */ 192 : /************************************************************************/ 193 : 194 28 : const char *SDTS_CATD::GetModuleFilePath(const char *pszModule) const 195 : 196 : { 197 188 : for (int i = 0; i < nEntries; i++) 198 : { 199 188 : if (EQUAL(papoEntries[i]->pszModule, pszModule)) 200 28 : return papoEntries[i]->pszFullPath; 201 : } 202 : 203 0 : return nullptr; 204 : } 205 : 206 : /************************************************************************/ 207 : /* GetEntryModule() */ 208 : /************************************************************************/ 209 : 210 34 : const char *SDTS_CATD::GetEntryModule(int iEntry) const 211 : 212 : { 213 34 : if (iEntry < 0 || iEntry >= nEntries) 214 0 : return nullptr; 215 : 216 34 : return papoEntries[iEntry]->pszModule; 217 : } 218 : 219 : /************************************************************************/ 220 : /* GetEntryTypeDesc() */ 221 : /************************************************************************/ 222 : 223 : /** 224 : * Fetch the type description of a module in the catalog. 225 : * 226 : * @param iEntry The module index within the CATD catalog. A number from 227 : * zero to GetEntryCount()-1. 228 : * 229 : * @return A pointer to an internal string with the type description for 230 : * this module. This is from the CATD file (subfield TYPE of field CATD), 231 : * and will be something like "Attribute Primary ". 232 : */ 233 : 234 0 : const char *SDTS_CATD::GetEntryTypeDesc(int iEntry) const 235 : 236 : { 237 0 : if (iEntry < 0 || iEntry >= nEntries) 238 0 : return nullptr; 239 : 240 0 : return papoEntries[iEntry]->pszType; 241 : } 242 : 243 : /************************************************************************/ 244 : /* GetEntryType() */ 245 : /************************************************************************/ 246 : 247 : /** 248 : * Fetch the enumerated type of a module in the catalog. 249 : * 250 : * @param iEntry The module index within the CATD catalog. A number from 251 : * zero to GetEntryCount()-1. 252 : * 253 : * @return A value from the SDTSLayerType enumeration indicating the type of 254 : * the module, and indicating the corresponding type of reader.<p> 255 : * 256 : * <ul> 257 : * <li> SLTPoint: Read with SDTSPointReader, underlying type of 258 : * <tt>Point-Node</tt>. 259 : * <li> SLTLine: Read with SDTSLineReader, underlying type of 260 : * <tt>Line</tt>. 261 : * <li> SLTAttr: Read with SDTSAttrReader, underlying type of 262 : * <tt>Attribute Primary</tt> or <tt>Attribute Secondary</tt>. 263 : * <li> SLTPolygon: Read with SDTSPolygonReader, underlying type of 264 : * <tt>Polygon</tt>. 265 : * </ul> 266 : */ 267 : 268 1281 : SDTSLayerType SDTS_CATD::GetEntryType(int iEntry) const 269 : 270 : { 271 1281 : if (iEntry < 0 || iEntry >= nEntries) 272 0 : return SLTUnknown; 273 : 274 1281 : else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Attribute Primary")) 275 600 : return SLTAttr; 276 : 277 681 : else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, 278 : "Attribute Secondary")) 279 0 : return SLTAttr; 280 : 281 681 : else if (EQUAL(papoEntries[iEntry]->pszType, "Line") || 282 681 : STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Line ")) 283 93 : return SLTLine; 284 : 285 588 : else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Point-Node")) 286 411 : return SLTPoint; 287 : 288 177 : else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Polygon")) 289 121 : return SLTPoly; 290 : 291 56 : else if (STARTS_WITH_CI(papoEntries[iEntry]->pszType, "Cell")) 292 6 : return SLTRaster; 293 : 294 : else 295 50 : return SLTUnknown; 296 : } 297 : 298 : /************************************************************************/ 299 : /* SetEntryTypeUnknown() */ 300 : /************************************************************************/ 301 : 302 0 : void SDTS_CATD::SetEntryTypeUnknown(int iEntry) 303 : { 304 0 : if (iEntry >= 0 && iEntry < nEntries) 305 : { 306 0 : CPLFree(papoEntries[iEntry]->pszType); 307 0 : papoEntries[iEntry]->pszType = CPLStrdup("Unknown"); 308 : } 309 0 : } 310 : 311 : /************************************************************************/ 312 : /* GetEntryFilePath() */ 313 : /************************************************************************/ 314 : 315 : /** 316 : * Fetch the full filename of the requested module. 317 : * 318 : * @param iEntry The module index within the CATD catalog. A number from 319 : * zero to GetEntryCount()-1. 320 : * 321 : * @return A pointer to an internal string containing the filename. This 322 : * string should not be altered, or freed by the application. 323 : */ 324 : 325 8 : const char *SDTS_CATD::GetEntryFilePath(int iEntry) const 326 : 327 : { 328 8 : if (iEntry < 0 || iEntry >= nEntries) 329 0 : return nullptr; 330 : 331 8 : return papoEntries[iEntry]->pszFullPath; 332 : }