Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: GPX Translator 4 : * Purpose: Implements OGRGPXDriver. 5 : * Author: Even Rouault, even dot rouault at spatialys.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2007-2008, Even Rouault <even dot rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #include "cpl_port.h" 14 : #include "ogr_gpx.h" 15 : 16 : #include <cstring> 17 : 18 : #include "cpl_conv.h" 19 : #include "cpl_error.h" 20 : #include "cpl_vsi.h" 21 : #include "gdal.h" 22 : #include "gdal_priv.h" 23 : #include "ogr_core.h" 24 : 25 : /************************************************************************/ 26 : /* Identify() */ 27 : /************************************************************************/ 28 : 29 47973 : static int OGRGPXDriverIdentify(GDALOpenInfo *poOpenInfo) 30 : 31 : { 32 47973 : if (poOpenInfo->eAccess == GA_Update || poOpenInfo->fpL == nullptr) 33 44002 : return false; 34 : 35 3971 : return strstr(reinterpret_cast<const char *>(poOpenInfo->pabyHeader), 36 3971 : "<gpx") != nullptr; 37 : } 38 : 39 : /************************************************************************/ 40 : /* Open() */ 41 : /************************************************************************/ 42 : 43 29 : static GDALDataset *OGRGPXDriverOpen(GDALOpenInfo *poOpenInfo) 44 : 45 : { 46 29 : if (poOpenInfo->eAccess == GA_Update || !OGRGPXDriverIdentify(poOpenInfo)) 47 0 : return nullptr; 48 : 49 29 : OGRGPXDataSource *poDS = new OGRGPXDataSource(); 50 : 51 29 : if (!poDS->Open(poOpenInfo)) 52 : { 53 0 : delete poDS; 54 0 : poDS = nullptr; 55 : } 56 : 57 29 : return poDS; 58 : } 59 : 60 : /************************************************************************/ 61 : /* Create() */ 62 : /************************************************************************/ 63 : 64 : static GDALDataset * 65 25 : OGRGPXDriverCreate(const char *pszName, CPL_UNUSED int nBands, 66 : CPL_UNUSED int nXSize, CPL_UNUSED int nYSize, 67 : CPL_UNUSED GDALDataType eDT, CPL_UNUSED char **papszOptions) 68 : { 69 25 : OGRGPXDataSource *poDS = new OGRGPXDataSource(); 70 : 71 25 : if (!poDS->Create(pszName, papszOptions)) 72 : { 73 1 : delete poDS; 74 1 : poDS = nullptr; 75 : } 76 : 77 25 : return poDS; 78 : } 79 : 80 : /************************************************************************/ 81 : /* Delete() */ 82 : /************************************************************************/ 83 : 84 16 : static CPLErr OGRGPXDriverDelete(const char *pszFilename) 85 : 86 : { 87 16 : if (VSIUnlink(pszFilename) == 0) 88 16 : return CE_None; 89 : else 90 0 : return CE_Failure; 91 : } 92 : 93 : /************************************************************************/ 94 : /* RegisterOGRGPX() */ 95 : /************************************************************************/ 96 : 97 1595 : void RegisterOGRGPX() 98 : 99 : { 100 1595 : if (!GDAL_CHECK_VERSION("OGR/GPX driver")) 101 0 : return; 102 : 103 1595 : if (GDALGetDriverByName("GPX") != nullptr) 104 302 : return; 105 : 106 1293 : GDALDriver *poDriver = new GDALDriver(); 107 : 108 1293 : poDriver->SetDescription("GPX"); 109 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 110 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES"); 111 1293 : poDriver->SetMetadataItem(GDAL_DCAP_DELETE_LAYER, "YES"); 112 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); 113 1293 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); 114 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GPX"); 115 1293 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gpx"); 116 1293 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/vector/gpx.html"); 117 1293 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS, "OGRSQL SQLITE"); 118 : 119 1293 : poDriver->SetMetadataItem( 120 : GDAL_DMD_OPENOPTIONLIST, 121 : "<OpenOptionList>" 122 : " <Option name='N_MAX_LINKS' type='integer' default='2' " 123 : "description='Maximum number of links attributes'/>" 124 : " <Option name='ELE_AS_25D' type='boolean' default='NO' " 125 : "description='Whether to use the value of the ele element as the Z " 126 : "ordinate of geometries'/>" 127 : " <Option name='SHORT_NAMES' type='boolean' default='NO' " 128 : "description='Whether to use short field names (typically for " 129 : "shapefile compatibility'/>" 130 1293 : "</OpenOptionList>"); 131 : 132 1293 : poDriver->SetMetadataItem( 133 : GDAL_DMD_CREATIONOPTIONLIST, 134 : "<CreationOptionList>" 135 : #ifdef _WIN32 136 : " <Option name='LINEFORMAT' type='string-select' " 137 : "description='end-of-line sequence' default='CRLF'>" 138 : #else 139 : " <Option name='LINEFORMAT' type='string-select' " 140 : "description='end-of-line sequence' default='LF'>" 141 : #endif 142 : " <Value>CRLF</Value>" 143 : " <Value>LF</Value>" 144 : " </Option>" 145 : " <Option name='GPX_USE_EXTENSIONS' type='boolean' " 146 : "description='Whether to write non-GPX attributes in an " 147 : "<extensions> tag' default='NO'/>" 148 : " <Option name='GPX_EXTENSIONS_NS' type='string' " 149 : "description='Namespace value used for extension tags' default='ogr'/>" 150 : " <Option name='GPX_EXTENSIONS_NS_URL' type='string' " 151 : "description='Namespace URI' default='http://osgeo.org/gdal'/>" 152 : " <Option name='METADATA_AUTHOR_EMAIL' type='string'/>" 153 : " <Option name='METADATA_AUTHOR_NAME' type='string'/>" 154 : " <Option name='METADATA_AUTHOR_LINK_HREF' type='string'/>" 155 : " <Option name='METADATA_AUTHOR_LINK_TEXT' type='string'/>" 156 : " <Option name='METADATA_AUTHOR_LINK_TYPE' type='string'/>" 157 : " <Option name='METADATA_COPYRIGHT_AUTHOR' type='string'/>" 158 : " <Option name='METADATA_COPYRIGHT_LICENSE' type='string'/>" 159 : " <Option name='METADATA_COPYRIGHT_YEAR' type='string'/>" 160 : " <Option name='METADATA_DESCRIPTION' type='string'/>" 161 : " <Option name='METADATA_KEYWORDS' type='string'/>" 162 : " <Option name='METADATA_LINK_*_HREF' type='string'/>" 163 : " <Option name='METADATA_LINK_*_TEXT' type='string'/>" 164 : " <Option name='METADATA_LINK_*_TYPE' type='string'/>" 165 : " <Option name='METADATA_NAME' type='string'/>" 166 : " <Option name='METADATA_TIME' type='string'/>" 167 : " <Option name='CREATOR' type='string'/>" 168 1293 : "</CreationOptionList>"); 169 : 170 1293 : poDriver->SetMetadataItem( 171 : GDAL_DS_LAYER_CREATIONOPTIONLIST, 172 : "<LayerCreationOptionList>" 173 : " <Option name='FORCE_GPX_TRACK' type='boolean' description='Whether " 174 : "to force layers with geometries of type wkbLineString as tracks' " 175 : "default='NO'/>" 176 : " <Option name='FORCE_GPX_ROUTE' type='boolean' description='Whether " 177 : "to force layers with geometries of type wkbMultiLineString (with " 178 : "single line string in them) as routes' default='NO'/>" 179 1293 : "</LayerCreationOptionList>"); 180 : 181 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 182 1293 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES"); 183 : 184 1293 : poDriver->pfnIdentify = OGRGPXDriverIdentify; 185 1293 : poDriver->pfnOpen = OGRGPXDriverOpen; 186 1293 : poDriver->pfnCreate = OGRGPXDriverCreate; 187 1293 : poDriver->pfnDelete = OGRGPXDriverDelete; 188 : 189 1293 : GetGDALDriverManager()->RegisterDriver(poDriver); 190 : }