Coverage Report

Created: 2026-11-12 08:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 */