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 : #ifdef _POSIX_C_SOURCE
14 : #undef _POSIX_C_SOURCE
15 : #endif
16 :
17 : #include "hdf5drivercore.h"
18 :
19 : #include "gdal_frmts.h"
20 : #include "gdalplugindriverproxy.h"
21 : #include "gdalsubdatasetinfo.h"
22 :
23 : #include <algorithm>
24 : #include <cctype>
25 :
26 : /************************************************************************/
27 : /* HDF5DatasetIdentify() */
28 : /************************************************************************/
29 :
30 63003 : int HDF5DatasetIdentify(GDALOpenInfo *poOpenInfo)
31 :
32 : {
33 63003 : if ((poOpenInfo->nOpenFlags & GDAL_OF_MULTIDIM_RASTER) &&
34 1588 : STARTS_WITH(poOpenInfo->pszFilename, "HDF5:"))
35 : {
36 16 : return TRUE;
37 : }
38 :
39 : // Is it an HDF5 file?
40 62987 : constexpr char achSignature[] = "\211HDF\r\n\032\n";
41 :
42 62987 : if (!poOpenInfo->pabyHeader)
43 57713 : return FALSE;
44 :
45 10548 : const CPLString osExt(poOpenInfo->osExtension);
46 :
47 826 : const auto IsRecognizedByNetCDFDriver = [&osExt, poOpenInfo]()
48 : {
49 413 : if ((EQUAL(osExt, "NC") || EQUAL(osExt, "CDF") || EQUAL(osExt, "NC4") ||
50 418 : EQUAL(osExt, "gmac")) &&
51 5 : GDALGetDriverByName("netCDF") != nullptr)
52 : {
53 5 : const char *const apszAllowedDriver[] = {"netCDF", nullptr};
54 5 : CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
55 10 : return std::unique_ptr<GDALDataset>(GDALDataset::Open(
56 5 : poOpenInfo->pszFilename,
57 : GDAL_OF_RASTER | GDAL_OF_MULTIDIM_RASTER |
58 : GDAL_OF_VECTOR,
59 5 : apszAllowedDriver, nullptr, nullptr)) != nullptr;
60 : }
61 204 : return false;
62 5274 : };
63 :
64 5274 : if (memcmp(poOpenInfo->pabyHeader, achSignature, 8) == 0 ||
65 5062 : (poOpenInfo->nHeaderBytes > 512 + 8 &&
66 3703 : memcmp(poOpenInfo->pabyHeader + 512, achSignature, 8) == 0))
67 : {
68 212 : if (poOpenInfo->IsSingleAllowedDriver("HDF5"))
69 : {
70 4 : return TRUE;
71 : }
72 :
73 : // The tests to avoid opening KEA and BAG drivers are not
74 : // necessary when drivers are built in the core lib, as they
75 : // are registered after HDF5, but in the case of plugins, we
76 : // cannot do assumptions about the registration order.
77 :
78 : // Avoid opening kea files if the kea driver is available.
79 208 : if (EQUAL(osExt, "KEA") && GDALGetDriverByName("KEA") != nullptr)
80 : {
81 0 : return FALSE;
82 : }
83 :
84 : // Avoid opening BAG files if the bag driver is available.
85 208 : if (EQUAL(osExt, "BAG") && GDALGetDriverByName("BAG") != nullptr)
86 : {
87 1 : return FALSE;
88 : }
89 :
90 : // Avoid opening NC files if the netCDF driver is available and
91 : // they are recognized by it.
92 207 : if (IsRecognizedByNetCDFDriver())
93 : {
94 3 : return FALSE;
95 : }
96 :
97 204 : return TRUE;
98 : }
99 :
100 5062 : if (memcmp(poOpenInfo->pabyHeader, "<HDF_UserBlock>", 15) == 0)
101 : {
102 0 : return TRUE;
103 : }
104 :
105 : // The HDF5 signature can be at offsets 512, 1024, 2048, etc.
106 10068 : if (poOpenInfo->fpL != nullptr &&
107 5006 : (EQUAL(osExt, "h5") || EQUAL(osExt, "hdf5") || EQUAL(osExt, "nc") ||
108 4992 : EQUAL(osExt, "cdf") || EQUAL(osExt, "nc4") ||
109 4992 : poOpenInfo->IsSingleAllowedDriver("HDF5")))
110 : {
111 16 : vsi_l_offset nOffset = 512;
112 40 : for (int i = 0; i < 64; i++)
113 : {
114 : GByte abyBuf[8];
115 80 : if (VSIFSeekL(poOpenInfo->fpL, nOffset, SEEK_SET) != 0 ||
116 40 : VSIFReadL(abyBuf, 1, 8, poOpenInfo->fpL) != 8)
117 : {
118 10 : break;
119 : }
120 30 : if (memcmp(abyBuf, achSignature, 8) == 0)
121 : {
122 6 : if (poOpenInfo->IsSingleAllowedDriver("HDF5"))
123 : {
124 6 : return TRUE;
125 : }
126 : // Avoid opening NC files if the netCDF driver is available and
127 : // they are recognized by it.
128 2 : if (IsRecognizedByNetCDFDriver())
129 : {
130 0 : return FALSE;
131 : }
132 :
133 2 : return TRUE;
134 : }
135 24 : nOffset *= 2;
136 : }
137 : }
138 :
139 5056 : return FALSE;
140 : }
141 :
142 : /************************************************************************/
143 : /* HDF5ImageDatasetIdentify() */
144 : /************************************************************************/
145 :
146 61292 : int HDF5ImageDatasetIdentify(GDALOpenInfo *poOpenInfo)
147 :
148 : {
149 61292 : if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:"))
150 61229 : return FALSE;
151 :
152 63 : return TRUE;
153 : }
154 :
155 : /************************************************************************/
156 : /* HDF5DriverGetSubdatasetInfo() */
157 : /************************************************************************/
158 :
159 : struct HDF5DriverSubdatasetInfo final : public GDALSubdatasetInfo
160 : {
161 : public:
162 40 : explicit HDF5DriverSubdatasetInfo(const std::string &fileName)
163 40 : : GDALSubdatasetInfo(fileName)
164 : {
165 40 : }
166 :
167 : // GDALSubdatasetInfo interface
168 : private:
169 : void parseFileName() override;
170 : };
171 :
172 40 : void HDF5DriverSubdatasetInfo::parseFileName()
173 : {
174 :
175 40 : if (!STARTS_WITH_CI(m_fileName.c_str(), "HDF5:"))
176 : {
177 0 : return;
178 : }
179 :
180 80 : CPLStringList aosParts{CSLTokenizeString2(m_fileName.c_str(), ":", 0)};
181 40 : const int iPartsCount{CSLCount(aosParts)};
182 :
183 40 : if (iPartsCount >= 3)
184 : {
185 :
186 38 : m_driverPrefixComponent = aosParts[0];
187 :
188 76 : std::string part1{aosParts[1]};
189 38 : if (!part1.empty() && part1[0] == '"')
190 : {
191 34 : part1 = part1.substr(1);
192 : }
193 :
194 38 : int subdatasetIndex{2};
195 : const bool hasDriveLetter{
196 38 : part1.length() == 1 &&
197 44 : std::isalpha(static_cast<unsigned char>(part1.at(0))) &&
198 6 : (strlen(aosParts[2]) > 1 &&
199 5 : (aosParts[2][0] == '\\' ||
200 3 : (aosParts[2][0] == '/' && aosParts[2][1] != '/')))};
201 :
202 75 : const bool hasProtocol{part1 == "/vsicurl/http" ||
203 74 : part1 == "/vsicurl/https" ||
204 112 : part1 == "/vsicurl_streaming/http" ||
205 37 : part1 == "/vsicurl_streaming/https"};
206 :
207 38 : m_pathComponent = aosParts[1];
208 :
209 38 : if (hasDriveLetter || hasProtocol)
210 : {
211 5 : m_pathComponent.append(":");
212 5 : m_pathComponent.append(aosParts[2]);
213 5 : subdatasetIndex++;
214 : }
215 :
216 38 : if (iPartsCount > subdatasetIndex)
217 : {
218 38 : m_subdatasetComponent = aosParts[subdatasetIndex];
219 :
220 : // Append any remaining part
221 38 : for (int i = subdatasetIndex + 1; i < iPartsCount; ++i)
222 : {
223 0 : m_subdatasetComponent.append(":");
224 0 : m_subdatasetComponent.append(aosParts[i]);
225 : }
226 : }
227 : }
228 : }
229 :
230 2769 : static GDALSubdatasetInfo *HDF5DriverGetSubdatasetInfo(const char *pszFileName)
231 : {
232 2769 : if (STARTS_WITH_CI(pszFileName, "HDF5:"))
233 : {
234 : std::unique_ptr<GDALSubdatasetInfo> info =
235 40 : std::make_unique<HDF5DriverSubdatasetInfo>(pszFileName);
236 118 : if (!info->GetSubdatasetComponent().empty() &&
237 78 : !info->GetPathComponent().empty())
238 : {
239 38 : return info.release();
240 : }
241 : }
242 2731 : return nullptr;
243 : }
244 :
245 : /************************************************************************/
246 : /* IdentifySxx() */
247 : /************************************************************************/
248 :
249 189371 : static bool IdentifySxx(GDALOpenInfo *poOpenInfo, const char *pszDriverName,
250 : const char *pszConfigOption,
251 : const char *pszMainGroupName)
252 : {
253 189371 : if (STARTS_WITH(poOpenInfo->pszFilename, pszDriverName) &&
254 188 : poOpenInfo->pszFilename[strlen(pszDriverName)] == ':')
255 188 : return TRUE;
256 :
257 : // Is it an HDF5 file?
258 : static const char achSignature[] = "\211HDF\r\n\032\n";
259 :
260 189183 : if (poOpenInfo->pabyHeader == nullptr ||
261 15737 : memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
262 188615 : return FALSE;
263 :
264 568 : if (poOpenInfo->IsSingleAllowedDriver(pszDriverName))
265 : {
266 35 : return TRUE;
267 : }
268 :
269 : // GDAL_Sxxx_IDENTIFY can be set to NO only for tests, to test that
270 : // HDF5Dataset::Open() can redirect to Sxxx if the below logic fails
271 533 : if (CPLTestBool(CPLGetConfigOption(pszConfigOption, "YES")))
272 : {
273 : // The below identification logic may be a bit fragile...
274 : // Works at least on:
275 : // - /vsis3/noaa-s102-pds/ed2.1.0/national_bathymetric_source/boston/dcf2/tiles/102US00_US4MA1GC.h5
276 : // - https://datahub.admiralty.co.uk/portal/sharing/rest/content/items/6fd07bde26124d48820b6dee60695389/data (S-102_Liverpool_Trial_Cells.zip)
277 532 : const int nLenMainGroup = static_cast<int>(strlen(pszMainGroupName));
278 532 : const int nLenGroupF = static_cast<int>(strlen("Group_F"));
279 532 : const int nLenProductSpecification =
280 : static_cast<int>(strlen("productSpecification"));
281 532 : bool bFoundMainGroup = false;
282 532 : bool bFoundGroupF = false;
283 532 : bool bFoundProductSpecification = false;
284 572 : for (int iTry = 0; iTry < 2; ++iTry)
285 : {
286 879438 : for (int i = 0; i <= poOpenInfo->nHeaderBytes - nLenGroupF; ++i)
287 : {
288 879025 : if (i <= poOpenInfo->nHeaderBytes - nLenMainGroup &&
289 875902 : poOpenInfo->pabyHeader[i] == pszMainGroupName[0] &&
290 712 : memcmp(poOpenInfo->pabyHeader + i, pszMainGroupName,
291 : nLenMainGroup) == 0)
292 : {
293 170 : bFoundMainGroup = true;
294 170 : if (bFoundGroupF)
295 0 : return true;
296 : }
297 879025 : if (poOpenInfo->pabyHeader[i] == 'G' &&
298 548 : memcmp(poOpenInfo->pabyHeader + i, "Group_F", nLenGroupF) ==
299 : 0)
300 : {
301 196 : bFoundGroupF = true;
302 196 : if (bFoundMainGroup)
303 159 : return true;
304 : }
305 878866 : if (i <= poOpenInfo->nHeaderBytes - nLenProductSpecification &&
306 873497 : poOpenInfo->pabyHeader[i] == 'p' &&
307 866 : memcmp(poOpenInfo->pabyHeader + i, "productSpecification",
308 : nLenProductSpecification) == 0)
309 : {
310 : // For 102DE00OS08J.H5
311 151 : bFoundProductSpecification = true;
312 : }
313 : }
314 524 : if (!(iTry == 0 && bFoundProductSpecification &&
315 111 : poOpenInfo->nHeaderBytes == 1024 &&
316 40 : poOpenInfo->TryToIngest(4096)))
317 : {
318 373 : break;
319 : }
320 : }
321 : }
322 :
323 374 : return false;
324 : }
325 :
326 : /************************************************************************/
327 : /* S102DatasetIdentify() */
328 : /************************************************************************/
329 :
330 63135 : int S102DatasetIdentify(GDALOpenInfo *poOpenInfo)
331 :
332 : {
333 63135 : return IdentifySxx(poOpenInfo, "S102", "GDAL_S102_IDENTIFY",
334 63135 : "BathymetryCoverage");
335 : }
336 :
337 : /************************************************************************/
338 : /* S104DatasetIdentify() */
339 : /************************************************************************/
340 :
341 63156 : int S104DatasetIdentify(GDALOpenInfo *poOpenInfo)
342 :
343 : {
344 63156 : return IdentifySxx(poOpenInfo, "S104", "GDAL_S104_IDENTIFY", "WaterLevel");
345 : }
346 :
347 : /************************************************************************/
348 : /* S111DatasetIdentify() */
349 : /************************************************************************/
350 :
351 63080 : int S111DatasetIdentify(GDALOpenInfo *poOpenInfo)
352 :
353 : {
354 63080 : return IdentifySxx(poOpenInfo, "S111", "GDAL_S111_IDENTIFY",
355 63080 : "SurfaceCurrent");
356 : }
357 :
358 : /************************************************************************/
359 : /* BAGDatasetIdentify() */
360 : /************************************************************************/
361 :
362 74541 : int BAGDatasetIdentify(GDALOpenInfo *poOpenInfo)
363 :
364 : {
365 74541 : if (STARTS_WITH(poOpenInfo->pszFilename, "BAG:"))
366 30 : return TRUE;
367 :
368 : // Is it an HDF5 file?
369 : static const char achSignature[] = "\211HDF\r\n\032\n";
370 :
371 74511 : if (poOpenInfo->pabyHeader == nullptr ||
372 13990 : memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0)
373 74208 : return FALSE;
374 :
375 : // Does it have the extension .bag?
376 303 : if (!poOpenInfo->IsExtensionEqualToCI("bag"))
377 : {
378 167 : if (poOpenInfo->IsSingleAllowedDriver("BAG"))
379 : {
380 1 : return TRUE;
381 : }
382 166 : return FALSE;
383 : }
384 :
385 136 : return TRUE;
386 : }
387 :
388 : /************************************************************************/
389 : /* HDF5DriverSetCommonMetadata() */
390 : /************************************************************************/
391 :
392 1819 : void HDF5DriverSetCommonMetadata(GDALDriver *poDriver)
393 : {
394 1819 : poDriver->SetDescription(HDF5_DRIVER_NAME);
395 1819 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
396 1819 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
397 1819 : "Hierarchical Data Format Release 5");
398 1819 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
399 1819 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "h5 hdf5");
400 1819 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
401 1819 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
402 :
403 1819 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
404 :
405 1819 : poDriver->pfnIdentify = HDF5DatasetIdentify;
406 1819 : poDriver->pfnGetSubdatasetInfoFunc = HDF5DriverGetSubdatasetInfo;
407 1819 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
408 1819 : }
409 :
410 : /************************************************************************/
411 : /* HDF5ImageDriverSetCommonMetadata() */
412 : /************************************************************************/
413 :
414 1819 : void HDF5ImageDriverSetCommonMetadata(GDALDriver *poDriver)
415 : {
416 1819 : poDriver->SetDescription(HDF5_IMAGE_DRIVER_NAME);
417 1819 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
418 1819 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "HDF5 Dataset");
419 1819 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/hdf5.html");
420 1819 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
421 :
422 1819 : poDriver->pfnIdentify = HDF5ImageDatasetIdentify;
423 1819 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
424 1819 : }
425 :
426 : /************************************************************************/
427 : /* BAGDriverSetCommonMetadata() */
428 : /************************************************************************/
429 :
430 1819 : void BAGDriverSetCommonMetadata(GDALDriver *poDriver)
431 : {
432 1819 : poDriver->SetDescription(BAG_DRIVER_NAME);
433 1819 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
434 1819 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
435 1819 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Bathymetry Attributed Grid");
436 1819 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/bag.html");
437 1819 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
438 1819 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "bag");
439 :
440 1819 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32");
441 :
442 1819 : poDriver->SetMetadataItem(
443 : GDAL_DMD_OPENOPTIONLIST,
444 : "<OpenOptionList>"
445 : " <Option name='MODE' type='string-select' default='AUTO'>"
446 : " <Value>AUTO</Value>"
447 : " <Value>LOW_RES_GRID</Value>"
448 : " <Value>LIST_SUPERGRIDS</Value>"
449 : " <Value>RESAMPLED_GRID</Value>"
450 : " <Value>INTERPOLATED</Value>"
451 : " </Option>"
452 : " <Option name='SUPERGRIDS_INDICES' type='string' description="
453 : "'Tuple(s) (y1,x1),(y2,x2),... of supergrids, by indices, to expose "
454 : "as subdatasets'/>"
455 : " <Option name='MINX' type='float' description='Minimum X value of "
456 : "area of interest'/>"
457 : " <Option name='MINY' type='float' description='Minimum Y value of "
458 : "area of interest'/>"
459 : " <Option name='MAXX' type='float' description='Maximum X value of "
460 : "area of interest'/>"
461 : " <Option name='MAXY' type='float' description='Maximum Y value of "
462 : "area of interest'/>"
463 : " <Option name='RESX' type='float' description="
464 : "'Horizontal resolution. Only used for "
465 : "MODE=RESAMPLED_GRID/INTERPOLATED'/>"
466 : " <Option name='RESY' type='float' description="
467 : "'Vertical resolution (positive value). Only used for "
468 : "MODE=RESAMPLED_GRID/INTERPOLATED'/>"
469 : " <Option name='RES_STRATEGY' type='string-select' description="
470 : "'Which strategy to apply to select the resampled grid resolution. "
471 : "Only used for MODE=RESAMPLED_GRID/INTERPOLATED' default='AUTO'>"
472 : " <Value>AUTO</Value>"
473 : " <Value>MIN</Value>"
474 : " <Value>MAX</Value>"
475 : " <Value>MEAN</Value>"
476 : " </Option>"
477 : " <Option name='RES_FILTER_MIN' type='float' description="
478 : "'Minimum resolution of supergrids to take into account (excluded "
479 : "bound). "
480 : "Only used for MODE=RESAMPLED_GRID, INTERPOLATED or LIST_SUPERGRIDS' "
481 : "default='0'/>"
482 : " <Option name='RES_FILTER_MAX' type='float' description="
483 : "'Maximum resolution of supergrids to take into account (included "
484 : "bound). "
485 : "Only used for MODE=RESAMPLED_GRID, INTERPOLATED or LIST_SUPERGRIDS' "
486 : "default='inf'/>"
487 : " <Option name='VALUE_POPULATION' type='string-select' description="
488 : "'Which value population strategy to apply to compute the resampled "
489 : "cell "
490 : "values. Only used for MODE=RESAMPLED_GRID' default='MAX'>"
491 : " <Value>MIN</Value>"
492 : " <Value>MAX</Value>"
493 : " <Value>MEAN</Value>"
494 : " <Value>COUNT</Value>"
495 : " </Option>"
496 : " <Option name='SUPERGRIDS_MASK' type='boolean' description="
497 : "'Whether the dataset should consist of a mask band indicating if a "
498 : "supergrid node matches each target pixel. Only used for "
499 : "MODE=RESAMPLED_GRID' default='NO'/>"
500 : " <Option name='NODATA_VALUE' type='float' default='1000000'/>"
501 : " <Option name='REPORT_VERTCRS' type='boolean' default='YES'/>"
502 1819 : "</OpenOptionList>");
503 :
504 1819 : poDriver->SetMetadataItem(
505 : GDAL_DMD_CREATIONOPTIONLIST,
506 : "<CreationOptionList>"
507 : " <Option name='VAR_*' type='string' description="
508 : "'Value to substitute to a variable in the template'/>"
509 : " <Option name='TEMPLATE' type='string' description="
510 : "'.xml template to use'/>"
511 : " <Option name='BAG_VERSION' type='string' description="
512 : "'Version to write in the Bag Version attribute' default='1.6.2'/>"
513 : " <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
514 : " <Value>NONE</Value>"
515 : " <Value>DEFLATE</Value>"
516 : " </Option>"
517 : " <Option name='ZLEVEL' type='int' "
518 : "description='DEFLATE compression level 1-9' default='6' />"
519 : " <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
520 1819 : "</CreationOptionList>");
521 :
522 1819 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
523 :
524 1819 : poDriver->pfnIdentify = BAGDatasetIdentify;
525 1819 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
526 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
527 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
528 1819 : }
529 :
530 : /************************************************************************/
531 : /* S102DriverSetCommonMetadata() */
532 : /************************************************************************/
533 :
534 1819 : void S102DriverSetCommonMetadata(GDALDriver *poDriver)
535 : {
536 1819 : poDriver->SetDescription(S102_DRIVER_NAME);
537 1819 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
538 1819 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
539 1819 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
540 1819 : "S-102 Bathymetric Surface Product");
541 1819 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s102.html");
542 1819 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
543 1819 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
544 1819 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
545 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
546 :
547 1819 : poDriver->SetMetadataItem(
548 : GDAL_DMD_OPENOPTIONLIST,
549 : "<OpenOptionList>"
550 : " <Option name='DEPTH_OR_ELEVATION' type='string-select' "
551 : "default='DEPTH'>"
552 : " <Value>DEPTH</Value>"
553 : " <Value>ELEVATION</Value>"
554 : " </Option>"
555 : " <Option name='NORTH_UP' type='boolean' default='YES' "
556 : "description='Whether the top line of the dataset should be the "
557 : "northern-most one'/>"
558 1819 : "</OpenOptionList>");
559 :
560 1819 : poDriver->SetMetadataItem(
561 : GDAL_DMD_CREATIONOPTIONLIST,
562 : "<CreationOptionList>"
563 : " <Option name='VERTICAL_DATUM' type='string' description="
564 : "'Vertical datum abbreviation or code (required)'/>"
565 : " <Option name='ISSUE_DATE' type='string' description="
566 : "'Issue date as YYYYMMDD'/>"
567 : " <Option name='ISSUE_TIME' type='string' description="
568 : "'Issue time as hhmmssZ or hhmmss[+-]HHMM'/>"
569 : " <Option name='HORIZONTAL_POSITION_UNCERTAINTY' type='float' "
570 : "description='Horizontal position uncertainty in meter'/>"
571 : " <Option name='VERTICAL_UNCERTAINTY' type='float' "
572 : "description='Vertical uncertainty in meter'/>"
573 : " <Option name='QUALITY_DATASET' type='string' description="
574 : "'Path to a dataset with the quality of bathymetric coverage'/>"
575 : " <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
576 : " <Value>NONE</Value>"
577 : " <Value>DEFLATE</Value>"
578 : " </Option>"
579 : " <Option name='ZLEVEL' type='int' "
580 : "description='DEFLATE compression level 1-9' default='6' />"
581 : " <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
582 1819 : "</CreationOptionList>");
583 :
584 1819 : poDriver->pfnIdentify = S102DatasetIdentify;
585 1819 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
586 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
587 1819 : }
588 :
589 : /************************************************************************/
590 : /* S104DriverSetCommonMetadata() */
591 : /************************************************************************/
592 :
593 1819 : void S104DriverSetCommonMetadata(GDALDriver *poDriver)
594 : {
595 1819 : poDriver->SetDescription(S104_DRIVER_NAME);
596 1819 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
597 1819 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
598 1819 : poDriver->SetMetadataItem(
599 : GDAL_DMD_LONGNAME,
600 1819 : "S-104 Water Level Information for Surface Navigation Product");
601 1819 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s104.html");
602 1819 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
603 1819 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
604 1819 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
605 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
606 :
607 1819 : poDriver->SetMetadataItem(
608 : GDAL_DMD_OPENOPTIONLIST,
609 : "<OpenOptionList>"
610 : " <Option name='NORTH_UP' type='boolean' default='YES' "
611 : "description='Whether the top line of the dataset should be the "
612 : "northern-most one'/>"
613 1819 : "</OpenOptionList>");
614 :
615 1819 : poDriver->SetMetadataItem(
616 : GDAL_DMD_CREATIONOPTIONLIST,
617 : "<CreationOptionList>"
618 : " <Option name='TIME_POINT' type='string' description="
619 : "'Timestamp as YYYYMMDDTHHMMSSZ format (required)'/>"
620 : " <Option name='VERTICAL_DATUM' type='string' description="
621 : "'Vertical datum abbreviation or code (required)'/>"
622 : " <Option name='VERTICAL_CS' type='string-select' description="
623 : "'Vertical coordinate system (required).'>"
624 : " <Value alias='6498'>DEPTH</Value>"
625 : " <Value alias='6499'>HEIGHT</Value>"
626 : " </Option>"
627 : " <Option name='WATER_LEVEL_TREND_THRESHOLD' type='float' description="
628 : "'Critical value used to determine steady water level trend (required)."
629 : "Units are meters/hour (m/hr)'/>"
630 : " <Option name='DATA_DYNAMICITY' type='string-select' description="
631 : "'Classification of data according to the relationship between the "
632 : "time of its collection, generation, or calculation of generation "
633 : "parameters, in relation to the time of publication of the dataset "
634 : "(required).'>"
635 : " <Value alias='1'>observation</Value>"
636 : " <Value alias='2'>astronomicalPrediction</Value>"
637 : " <Value alias='3'>analysisOrHybrid</Value>"
638 : " <Value alias='5'>hydrodynamicForecast</Value>"
639 : " </Option>"
640 : " <Option name='DATASETS' type='string' description="
641 : "'Comma separated list of datasets at different timestamps.'/>"
642 : " <Option name='DATASETS_TIME_POINT' type='string' description="
643 : "'Comma separated list of the time point value of each dataset of "
644 : "DATASETS.'/>"
645 : " <Option name='GEOGRAPHIC_IDENTIFIER' type='string' description="
646 : "'Description, or location code from list agreed by data producers'/>"
647 : " <Option name='ISSUE_DATE' type='string' description="
648 : "'Issue date as YYYYMMDD'/>"
649 : " <Option name='ISSUE_TIME' type='string' description="
650 : "'Issue time as hhmmssZ or hhmmss[+-]HHMM'/>"
651 : " <Option name='TREND_INTERVAL' type='integer' "
652 : "description='Interval, in minutes, over which trend at a a particular "
653 : "time is calculated'/>"
654 : " <Option name='DATASET_DELIVERY_INTERVAL' type='string' description="
655 : "'Expected time interval between availability of successive datasets "
656 : "for time-varying data. Must be formatted as PnYnMnDTnHnMnS "
657 : "(ISO8601 duration)'/>"
658 : " <Option name='TIME_RECORD_INTERVAL' type='integer' description="
659 : "'Interval in seconds between time records.'/>"
660 : " <Option name='COMMON_POINT_RULE' type='string-select' description="
661 : "'Procedure used for evaluating the coverage at a position that falls "
662 : "on the boundary or in an area of overlap between geographic objects' "
663 : "default='all'>"
664 : " <Value alias='1'>average</Value>"
665 : " <Value alias='2'>low</Value>"
666 : " <Value alias='3'>high</Value>"
667 : " <Value alias='4'>all</Value>"
668 : " </Option>"
669 : " <Option name='UNCERTAINTY' type='float' "
670 : "description='Uncertainty of depth values in meter'/>"
671 : " <Option name='HORIZONTAL_POSITION_UNCERTAINTY' type='float' "
672 : "description='Horizontal position uncertainty in meter'/>"
673 : " <Option name='VERTICAL_UNCERTAINTY' type='float' "
674 : "description='Vertical uncertainty in meter'/>"
675 : " <Option name='TIME_UNCERTAINTY' type='float' "
676 : "description='Time uncertainty in second'/>"
677 : " <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
678 : " <Value>NONE</Value>"
679 : " <Value>DEFLATE</Value>"
680 : " </Option>"
681 : " <Option name='ZLEVEL' type='int' "
682 : "description='DEFLATE compression level 1-9' default='6' />"
683 : " <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
684 1819 : "</CreationOptionList>");
685 :
686 1819 : poDriver->pfnIdentify = S104DatasetIdentify;
687 1819 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
688 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
689 1819 : }
690 :
691 : /************************************************************************/
692 : /* S111DriverSetCommonMetadata() */
693 : /************************************************************************/
694 :
695 1819 : void S111DriverSetCommonMetadata(GDALDriver *poDriver)
696 : {
697 1819 : poDriver->SetDescription(S111_DRIVER_NAME);
698 1819 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
699 1819 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIDIM_RASTER, "YES");
700 1819 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
701 1819 : "S-111 Surface Currents Product");
702 1819 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/s111.html");
703 1819 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
704 1819 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "h5");
705 1819 : poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
706 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_SUBDATASETS, "YES");
707 :
708 1819 : poDriver->SetMetadataItem(
709 : GDAL_DMD_OPENOPTIONLIST,
710 : "<OpenOptionList>"
711 : " <Option name='NORTH_UP' type='boolean' default='YES' "
712 : "description='Whether the top line of the dataset should be the "
713 : "northern-most one'/>"
714 1819 : "</OpenOptionList>");
715 :
716 1819 : poDriver->SetMetadataItem(
717 : GDAL_DMD_CREATIONOPTIONLIST,
718 : "<CreationOptionList>"
719 : " <Option name='TIME_POINT' type='string' description="
720 : "'Timestamp as YYYYMMDDTHHMMSSZ format (required)'/>"
721 : " <Option name='DEPTH_TYPE' type='string-select' description="
722 : "'Type of depth (required). When selecting heightOrDepth, "
723 : "the interpretation depends on the VERTICAL_CS value.'>"
724 : " <Value alias='1'>heightOrDepth</Value>"
725 : " <Value alias='2'>layerAverage</Value>"
726 : " </Option>"
727 : " <Option name='VERTICAL_DATUM' type='string' description="
728 : "'Vertical datum abbreviation or code (required if "
729 : "DEPTH_TYPE=heightOrDepth)'/>"
730 : " <Option name='VERTICAL_CS' type='string-select' description="
731 : "'Vertical coordinate system (required if DEPTH_TYPE=heightOrDepth).'>"
732 : " <Value alias='6498'>DEPTH</Value>"
733 : " <Value alias='6499'>HEIGHT</Value>"
734 : " </Option>"
735 : " <Option name='SURFACE_CURRENT_DEPTH' type='float' description="
736 : "'Depth/height value or layer thickness (m) (required)'/>"
737 : " <Option name='DATA_DYNAMICITY' type='string-select' description="
738 : "'Classification of data according to the relationship between the "
739 : "time of its collection, generation, or calculation of generation "
740 : "parameters, in relation to the time of publication of the dataset "
741 : "(required).'>"
742 : " <Value alias='1'>observation</Value>"
743 : " <Value alias='2'>astronomicalPrediction</Value>"
744 : " <Value alias='3'>analysisOrHybrid</Value>"
745 : " <Value alias='5'>hydrodynamicForecast</Value>"
746 : " </Option>"
747 : " <Option name='DATASETS' type='string' description="
748 : "'Comma separated list of datasets at different timestamps.'/>"
749 : " <Option name='DATASETS_TIME_POINT' type='string' description="
750 : "'Comma separated list of the time point value of each dataset of "
751 : "DATASETS.'/>"
752 : " <Option name='GEOGRAPHIC_IDENTIFIER' type='string' description="
753 : "'Description, or location code from list agreed by data producers'/>"
754 : " <Option name='ISSUE_DATE' type='string' description="
755 : "'Issue date as YYYYMMDD'/>"
756 : " <Option name='ISSUE_TIME' type='string' description="
757 : "'Issue time as hhmmssZ or hhmmss[+-]HHMM'/>"
758 : " <Option name='DATASET_DELIVERY_INTERVAL' type='string' description="
759 : "'Expected time interval between availability of successive datasets "
760 : "for time-varying data. Must be formatted as PnYnMnDTnHnMnS "
761 : "(ISO8601 duration)'/>"
762 : " <Option name='TIME_RECORD_INTERVAL' type='integer' description="
763 : "'Interval in seconds between time records.'/>"
764 : " <Option name='COMMON_POINT_RULE' type='string-select' description="
765 : "'Procedure used for evaluating the coverage at a position that falls "
766 : "on the boundary or in an area of overlap between geographic objects' "
767 : "default='high'>"
768 : " <Value alias='1'>average</Value>"
769 : " <Value alias='2'>low</Value>"
770 : " <Value alias='3'>high</Value>"
771 : " <Value alias='4'>all</Value>"
772 : " </Option>"
773 : " <Option name='UNCERTAINTY_SPEED' type='float' "
774 : "description='Uncertainty of speeds in knot'/>"
775 : " <Option name='UNCERTAINTY_DIRECTION' type='float' "
776 : "description='Uncertainty of direction angles in degree'/>"
777 : " <Option name='HORIZONTAL_POSITION_UNCERTAINTY' type='float' "
778 : "description='Horizontal position uncertainty in meter'/>"
779 : " <Option name='VERTICAL_UNCERTAINTY' type='float' "
780 : "description='Vertical uncertainty in meter'/>"
781 : " <Option name='TIME_UNCERTAINTY' type='float' "
782 : "description='Time uncertainty in second'/>"
783 : " <Option name='COMPRESS' type='string-select' default='DEFLATE'>"
784 : " <Value>NONE</Value>"
785 : " <Value>DEFLATE</Value>"
786 : " </Option>"
787 : " <Option name='ZLEVEL' type='int' "
788 : "description='DEFLATE compression level 1-9' default='6' />"
789 : " <Option name='BLOCK_SIZE' type='int' description='Chunk size' />"
790 1819 : "</CreationOptionList>");
791 :
792 1819 : poDriver->pfnIdentify = S111DatasetIdentify;
793 1819 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
794 1819 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
795 1819 : }
796 :
797 : /************************************************************************/
798 : /* DeclareDeferredHDF5Plugin() */
799 : /************************************************************************/
800 :
801 : #ifdef PLUGIN_FILENAME
802 2068 : void DeclareDeferredHDF5Plugin()
803 : {
804 2068 : if (GDALGetDriverByName(HDF5_DRIVER_NAME) != nullptr)
805 : {
806 263 : return;
807 : }
808 : {
809 1805 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
810 : #ifdef PLUGIN_INSTALLATION_MESSAGE
811 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
812 : PLUGIN_INSTALLATION_MESSAGE);
813 : #endif
814 1805 : HDF5DriverSetCommonMetadata(poDriver);
815 1805 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
816 : }
817 : {
818 1805 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
819 : #ifdef PLUGIN_INSTALLATION_MESSAGE
820 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
821 : PLUGIN_INSTALLATION_MESSAGE);
822 : #endif
823 1805 : HDF5ImageDriverSetCommonMetadata(poDriver);
824 1805 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
825 : }
826 : {
827 1805 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
828 : #ifdef PLUGIN_INSTALLATION_MESSAGE
829 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
830 : PLUGIN_INSTALLATION_MESSAGE);
831 : #endif
832 1805 : BAGDriverSetCommonMetadata(poDriver);
833 1805 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
834 : }
835 : {
836 1805 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
837 : #ifdef PLUGIN_INSTALLATION_MESSAGE
838 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
839 : PLUGIN_INSTALLATION_MESSAGE);
840 : #endif
841 1805 : S102DriverSetCommonMetadata(poDriver);
842 1805 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
843 : }
844 : {
845 1805 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
846 : #ifdef PLUGIN_INSTALLATION_MESSAGE
847 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
848 : PLUGIN_INSTALLATION_MESSAGE);
849 : #endif
850 1805 : S104DriverSetCommonMetadata(poDriver);
851 1805 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
852 : }
853 : {
854 1805 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
855 : #ifdef PLUGIN_INSTALLATION_MESSAGE
856 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
857 : PLUGIN_INSTALLATION_MESSAGE);
858 : #endif
859 1805 : S111DriverSetCommonMetadata(poDriver);
860 1805 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
861 : }
862 : }
863 : #endif
|