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