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 119 : bool MM_IsNANDouble(double x) 17 : { 18 119 : return std::isnan(x); 19 : } 20 : 21 119 : bool MM_IsDoubleInfinite(double x) 22 : { 23 119 : return std::isinf(x); 24 : } 25 : 26 : /************************************************************************/ 27 : /* OGRMMDriverIdentify() */ 28 : /************************************************************************/ 29 : 30 52362 : static int OGRMiraMonDriverIdentify(GDALOpenInfo *poOpenInfo) 31 : 32 : { 33 52362 : if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 7) 34 51101 : return FALSE; 35 2435 : else if (poOpenInfo->IsExtensionEqualToCI("PNT") || 36 2435 : poOpenInfo->IsExtensionEqualToCI("ARC") || 37 1112 : poOpenInfo->IsExtensionEqualToCI("POL")) 38 : { 39 : // Format 40 245 : if ((poOpenInfo->pabyHeader[0] == 'P' && 41 183 : poOpenInfo->pabyHeader[1] == 'N' && 42 87 : poOpenInfo->pabyHeader[2] == 'T') || 43 158 : (poOpenInfo->pabyHeader[0] == 'A' && 44 62 : poOpenInfo->pabyHeader[1] == 'R' && 45 62 : 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 245 : if ((poOpenInfo->pabyHeader[3] == ' ' && 52 245 : poOpenInfo->pabyHeader[4] == '1' && 53 230 : poOpenInfo->pabyHeader[5] == '.' && 54 230 : 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 242 : return TRUE; 61 : } 62 : } 63 : } 64 : 65 1019 : return FALSE; 66 : } 67 : 68 : /************************************************************************/ 69 : /* OGRMiraMonDriverOpen() */ 70 : /************************************************************************/ 71 : 72 121 : static GDALDataset *OGRMiraMonDriverOpen(GDALOpenInfo *poOpenInfo) 73 : 74 : { 75 121 : if (OGRMiraMonDriverIdentify(poOpenInfo) == FALSE) 76 0 : return nullptr; 77 : 78 242 : auto poDS = std::make_unique<OGRMiraMonDataSource>(); 79 242 : if (!poDS->Open(poOpenInfo->pszFilename, nullptr, nullptr, 80 121 : poOpenInfo->papszOpenOptions)) 81 : { 82 8 : poDS.reset(); 83 : } 84 : 85 121 : if (poDS && poOpenInfo->eAccess == GA_Update) 86 : { 87 0 : GDALDataset::ReportUpdateNotSupportedByDriver("MiraMonVector"); 88 0 : return nullptr; 89 : } 90 : 91 121 : return poDS.release(); 92 : } 93 : 94 : /************************************************************************/ 95 : /* OGRMiraMonDriverCreate() */ 96 : /************************************************************************/ 97 : 98 69 : static GDALDataset *OGRMiraMonDriverCreate(const char *pszName, 99 : CPL_UNUSED int /*nBands*/, 100 : CPL_UNUSED int /*nXSize*/, 101 : CPL_UNUSED int /*nYSize*/, 102 : CPL_UNUSED GDALDataType /*eDT*/, 103 : CSLConstList papszOptions) 104 : { 105 138 : auto poDS = std::make_unique<OGRMiraMonDataSource>(); 106 : 107 69 : if (!poDS->Create(pszName, papszOptions)) 108 : { 109 0 : poDS.reset(); 110 : } 111 : 112 138 : return poDS.release(); 113 : } 114 : 115 : /************************************************************************/ 116 : /* RegisterOGRMM() */ 117 : /************************************************************************/ 118 : 119 2059 : void RegisterOGRMiraMon() 120 : 121 : { 122 2059 : if (GDALGetDriverByName("MiraMonVector") != nullptr) 123 283 : return; 124 : 125 1776 : GDALDriver *poDriver = new GDALDriver(); 126 1776 : poDriver->SetDescription("MiraMonVector"); 127 1776 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 128 1776 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES"); 129 1776 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES"); 130 1776 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); 131 1776 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 132 1776 : "MiraMon Vectors (.pol, .arc, .pnt)"); 133 1776 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "pol arc pnt"); 134 1776 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, 135 1776 : "drivers/vector/miramon.html"); 136 1776 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 137 1776 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); 138 : 139 1776 : poDriver->SetMetadataItem( 140 : GDAL_DMD_OPENOPTIONLIST, 141 : "<OpenOptionList>" 142 : " <Option name='Height' scope='vector' type='string-select' " 143 : " description='Sets which of the possible heights is chosen: " 144 : "the first, the highest or the lowest one.'>" 145 : " <Value>First</Value>" 146 : " <Value>Lowest</Value>" 147 : " <Value>Highest</Value>" 148 : " </Option>" 149 : " <Option name='MultiRecordIndex' scope='vector' type='string' " 150 : " description='Sets which of the possible records is chosen: " 151 : "0, 1, 2,... or the Last one. Use JSON when a serialized " 152 : "JSON is wanted'>" 153 : " </Option>" 154 : " <Option name='OpenLanguage' scope='vector' type='string-select' " 155 : " description='If the layer to be opened is multilingual " 156 : "(in fact the *.rel* file), this parameter sets the language " 157 : "to be read.'>" 158 : " <Value>ENG</Value>" 159 : " <Value>CAT</Value>" 160 : " <Value>SPA</Value>" 161 : " </Option>" 162 1776 : "</OpenOptionList>"); 163 : 164 1776 : poDriver->SetMetadataItem( 165 : GDAL_DS_LAYER_CREATIONOPTIONLIST, 166 : "<LayerCreationOptionList>" 167 : " <Option name='Version' type='string-select' description='Version of " 168 : "the file. " 169 : "V1.1 is a limited 32 bits for FID and for internal offsets. " 170 : "V2.0 is the 64 bits version, with practically no limits for FID nor " 171 : "for internal offsets.' " 172 : "default='last_version'>" 173 : "<Value>V1.1</Value>" 174 : "<Value>V2.0</Value>" 175 : "<Value>last_version</Value>" 176 : "</Option>" 177 : " <Option name='DBFEncoding' type='string-select' " 178 : "description='Encoding of " 179 : "the " 180 : ".dbf files." 181 : "MiraMon can write *.dbf* files in these two charsets.' " 182 : "default='ANSI'>" 183 : "<Value>UTF8</Value>" 184 : "<Value>ANSI</Value>" 185 : "</Option>" 186 : " <Option name='CreationLanguage' scope='vector' type='string-select' " 187 : " description='If the layer to be opened is multilingual " 188 : "(in fact the *.rel* file), this parameter sets the language " 189 : "to be read.'>" 190 : " <Value>ENG</Value>" 191 : " <Value>CAT</Value>" 192 : " <Value>SPA</Value>" 193 : " </Option>" 194 1776 : "</LayerCreationOptionList>"); 195 : 196 1776 : poDriver->SetMetadataItem( 197 : GDAL_DMD_CREATIONFIELDDATATYPES, 198 : "Integer Integer64 Real String Date Time " 199 1776 : "Binary IntegerList Integer64List RealList StringList"); 200 1776 : poDriver->pfnOpen = OGRMiraMonDriverOpen; 201 1776 : poDriver->pfnIdentify = OGRMiraMonDriverIdentify; 202 1776 : poDriver->pfnCreate = OGRMiraMonDriverCreate; 203 : 204 1776 : GetGDALDriverManager()->RegisterDriver(poDriver); 205 : }