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