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