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 43921 : static int OGRMiraMonDriverIdentify(GDALOpenInfo *poOpenInfo) 31 : 32 : { 33 43921 : if (poOpenInfo->fpL == nullptr || poOpenInfo->nHeaderBytes < 7) 34 43028 : return FALSE; 35 1701 : else if (poOpenInfo->IsExtensionEqualToCI("PNT") || 36 1701 : poOpenInfo->IsExtensionEqualToCI("ARC") || 37 748 : poOpenInfo->IsExtensionEqualToCI("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 655 : 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 : GDALDataset::ReportUpdateNotSupportedByDriver("MiraMonVector"); 88 0 : return nullptr; 89 : } 90 : 91 119 : return poDS.release(); 92 : } 93 : 94 : /****************************************************************************/ 95 : /* OGRMiraMonDriverCreate() */ 96 : /****************************************************************************/ 97 : 98 : static GDALDataset * 99 67 : OGRMiraMonDriverCreate(const char *pszName, CPL_UNUSED int /*nBands*/, 100 : CPL_UNUSED int /*nXSize*/, CPL_UNUSED int /*nYSize*/, 101 : CPL_UNUSED GDALDataType /*eDT*/, char **papszOptions) 102 : { 103 134 : auto poDS = std::make_unique<OGRMiraMonDataSource>(); 104 : 105 67 : if (!poDS->Create(pszName, papszOptions)) 106 : { 107 0 : poDS.reset(); 108 : } 109 : 110 134 : return poDS.release(); 111 : } 112 : 113 : /****************************************************************************/ 114 : /* RegisterOGRMM() */ 115 : /****************************************************************************/ 116 : 117 1686 : void RegisterOGRMiraMon() 118 : 119 : { 120 1686 : if (GDALGetDriverByName("MiraMonVector") != nullptr) 121 302 : return; 122 : 123 1384 : GDALDriver *poDriver = new GDALDriver(); 124 1384 : poDriver->SetDescription("MiraMonVector"); 125 1384 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES"); 126 1384 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES"); 127 1384 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES"); 128 1384 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, 129 1384 : "MiraMon Vectors (.pol, .arc, .pnt)"); 130 1384 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "pol arc pnt"); 131 1384 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, 132 1384 : "drivers/vector/miramon.html"); 133 1384 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); 134 1384 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES"); 135 : 136 1384 : poDriver->SetMetadataItem( 137 : GDAL_DMD_OPENOPTIONLIST, 138 : "<OpenOptionList>" 139 : " <Option name='Height' scope='vector' type='string-select' " 140 : " description='Sets which of the possible heights is chosen: " 141 : "the first, the highest or the lowest one.'>" 142 : " <Value>First</Value>" 143 : " <Value>Lowest</Value>" 144 : " <Value>Highest</Value>" 145 : " </Option>" 146 : " <Option name='MultiRecordIndex' scope='vector' type='string' " 147 : " description='Sets which of the possible records is chosen: " 148 : "0, 1, 2,... or the Last one. Use JSON when a serialized " 149 : "JSON is wanted'>" 150 : " </Option>" 151 : " <Option name='OpenLanguage' scope='vector' type='string-select' " 152 : " description='If the layer to be opened is multilingual " 153 : "(in fact the *.rel* file), this parameter sets the language " 154 : "to be read.'>" 155 : " <Value>ENG</Value>" 156 : " <Value>CAT</Value>" 157 : " <Value>SPA</Value>" 158 : " </Option>" 159 1384 : "</OpenOptionList>"); 160 : 161 1384 : poDriver->SetMetadataItem( 162 : GDAL_DS_LAYER_CREATIONOPTIONLIST, 163 : "<LayerCreationOptionList>" 164 : " <Option name='Version' type='string-select' description='Version of " 165 : "the file. " 166 : "V1.1 is a limited 32 bits for FID and for internal offsets. " 167 : "V2.0 is the 64 bits version, with practically no limits for FID nor " 168 : "for internal offsets.' " 169 : "default='last_version'>" 170 : "<Value>V1.1</Value>" 171 : "<Value>V2.0</Value>" 172 : "<Value>last_version</Value>" 173 : "</Option>" 174 : " <Option name='DBFEncoding' type='string-select' " 175 : "description='Encoding of " 176 : "the " 177 : ".dbf files." 178 : "MiraMon can write *.dbf* files in these two charsets.' " 179 : "default='ANSI'>" 180 : "<Value>UTF8</Value>" 181 : "<Value>ANSI</Value>" 182 : "</Option>" 183 : " <Option name='CreationLanguage' scope='vector' type='string-select' " 184 : " description='If the layer to be opened is multilingual " 185 : "(in fact the *.rel* file), this parameter sets the language " 186 : "to be read.'>" 187 : " <Value>ENG</Value>" 188 : " <Value>CAT</Value>" 189 : " <Value>SPA</Value>" 190 : " </Option>" 191 1384 : "</LayerCreationOptionList>"); 192 : 193 1384 : poDriver->SetMetadataItem( 194 : GDAL_DMD_CREATIONFIELDDATATYPES, 195 : "Integer Integer64 Real String Date Time " 196 1384 : "Binary IntegerList Integer64List RealList StringList"); 197 1384 : poDriver->pfnOpen = OGRMiraMonDriverOpen; 198 1384 : poDriver->pfnIdentify = OGRMiraMonDriverIdentify; 199 1384 : poDriver->pfnCreate = OGRMiraMonDriverCreate; 200 : 201 1384 : GetGDALDriverManager()->RegisterDriver(poDriver); 202 : }