/src/gdal/ogr/ogrsf_frmts/gpx/ogr_gpx.h
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: GPX Translator |
4 | | * Purpose: Definition of classes for OGR .gpx driver. |
5 | | * Author: Even Rouault, even dot rouault at spatialys.com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2007-2010, Even Rouault <even dot rouault at spatialys.com> |
9 | | * |
10 | | * SPDX-License-Identifier: MIT |
11 | | ****************************************************************************/ |
12 | | |
13 | | #ifndef OGR_GPX_H_INCLUDED |
14 | | #define OGR_GPX_H_INCLUDED |
15 | | |
16 | | #include "cpl_vsi_virtual.h" |
17 | | #include "ogrsf_frmts.h" |
18 | | |
19 | | #ifdef HAVE_EXPAT |
20 | | #include "ogr_expat.h" |
21 | | #endif |
22 | | |
23 | | #include <limits> |
24 | | #include <deque> |
25 | | |
26 | | class OGRGPXDataSource; |
27 | | |
28 | | typedef enum |
29 | | { |
30 | | GPX_NONE, |
31 | | GPX_WPT, |
32 | | GPX_TRACK, |
33 | | GPX_ROUTE, |
34 | | GPX_ROUTE_POINT, |
35 | | GPX_TRACK_POINT, |
36 | | } GPXGeometryType; |
37 | | |
38 | | constexpr int PARSER_BUF_SIZE = 8192; |
39 | | |
40 | | /************************************************************************/ |
41 | | /* OGRGPXLayer */ |
42 | | /************************************************************************/ |
43 | | |
44 | | class OGRGPXLayer final : public OGRLayer |
45 | | { |
46 | | OGRFeatureDefn *m_poFeatureDefn = nullptr; |
47 | | OGRSpatialReference *m_poSRS = nullptr; |
48 | | OGRGPXDataSource *m_poDS = nullptr; |
49 | | |
50 | | GPXGeometryType m_gpxGeomType = GPX_NONE; |
51 | | |
52 | | int m_nGPXFields = 0; |
53 | | |
54 | | bool m_bWriteMode = false; |
55 | | GIntBig m_nNextFID = 0; |
56 | | VSIVirtualHandleUniquePtr m_fpGPX{}; |
57 | | #ifdef HAVE_EXPAT |
58 | | XML_Parser m_oParser = nullptr; |
59 | | XML_Parser m_oSchemaParser = nullptr; |
60 | | #endif |
61 | | bool m_inInterestingElement = false; |
62 | | bool m_hasFoundLat = false; |
63 | | bool m_hasFoundLon = false; |
64 | | #ifdef HAVE_EXPAT |
65 | | double m_latVal = 0; |
66 | | double m_lonVal = 0; |
67 | | #endif |
68 | | std::string m_osSubElementName{}; |
69 | | std::string m_osSubElementValue{}; |
70 | | #ifdef HAVE_EXPAT |
71 | | int m_iCurrentField = 0; |
72 | | #endif |
73 | | |
74 | | std::unique_ptr<OGRFeature> m_poFeature{}; |
75 | | std::deque<std::unique_ptr<OGRFeature>> m_oFeatureQueue{}; |
76 | | |
77 | | std::unique_ptr<OGRMultiLineString> m_multiLineString{}; |
78 | | std::unique_ptr<OGRLineString> m_lineString{}; |
79 | | |
80 | | int m_depthLevel = 0; |
81 | | int m_interestingDepthLevel = 0; |
82 | | |
83 | | #ifdef HAVE_EXPAT |
84 | | OGRFieldDefn *m_currentFieldDefn = nullptr; |
85 | | bool m_inExtensions = false; |
86 | | int m_extensionsDepthLevel = 0; |
87 | | |
88 | | bool m_inLink = 0; |
89 | | int m_iCountLink = 0; |
90 | | #endif |
91 | | int m_nMaxLinks = 0; |
92 | | |
93 | | bool m_bEleAs25D = false; |
94 | | |
95 | | int m_trkFID = 0; |
96 | | int m_trkSegId = 0; |
97 | | int m_trkSegPtId = 0; |
98 | | |
99 | | int m_rteFID = 0; |
100 | | int m_rtePtId = 0; |
101 | | |
102 | | #ifdef HAVE_EXPAT |
103 | | bool m_bStopParsing = false; |
104 | | int m_nWithoutEventCounter = 0; |
105 | | int m_nDataHandlerCounter = 0; |
106 | | #endif |
107 | | |
108 | | int m_iFirstGPXField = 0; |
109 | | |
110 | | CPL_DISALLOW_COPY_ASSIGN(OGRGPXLayer) |
111 | | |
112 | | private: |
113 | | void WriteFeatureAttributes(const OGRFeature *poFeature, |
114 | | int nIdentLevel = 1); |
115 | | void LoadExtensionsSchema(); |
116 | | #ifdef HAVE_EXPAT |
117 | | void AddStrToSubElementValue(const char *pszStr); |
118 | | #endif |
119 | | bool OGRGPX_WriteXMLExtension(const char *pszTagName, |
120 | | const char *pszContent); |
121 | | |
122 | | public: |
123 | | OGRGPXLayer(const char *pszFilename, const char *layerName, |
124 | | GPXGeometryType gpxGeomType, OGRGPXDataSource *poDS, |
125 | | bool bWriteMode, CSLConstList papszOpenOptions); |
126 | | ~OGRGPXLayer() override; |
127 | | |
128 | | void ResetReading() override; |
129 | | OGRFeature *GetNextFeature() override; |
130 | | |
131 | | OGRErr ICreateFeature(OGRFeature *poFeature) override; |
132 | | OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override; |
133 | | |
134 | | const OGRFeatureDefn *GetLayerDefn() const override |
135 | 53.9k | { |
136 | 53.9k | return m_poFeatureDefn; |
137 | 53.9k | } |
138 | | |
139 | | bool TestCapability(const char *) const override; |
140 | | |
141 | | GDALDataset *GetDataset() override; |
142 | | |
143 | | #ifdef HAVE_EXPAT |
144 | | void startElementCbk(const char *pszName, const char **ppszAttr); |
145 | | void endElementCbk(const char *pszName); |
146 | | void dataHandlerCbk(const char *data, int nLen); |
147 | | |
148 | | void startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr); |
149 | | void endElementLoadSchemaCbk(const char *pszName); |
150 | | void dataHandlerLoadSchemaCbk(const char *data, int nLen); |
151 | | #endif |
152 | | |
153 | | static OGRErr CheckAndFixCoordinatesValidity(double *pdfLatitude, |
154 | | double *pdfLongitude); |
155 | | }; |
156 | | |
157 | | /************************************************************************/ |
158 | | /* OGRGPXDataSource */ |
159 | | /************************************************************************/ |
160 | | |
161 | | typedef enum |
162 | | { |
163 | | GPX_VALIDITY_UNKNOWN, |
164 | | GPX_VALIDITY_INVALID, |
165 | | GPX_VALIDITY_VALID |
166 | | } OGRGPXValidity; |
167 | | |
168 | | class OGRGPXDataSource final : public GDALDataset |
169 | | { |
170 | | std::vector<std::unique_ptr<OGRGPXLayer>> m_apoLayers{}; |
171 | | |
172 | | /* Export related */ |
173 | | VSIVirtualHandleUniquePtr m_fpOutput{}; |
174 | | bool m_bIsBackSeekable = true; |
175 | | const char *m_pszEOL = "\n"; |
176 | | vsi_l_offset m_nOffsetBounds = 0; |
177 | | double m_dfMinLat = std::numeric_limits<double>::infinity(); |
178 | | double m_dfMinLon = std::numeric_limits<double>::infinity(); |
179 | | double m_dfMaxLat = -std::numeric_limits<double>::infinity(); |
180 | | double m_dfMaxLon = -std::numeric_limits<double>::infinity(); |
181 | | |
182 | | GPXGeometryType m_lastGPXGeomTypeWritten = GPX_NONE; |
183 | | |
184 | | bool m_bUseExtensions = false; |
185 | | std::string m_osExtensionsNS{}; |
186 | | |
187 | | #ifdef HAVE_EXPAT |
188 | | OGRGPXValidity m_validity = GPX_VALIDITY_UNKNOWN; |
189 | | std::string m_osVersion{}; |
190 | | XML_Parser m_oCurrentParser = nullptr; |
191 | | int m_nDataHandlerCounter = 0; |
192 | | bool m_bInMetadata = false; |
193 | | bool m_bInMetadataAuthor = false; |
194 | | bool m_bInMetadataAuthorLink = false; |
195 | | bool m_bInMetadataCopyright = false; |
196 | | bool m_bInMetadataLink = false; |
197 | | int m_nMetadataLinkCounter = 0; |
198 | | int m_nDepth = 0; |
199 | | std::string m_osMetadataKey{}; |
200 | | std::string m_osMetadataValue{}; |
201 | | #endif |
202 | | |
203 | | CPL_DISALLOW_COPY_ASSIGN(OGRGPXDataSource) |
204 | | |
205 | | public: |
206 | 1.69k | OGRGPXDataSource() = default; |
207 | | ~OGRGPXDataSource() override; |
208 | | |
209 | | int m_nLastRteId = -1; |
210 | | int m_nLastTrkId = -1; |
211 | | int m_nLastTrkSegId = -1; |
212 | | |
213 | | int Open(GDALOpenInfo *poOpenInfo); |
214 | | |
215 | | int Create(const char *pszFilename, CSLConstList papszOptions); |
216 | | |
217 | | int GetLayerCount() const override |
218 | 1.46k | { |
219 | 1.46k | return static_cast<int>(m_apoLayers.size()); |
220 | 1.46k | } |
221 | | |
222 | | const OGRLayer *GetLayer(int) const override; |
223 | | |
224 | | OGRLayer *ICreateLayer(const char *pszName, |
225 | | const OGRGeomFieldDefn *poGeomFieldDefn, |
226 | | CSLConstList papszOptions) override; |
227 | | |
228 | | bool TestCapability(const char *) const override; |
229 | | |
230 | | VSILFILE *GetOutputFP() |
231 | 96.8k | { |
232 | 96.8k | return m_fpOutput.get(); |
233 | 96.8k | } |
234 | | |
235 | | void SetLastGPXGeomTypeWritten(GPXGeometryType gpxGeomType) |
236 | 48.4k | { |
237 | 48.4k | m_lastGPXGeomTypeWritten = gpxGeomType; |
238 | 48.4k | } |
239 | | |
240 | | GPXGeometryType GetLastGPXGeomTypeWritten() const |
241 | 98.0k | { |
242 | 98.0k | return m_lastGPXGeomTypeWritten; |
243 | 98.0k | } |
244 | | |
245 | | bool GetUseExtensions() const |
246 | 3.34k | { |
247 | 3.34k | return m_bUseExtensions; |
248 | 3.34k | } |
249 | | |
250 | | const std::string &GetExtensionsNS() const |
251 | 0 | { |
252 | 0 | return m_osExtensionsNS; |
253 | 0 | } |
254 | | |
255 | | #ifdef HAVE_EXPAT |
256 | | void startElementValidateCbk(const char *pszName, const char **ppszAttr); |
257 | | void endElementValidateCbk(const char *pszName); |
258 | | void dataHandlerValidateCbk(const char *data, int nLen); |
259 | | |
260 | | const char *GetVersion() const |
261 | 1.83k | { |
262 | 1.83k | return m_osVersion.c_str(); |
263 | 1.83k | } |
264 | | #endif |
265 | | |
266 | | void AddCoord(double dfLon, double dfLat); |
267 | | |
268 | | void PrintLine(const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3); |
269 | | }; |
270 | | |
271 | | #endif /* ndef OGR_GPX_H_INCLUDED */ |