/src/gdal/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: Interlis 1 Translator |
4 | | * Purpose: Implements OGRILI1DataSource class. |
5 | | * Author: Pirmin Kalberer, Sourcepole AG |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG |
9 | | * Copyright (c) 2007-2008, Even Rouault <even dot rouault at spatialys.com> |
10 | | * |
11 | | * SPDX-License-Identifier: MIT |
12 | | ****************************************************************************/ |
13 | | |
14 | | #include "cpl_conv.h" |
15 | | #include "cpl_string.h" |
16 | | |
17 | | #include "ili1reader.h" |
18 | | #include "ogr_ili1.h" |
19 | | |
20 | | #include <string> |
21 | | |
22 | | /************************************************************************/ |
23 | | /* OGRILI1DataSource() */ |
24 | | /************************************************************************/ |
25 | | |
26 | | OGRILI1DataSource::OGRILI1DataSource() |
27 | 17.4k | : poImdReader(new ImdReader(1)), poReader(nullptr), nLayers(0), |
28 | 17.4k | papoLayers(nullptr) |
29 | 17.4k | { |
30 | 17.4k | } |
31 | | |
32 | | /************************************************************************/ |
33 | | /* ~OGRILI1DataSource() */ |
34 | | /************************************************************************/ |
35 | | |
36 | | OGRILI1DataSource::~OGRILI1DataSource() |
37 | | |
38 | 17.4k | { |
39 | 17.4k | for (int i = 0; i < nLayers; i++) |
40 | 0 | { |
41 | 0 | delete papoLayers[i]; |
42 | 0 | } |
43 | 17.4k | CPLFree(papoLayers); |
44 | | |
45 | 17.4k | DestroyILI1Reader(poReader); |
46 | 17.4k | delete poImdReader; |
47 | 17.4k | } |
48 | | |
49 | | /************************************************************************/ |
50 | | /* Open() */ |
51 | | /************************************************************************/ |
52 | | |
53 | | int OGRILI1DataSource::Open(const char *pszNewName, char **papszOpenOptionsIn, |
54 | | int bTestOpen) |
55 | | |
56 | 17.4k | { |
57 | 17.4k | if (strlen(pszNewName) == 0) |
58 | 0 | { |
59 | 0 | return FALSE; |
60 | 0 | } |
61 | | |
62 | 17.4k | std::string osBasename; |
63 | 17.4k | std::string osModelFilename; |
64 | 17.4k | if (CSLFetchNameValue(papszOpenOptionsIn, "MODEL") != nullptr) |
65 | 0 | { |
66 | 0 | osBasename = pszNewName; |
67 | 0 | osModelFilename = CSLFetchNameValue(papszOpenOptionsIn, "MODEL"); |
68 | 0 | } |
69 | 17.4k | else |
70 | 17.4k | { |
71 | 17.4k | char **filenames = CSLTokenizeString2(pszNewName, ",", 0); |
72 | 17.4k | int nCount = CSLCount(filenames); |
73 | 17.4k | if (nCount == 0) |
74 | 0 | { |
75 | 0 | CSLDestroy(filenames); |
76 | 0 | return FALSE; |
77 | 0 | } |
78 | 17.4k | osBasename = filenames[0]; |
79 | | |
80 | 17.4k | if (nCount > 1) |
81 | 8.89k | osModelFilename = filenames[1]; |
82 | | |
83 | 17.4k | CSLDestroy(filenames); |
84 | 17.4k | } |
85 | | |
86 | | /* -------------------------------------------------------------------- */ |
87 | | /* Open the source file. */ |
88 | | /* -------------------------------------------------------------------- */ |
89 | 17.4k | VSILFILE *fp = VSIFOpenL(osBasename.c_str(), "r"); |
90 | 17.4k | if (fp == nullptr) |
91 | 8.48k | { |
92 | 8.48k | if (!bTestOpen) |
93 | 0 | CPLError(CE_Failure, CPLE_OpenFailed, |
94 | 0 | "Failed to open ILI1 file `%s'.", pszNewName); |
95 | | |
96 | 8.48k | return FALSE; |
97 | 8.48k | } |
98 | | |
99 | | /* -------------------------------------------------------------------- */ |
100 | | /* If we aren't sure it is ILI1, load a header chunk and check */ |
101 | | /* for signs it is ILI1 */ |
102 | | /* -------------------------------------------------------------------- */ |
103 | 8.93k | char szHeader[1000]; |
104 | | |
105 | 8.93k | if (bTestOpen) |
106 | 8.93k | { |
107 | 8.93k | int nLen = (int)VSIFReadL(szHeader, 1, sizeof(szHeader), fp); |
108 | 8.93k | if (nLen == sizeof(szHeader)) |
109 | 6.62k | szHeader[sizeof(szHeader) - 1] = '\0'; |
110 | 2.30k | else |
111 | 2.30k | szHeader[nLen] = '\0'; |
112 | | |
113 | 8.93k | if (strstr(szHeader, "SCNT") == nullptr) |
114 | 1.24k | { |
115 | 1.24k | VSIFCloseL(fp); |
116 | 1.24k | return FALSE; |
117 | 1.24k | } |
118 | 8.93k | } |
119 | | |
120 | | /* -------------------------------------------------------------------- */ |
121 | | /* We assume now that it is ILI1. Close and instantiate a */ |
122 | | /* ILI1Reader on it. */ |
123 | | /* -------------------------------------------------------------------- */ |
124 | 7.69k | VSIFCloseL(fp); |
125 | | |
126 | 7.69k | poReader = CreateILI1Reader(); |
127 | 7.69k | if (poReader == nullptr) |
128 | 0 | { |
129 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
130 | 0 | "File %s appears to be ILI1 but the ILI1 reader cannot\n" |
131 | 0 | "be instantiated, likely because Xerces support was not\n" |
132 | 0 | "configured in.", |
133 | 0 | pszNewName); |
134 | 0 | return FALSE; |
135 | 0 | } |
136 | | |
137 | 7.69k | poReader->OpenFile(osBasename.c_str()); |
138 | | |
139 | 7.69k | if (osModelFilename.length() > 0) |
140 | 0 | poReader->ReadModel(poImdReader, osModelFilename.c_str(), this); |
141 | | |
142 | 7.69k | CPLConfigOptionSetter oSetter("OGR_ARC_STEPSIZE", "0.96", |
143 | 7.69k | /* bSetOnlyIfUndefined = */ true); |
144 | | |
145 | | // Parse model and read data - without surface join and area polygonizing. |
146 | 7.69k | poReader->ReadFeatures(); |
147 | | |
148 | 7.69k | return TRUE; |
149 | 7.69k | } |
150 | | |
151 | | /************************************************************************/ |
152 | | /* TestCapability() */ |
153 | | /************************************************************************/ |
154 | | |
155 | | int OGRILI1DataSource::TestCapability(const char *pszCap) |
156 | | |
157 | 0 | { |
158 | 0 | if (EQUAL(pszCap, ODsCCurveGeometries)) |
159 | 0 | return TRUE; |
160 | 0 | else if (EQUAL(pszCap, ODsCZGeometries)) |
161 | 0 | return TRUE; |
162 | | |
163 | 0 | return FALSE; |
164 | 0 | } |
165 | | |
166 | | /************************************************************************/ |
167 | | /* GetLayer() */ |
168 | | /************************************************************************/ |
169 | | |
170 | | OGRLayer *OGRILI1DataSource::GetLayer(int iLayer) |
171 | 4.58k | { |
172 | 4.58k | if (!poReader) |
173 | 0 | { |
174 | 0 | if (iLayer < 0 || iLayer >= nLayers) |
175 | 0 | return nullptr; |
176 | 0 | return papoLayers[iLayer]; |
177 | 0 | } |
178 | 4.58k | return poReader->GetLayer(iLayer); |
179 | 4.58k | } |
180 | | |
181 | | /************************************************************************/ |
182 | | /* GetLayerByName() */ |
183 | | /************************************************************************/ |
184 | | |
185 | | OGRILI1Layer *OGRILI1DataSource::GetLayerByName(const char *pszLayerName) |
186 | 1.06k | { |
187 | 1.06k | if (!poReader) |
188 | 0 | { |
189 | 0 | return cpl::down_cast<OGRILI1Layer *>( |
190 | 0 | GDALDataset::GetLayerByName(pszLayerName)); |
191 | 0 | } |
192 | | |
193 | 1.06k | return cpl::down_cast<OGRILI1Layer *>( |
194 | 1.06k | poReader->GetLayerByName(pszLayerName)); |
195 | 1.06k | } |