Line data Source code
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(); 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 364 : OGRFeatureDefn *GetLayerDefn() override 135 : { 136 364 : return m_poFeatureDefn; 137 : } 138 : 139 : int TestCapability(const char *) 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 54 : OGRGPXDataSource() = default; 207 : ~OGRGPXDataSource(); 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, char **papszOptions); 216 : 217 160 : int GetLayerCount() override 218 : { 219 160 : return static_cast<int>(m_apoLayers.size()); 220 : } 221 : 222 : OGRLayer *GetLayer(int) override; 223 : 224 : OGRLayer *ICreateLayer(const char *pszName, 225 : const OGRGeomFieldDefn *poGeomFieldDefn, 226 : CSLConstList papszOptions) override; 227 : 228 : int TestCapability(const char *) override; 229 : 230 88 : VSILFILE *GetOutputFP() 231 : { 232 88 : return m_fpOutput.get(); 233 : } 234 : 235 49 : void SetLastGPXGeomTypeWritten(GPXGeometryType gpxGeomType) 236 : { 237 49 : m_lastGPXGeomTypeWritten = gpxGeomType; 238 49 : } 239 : 240 105 : GPXGeometryType GetLastGPXGeomTypeWritten() const 241 : { 242 105 : return m_lastGPXGeomTypeWritten; 243 : } 244 : 245 205 : bool GetUseExtensions() const 246 : { 247 205 : return m_bUseExtensions; 248 : } 249 : 250 2 : const std::string &GetExtensionsNS() const 251 : { 252 2 : return m_osExtensionsNS; 253 : } 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 165 : const char *GetVersion() const 261 : { 262 165 : return m_osVersion.c_str(); 263 : } 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 */