Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: OpenGIS Simple Features Reference Implementation 4 : * Purpose: Implements OGRMiraMonDriver class. 5 : * Author: Abel Pau 6 : ****************************************************************************** 7 : * Copyright (c) 2024, Xavier Pons 8 : * 9 : * SPDX-License-Identifier: MIT 10 : ****************************************************************************/ 11 : 12 : #include "ogrmiramon.h" 13 : 14 : #include <cmath> 15 : 16 233 : bool MM_IsNANDouble(double x) 17 : { 18 233 : return std::isnan(x); 19 : } 20 : 21 233 : bool MM_IsDoubleInfinite(double x) 22 : { 23 233 : return std::isinf(x); 24 : } 25 : 26 : /****************************************************************************/ 27 : /* OGRMMDriverIdentify() */ 28 : /****************************************************************************/ 29 : 30 43006 : static int OGRMiraMonDriverIdentify(GDALOpenInfo *poOpenInfo) 31 : 32 : { 33 43006 : if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 7) 34 42112 : return FALSE; 35 894 : else if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "PNT") || 36 1643 : EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "ARC") || 37 749 : EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "POL")) 38 : { 39 : // Format 40 241 : if ((poOpenInfo->pabyHeader[0] == 'P' && 41 181 : poOpenInfo->pabyHeader[1] == 'N' && 42 85 : poOpenInfo->pabyHeader[2] == 'T') || 43 156 : (poOpenInfo->pabyHeader[0] == 'A' && 44 60 : poOpenInfo->pabyHeader[1] == 'R' && 45 60 : poOpenInfo->pabyHeader[2] == 'C') || 46 96 : (poOpenInfo->pabyHeader[0] == 'P' && 47 96 : poOpenInfo->pabyHeader[1] == 'O' && 48 96 : poOpenInfo->pabyHeader[2] == 'L')) 49 : { 50 : // Version 1.1 or 2.0 51 241 : if ((poOpenInfo->pabyHeader[3] == ' ' && 52 241 : poOpenInfo->pabyHeader[4] == '1' && 53 226 : poOpenInfo->pabyHeader[5] == '.' && 54 226 : poOpenInfo->pabyHeader[6] == '1') || 55 15 : (poOpenInfo->pabyHeader[3] == ' ' && 56 15 : poOpenInfo->pabyHeader[4] == '2' && 57 12 : poOpenInfo->pabyHeader[5] == '.' && 58 12 : poOpenInfo->pabyHeader[6] == '0')) 59 : { 60 238 : return TRUE; 61 : } 62 : } 63 : } 64 : 65 656 : return FALSE; 66 : } 67 : 68 : /****************************************************************************/ 69 : /* OGRMiraMonDriverOpen() */ 70 : /****************************************************************************/ 71 : 72 119 : static GDALDataset *OGRMiraMonDriverOpen(GDALOpenInfo *poOpenInfo) 73 : 74 : { 75 119 : if (OGRMiraMonDriverIdentify(poOpenInfo) == FALSE) 76 0 : return nullptr; 77 : 78 238 : auto poDS = std::make_unique<OGRMiraMonDataSource>(); 79 238 : if (!poDS->Open(poOpenInfo->pszFilename, nullptr, nullptr, 80 119 : poOpenInfo->papszOpenOptions)) 81 : { 82 8 : poDS.reset(); 83 : } 84 : 85 119 : if (poDS && poOpenInfo->eAccess == GA_Update) 86 : { 87 0 : CPLError(CE_Failure, CPLE_OpenFailed, 88 : "MiraMonVector driver does not support update."); 89 0 : return nullptr; 90 : } 91 : 92 119 : return poDS.release(); 93 : } 94 : 95 : /****************************************************************************/ 96 : /* OGRMiraMonDriverCreate() */ 97 : /****************************************************************************/ 98 : 99 : static GDALDataset * 100 67 : OGRMiraMonDriverCreate(const char *pszName, CPL_UNUSED int /*nBands*/, 101 : CPL_UNUSED int /*nXSize*/, CPL_UNUSED int /*nYSize*/, 102 : CPL_UNUSED GDALDataType /*eDT*/, char **papszOptions) 103 : { 104 134 : auto poDS = std::make_unique<OGRMiraMonDataSource>(); 105 : 106 67 : if (!poDS->Create(pszName, papszOptions)) 107 : { 108 0 : poDS.reset(); 109 : } 110 : 111 134 : return poDS.release(); 112 : } 113 : 114 : /****************************************************************************/ 115 : /* RegisterOGRMM() */ 116 : /****************************************************************************/ 117 : 118 1595 : void RegisterOGRMiraMon() 119 : 120 : { 121 1595 : if (GDALGetDriverByName("MiraMonVector") != nullptr) 122 302 : return; 123 : 124 1293 : GDALDriver *poDriver = new GDALDriver(); 125 1293 : poDriver->SetDescription("MiraMonVector"); 126 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 127 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES"); 128 1293 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); 129 1293 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 130 1293 : "MiraMon Vectors (.pol, .arc, .pnt)"); 131 1293 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "pol arc pnt"); 132 1293 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, 133 1293 : "drivers/vector/miramon.html"); 134 1293 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 135 1293 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); 136 : 137 1293 : poDriver->SetMetadataItem( 138 : GDAL_DMD_OPENOPTIONLIST, 139 : "<OpenOptionList>" 140 : " <Option name='Height' scope='vector' type='string-select' " 141 : " description='Sets which of the possible heights is chosen: " 142 : "the first, the highest or the lowest one.'>" 143 : " <Value>First</Value>" 144 : " <Value>Lowest</Value>" 145 : " <Value>Highest</Value>" 146 : " </Option>" 147 : " <Option name='MultiRecordIndex' scope='vector' type='string' " 148 : " description='Sets which of the possible records is chosen: " 149 : "0, 1, 2,... or the Last one. Use JSON when a serialized " 150 : "JSON is wanted'>" 151 : " </Option>" 152 : " <Option name='OpenLanguage' scope='vector' type='string-select' " 153 : " description='If the layer to be opened is multilingual " 154 : "(in fact the *.rel* file), this parameter sets the language " 155 : "to be read.'>" 156 : " <Value>ENG</Value>" 157 : " <Value>CAT</Value>" 158 : " <Value>SPA</Value>" 159 : " </Option>" 160 1293 : "</OpenOptionList>"); 161 : 162 1293 : poDriver->SetMetadataItem( 163 : GDAL_DS_LAYER_CREATIONOPTIONLIST, 164 : "<LayerCreationOptionList>" 165 : " <Option name='Version' type='string-select' description='Version of " 166 : "the file. " 167 : "V1.1 is a limited 32 bits for FID and for internal offsets. " 168 : "V2.0 is the 64 bits version, with practically no limits for FID nor " 169 : "for internal offsets.' " 170 : "default='last_version'>" 171 : "<Value>V1.1</Value>" 172 : "<Value>V2.0</Value>" 173 : "<Value>last_version</Value>" 174 : "</Option>" 175 : " <Option name='DBFEncoding' type='string-select' " 176 : "description='Encoding of " 177 : "the " 178 : ".dbf files." 179 : "MiraMon can write *.dbf* files in these two charsets.' " 180 : "default='ANSI'>" 181 : "<Value>UTF8</Value>" 182 : "<Value>ANSI</Value>" 183 : "</Option>" 184 : " <Option name='CreationLanguage' scope='vector' type='string-select' " 185 : " description='If the layer to be opened is multilingual " 186 : "(in fact the *.rel* file), this parameter sets the language " 187 : "to be read.'>" 188 : " <Value>ENG</Value>" 189 : " <Value>CAT</Value>" 190 : " <Value>SPA</Value>" 191 : " </Option>" 192 1293 : "</LayerCreationOptionList>"); 193 : 194 1293 : poDriver->SetMetadataItem( 195 : GDAL_DMD_CREATIONFIELDDATATYPES, 196 : "Integer Integer64 Real String Date Time " 197 1293 : "Binary IntegerList Integer64List RealList StringList"); 198 1293 : poDriver->pfnOpen = OGRMiraMonDriverOpen; 199 1293 : poDriver->pfnIdentify = OGRMiraMonDriverIdentify; 200 1293 : poDriver->pfnCreate = OGRMiraMonDriverCreate; 201 : 202 1293 : GetGDALDriverManager()->RegisterDriver(poDriver); 203 : }