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