Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: HDF5 driver
5 : * Author: Even Rouault, <even.rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, Even Rouault, <even.rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "hdf5drivercore.h"
14 :
15 : #include <algorithm>
16 : #include <cctype>
17 :
18 : /************************************************************************/
19 : /* HDF5DatasetIdentify() */
20 : /************************************************************************/
21 :
22 51688 : int HDF5DatasetIdentify(GDALOpenInfo *poOpenInfo)
23 :
24 : {
25 51688 : if ((poOpenInfo->nOpenFlags & GDAL_OF_MULTIDIM_RASTER) &&
26 613 : STARTS_WITH(poOpenInfo->pszFilename, "HDF5:"))
27 : {
28 14 : return TRUE;
29 : }
30 :
31 : // Is it an HDF5 file?
32 51674 : constexpr char achSignature[] = "\211HDF\r\n\032\n";
33 :
34 51674 : if (!poOpenInfo->pabyHeader)
35 48238 : return FALSE;
36 :
37 6871 : const CPLString osExt(CPLGetExtension(poOpenInfo->pszFilename));
38 :
39 678 : const auto IsRecognizedByNetCDFDriver = [&osExt, poOpenInfo]()
40 : {
41 339 : if ((EQUAL(osExt, "NC") || EQUAL(osExt, "CDF") || EQUAL(osExt, "NC4") ||
42 344 : EQUAL(osExt, "gmac")) &&
43 5 : GDALGetDriverByName("netCDF") != nullptr)
44 : {
45 5 : const char *const apszAllowedDriver[] = {"netCDF", nullptr};
46 5 : CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
47 10 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
48 5 : poOpenInfo->pszFilename,
49 : GDAL_OF_RASTER | GDAL_OF_MULTIDIM_RASTER |
50 : GDAL_OF_VECTOR,
51 5 : apszAllowedDriver, nullptr, nullptr)) != nullptr;
52 : }
53 167 : return false;
54 3435 : };
55 :
56 3435 : if (memcmp(poOpenInfo->pabyHeader, achSignature, 8) == 0 ||
57 3262 : (poOpenInfo->nHeaderBytes > 512 + 8 &&
58 2032 : memcmp(poOpenInfo->pabyHeader + 512, achSignature, 8) == 0))
59 : {
60 173 : if (poOpenInfo->IsSingleAllowedDriver("HDF5"))
61 : {
62 2 : return TRUE;
63 : }
64 :
65 : // The tests to avoid opening KEA and BAG drivers are not
66 : // necessary when drivers are built in the core lib, as they
67 : // are registered after HDF5, but in the case of plugins, we
68 : // cannot do assumptions about the registration order.
69 :
70 : // Avoid opening kea files if the kea driver is available.
71 171 : if (EQUAL(osExt, "KEA") && GDALGetDriverByName("KEA") != nullptr)
72 : {
73 0 : return FALSE;
74 : }
75 :
76 : // Avoid opening BAG files if the bag driver is available.
77 171 : if (EQUAL(osExt, "BAG") && GDALGetDriverByName("BAG") != nullptr)
78 : {
79 1 : return FALSE;
80 : }
81 :
82 : // Avoid opening NC files if the netCDF driver is available and
83 : // they are recognized by it.
84 170 : if (IsRecognizedByNetCDFDriver())
85 : {
86 3 : return FALSE;
87 : }
88 :
89 167 : return TRUE;
90 : }
91 :
92 3262 : if (memcmp(poOpenInfo->pabyHeader, "<HDF_UserBlock>", 15) == 0)
93 : {
94 0 : return TRUE;
95 : }
96 :
97 : // The HDF5 signature can be at offsets 512, 1024, 2048, etc.
98 6461 : if (poOpenInfo->fpL != nullptr &&
99 3199 : (EQUAL(osExt, "h5") || EQUAL(osExt, "hdf5") || EQUAL(osExt, "nc") ||
100 3187 : EQUAL(osExt, "cdf") || EQUAL(osExt, "nc4") ||
101 3187 : poOpenInfo->IsSingleAllowedDriver("HDF5")))
102 : {
103 14 : vsi_l_offset nOffset = 512;
104 38 : for (int i = 0; i < 64; i++)
105 : {
106 : GByte abyBuf[8];
107 76 : if (VSIFSeekL(poOpenInfo->fpL, nOffset, SEEK_SET) != 0 ||
108 38 : VSIFReadL(abyBuf, 1, 8, poOpenInfo->fpL) != 8)
109 : {
110 8 : break;
111 : }
112 30 : if (memcmp(abyBuf, achSignature, 8) == 0)
113 : {
114 6 : if (poOpenInfo->IsSingleAllowedDriver("HDF5"))
115 : {
116 6 : return TRUE;
117 : }
118 : // Avoid opening NC files if the netCDF driver is available and
119 : // they are recognized by it.
120 2 : if (IsRecognizedByNetCDFDriver())
121 : {
122 0 : return FALSE;
123 : }
124 :
125 2 : return TRUE;
126 : }
127 24 : nOffset *= 2;
128 : }
129 : }
130 :
131 3256 : return FALSE;
132 : }
133 :
134 : /************************************************************************/
135 : /* HDF5ImageDatasetIdentify() */
136 : /************************************************************************/
137 :
138 50919 : int HDF5ImageDatasetIdentify(GDALOpenInfo *poOpenInfo)
139 :
140 : {
141 50919 : if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:"))
142 50857 : return FALSE;
143 :
144 62 : return TRUE;
145 : }
146 :
147 : /************************************************************************/
148 : /* HDF5DriverGetSubdatasetInfo() */
149 : /************************************************************************/
150 :
151 : struct HDF5DriverSubdatasetInfo : public GDALSubdatasetInfo
152 : {
153 : public:
154 12 : explicit HDF5DriverSubdatasetInfo(const std::string &fileName)
155 12 : : GDALSubdatasetInfo(fileName)
156 : {
157 12 : }
158 :
159 : // GDALSubdatasetInfo interface
160 : private:
161 12 : void parseFileName() override
162 : {
163 :
164 12 : if (!STARTS_WITH_CI(m_fileName.c_str(), "HDF5:"))
165 : {
166 0 : return;
167 : }
168 :
169 24 : CPLStringList aosParts{CSLTokenizeString2(m_fileName.c_str(), ":", 0)};
170 12 : const int iPartsCount{CSLCount(aosParts)};
171 :
172 12 : if (iPartsCount >= 3)
173 : {
174 :
175 10 : m_driverPrefixComponent = aosParts[0];
176 :
177 20 : std::string part1{aosParts[1]};
178 10 : if (!part1.empty() && part1[0] == '"')
179 : {
180 6 : part1 = part1.substr(1);
181 : }
182 :
183 10 : int subdatasetIndex{2};
184 : const bool hasDriveLetter{
185 10 : part1.length() == 1 &&
186 16 : std::isalpha(static_cast<unsigned char>(part1.at(0))) &&
187 6 : (strlen(aosParts[2]) > 1 &&
188 5 : (aosParts[2][0] == '\\' ||
189 3 : (aosParts[2][0] == '/' && aosParts[2][1] != '/')))};
190 :
191 19 : const bool hasProtocol{part1 == "/vsicurl/http" ||
192 18 : part1 == "/vsicurl/https" ||
193 28 : part1 == "/vsicurl_streaming/http" ||
194 9 : part1 == "/vsicurl_streaming/https"};
195 :
196 10 : m_pathComponent = aosParts[1];
197 :
198 10 : if (hasDriveLetter || hasProtocol)
199 : {
200 5 : m_pathComponent.append(":");
201 5 : m_pathComponent.append(aosParts[2]);
202 5 : subdatasetIndex++;
203 : }
204 :
205 10 : if (iPartsCount > subdatasetIndex)
206 : {
207 10 : m_subdatasetComponent = aosParts[subdatasetIndex];
208 :
209 : // Append any remaining part
210 10 : for (int i = subdatasetIndex + 1; i < iPartsCount; ++i)
211 : {
212 0 : m_subdatasetComponent.append(":");
213 0 : m_subdatasetComponent.append(aosParts[i]);
214 : }
215 : }
216 : }
217 : }
218 : };
219 :
220 2609 : static GDALSubdatasetInfo *HDF5DriverGetSubdatasetInfo(const char *pszFileName)
221 : {
222 2609 : if (STARTS_WITH_CI(pszFileName, "HDF5:"))
223 : {
224 : std::unique_ptr<GDALSubdatasetInfo> info =
225 12 : std::make_unique<HDF5DriverSubdatasetInfo>(pszFileName);
226 34 : if (!info->GetSubdatasetComponent().empty() &&
227 22 : !info->GetPathComponent().empty())
228 : {
229 10 : return info.release();
230 : }
231 : }
232 2599 : return nullptr;
233 : }
234 :
235 : /************************************************************************/
236 : /* IdentifySxx() */
237 : /************************************************************************/
238 :
239 154841 : static bool IdentifySxx(GDALOpenInfo *poOpenInfo, const char *pszDriverName,
240 : const char *pszConfigOption,
241 : const char *pszMainGroupName)
242 : {
243 154841 : if (STARTS_WITH(poOpenInfo->pszFilename, pszDriverName) &&
244 34 : poOpenInfo->pszFilename[strlen(pszDriverName)] == ':')
245 34 : return TRUE;
246 :
247 : // Is it an HDF5 file?
248 : static const char achSignature[] = "\211HDF\r\n\032\n";
249 :
250 154807 : if (poOpenInfo->pabyHeader == nullptr ||
251 10074 : memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
252 154500 : return FALSE;
253 :
254 307 : if (poOpenInfo->IsSingleAllowedDriver(pszDriverName))
255 : {
256 1 : return TRUE;
257 : }
258 :
259 : // GDAL_Sxxx_IDENTIFY can be set to NO only for tests, to test that
260 : // HDF5Dataset::Open() can redirect to Sxxx if the below logic fails
261 306 : if (CPLTestBool(CPLGetConfigOption(pszConfigOption, "YES")))
262 : {
263 : // The below identification logic may be a bit fragile...
264 : // Works at least on:
265 : // - /vsis3/noaa-s102-pds/ed2.1.0/national_bathymetric_source/boston/dcf2/tiles/102US00_US4MA1GC.h5
266 : // - https://datahub.admiralty.co.uk/portal/sharing/rest/content/items/6fd07bde26124d48820b6dee60695389/data (S-102_Liverpool_Trial_Cells.zip)
267 305 : const int nLenMainGroup =
268 305 : static_cast<int>(strlen(pszMainGroupName) + 1);
269 305 : const int nLenGroupF = static_cast<int>(strlen("Group_F\0") + 1);
270 305 : bool bFoundMainGroup = false;
271 305 : bool bFoundGroupF = false;
272 298298 : for (int i = 0;
273 298298 : i < poOpenInfo->nHeaderBytes - std::max(nLenMainGroup, nLenGroupF);
274 : ++i)
275 : {
276 298029 : if (poOpenInfo->pabyHeader[i] == pszMainGroupName[0] &&
277 222 : memcmp(poOpenInfo->pabyHeader + i, pszMainGroupName,
278 : nLenMainGroup) == 0)
279 : {
280 36 : bFoundMainGroup = true;
281 36 : if (bFoundGroupF)
282 36 : return true;
283 : }
284 298029 : if (poOpenInfo->pabyHeader[i] == 'G' &&
285 293 : memcmp(poOpenInfo->pabyHeader + i, "Group_F\0", nLenGroupF) ==
286 : 0)
287 : {
288 44 : bFoundGroupF = true;
289 44 : if (bFoundMainGroup)
290 36 : return true;
291 : }
292 : }
293 : }
294 :
295 270 : return false;
296 : }
297 :
298 : /************************************************************************/
299 : /* S102DatasetIdentify() */
300 : /************************************************************************/
301 :
302 51648 : int S102DatasetIdentify(GDALOpenInfo *poOpenInfo)
303 :
304 : {
305 51648 : return IdentifySxx(poOpenInfo, "S102", "GDAL_S102_IDENTIFY",
306 51642 : "BathymetryCoverage");
307 : }
308 :
309 : /************************************************************************/
310 : /* S104DatasetIdentify() */
311 : /************************************************************************/
312 :
313 51600 : int S104DatasetIdentify(GDALOpenInfo *poOpenInfo)
314 :
315 : {
316 51600 : return IdentifySxx(poOpenInfo, "S104", "GDAL_S104_IDENTIFY", "WaterLevel");
317 : }
318 :
319 : /************************************************************************/
320 : /* S111DatasetIdentify() */
321 : /************************************************************************/
322 :
323 51598 : int S111DatasetIdentify(GDALOpenInfo *poOpenInfo)
324 :
325 : {
326 51598 : return IdentifySxx(poOpenInfo, "S111", "GDAL_S111_IDENTIFY",
327 51599 : "SurfaceCurrent");
328 : }
329 :
330 : /************************************************************************/
331 : /* BAGDatasetIdentify() */
332 : /************************************************************************/
333 :
334 61496 : int BAGDatasetIdentify(GDALOpenInfo *poOpenInfo)
335 :
336 : {
337 61496 : if (STARTS_WITH(poOpenInfo->pszFilename, "BAG:"))
338 30 : return TRUE;
339 :
340 : // Is it an HDF5 file?
341 : static const char achSignature[] = "\211HDF\r\n\032\n";
342 :
343 61466 : if (poOpenInfo->pabyHeader == nullptr ||
344 10805 : memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
345 61214 : return FALSE;
346 :
347 : // Does it have the extension .bag?
348 252 : if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "bag"))
349 : {
350 118 : if (poOpenInfo->IsSingleAllowedDriver("BAG"))
351 : {
352 1 : return TRUE;
353 : }
354 117 : return FALSE;
355 : }
356 :
357 134 : return TRUE;
358 : }
359 :
360 : /************************************************************************/
361 : /* HDF5DriverSetCommonMetadata() */
362 : /************************************************************************/
363 :
364 1303 : void HDF5DriverSetCommonMetadata(GDALDriver *poDriver)
365 : {
366 1303 : poDriver->SetDescription(HDF5_DRIVER_NAME);
367 1303 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
368 1303 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
369 1303 : "Hierarchical Data Format Release 5");
370 1303 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
371 1303 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "h5 hdf5");
372 1303 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
373 1303 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
374 :
375 1303 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
376 :
377 1303 : poDriver->pfnIdentify = HDF5DatasetIdentify;
378 1303 : poDriver->pfnGetSubdatasetInfoFunc = HDF5DriverGetSubdatasetInfo;
379 1303 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
380 1303 : }
381 :
382 : /************************************************************************/
383 : /* HDF5ImageDriverSetCommonMetadata() */
384 : /************************************************************************/
385 :
386 1303 : void HDF5ImageDriverSetCommonMetadata(GDALDriver *poDriver)
387 : {
388 1303 : poDriver->SetDescription(HDF5_IMAGE_DRIVER_NAME);
389 1303 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
390 1303 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "HDF5 Dataset");
391 1303 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
392 1303 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
393 :
394 1303 : poDriver->pfnIdentify = HDF5ImageDatasetIdentify;
395 1303 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
396 1303 : }
397 :
398 : /************************************************************************/
399 : /* BAGDriverSetCommonMetadata() */
400 : /************************************************************************/
401 :
402 1303 : void BAGDriverSetCommonMetadata(GDALDriver *poDriver)
403 : {
404 1303 : poDriver->SetDescription(BAG_DRIVER_NAME);
405 1303 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
406 1303 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
407 1303 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Bathymetry Attributed Grid");
408 1303 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/bag.html");
409 1303 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
410 1303 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "bag");
411 :
412 1303 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32");
413 :
414 1303 : poDriver->SetMetadataItem(
415 : GDAL_DMD_OPENOPTIONLIST,
416 : "<OpenOptionList>"
417 : " <Option name='MODE' type='string-select' default='AUTO'>"
418 : " <Value>AUTO</Value>"
419 : " <Value>LOW_RES_GRID</Value>"
420 : " <Value>LIST_SUPERGRIDS</Value>"
421 : " <Value>RESAMPLED_GRID</Value>"
422 : " <Value>INTERPOLATED</Value>"
423 : " </Option>"
424 : " <Option name='SUPERGRIDS_INDICES' type='string' description="
425 : "'Tuple(s) (y1,x1),(y2,x2),... of supergrids, by indices, to expose "
426 : "as subdatasets'/>"
427 : " <Option name='MINX' type='float' description='Minimum X value of "
428 : "area of interest'/>"
429 : " <Option name='MINY' type='float' description='Minimum Y value of "
430 : "area of interest'/>"
431 : " <Option name='MAXX' type='float' description='Maximum X value of "
432 : "area of interest'/>"
433 : " <Option name='MAXY' type='float' description='Maximum Y value of "
434 : "area of interest'/>"
435 : " <Option name='RESX' type='float' description="
436 : "'Horizontal resolution. Only used for "
437 : "MODE=RESAMPLED_GRID/INTERPOLATED'/>"
438 : " <Option name='RESY' type='float' description="
439 : "'Vertical resolution (positive value). Only used for "
440 : "MODE=RESAMPLED_GRID/INTERPOLATED'/>"
441 : " <Option name='RES_STRATEGY' type='string-select' description="
442 : "'Which strategy to apply to select the resampled grid resolution. "
443 : "Only used for MODE=RESAMPLED_GRID/INTERPOLATED' default='AUTO'>"
444 : " <Value>AUTO</Value>"
445 : " <Value>MIN</Value>"
446 : " <Value>MAX</Value>"
447 : " <Value>MEAN</Value>"
448 : " </Option>"
449 : " <Option name='RES_FILTER_MIN' type='float' description="
450 : "'Minimum resolution of supergrids to take into account (excluded "
451 : "bound). "
452 : "Only used for MODE=RESAMPLED_GRID, INTERPOLATED or LIST_SUPERGRIDS' "
453 : "default='0'/>"
454 : " <Option name='RES_FILTER_MAX' type='float' description="
455 : "'Maximum resolution of supergrids to take into account (included "
456 : "bound). "
457 : "Only used for MODE=RESAMPLED_GRID, INTERPOLATED or LIST_SUPERGRIDS' "
458 : "default='inf'/>"
459 : " <Option name='VALUE_POPULATION' type='string-select' description="
460 : "'Which value population strategy to apply to compute the resampled "
461 : "cell "
462 : "values. Only used for MODE=RESAMPLED_GRID' default='MAX'>"
463 : " <Value>MIN</Value>"
464 : " <Value>MAX</Value>"
465 : " <Value>MEAN</Value>"
466 : " <Value>COUNT</Value>"
467 : " </Option>"
468 : " <Option name='SUPERGRIDS_MASK' type='boolean' description="
469 : "'Whether the dataset should consist of a mask band indicating if a "
470 : "supergrid node matches each target pixel. Only used for "
471 : "MODE=RESAMPLED_GRID' default='NO'/>"
472 : " <Option name='NODATA_VALUE' type='float' default='1000000'/>"
473 : " <Option name='REPORT_VERTCRS' type='boolean' default='YES'/>"
474 1303 : "</OpenOptionList>");
475 :
476 1303 : poDriver->SetMetadataItem(
477 : GDAL_DMD_CREATIONOPTIONLIST,
478 : "<CreationOptionList>"
479 : " <Option name='VAR_*' type='string' description="
480 : "'Value to substitute to a variable in the template'/>"
481 : " <Option name='TEMPLATE' type='string' description="
482 : "'.xml template to use'/>"
483 : " <Option name='BAG_VERSION' type='string' description="
484 : "'Version to write in the Bag Version attribute' default='1.6.2'/>"
485 : " <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
486 : " <Value>NONE</Value>"
487 : " <Value>DEFLATE</Value>"
488 : " </Option>"
489 : " <Option name='ZLEVEL' type='int' "
490 : "description='DEFLATE compression level 1-9' default='6' />"
491 : " <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
492 1303 : "</CreationOptionList>");
493 :
494 1303 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
495 :
496 1303 : poDriver->pfnIdentify = BAGDatasetIdentify;
497 1303 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
498 1303 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
499 1303 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
500 1303 : }
501 :
502 : /************************************************************************/
503 : /* S102DriverSetCommonMetadata() */
504 : /************************************************************************/
505 :
506 1303 : void S102DriverSetCommonMetadata(GDALDriver *poDriver)
507 : {
508 1303 : poDriver->SetDescription(S102_DRIVER_NAME);
509 1303 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
510 1303 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
511 1303 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
512 1303 : "S-102 Bathymetric Surface Product");
513 1303 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s102.html");
514 1303 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
515 1303 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
516 1303 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
517 :
518 1303 : poDriver->SetMetadataItem(
519 : GDAL_DMD_OPENOPTIONLIST,
520 : "<OpenOptionList>"
521 : " <Option name='DEPTH_OR_ELEVATION' type='string-select' "
522 : "default='DEPTH'>"
523 : " <Value>DEPTH</Value>"
524 : " <Value>ELEVATION</Value>"
525 : " </Option>"
526 : " <Option name='NORTH_UP' type='boolean' default='YES' "
527 : "description='Whether the top line of the dataset should be the "
528 : "northern-most one'/>"
529 1303 : "</OpenOptionList>");
530 1303 : poDriver->pfnIdentify = S102DatasetIdentify;
531 1303 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
532 1303 : }
533 :
534 : /************************************************************************/
535 : /* S104DriverSetCommonMetadata() */
536 : /************************************************************************/
537 :
538 1303 : void S104DriverSetCommonMetadata(GDALDriver *poDriver)
539 : {
540 1303 : poDriver->SetDescription(S104_DRIVER_NAME);
541 1303 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
542 1303 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
543 1303 : poDriver->SetMetadataItem(
544 : GDAL_DMD_LONGNAME,
545 1303 : "S-104 Water Level Information for Surface Navigation Product");
546 1303 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s104.html");
547 1303 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
548 1303 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
549 :
550 1303 : poDriver->SetMetadataItem(
551 : GDAL_DMD_OPENOPTIONLIST,
552 : "<OpenOptionList>"
553 : " <Option name='NORTH_UP' type='boolean' default='YES' "
554 : "description='Whether the top line of the dataset should be the "
555 : "northern-most one'/>"
556 1303 : "</OpenOptionList>");
557 1303 : poDriver->pfnIdentify = S104DatasetIdentify;
558 1303 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
559 1303 : }
560 :
561 : /************************************************************************/
562 : /* S111DriverSetCommonMetadata() */
563 : /************************************************************************/
564 :
565 1303 : void S111DriverSetCommonMetadata(GDALDriver *poDriver)
566 : {
567 1303 : poDriver->SetDescription(S111_DRIVER_NAME);
568 1303 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
569 1303 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
570 1303 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Surface Currents Product");
571 1303 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s111.html");
572 1303 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
573 1303 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
574 :
575 1303 : poDriver->SetMetadataItem(
576 : GDAL_DMD_OPENOPTIONLIST,
577 : "<OpenOptionList>"
578 : " <Option name='NORTH_UP' type='boolean' default='YES' "
579 : "description='Whether the top line of the dataset should be the "
580 : "northern-most one'/>"
581 1303 : "</OpenOptionList>");
582 1303 : poDriver->pfnIdentify = S111DatasetIdentify;
583 1303 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
584 1303 : }
585 :
586 : /************************************************************************/
587 : /* DeclareDeferredHDF5Plugin() */
588 : /************************************************************************/
589 :
590 : #ifdef PLUGIN_FILENAME
591 1595 : void DeclareDeferredHDF5Plugin()
592 : {
593 1595 : if (GDALGetDriverByName(HDF5_DRIVER_NAME) != nullptr)
594 : {
595 302 : return;
596 : }
597 : {
598 1293 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
599 : #ifdef PLUGIN_INSTALLATION_MESSAGE
600 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
601 : PLUGIN_INSTALLATION_MESSAGE);
602 : #endif
603 1293 : HDF5DriverSetCommonMetadata(poDriver);
604 1293 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
605 : }
606 : {
607 1293 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
608 : #ifdef PLUGIN_INSTALLATION_MESSAGE
609 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
610 : PLUGIN_INSTALLATION_MESSAGE);
611 : #endif
612 1293 : HDF5ImageDriverSetCommonMetadata(poDriver);
613 1293 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
614 : }
615 : {
616 1293 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
617 : #ifdef PLUGIN_INSTALLATION_MESSAGE
618 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
619 : PLUGIN_INSTALLATION_MESSAGE);
620 : #endif
621 1293 : BAGDriverSetCommonMetadata(poDriver);
622 1293 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
623 : }
624 : {
625 1293 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
626 : #ifdef PLUGIN_INSTALLATION_MESSAGE
627 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
628 : PLUGIN_INSTALLATION_MESSAGE);
629 : #endif
630 1293 : S102DriverSetCommonMetadata(poDriver);
631 1293 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
632 : }
633 : {
634 1293 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
635 : #ifdef PLUGIN_INSTALLATION_MESSAGE
636 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
637 : PLUGIN_INSTALLATION_MESSAGE);
638 : #endif
639 1293 : S104DriverSetCommonMetadata(poDriver);
640 1293 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
641 : }
642 : {
643 1293 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
644 : #ifdef PLUGIN_INSTALLATION_MESSAGE
645 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
646 : PLUGIN_INSTALLATION_MESSAGE);
647 : #endif
648 1293 : S111DriverSetCommonMetadata(poDriver);
649 1293 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
650 : }
651 : }
652 : #endif
|