Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: HDF4 read Driver
4 : * Author: Even Rouault <even.rouault at spatialys.com>
5 : *
6 : ******************************************************************************
7 : * Copyright (c) 2019, Even Rouault <even.rouault at spatialys.com>
8 : *
9 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #include "hdf4dataset.h"
29 :
30 : #include "hdf.h"
31 : #include "mfhdf.h"
32 :
33 : #include "HdfEosDef.h"
34 :
35 : #include "cpl_string.h"
36 :
37 : #include <algorithm>
38 : #include <map>
39 : #include <set>
40 :
41 : #if defined(__clang__) || defined(_MSC_VER)
42 : #define COMPILER_WARNS_ABOUT_ABSTRACT_VBASE_INIT
43 : #endif
44 :
45 : extern CPLMutex *hHDF4Mutex;
46 : extern const char *const pszGDALSignature;
47 :
48 : /************************************************************************/
49 : /* HDF4SharedResources */
50 : /************************************************************************/
51 :
52 : class HDF4SharedResources
53 : {
54 : friend class ::HDF4Dataset;
55 : int32 m_hSD = -1;
56 : std::string m_osFilename;
57 : CPLStringList m_aosOpenOptions;
58 : std::shared_ptr<GDALPamMultiDim> m_poPAM{};
59 :
60 : public:
61 : explicit HDF4SharedResources(const std::string &osFilename);
62 : ~HDF4SharedResources();
63 :
64 65 : int32 GetSDHandle() const
65 : {
66 65 : return m_hSD;
67 : }
68 :
69 40 : const std::string &GetFilename() const
70 : {
71 40 : return m_osFilename;
72 : }
73 :
74 4 : const char *FetchOpenOption(const char *pszName,
75 : const char *pszDefault) const
76 : {
77 4 : return m_aosOpenOptions.FetchNameValueDef(pszName, pszDefault);
78 : }
79 :
80 10 : const std::shared_ptr<GDALPamMultiDim> &GetPAM()
81 : {
82 10 : return m_poPAM;
83 : }
84 : };
85 :
86 : /************************************************************************/
87 : /* HDF4Group */
88 : /************************************************************************/
89 :
90 : class HDF4SDSGroup;
91 :
92 : class HDF4Group final : public GDALGroup
93 : {
94 : std::shared_ptr<HDF4SharedResources> m_poShared;
95 : std::shared_ptr<HDF4SDSGroup> m_poGDALGroup{};
96 :
97 : protected:
98 : HDF4Group(const std::string &osParentName, const std::string &osName,
99 : const std::shared_ptr<HDF4SharedResources> &poShared);
100 :
101 : public:
102 : static std::shared_ptr<HDF4Group>
103 6 : Create(const std::string &osParentName, const std::string &osName,
104 : const std::shared_ptr<HDF4SharedResources> &poShared)
105 : {
106 : auto poGroup = std::shared_ptr<HDF4Group>(
107 6 : new HDF4Group(osParentName, osName, poShared));
108 6 : poGroup->SetSelf(poGroup);
109 6 : return poGroup;
110 : }
111 :
112 : std::vector<std::shared_ptr<GDALAttribute>>
113 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
114 :
115 : std::vector<std::string>
116 : GetGroupNames(CSLConstList papszOptions) const override;
117 : std::shared_ptr<GDALGroup> OpenGroup(const std::string &osName,
118 : CSLConstList) const override;
119 :
120 : std::vector<std::shared_ptr<GDALDimension>>
121 : GetDimensions(CSLConstList papszOptions = nullptr) const override;
122 :
123 : std::vector<std::string>
124 : GetMDArrayNames(CSLConstList papszOptions) const override;
125 : std::shared_ptr<GDALMDArray>
126 : OpenMDArray(const std::string &osName,
127 : CSLConstList papszOptions) const override;
128 : };
129 :
130 : /************************************************************************/
131 : /* HDF4AbstractAttribute */
132 : /************************************************************************/
133 :
134 : class HDF4AbstractAttribute : public GDALAttribute
135 : {
136 : std::shared_ptr<HDF4SharedResources> m_poShared;
137 : std::vector<std::shared_ptr<GDALDimension>> m_dims{};
138 : GDALExtendedDataType m_dt = GDALExtendedDataType::Create(GDT_Unknown);
139 : int32 m_nValues = 0;
140 :
141 : protected:
142 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
143 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
144 : const GDALExtendedDataType &bufferDataType,
145 : void *pDstBuffer) const override;
146 :
147 : public:
148 : HDF4AbstractAttribute(const std::string &osParentName,
149 : const std::string &osName,
150 : const std::shared_ptr<HDF4SharedResources> &poShared,
151 : int32 iNumType, int32 nValues);
152 :
153 : const std::vector<std::shared_ptr<GDALDimension>> &
154 35 : GetDimensions() const override
155 : {
156 35 : return m_dims;
157 : }
158 :
159 26 : const GDALExtendedDataType &GetDataType() const override
160 : {
161 26 : return m_dt;
162 : }
163 :
164 : virtual void ReadData(void *pDstBuffer) const = 0;
165 : };
166 :
167 : /************************************************************************/
168 : /* HDF4SwathsHandle */
169 : /************************************************************************/
170 :
171 : struct HDF4SwathsHandle
172 : {
173 : int32 m_handle;
174 :
175 0 : explicit HDF4SwathsHandle(int32 handle) : m_handle(handle)
176 : {
177 0 : }
178 :
179 0 : ~HDF4SwathsHandle()
180 0 : {
181 0 : CPLMutexHolderD(&hHDF4Mutex);
182 0 : SWclose(m_handle);
183 0 : }
184 : };
185 :
186 : /************************************************************************/
187 : /* HDF4SwathHandle */
188 : /************************************************************************/
189 :
190 : struct HDF4SwathHandle
191 : {
192 : std::shared_ptr<HDF4SwathsHandle> m_poSwathsHandle;
193 : int32 m_handle;
194 :
195 0 : explicit HDF4SwathHandle(
196 : const std::shared_ptr<HDF4SwathsHandle> &poSwathsHandle, int32 handle)
197 0 : : m_poSwathsHandle(poSwathsHandle), m_handle(handle)
198 : {
199 0 : }
200 :
201 0 : ~HDF4SwathHandle()
202 0 : {
203 0 : CPLMutexHolderD(&hHDF4Mutex);
204 0 : SWdetach(m_handle);
205 0 : }
206 : };
207 :
208 : /************************************************************************/
209 : /* HDF4SwathsGroup */
210 : /************************************************************************/
211 :
212 : class HDF4SwathsGroup final : public GDALGroup
213 : {
214 : std::shared_ptr<HDF4SharedResources> m_poShared;
215 : std::shared_ptr<HDF4SwathsHandle> m_poSwathsHandle;
216 :
217 : public:
218 0 : HDF4SwathsGroup(const std::string &osParentName, const std::string &osName,
219 : const std::shared_ptr<HDF4SharedResources> &poShared,
220 : const std::shared_ptr<HDF4SwathsHandle> &poSwathsHandle)
221 0 : : GDALGroup(osParentName, osName), m_poShared(poShared),
222 0 : m_poSwathsHandle(poSwathsHandle)
223 : {
224 0 : }
225 :
226 : std::vector<std::string>
227 : GetGroupNames(CSLConstList papszOptions) const override;
228 : std::shared_ptr<GDALGroup> OpenGroup(const std::string &osName,
229 : CSLConstList) const override;
230 : };
231 :
232 : /************************************************************************/
233 : /* HDF4SwathGroup */
234 : /************************************************************************/
235 :
236 : class HDF4SwathGroup final : public GDALGroup
237 : {
238 : std::shared_ptr<HDF4SharedResources> m_poShared;
239 : std::shared_ptr<HDF4SwathHandle> m_poSwathHandle;
240 : mutable std::vector<std::shared_ptr<GDALDimension>> m_dims{};
241 :
242 : public:
243 0 : HDF4SwathGroup(const std::string &osParentName, const std::string &osName,
244 : const std::shared_ptr<HDF4SharedResources> &poShared,
245 : const std::shared_ptr<HDF4SwathHandle> &poSwathHandle)
246 0 : : GDALGroup(osParentName, osName), m_poShared(poShared),
247 0 : m_poSwathHandle(poSwathHandle)
248 : {
249 0 : }
250 :
251 : std::vector<std::shared_ptr<GDALDimension>>
252 : GetDimensions(CSLConstList papszOptions = nullptr) const override;
253 :
254 : std::vector<std::shared_ptr<GDALAttribute>>
255 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
256 :
257 : std::vector<std::string>
258 : GetGroupNames(CSLConstList papszOptions) const override;
259 : std::shared_ptr<GDALGroup> OpenGroup(const std::string &osName,
260 : CSLConstList) const override;
261 : };
262 :
263 : /************************************************************************/
264 : /* HDF4SwathSubGroup */
265 : /************************************************************************/
266 :
267 : class HDF4SwathSubGroup final : public GDALGroup
268 : {
269 : std::shared_ptr<HDF4SharedResources> m_poShared;
270 : std::shared_ptr<HDF4SwathHandle> m_poSwathHandle;
271 : int32 m_entryType;
272 : std::vector<std::shared_ptr<GDALDimension>> m_groupDims{};
273 :
274 : public:
275 0 : HDF4SwathSubGroup(
276 : const std::string &osParentName, const std::string &osName,
277 : const std::shared_ptr<HDF4SharedResources> &poShared,
278 : const std::shared_ptr<HDF4SwathHandle> &poSwathHandle, int32 entryType,
279 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims)
280 0 : : GDALGroup(osParentName, osName), m_poShared(poShared),
281 : m_poSwathHandle(poSwathHandle), m_entryType(entryType),
282 0 : m_groupDims(groupDims)
283 : {
284 0 : }
285 :
286 : std::vector<std::string>
287 : GetMDArrayNames(CSLConstList papszOptions) const override;
288 : std::shared_ptr<GDALMDArray>
289 : OpenMDArray(const std::string &osName,
290 : CSLConstList papszOptions) const override;
291 : };
292 :
293 : /************************************************************************/
294 : /* HDF4SwathArray */
295 : /************************************************************************/
296 :
297 : class HDF4SwathArray final : public GDALPamMDArray
298 : {
299 : std::shared_ptr<HDF4SharedResources> m_poShared;
300 : std::shared_ptr<HDF4SwathHandle> m_poSwathHandle;
301 : std::vector<std::shared_ptr<GDALDimension>> m_dims{};
302 : GDALExtendedDataType m_dt = GDALExtendedDataType::Create(GDT_Unknown);
303 : mutable std::vector<GByte> m_abyNoData{};
304 :
305 : protected:
306 : HDF4SwathArray(
307 : const std::string &osParentName, const std::string &osName,
308 : const std::shared_ptr<HDF4SharedResources> &poShared,
309 : const std::shared_ptr<HDF4SwathHandle> &poSwathHandle,
310 : const std::vector<int32> &aiDimSizes, const std::string &dimNames,
311 : int32 iNumType,
312 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims);
313 :
314 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
315 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
316 : const GDALExtendedDataType &bufferDataType,
317 : void *pDstBuffer) const override;
318 :
319 : public:
320 : static std::shared_ptr<HDF4SwathArray>
321 0 : Create(const std::string &osParentName, const std::string &osName,
322 : const std::shared_ptr<HDF4SharedResources> &poShared,
323 : const std::shared_ptr<HDF4SwathHandle> &poSwathHandle,
324 : const std::vector<int32> &aiDimSizes, const std::string &dimNames,
325 : int32 iNumType,
326 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims)
327 : {
328 : auto ar(std::shared_ptr<HDF4SwathArray>(
329 : new HDF4SwathArray(osParentName, osName, poShared, poSwathHandle,
330 0 : aiDimSizes, dimNames, iNumType, groupDims)));
331 0 : ar->SetSelf(ar);
332 0 : return ar;
333 : }
334 :
335 0 : bool IsWritable() const override
336 : {
337 0 : return false;
338 : }
339 :
340 0 : const std::string &GetFilename() const override
341 : {
342 0 : return m_poShared->GetFilename();
343 : }
344 :
345 : const std::vector<std::shared_ptr<GDALDimension>> &
346 0 : GetDimensions() const override
347 : {
348 0 : return m_dims;
349 : }
350 :
351 0 : const GDALExtendedDataType &GetDataType() const override
352 : {
353 0 : return m_dt;
354 : }
355 :
356 : std::vector<std::shared_ptr<GDALAttribute>>
357 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
358 :
359 : const void *GetRawNoDataValue() const override;
360 : };
361 :
362 : /************************************************************************/
363 : /* HDF4SDAttribute */
364 : /************************************************************************/
365 :
366 : class HDF4SwathAttribute final : public HDF4AbstractAttribute
367 : {
368 : std::shared_ptr<HDF4SwathHandle> m_poSwathHandle;
369 :
370 : public:
371 0 : HDF4SwathAttribute(const std::string &osParentName,
372 : const std::string &osName,
373 : const std::shared_ptr<HDF4SharedResources> &poShared,
374 : const std::shared_ptr<HDF4SwathHandle> &poSwathHandle,
375 : int32 iNumType, int32 nValues)
376 0 : : GDALAbstractMDArray(osParentName, osName),
377 : HDF4AbstractAttribute(osParentName, osName, poShared, iNumType,
378 : nValues),
379 0 : m_poSwathHandle(poSwathHandle)
380 : {
381 0 : }
382 :
383 0 : void ReadData(void *pDstBuffer) const override
384 : {
385 0 : SWreadattr(m_poSwathHandle->m_handle, GetName().c_str(), pDstBuffer);
386 0 : }
387 : };
388 :
389 : /************************************************************************/
390 : /* HDF4GDsHandle */
391 : /************************************************************************/
392 :
393 : struct HDF4GDsHandle
394 : {
395 : int32 m_handle;
396 :
397 0 : explicit HDF4GDsHandle(int32 handle) : m_handle(handle)
398 : {
399 0 : }
400 :
401 0 : ~HDF4GDsHandle()
402 0 : {
403 0 : CPLMutexHolderD(&hHDF4Mutex);
404 0 : GDclose(m_handle);
405 0 : }
406 : };
407 :
408 : /************************************************************************/
409 : /* HDF4GDHandle */
410 : /************************************************************************/
411 :
412 : struct HDF4GDHandle
413 : {
414 : std::shared_ptr<HDF4GDsHandle> m_poGDsHandle;
415 : int32 m_handle;
416 :
417 0 : explicit HDF4GDHandle(const std::shared_ptr<HDF4GDsHandle> &poGDsHandle,
418 : int32 handle)
419 0 : : m_poGDsHandle(poGDsHandle), m_handle(handle)
420 : {
421 0 : }
422 :
423 0 : ~HDF4GDHandle()
424 0 : {
425 0 : CPLMutexHolderD(&hHDF4Mutex);
426 0 : GDdetach(m_handle);
427 0 : }
428 : };
429 :
430 : /************************************************************************/
431 : /* HDF4EOSGridsGroup */
432 : /************************************************************************/
433 :
434 : class HDF4EOSGridsGroup final : public GDALGroup
435 : {
436 : std::shared_ptr<HDF4SharedResources> m_poShared;
437 : std::shared_ptr<HDF4GDsHandle> m_poGDsHandle;
438 :
439 : public:
440 0 : HDF4EOSGridsGroup(const std::string &osParentName,
441 : const std::string &osName,
442 : const std::shared_ptr<HDF4SharedResources> &poShared,
443 : const std::shared_ptr<HDF4GDsHandle> &poGDsHandle)
444 0 : : GDALGroup(osParentName, osName), m_poShared(poShared),
445 0 : m_poGDsHandle(poGDsHandle)
446 : {
447 0 : }
448 :
449 : std::vector<std::string>
450 : GetGroupNames(CSLConstList papszOptions) const override;
451 : std::shared_ptr<GDALGroup> OpenGroup(const std::string &osName,
452 : CSLConstList) const override;
453 : };
454 :
455 : /************************************************************************/
456 : /* HDF4EOSGridGroup */
457 : /************************************************************************/
458 :
459 : class HDF4EOSGridGroup final : public GDALGroup
460 : {
461 : std::shared_ptr<HDF4SharedResources> m_poShared;
462 : std::shared_ptr<HDF4GDHandle> m_poGDHandle;
463 : mutable std::vector<std::shared_ptr<GDALDimension>> m_dims{};
464 : mutable std::shared_ptr<GDALMDArray> m_varX{};
465 : mutable std::shared_ptr<GDALMDArray> m_varY{};
466 :
467 : public:
468 0 : HDF4EOSGridGroup(const std::string &osParentName, const std::string &osName,
469 : const std::shared_ptr<HDF4SharedResources> &poShared,
470 : const std::shared_ptr<HDF4GDHandle> &poGDHandle)
471 0 : : GDALGroup(osParentName, osName), m_poShared(poShared),
472 0 : m_poGDHandle(poGDHandle)
473 : {
474 0 : }
475 :
476 : std::vector<std::shared_ptr<GDALDimension>>
477 : GetDimensions(CSLConstList papszOptions = nullptr) const override;
478 :
479 : std::vector<std::string>
480 : GetMDArrayNames(CSLConstList papszOptions) const override;
481 : std::shared_ptr<GDALMDArray>
482 : OpenMDArray(const std::string &osName,
483 : CSLConstList papszOptions) const override;
484 :
485 : std::vector<std::string>
486 : GetGroupNames(CSLConstList papszOptions) const override;
487 : std::shared_ptr<GDALGroup> OpenGroup(const std::string &osName,
488 : CSLConstList) const override;
489 :
490 : std::vector<std::shared_ptr<GDALAttribute>>
491 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
492 : };
493 :
494 : /************************************************************************/
495 : /* HDF4EOSGridSubGroup */
496 : /************************************************************************/
497 :
498 : class HDF4EOSGridSubGroup final : public GDALGroup
499 : {
500 : std::shared_ptr<HDF4SharedResources> m_poShared;
501 : std::shared_ptr<HDF4GDHandle> m_poGDHandle;
502 : int32 m_entryType;
503 : std::vector<std::shared_ptr<GDALDimension>> m_groupDims{};
504 :
505 : public:
506 0 : HDF4EOSGridSubGroup(
507 : const std::string &osParentName, const std::string &osName,
508 : const std::shared_ptr<HDF4SharedResources> &poShared,
509 : const std::shared_ptr<HDF4GDHandle> &poGDHandle, int32 entryType,
510 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims)
511 0 : : GDALGroup(osParentName, osName), m_poShared(poShared),
512 : m_poGDHandle(poGDHandle), m_entryType(entryType),
513 0 : m_groupDims(groupDims)
514 : {
515 0 : }
516 :
517 : std::vector<std::string>
518 : GetMDArrayNames(CSLConstList papszOptions) const override;
519 : std::shared_ptr<GDALMDArray>
520 : OpenMDArray(const std::string &osName,
521 : CSLConstList papszOptions) const override;
522 : };
523 :
524 : /************************************************************************/
525 : /* HDF4EOSGridArray */
526 : /************************************************************************/
527 :
528 : class HDF4EOSGridArray final : public GDALPamMDArray
529 : {
530 : std::shared_ptr<HDF4SharedResources> m_poShared;
531 : std::shared_ptr<HDF4GDHandle> m_poGDHandle;
532 : std::vector<std::shared_ptr<GDALDimension>> m_dims{};
533 : GDALExtendedDataType m_dt = GDALExtendedDataType::Create(GDT_Unknown);
534 : mutable std::vector<GByte> m_abyNoData{};
535 : mutable std::string m_osUnit{};
536 :
537 : protected:
538 : HDF4EOSGridArray(
539 : const std::string &osParentName, const std::string &osName,
540 : const std::shared_ptr<HDF4SharedResources> &poShared,
541 : const std::shared_ptr<HDF4GDHandle> &poGDHandle,
542 : const std::vector<int32> &aiDimSizes, const std::string &dimNames,
543 : int32 iNumType,
544 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims);
545 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
546 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
547 : const GDALExtendedDataType &bufferDataType,
548 : void *pDstBuffer) const override;
549 :
550 : public:
551 : static std::shared_ptr<HDF4EOSGridArray>
552 0 : Create(const std::string &osParentName, const std::string &osName,
553 : const std::shared_ptr<HDF4SharedResources> &poShared,
554 : const std::shared_ptr<HDF4GDHandle> &poGDHandle,
555 : const std::vector<int32> &aiDimSizes, const std::string &dimNames,
556 : int32 iNumType,
557 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims)
558 : {
559 : auto ar(std::shared_ptr<HDF4EOSGridArray>(
560 : new HDF4EOSGridArray(osParentName, osName, poShared, poGDHandle,
561 0 : aiDimSizes, dimNames, iNumType, groupDims)));
562 0 : ar->SetSelf(ar);
563 0 : return ar;
564 : }
565 :
566 0 : bool IsWritable() const override
567 : {
568 0 : return false;
569 : }
570 :
571 0 : const std::string &GetFilename() const override
572 : {
573 0 : return m_poShared->GetFilename();
574 : }
575 :
576 : const std::vector<std::shared_ptr<GDALDimension>> &
577 0 : GetDimensions() const override
578 : {
579 0 : return m_dims;
580 : }
581 :
582 0 : const GDALExtendedDataType &GetDataType() const override
583 : {
584 0 : return m_dt;
585 : }
586 :
587 : std::vector<std::shared_ptr<GDALAttribute>>
588 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
589 :
590 : const void *GetRawNoDataValue() const override;
591 :
592 : double GetOffset(bool *pbHasOffset = nullptr,
593 : GDALDataType *peStorageType = nullptr) const override;
594 :
595 : double GetScale(bool *pbHasScale = nullptr,
596 : GDALDataType *peStorageType = nullptr) const override;
597 :
598 : const std::string &GetUnit() const override;
599 :
600 : std::shared_ptr<OGRSpatialReference> GetSpatialRef() const override;
601 :
602 0 : std::shared_ptr<GDALGroup> GetRootGroup() const override
603 : {
604 0 : return HDF4Group::Create(std::string(), "/", m_poShared);
605 : }
606 : };
607 :
608 : /************************************************************************/
609 : /* HDF4EOSGridAttribute */
610 : /************************************************************************/
611 :
612 : class HDF4EOSGridAttribute final : public HDF4AbstractAttribute
613 : {
614 : std::shared_ptr<HDF4GDHandle> m_poGDHandle;
615 :
616 : public:
617 0 : HDF4EOSGridAttribute(const std::string &osParentName,
618 : const std::string &osName,
619 : const std::shared_ptr<HDF4SharedResources> &poShared,
620 : const std::shared_ptr<HDF4GDHandle> &poGDHandle,
621 : int32 iNumType, int32 nValues)
622 0 : : GDALAbstractMDArray(osParentName, osName),
623 : HDF4AbstractAttribute(osParentName, osName, poShared, iNumType,
624 : nValues),
625 0 : m_poGDHandle(poGDHandle)
626 : {
627 0 : }
628 :
629 0 : void ReadData(void *pDstBuffer) const override
630 : {
631 0 : GDreadattr(m_poGDHandle->m_handle, GetName().c_str(), pDstBuffer);
632 0 : }
633 : };
634 :
635 : /************************************************************************/
636 : /* HDF4SDSGroup */
637 : /************************************************************************/
638 :
639 : class HDF4SDSGroup final : public GDALGroup
640 : {
641 : std::shared_ptr<HDF4SharedResources> m_poShared;
642 : mutable std::map<std::string, int> m_oMapNameToSDSIdx{};
643 : mutable std::vector<std::shared_ptr<GDALDimension>> m_dims{};
644 : mutable std::vector<std::shared_ptr<GDALMDArray>> m_oSetIndexingVariables{};
645 : mutable bool m_bInGetDimensions = false;
646 : bool m_bIsGDALDataset = false;
647 : std::vector<std::shared_ptr<GDALAttribute>> m_oGlobalAttributes{};
648 : mutable std::shared_ptr<GDALMDArray> m_varX{};
649 : mutable std::shared_ptr<GDALMDArray> m_varY{};
650 :
651 : public:
652 4 : HDF4SDSGroup(const std::string &osParentName, const std::string &osName,
653 : const std::shared_ptr<HDF4SharedResources> &poShared)
654 4 : : GDALGroup(osParentName, osName), m_poShared(poShared)
655 : {
656 4 : }
657 :
658 2 : void SetIsGDALDataset()
659 : {
660 2 : m_bIsGDALDataset = true;
661 2 : }
662 :
663 2 : void SetGlobalAttributes(
664 : const std::vector<std::shared_ptr<GDALAttribute>> &attrs)
665 : {
666 2 : m_oGlobalAttributes = attrs;
667 2 : }
668 :
669 : std::vector<std::shared_ptr<GDALDimension>>
670 : GetDimensions(CSLConstList papszOptions = nullptr) const override;
671 :
672 : std::vector<std::string>
673 : GetMDArrayNames(CSLConstList papszOptions) const override;
674 : std::shared_ptr<GDALMDArray>
675 : OpenMDArray(const std::string &osName,
676 : CSLConstList papszOptions) const override;
677 : };
678 :
679 : /************************************************************************/
680 : /* HDF4SDSArray */
681 : /************************************************************************/
682 :
683 : class HDF4SDSArray final : public GDALPamMDArray
684 : {
685 : std::shared_ptr<HDF4SharedResources> m_poShared;
686 : int32 m_iSDS;
687 : std::vector<std::shared_ptr<GDALDimension>> m_dims{};
688 : GDALExtendedDataType m_dt = GDALExtendedDataType::Create(GDT_Unknown);
689 : int32 m_nAttributes;
690 : mutable std::string m_osUnit{};
691 : std::vector<std::shared_ptr<GDALAttribute>> m_oGlobalAttributes{};
692 : bool m_bIsGDALDataset;
693 : mutable std::vector<GByte> m_abyNoData{};
694 :
695 : protected:
696 : HDF4SDSArray(const std::string &osParentName, const std::string &osName,
697 : const std::shared_ptr<HDF4SharedResources> &poShared,
698 : int32 iSDS, const std::vector<int32> &aiDimSizes,
699 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims,
700 : int32 iNumType, int32 nAttrs, bool bIsGDALDS);
701 :
702 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
703 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
704 : const GDALExtendedDataType &bufferDataType,
705 : void *pDstBuffer) const override;
706 :
707 : public:
708 : static std::shared_ptr<HDF4SDSArray>
709 8 : Create(const std::string &osParentName, const std::string &osName,
710 : const std::shared_ptr<HDF4SharedResources> &poShared, int32 iSDS,
711 : const std::vector<int32> &aiDimSizes,
712 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims,
713 : int32 iNumType, int32 nAttrs, bool bIsGDALDS)
714 : {
715 : auto ar(std::shared_ptr<HDF4SDSArray>(
716 : new HDF4SDSArray(osParentName, osName, poShared, iSDS, aiDimSizes,
717 8 : groupDims, iNumType, nAttrs, bIsGDALDS)));
718 8 : ar->SetSelf(ar);
719 8 : return ar;
720 : }
721 :
722 : ~HDF4SDSArray();
723 :
724 2 : void SetGlobalAttributes(
725 : const std::vector<std::shared_ptr<GDALAttribute>> &attrs)
726 : {
727 2 : m_oGlobalAttributes = attrs;
728 2 : }
729 :
730 0 : bool IsWritable() const override
731 : {
732 0 : return false;
733 : }
734 :
735 8 : const std::string &GetFilename() const override
736 : {
737 8 : return m_poShared->GetFilename();
738 : }
739 :
740 : const std::vector<std::shared_ptr<GDALDimension>> &
741 28 : GetDimensions() const override
742 : {
743 28 : return m_dims;
744 : }
745 :
746 17 : const GDALExtendedDataType &GetDataType() const override
747 : {
748 17 : return m_dt;
749 : }
750 :
751 : std::vector<std::shared_ptr<GDALAttribute>>
752 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
753 :
754 : const void *GetRawNoDataValue() const override;
755 :
756 : double GetOffset(bool *pbHasOffset = nullptr,
757 : GDALDataType *peStorageType = nullptr) const override;
758 :
759 : double GetScale(bool *pbHasScale = nullptr,
760 : GDALDataType *peStorageType = nullptr) const override;
761 :
762 : const std::string &GetUnit() const override;
763 :
764 : std::shared_ptr<OGRSpatialReference> GetSpatialRef() const override;
765 :
766 0 : std::shared_ptr<GDALGroup> GetRootGroup() const override
767 : {
768 0 : return HDF4Group::Create(std::string(), "/", m_poShared);
769 : }
770 : };
771 :
772 : /************************************************************************/
773 : /* HDF4GRsHandle */
774 : /************************************************************************/
775 :
776 : struct HDF4GRsHandle
777 : {
778 : int32 m_hHandle;
779 : int32 m_grHandle;
780 :
781 2 : explicit HDF4GRsHandle(int32 hHandle, int32 grHandle)
782 2 : : m_hHandle(hHandle), m_grHandle(grHandle)
783 : {
784 2 : }
785 :
786 2 : ~HDF4GRsHandle()
787 2 : {
788 4 : CPLMutexHolderD(&hHDF4Mutex);
789 2 : GRend(m_grHandle);
790 2 : Hclose(m_hHandle);
791 2 : }
792 : };
793 :
794 : /************************************************************************/
795 : /* HDF4GRHandle */
796 : /************************************************************************/
797 :
798 : struct HDF4GRHandle
799 : {
800 : std::shared_ptr<HDF4GRsHandle> m_poGRsHandle;
801 : int32 m_iGR;
802 :
803 2 : explicit HDF4GRHandle(const std::shared_ptr<HDF4GRsHandle> &poGRsHandle,
804 : int32 iGR)
805 2 : : m_poGRsHandle(poGRsHandle), m_iGR(iGR)
806 : {
807 2 : }
808 :
809 2 : ~HDF4GRHandle()
810 2 : {
811 4 : CPLMutexHolderD(&hHDF4Mutex);
812 2 : GRendaccess(m_iGR);
813 2 : }
814 : };
815 :
816 : /************************************************************************/
817 : /* HDF4GRsGroup */
818 : /************************************************************************/
819 :
820 : class HDF4GRsGroup final : public GDALGroup
821 : {
822 : std::shared_ptr<HDF4SharedResources> m_poShared;
823 : std::shared_ptr<HDF4GRsHandle> m_poGRsHandle;
824 : mutable std::map<std::string, int> m_oMapNameToGRIdx{};
825 :
826 : public:
827 2 : HDF4GRsGroup(const std::string &osParentName, const std::string &osName,
828 : const std::shared_ptr<HDF4SharedResources> &poShared,
829 : const std::shared_ptr<HDF4GRsHandle> &poGRsHandle)
830 2 : : GDALGroup(osParentName, osName), m_poShared(poShared),
831 2 : m_poGRsHandle(poGRsHandle)
832 : {
833 2 : }
834 :
835 : std::vector<std::string>
836 : GetMDArrayNames(CSLConstList papszOptions) const override;
837 : std::shared_ptr<GDALMDArray>
838 : OpenMDArray(const std::string &osName,
839 : CSLConstList papszOptions) const override;
840 :
841 : std::vector<std::shared_ptr<GDALAttribute>>
842 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
843 : };
844 :
845 : /************************************************************************/
846 : /* HDF4GRArray */
847 : /************************************************************************/
848 :
849 : class HDF4GRArray final : public GDALPamMDArray
850 : {
851 : std::shared_ptr<HDF4SharedResources> m_poShared;
852 : std::shared_ptr<HDF4GRHandle> m_poGRHandle;
853 : std::vector<std::shared_ptr<GDALDimension>> m_dims{};
854 : GDALExtendedDataType m_dt = GDALExtendedDataType::Create(GDT_Unknown);
855 : int32 m_nAttributes;
856 :
857 : protected:
858 : HDF4GRArray(const std::string &osParentName, const std::string &osName,
859 : const std::shared_ptr<HDF4SharedResources> &poShared,
860 : const std::shared_ptr<HDF4GRHandle> &poGRHandle, int32 nBands,
861 : const std::vector<int32> &aiDimSizes, int32 iNumType,
862 : int32 nAttrs);
863 :
864 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
865 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
866 : const GDALExtendedDataType &bufferDataType,
867 : void *pDstBuffer) const override;
868 :
869 : public:
870 : static std::shared_ptr<HDF4GRArray>
871 2 : Create(const std::string &osParentName, const std::string &osName,
872 : const std::shared_ptr<HDF4SharedResources> &poShared,
873 : const std::shared_ptr<HDF4GRHandle> &poGRHandle, int32 nBands,
874 : const std::vector<int32> &aiDimSizes, int32 iNumType, int32 nAttrs)
875 : {
876 : auto ar(std::shared_ptr<HDF4GRArray>(
877 : new HDF4GRArray(osParentName, osName, poShared, poGRHandle, nBands,
878 2 : aiDimSizes, iNumType, nAttrs)));
879 2 : ar->SetSelf(ar);
880 2 : return ar;
881 : }
882 :
883 0 : bool IsWritable() const override
884 : {
885 0 : return false;
886 : }
887 :
888 2 : const std::string &GetFilename() const override
889 : {
890 2 : return m_poShared->GetFilename();
891 : }
892 :
893 : const std::vector<std::shared_ptr<GDALDimension>> &
894 20 : GetDimensions() const override
895 : {
896 20 : return m_dims;
897 : }
898 :
899 12 : const GDALExtendedDataType &GetDataType() const override
900 : {
901 12 : return m_dt;
902 : }
903 :
904 : std::vector<std::shared_ptr<GDALAttribute>>
905 : GetAttributes(CSLConstList papszOptions = nullptr) const override;
906 :
907 0 : std::shared_ptr<GDALGroup> GetRootGroup() const override
908 : {
909 0 : return HDF4Group::Create(std::string(), "/", m_poShared);
910 : }
911 : };
912 :
913 : /************************************************************************/
914 : /* HDF4SDAttribute */
915 : /************************************************************************/
916 :
917 : class HDF4SDAttribute final : public HDF4AbstractAttribute
918 : {
919 : std::shared_ptr<HDF4SwathHandle> m_poSwathHandle;
920 : std::shared_ptr<HDF4GDHandle> m_poGDHandle;
921 : int32 m_sdHandle = 0;
922 : int32 m_iAttribute = 0;
923 :
924 : public:
925 18 : HDF4SDAttribute(const std::string &osParentName, const std::string &osName,
926 : const std::shared_ptr<HDF4SharedResources> &poShared,
927 : const std::shared_ptr<HDF4SwathHandle> &poSwathHandle,
928 : const std::shared_ptr<HDF4GDHandle> &poGDHandle,
929 : int32 sdHandle, int32 iAttribute, int32 iNumType,
930 : int32 nValues)
931 18 : : GDALAbstractMDArray(osParentName, osName),
932 : HDF4AbstractAttribute(osParentName, osName, poShared, iNumType,
933 : nValues),
934 : m_poSwathHandle(poSwathHandle), m_poGDHandle(poGDHandle),
935 18 : m_sdHandle(sdHandle), m_iAttribute(iAttribute)
936 : {
937 18 : }
938 :
939 10 : void ReadData(void *pDstBuffer) const override
940 : {
941 10 : SDreadattr(m_sdHandle, m_iAttribute, pDstBuffer);
942 10 : }
943 : };
944 :
945 : /************************************************************************/
946 : /* HDF4GRAttribute */
947 : /************************************************************************/
948 :
949 : class HDF4GRAttribute final : public HDF4AbstractAttribute
950 : {
951 : std::shared_ptr<HDF4GRsHandle> m_poGRsHandle;
952 : std::shared_ptr<HDF4GRHandle> m_poGRHandle;
953 : int32 m_grHandle = 0;
954 : int32 m_iAttribute = 0;
955 :
956 : public:
957 10 : HDF4GRAttribute(const std::string &osParentName, const std::string &osName,
958 : const std::shared_ptr<HDF4SharedResources> &poShared,
959 : const std::shared_ptr<HDF4GRsHandle> &poGRsHandle,
960 : const std::shared_ptr<HDF4GRHandle> &poGRHandle,
961 : int32 iGRHandle, int32 iAttribute, int32 iNumType,
962 : int32 nValues)
963 10 : : GDALAbstractMDArray(osParentName, osName),
964 : HDF4AbstractAttribute(osParentName, osName, poShared, iNumType,
965 : nValues),
966 : m_poGRsHandle(poGRsHandle), m_poGRHandle(poGRHandle),
967 10 : m_grHandle(iGRHandle), m_iAttribute(iAttribute)
968 : {
969 10 : }
970 :
971 3 : void ReadData(void *pDstBuffer) const override
972 : {
973 3 : GRgetattr(m_grHandle, m_iAttribute, pDstBuffer);
974 3 : }
975 : };
976 :
977 : /************************************************************************/
978 : /* HDF4GRPalette */
979 : /************************************************************************/
980 :
981 : class HDF4GRPalette final : public GDALAttribute
982 : {
983 : std::shared_ptr<HDF4SharedResources> m_poShared;
984 : std::shared_ptr<HDF4GRHandle> m_poGRHandle;
985 : std::vector<std::shared_ptr<GDALDimension>> m_dims{};
986 : GDALExtendedDataType m_dt = GDALExtendedDataType::Create(GDT_Byte);
987 : int32 m_iPal = 0;
988 : int32 m_nValues = 0;
989 :
990 : protected:
991 : bool IRead(const GUInt64 *arrayStartIdx, const size_t *count,
992 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
993 : const GDALExtendedDataType &bufferDataType,
994 : void *pDstBuffer) const override;
995 :
996 : public:
997 : HDF4GRPalette(const std::string &osParentName, const std::string &osName,
998 : const std::shared_ptr<HDF4SharedResources> &poShared,
999 : const std::shared_ptr<HDF4GRHandle> &poGRHandle, int32 iPal,
1000 : int32 nValues);
1001 :
1002 : const std::vector<std::shared_ptr<GDALDimension>> &
1003 5 : GetDimensions() const override
1004 : {
1005 5 : return m_dims;
1006 : }
1007 :
1008 2 : const GDALExtendedDataType &GetDataType() const override
1009 : {
1010 2 : return m_dt;
1011 : }
1012 : };
1013 :
1014 : /************************************************************************/
1015 : /* HDF4SharedResources() */
1016 : /************************************************************************/
1017 :
1018 6 : HDF4SharedResources::HDF4SharedResources(const std::string &osFilename)
1019 : : m_osFilename(osFilename),
1020 6 : m_poPAM(std::make_shared<GDALPamMultiDim>(osFilename))
1021 : {
1022 6 : }
1023 :
1024 : /************************************************************************/
1025 : /* ~HDF4SharedResources() */
1026 : /************************************************************************/
1027 :
1028 6 : HDF4SharedResources::~HDF4SharedResources()
1029 : {
1030 12 : CPLMutexHolderD(&hHDF4Mutex);
1031 :
1032 6 : if (m_hSD)
1033 6 : SDend(m_hSD);
1034 6 : }
1035 :
1036 : /************************************************************************/
1037 : /* HDF4Group() */
1038 : /************************************************************************/
1039 :
1040 6 : HDF4Group::HDF4Group(const std::string &osParentName, const std::string &osName,
1041 6 : const std::shared_ptr<HDF4SharedResources> &poShared)
1042 6 : : GDALGroup(osParentName, osName), m_poShared(poShared)
1043 : {
1044 6 : bool bIsGDALDS = false;
1045 18 : auto poAttr = GetAttribute("Signature");
1046 6 : if (poAttr && poAttr->GetDataType().GetClass() == GEDTC_STRING)
1047 : {
1048 2 : const char *pszVal = poAttr->ReadAsString();
1049 2 : if (pszVal && EQUAL(pszVal, pszGDALSignature))
1050 : {
1051 2 : bIsGDALDS = true;
1052 : }
1053 : }
1054 6 : if (bIsGDALDS)
1055 : {
1056 : m_poGDALGroup =
1057 2 : std::make_shared<HDF4SDSGroup>(std::string(), "/", m_poShared);
1058 2 : m_poGDALGroup->SetIsGDALDataset();
1059 2 : m_poGDALGroup->SetGlobalAttributes(GetAttributes(nullptr));
1060 : }
1061 6 : }
1062 :
1063 : /************************************************************************/
1064 : /* GetAttributes() */
1065 : /************************************************************************/
1066 :
1067 : std::vector<std::shared_ptr<GDALAttribute>>
1068 9 : HDF4Group::GetAttributes(CSLConstList) const
1069 : {
1070 18 : CPLMutexHolderD(&hHDF4Mutex);
1071 9 : std::vector<std::shared_ptr<GDALAttribute>> ret;
1072 9 : int32 nDatasets = 0;
1073 9 : int32 nAttributes = 0;
1074 9 : if (SDfileinfo(m_poShared->GetSDHandle(), &nDatasets, &nAttributes) != 0)
1075 0 : return ret;
1076 :
1077 18 : std::map<CPLString, std::shared_ptr<GDALAttribute>> oMapAttrs;
1078 : const auto AddAttribute =
1079 56 : [&ret, &oMapAttrs](const std::shared_ptr<GDALAttribute> &poNewAttr)
1080 : {
1081 14 : auto oIter = oMapAttrs.find(poNewAttr->GetName());
1082 14 : if (oIter != oMapAttrs.end())
1083 : {
1084 0 : const char *pszOldVal = oIter->second->ReadAsString();
1085 0 : const char *pszNewVal = poNewAttr->ReadAsString();
1086 : // As found in MOD35_L2.A2017161.1525.061.2017315035809.hdf
1087 : // product of https://github.com/OSGeo/gdal/issues/2848,
1088 : // the identifier_product_doi attribute is found in a
1089 : // HDF4EOS attribute bundle, as well as a standalone attribute
1090 0 : if (pszOldVal && pszNewVal && strcmp(pszOldVal, pszNewVal) == 0)
1091 0 : return;
1092 : // TODO
1093 0 : CPLDebug("HDF4",
1094 : "Attribute with same name (%s) found, but different value",
1095 0 : poNewAttr->GetName().c_str());
1096 : }
1097 : // cppcheck-suppress unreadVariable
1098 14 : oMapAttrs[poNewAttr->GetName()] = poNewAttr;
1099 14 : ret.emplace_back(poNewAttr);
1100 9 : };
1101 :
1102 23 : for (int32 iAttribute = 0; iAttribute < nAttributes; iAttribute++)
1103 : {
1104 14 : int32 iNumType = 0;
1105 14 : int32 nValues = 0;
1106 :
1107 14 : std::string osAttrName;
1108 14 : osAttrName.resize(H4_MAX_NC_NAME);
1109 14 : SDattrinfo(m_poShared->GetSDHandle(), iAttribute, &osAttrName[0],
1110 : &iNumType, &nValues);
1111 14 : osAttrName.resize(strlen(osAttrName.c_str()));
1112 :
1113 14 : if (STARTS_WITH_CI(osAttrName.c_str(), "coremetadata") ||
1114 14 : STARTS_WITH_CI(osAttrName.c_str(), "archivemetadata.") ||
1115 14 : STARTS_WITH_CI(osAttrName.c_str(), "productmetadata.") ||
1116 14 : STARTS_WITH_CI(osAttrName.c_str(), "badpixelinformation") ||
1117 14 : STARTS_WITH_CI(osAttrName.c_str(), "product_summary") ||
1118 14 : STARTS_WITH_CI(osAttrName.c_str(), "dem_specific") ||
1119 14 : STARTS_WITH_CI(osAttrName.c_str(), "bts_specific") ||
1120 14 : STARTS_WITH_CI(osAttrName.c_str(), "etse_specific") ||
1121 14 : STARTS_WITH_CI(osAttrName.c_str(), "dst_specific") ||
1122 14 : STARTS_WITH_CI(osAttrName.c_str(), "acv_specific") ||
1123 14 : STARTS_WITH_CI(osAttrName.c_str(), "act_specific") ||
1124 42 : STARTS_WITH_CI(osAttrName.c_str(), "etst_specific") ||
1125 14 : STARTS_WITH_CI(osAttrName.c_str(), "level_1_carryover"))
1126 : {
1127 0 : char **papszMD = HDF4Dataset::TranslateHDF4EOSAttributes(
1128 0 : m_poShared->GetSDHandle(), iAttribute, nValues, nullptr);
1129 0 : for (char **iter = papszMD; iter && *iter; ++iter)
1130 : {
1131 0 : char *pszKey = nullptr;
1132 0 : const char *pszValue = CPLParseNameValue(*iter, &pszKey);
1133 0 : if (pszKey && pszValue)
1134 : {
1135 0 : AddAttribute(std::make_shared<GDALAttributeString>(
1136 0 : GetFullName(), pszKey, pszValue));
1137 : }
1138 0 : CPLFree(pszKey);
1139 : }
1140 0 : CSLDestroy(papszMD);
1141 : }
1142 :
1143 : // Skip "StructMetadata.N" records. We will fetch information
1144 : // from them using HDF-EOS API
1145 14 : else if (STARTS_WITH_CI(osAttrName.c_str(), "structmetadata."))
1146 : {
1147 0 : continue;
1148 : }
1149 : else
1150 : {
1151 14 : AddAttribute(std::make_shared<HDF4SDAttribute>(
1152 0 : GetFullName(), osAttrName, m_poShared, nullptr, nullptr,
1153 28 : m_poShared->GetSDHandle(), iAttribute, iNumType, nValues));
1154 : }
1155 : }
1156 9 : return ret;
1157 : }
1158 :
1159 : /************************************************************************/
1160 : /* GetGroupNames() */
1161 : /************************************************************************/
1162 :
1163 6 : std::vector<std::string> HDF4Group::GetGroupNames(CSLConstList) const
1164 : {
1165 6 : if (m_poGDALGroup)
1166 2 : return {};
1167 :
1168 8 : CPLMutexHolderD(&hHDF4Mutex);
1169 8 : std::vector<std::string> res;
1170 4 : auto sw_handle = SWopen(m_poShared->GetFilename().c_str(), DFACC_READ);
1171 4 : if (sw_handle >= 0)
1172 : {
1173 4 : int32 nStrBufSize = 0;
1174 4 : int32 nSubDatasets = SWinqswath(m_poShared->GetFilename().c_str(),
1175 : nullptr, &nStrBufSize);
1176 4 : if (nSubDatasets > 0)
1177 : {
1178 0 : res.emplace_back("swaths");
1179 : }
1180 4 : SWclose(sw_handle);
1181 : }
1182 :
1183 4 : auto gd_handle = GDopen(m_poShared->GetFilename().c_str(), DFACC_READ);
1184 4 : if (gd_handle >= 0)
1185 : {
1186 4 : int32 nStrBufSize = 0;
1187 : int32 nSubDatasets =
1188 4 : GDinqgrid(m_poShared->GetFilename().c_str(), nullptr, &nStrBufSize);
1189 4 : if (nSubDatasets > 0)
1190 : {
1191 0 : res.emplace_back("eos_grids");
1192 : }
1193 4 : GDclose(gd_handle);
1194 : }
1195 :
1196 4 : const char *pszListSDS = m_poShared->FetchOpenOption("LIST_SDS", "AUTO");
1197 4 : if ((res.empty() && EQUAL(pszListSDS, "AUTO")) ||
1198 0 : (!EQUAL(pszListSDS, "AUTO") && CPLTestBool(pszListSDS)))
1199 : {
1200 4 : int32 nDatasets = 0;
1201 4 : int32 nAttrs = 0;
1202 8 : if (SDfileinfo(m_poShared->GetSDHandle(), &nDatasets, &nAttrs) == 0 &&
1203 4 : nDatasets > 0)
1204 : {
1205 2 : res.emplace_back("scientific_datasets");
1206 : }
1207 : }
1208 :
1209 4 : auto hHandle = Hopen(m_poShared->GetFilename().c_str(), DFACC_READ, 0);
1210 4 : if (hHandle >= 0)
1211 : {
1212 4 : auto grHandle = GRstart(hHandle);
1213 4 : if (grHandle >= 0)
1214 : {
1215 4 : int32 nImages = 0;
1216 4 : int32 nAttrs = 0;
1217 4 : if (GRfileinfo(grHandle, &nImages, &nAttrs) == 0 && nImages > 0)
1218 : {
1219 2 : res.emplace_back("general_rasters");
1220 : }
1221 4 : GRend(grHandle);
1222 : }
1223 4 : Hclose(hHandle);
1224 : }
1225 :
1226 4 : return res;
1227 : }
1228 :
1229 : /************************************************************************/
1230 : /* OpenGroup() */
1231 : /************************************************************************/
1232 :
1233 7 : std::shared_ptr<GDALGroup> HDF4Group::OpenGroup(const std::string &osName,
1234 : CSLConstList) const
1235 : {
1236 7 : if (m_poGDALGroup)
1237 2 : return nullptr;
1238 :
1239 10 : CPLMutexHolderD(&hHDF4Mutex);
1240 5 : if (osName == "swaths")
1241 : {
1242 0 : auto handle = SWopen(m_poShared->GetFilename().c_str(), DFACC_READ);
1243 0 : if (handle >= 0)
1244 0 : return std::make_shared<HDF4SwathsGroup>(
1245 0 : GetFullName(), osName, m_poShared,
1246 0 : std::make_shared<HDF4SwathsHandle>(handle));
1247 : }
1248 5 : if (osName == "eos_grids")
1249 : {
1250 0 : auto handle = GDopen(m_poShared->GetFilename().c_str(), DFACC_READ);
1251 0 : if (handle >= 0)
1252 0 : return std::make_shared<HDF4EOSGridsGroup>(
1253 0 : GetFullName(), osName, m_poShared,
1254 0 : std::make_shared<HDF4GDsHandle>(handle));
1255 : }
1256 5 : if (osName == "scientific_datasets")
1257 : {
1258 4 : return std::make_shared<HDF4SDSGroup>(GetFullName(), osName,
1259 4 : m_poShared);
1260 : }
1261 3 : if (osName == "general_rasters")
1262 : {
1263 2 : auto hHandle = Hopen(m_poShared->GetFilename().c_str(), DFACC_READ, 0);
1264 2 : if (hHandle >= 0)
1265 : {
1266 2 : auto grHandle = GRstart(hHandle);
1267 2 : if (grHandle >= 0)
1268 : {
1269 4 : return std::make_shared<HDF4GRsGroup>(
1270 2 : GetFullName(), osName, m_poShared,
1271 6 : std::make_shared<HDF4GRsHandle>(hHandle, grHandle));
1272 : }
1273 : else
1274 : {
1275 0 : Hclose(hHandle);
1276 : }
1277 : }
1278 : }
1279 1 : return nullptr;
1280 : }
1281 :
1282 : /************************************************************************/
1283 : /* GetMDArrayNames() */
1284 : /************************************************************************/
1285 :
1286 3 : std::vector<std::string> HDF4Group::GetMDArrayNames(CSLConstList) const
1287 : {
1288 3 : if (m_poGDALGroup)
1289 2 : return m_poGDALGroup->GetMDArrayNames(nullptr);
1290 1 : return {};
1291 : }
1292 :
1293 : /************************************************************************/
1294 : /* OpenMDArray() */
1295 : /************************************************************************/
1296 :
1297 5 : std::shared_ptr<GDALMDArray> HDF4Group::OpenMDArray(const std::string &osName,
1298 : CSLConstList) const
1299 : {
1300 5 : if (m_poGDALGroup)
1301 4 : return m_poGDALGroup->OpenMDArray(osName, nullptr);
1302 1 : return nullptr;
1303 : }
1304 :
1305 : /************************************************************************/
1306 : /* GetDimensions() */
1307 : /************************************************************************/
1308 :
1309 : std::vector<std::shared_ptr<GDALDimension>>
1310 2 : HDF4Group::GetDimensions(CSLConstList) const
1311 : {
1312 2 : if (m_poGDALGroup)
1313 2 : return m_poGDALGroup->GetDimensions(nullptr);
1314 0 : return {};
1315 : }
1316 :
1317 : /************************************************************************/
1318 : /* GetGroupNames() */
1319 : /************************************************************************/
1320 :
1321 0 : std::vector<std::string> HDF4SwathsGroup::GetGroupNames(CSLConstList) const
1322 : {
1323 0 : CPLMutexHolderD(&hHDF4Mutex);
1324 0 : std::vector<std::string> res;
1325 :
1326 0 : int32 nStrBufSize = 0;
1327 0 : SWinqswath(m_poShared->GetFilename().c_str(), nullptr, &nStrBufSize);
1328 :
1329 0 : std::string osSwathList;
1330 0 : osSwathList.resize(nStrBufSize);
1331 0 : SWinqswath(m_poShared->GetFilename().c_str(), &osSwathList[0],
1332 : &nStrBufSize);
1333 :
1334 : CPLStringList aosSwaths(
1335 0 : CSLTokenizeString2(osSwathList.c_str(), ",", CSLT_HONOURSTRINGS));
1336 0 : for (int i = 0; i < aosSwaths.size(); i++)
1337 0 : res.push_back(aosSwaths[i]);
1338 :
1339 0 : return res;
1340 : }
1341 :
1342 : /************************************************************************/
1343 : /* OpenGroup() */
1344 : /************************************************************************/
1345 :
1346 0 : std::shared_ptr<GDALGroup> HDF4SwathsGroup::OpenGroup(const std::string &osName,
1347 : CSLConstList) const
1348 : {
1349 0 : CPLMutexHolderD(&hHDF4Mutex);
1350 :
1351 0 : int32 swathHandle = SWattach(m_poSwathsHandle->m_handle, osName.c_str());
1352 0 : if (swathHandle < 0)
1353 : {
1354 0 : return nullptr;
1355 : }
1356 :
1357 0 : return std::make_shared<HDF4SwathGroup>(
1358 0 : GetFullName(), osName, m_poShared,
1359 0 : std::make_shared<HDF4SwathHandle>(m_poSwathsHandle, swathHandle));
1360 : }
1361 :
1362 : /************************************************************************/
1363 : /* GetMDArrayNames() */
1364 : /************************************************************************/
1365 :
1366 0 : std::vector<std::string> HDF4SwathSubGroup::GetMDArrayNames(CSLConstList) const
1367 : {
1368 0 : CPLMutexHolderD(&hHDF4Mutex);
1369 0 : std::vector<std::string> ret;
1370 :
1371 0 : int32 nStrBufSize = 0;
1372 : const int32 nFields =
1373 0 : SWnentries(m_poSwathHandle->m_handle, m_entryType, &nStrBufSize);
1374 0 : std::string osFieldList;
1375 0 : osFieldList.resize(nStrBufSize);
1376 0 : std::vector<int32> ranks(nFields);
1377 0 : std::vector<int32> numberTypes(nFields);
1378 :
1379 0 : if (m_entryType == HDFE_NENTDFLD)
1380 0 : SWinqdatafields(m_poSwathHandle->m_handle, &osFieldList[0], &ranks[0],
1381 0 : &numberTypes[0]);
1382 : else
1383 0 : SWinqgeofields(m_poSwathHandle->m_handle, &osFieldList[0], &ranks[0],
1384 0 : &numberTypes[0]);
1385 :
1386 : CPLStringList aosFields(
1387 0 : CSLTokenizeString2(osFieldList.c_str(), ",", CSLT_HONOURSTRINGS));
1388 0 : for (int i = 0; i < aosFields.size(); i++)
1389 0 : ret.push_back(aosFields[i]);
1390 :
1391 0 : return ret;
1392 : }
1393 :
1394 : /************************************************************************/
1395 : /* OpenMDArray() */
1396 : /************************************************************************/
1397 :
1398 : std::shared_ptr<GDALMDArray>
1399 0 : HDF4SwathSubGroup::OpenMDArray(const std::string &osName, CSLConstList) const
1400 : {
1401 0 : CPLMutexHolderD(&hHDF4Mutex);
1402 :
1403 : int32 iRank;
1404 : int32 iNumType;
1405 0 : std::vector<int32> aiDimSizes(H4_MAX_VAR_DIMS);
1406 0 : std::string dimNames;
1407 :
1408 0 : int32 nStrBufSize = 0;
1409 0 : if (SWnentries(m_poSwathHandle->m_handle, HDFE_NENTDIM, &nStrBufSize) < 0 ||
1410 0 : nStrBufSize <= 0)
1411 : {
1412 0 : return nullptr;
1413 : }
1414 0 : dimNames.resize(nStrBufSize);
1415 0 : if (SWfieldinfo(m_poSwathHandle->m_handle, osName.c_str(), &iRank,
1416 0 : &aiDimSizes[0], &iNumType, &dimNames[0]) < 0)
1417 : {
1418 0 : return nullptr;
1419 : }
1420 0 : aiDimSizes.resize(iRank);
1421 :
1422 0 : return HDF4SwathArray::Create(GetFullName(), osName, m_poShared,
1423 0 : m_poSwathHandle, aiDimSizes, dimNames,
1424 0 : iNumType, m_groupDims);
1425 : }
1426 :
1427 : /************************************************************************/
1428 : /* GetGroupNames() */
1429 : /************************************************************************/
1430 :
1431 0 : std::vector<std::string> HDF4SwathGroup::GetGroupNames(CSLConstList) const
1432 : {
1433 0 : std::vector<std::string> res;
1434 0 : res.push_back("Data Fields");
1435 0 : res.push_back("Geolocation Fields");
1436 0 : return res;
1437 : }
1438 :
1439 : /************************************************************************/
1440 : /* OpenGroup() */
1441 : /************************************************************************/
1442 :
1443 0 : std::shared_ptr<GDALGroup> HDF4SwathGroup::OpenGroup(const std::string &osName,
1444 : CSLConstList) const
1445 : {
1446 0 : if (osName == "Data Fields")
1447 : {
1448 0 : return std::make_shared<HDF4SwathSubGroup>(
1449 0 : GetFullName(), osName, m_poShared, m_poSwathHandle, HDFE_NENTDFLD,
1450 0 : GetDimensions());
1451 : }
1452 0 : if (osName == "Geolocation Fields")
1453 : {
1454 0 : return std::make_shared<HDF4SwathSubGroup>(
1455 0 : GetFullName(), osName, m_poShared, m_poSwathHandle, HDFE_NENTGFLD,
1456 0 : GetDimensions());
1457 : }
1458 0 : return nullptr;
1459 : }
1460 :
1461 : /************************************************************************/
1462 : /* GetDimensions() */
1463 : /************************************************************************/
1464 :
1465 : std::vector<std::shared_ptr<GDALDimension>>
1466 0 : HDF4SwathGroup::GetDimensions(CSLConstList) const
1467 : {
1468 0 : if (!m_dims.empty())
1469 0 : return m_dims;
1470 0 : std::string dimNames;
1471 0 : int32 nStrBufSize = 0;
1472 0 : if (SWnentries(m_poSwathHandle->m_handle, HDFE_NENTDIM, &nStrBufSize) < 0 ||
1473 0 : nStrBufSize <= 0)
1474 : {
1475 0 : return m_dims;
1476 : }
1477 0 : dimNames.resize(nStrBufSize);
1478 0 : int32 nDims = SWinqdims(m_poSwathHandle->m_handle, &dimNames[0], nullptr);
1479 0 : std::vector<int32> aiDimSizes(nDims);
1480 0 : SWinqdims(m_poSwathHandle->m_handle, &dimNames[0], &aiDimSizes[0]);
1481 : CPLStringList aosDimNames(
1482 0 : CSLTokenizeString2(dimNames.c_str(), ",", CSLT_HONOURSTRINGS));
1483 0 : if (static_cast<size_t>(aosDimNames.size()) == aiDimSizes.size())
1484 : {
1485 0 : for (int i = 0; i < aosDimNames.size(); i++)
1486 : {
1487 0 : m_dims.push_back(std::make_shared<GDALDimension>(
1488 0 : GetFullName(), aosDimNames[i], std::string(), std::string(),
1489 0 : aiDimSizes[i]));
1490 : }
1491 : }
1492 0 : return m_dims;
1493 : }
1494 :
1495 : /************************************************************************/
1496 : /* GetAttributes() */
1497 : /************************************************************************/
1498 :
1499 : std::vector<std::shared_ptr<GDALAttribute>>
1500 0 : HDF4SwathGroup::GetAttributes(CSLConstList) const
1501 : {
1502 0 : CPLMutexHolderD(&hHDF4Mutex);
1503 0 : std::vector<std::shared_ptr<GDALAttribute>> ret;
1504 0 : int32 nStrBufSize = 0;
1505 0 : if (SWinqattrs(m_poSwathHandle->m_handle, nullptr, &nStrBufSize) <= 0 ||
1506 0 : nStrBufSize <= 0)
1507 : {
1508 0 : return ret;
1509 : }
1510 0 : std::string osAttrs;
1511 0 : osAttrs.resize(nStrBufSize);
1512 0 : SWinqattrs(m_poSwathHandle->m_handle, &osAttrs[0], &nStrBufSize);
1513 :
1514 : CPLStringList aosAttrs(
1515 0 : CSLTokenizeString2(osAttrs.c_str(), ",", CSLT_HONOURSTRINGS));
1516 0 : for (int i = 0; i < aosAttrs.size(); i++)
1517 : {
1518 0 : int32 iNumType = 0;
1519 0 : int32 nSize = 0;
1520 :
1521 0 : const auto &osAttrName = aosAttrs[i];
1522 0 : if (SWattrinfo(m_poSwathHandle->m_handle, osAttrName, &iNumType,
1523 0 : &nSize) < 0)
1524 0 : continue;
1525 0 : const int nDataTypeSize = HDF4Dataset::GetDataTypeSize(iNumType);
1526 0 : if (nDataTypeSize == 0)
1527 0 : continue;
1528 :
1529 0 : ret.emplace_back(std::make_shared<HDF4SwathAttribute>(
1530 0 : GetFullName(), osAttrName, m_poShared, m_poSwathHandle, iNumType,
1531 0 : nSize / nDataTypeSize));
1532 : }
1533 0 : return ret;
1534 : }
1535 :
1536 : /************************************************************************/
1537 : /* HDF4SwathArray() */
1538 : /************************************************************************/
1539 :
1540 0 : HDF4SwathArray::HDF4SwathArray(
1541 : const std::string &osParentName, const std::string &osName,
1542 : const std::shared_ptr<HDF4SharedResources> &poShared,
1543 : const std::shared_ptr<HDF4SwathHandle> &poSwathHandle,
1544 : const std::vector<int32> &aiDimSizes, const std::string &dimNames,
1545 : int32 iNumType,
1546 0 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims)
1547 : : GDALAbstractMDArray(osParentName, osName),
1548 : GDALPamMDArray(osParentName, osName, poShared->GetPAM()),
1549 : m_poShared(poShared), m_poSwathHandle(poSwathHandle),
1550 : m_dt(iNumType == DFNT_CHAR8 ? GDALExtendedDataType::CreateString()
1551 : : GDALExtendedDataType::Create(
1552 0 : HDF4Dataset::GetDataType(iNumType)))
1553 : {
1554 : CPLStringList aosDimNames(
1555 0 : CSLTokenizeString2(dimNames.c_str(), ",", CSLT_HONOURSTRINGS));
1556 0 : if (static_cast<size_t>(aosDimNames.size()) == aiDimSizes.size())
1557 : {
1558 0 : for (int i = 0; i < aosDimNames.size(); i++)
1559 : {
1560 0 : bool bFound = false;
1561 0 : for (const auto &poDim : groupDims)
1562 : {
1563 0 : if (poDim->GetName() == aosDimNames[i] &&
1564 0 : poDim->GetSize() == static_cast<GUInt64>(aiDimSizes[i]))
1565 : {
1566 0 : bFound = true;
1567 0 : m_dims.push_back(poDim);
1568 0 : break;
1569 : }
1570 : }
1571 0 : if (!bFound)
1572 : {
1573 0 : m_dims.push_back(std::make_shared<GDALDimension>(
1574 0 : std::string(), aosDimNames[i], std::string(), std::string(),
1575 0 : aiDimSizes[i]));
1576 : }
1577 : }
1578 : }
1579 0 : }
1580 :
1581 : /************************************************************************/
1582 : /* GetAttributes() */
1583 : /************************************************************************/
1584 :
1585 : std::vector<std::shared_ptr<GDALAttribute>>
1586 0 : HDF4SwathArray::GetAttributes(CSLConstList) const
1587 : {
1588 0 : CPLMutexHolderD(&hHDF4Mutex);
1589 0 : std::vector<std::shared_ptr<GDALAttribute>> ret;
1590 0 : int32 iSDS = 0;
1591 0 : if (SWsdid(m_poSwathHandle->m_handle, GetName().c_str(), &iSDS) != -1)
1592 : {
1593 0 : int32 iRank = 0;
1594 0 : int32 iNumType = 0;
1595 0 : int32 nAttrs = 0;
1596 0 : std::vector<int32> aiDimSizes(H4_MAX_VAR_DIMS);
1597 :
1598 0 : if (SDgetinfo(iSDS, nullptr, &iRank, &aiDimSizes[0], &iNumType,
1599 0 : &nAttrs) == 0)
1600 : {
1601 0 : for (int32 iAttribute = 0; iAttribute < nAttrs; iAttribute++)
1602 : {
1603 0 : std::string osAttrName;
1604 0 : osAttrName.resize(H4_MAX_NC_NAME);
1605 0 : iNumType = 0;
1606 0 : int32 nValues = 0;
1607 0 : SDattrinfo(iSDS, iAttribute, &osAttrName[0], &iNumType,
1608 : &nValues);
1609 0 : osAttrName.resize(strlen(osAttrName.c_str()));
1610 0 : ret.emplace_back(std::make_shared<HDF4SDAttribute>(
1611 0 : GetFullName(), osAttrName, m_poShared, m_poSwathHandle,
1612 0 : nullptr, iSDS, iAttribute, iNumType, nValues));
1613 : }
1614 : }
1615 : }
1616 0 : return ret;
1617 : }
1618 :
1619 : /************************************************************************/
1620 : /* ReadPixels() */
1621 : /************************************************************************/
1622 :
1623 : union ReadFunc
1624 : {
1625 : intn (*pReadField)(int32, const char *, int32[], int32[], int32[], VOIDP);
1626 : intn (*pReadData)(int32, int32[], int32[], int32[], VOIDP);
1627 : };
1628 :
1629 24 : static inline void IncrPointer(GByte *&ptr, GPtrDiff_t nInc, size_t nIncSize)
1630 : {
1631 24 : if (nInc < 0)
1632 6 : ptr -= (-nInc) * nIncSize;
1633 : else
1634 18 : ptr += nInc * nIncSize;
1635 24 : }
1636 :
1637 4 : static bool ReadPixels(const GUInt64 *arrayStartIdx, const size_t *count,
1638 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
1639 : const GDALExtendedDataType &bufferDataType,
1640 : void *pDstBuffer,
1641 : const std::shared_ptr<HDF4SharedResources> &poShared,
1642 : const GDALExtendedDataType &dt,
1643 : const std::vector<std::shared_ptr<GDALDimension>> &dims,
1644 : int32 handle, const char *pszFieldName,
1645 : ReadFunc readFunc)
1646 : {
1647 8 : CPLMutexHolderD(&hHDF4Mutex);
1648 : /* -------------------------------------------------------------------- */
1649 : /* HDF files with external data files, such as some landsat */
1650 : /* products (eg. data/hdf/L1G) need to be told what directory */
1651 : /* to look in to find the external files. Normally this is the */
1652 : /* directory holding the hdf file. */
1653 : /* -------------------------------------------------------------------- */
1654 4 : HXsetdir(CPLGetPath(poShared->GetFilename().c_str()));
1655 :
1656 4 : const size_t nDims(dims.size());
1657 8 : std::vector<int32> sw_start(nDims);
1658 8 : std::vector<int32> sw_stride(nDims);
1659 8 : std::vector<int32> sw_edge(nDims);
1660 8 : std::vector<GPtrDiff_t> newBufferStride(nDims);
1661 4 : GByte *pabyDstBuffer = static_cast<GByte *>(pDstBuffer);
1662 4 : const size_t nBufferDataTypeSize = bufferDataType.GetSize();
1663 14 : for (size_t i = 0; i < nDims; i++)
1664 : {
1665 10 : sw_start[i] = static_cast<int>(arrayStartIdx[i]);
1666 10 : sw_stride[i] = static_cast<int>(arrayStep[i]);
1667 10 : sw_edge[i] = static_cast<int>(count[i]);
1668 10 : newBufferStride[i] = bufferStride[i];
1669 10 : if (sw_stride[i] < 0)
1670 : {
1671 : // SWreadfield() doesn't like negative step / array stride, so
1672 : // transform the request to a classic "left-to-right" one
1673 0 : sw_start[i] += sw_stride[i] * (sw_edge[i] - 1);
1674 0 : sw_stride[i] = -sw_stride[i];
1675 0 : pabyDstBuffer +=
1676 0 : (sw_edge[i] - 1) * newBufferStride[i] * nBufferDataTypeSize;
1677 0 : newBufferStride[i] = -newBufferStride[i];
1678 : }
1679 : }
1680 4 : size_t nExpectedStride = 1;
1681 4 : bool bContiguousStride = true;
1682 14 : for (size_t i = nDims; i > 0;)
1683 : {
1684 10 : --i;
1685 10 : if (newBufferStride[i] != static_cast<GPtrDiff_t>(nExpectedStride))
1686 : {
1687 3 : bContiguousStride = false;
1688 : }
1689 10 : nExpectedStride *= count[i];
1690 : }
1691 4 : if (bufferDataType == dt && bContiguousStride)
1692 : {
1693 : auto status =
1694 : pszFieldName
1695 3 : ? readFunc.pReadField(handle, pszFieldName, &sw_start[0],
1696 0 : &sw_stride[0], &sw_edge[0], pabyDstBuffer)
1697 3 : : readFunc.pReadData(handle, &sw_start[0], &sw_stride[0],
1698 3 : &sw_edge[0], pabyDstBuffer);
1699 3 : return status == 0;
1700 : }
1701 : auto pabyTemp = static_cast<GByte *>(
1702 1 : VSI_MALLOC2_VERBOSE(dt.GetSize(), nExpectedStride));
1703 1 : if (pabyTemp == nullptr)
1704 0 : return false;
1705 : auto status =
1706 1 : pszFieldName ? readFunc.pReadField(handle, pszFieldName, &sw_start[0],
1707 0 : &sw_stride[0], &sw_edge[0], pabyTemp)
1708 1 : : readFunc.pReadData(handle, &sw_start[0], &sw_stride[0],
1709 1 : &sw_edge[0], pabyTemp);
1710 1 : if (status != 0)
1711 : {
1712 0 : VSIFree(pabyTemp);
1713 0 : return false;
1714 : }
1715 :
1716 1 : const size_t nSrcDataTypeSize = dt.GetSize();
1717 2 : std::vector<size_t> anStackCount(nDims);
1718 1 : GByte *pabySrc = pabyTemp;
1719 1 : std::vector<GByte *> pabyDstBufferStack(nDims + 1);
1720 1 : pabyDstBufferStack[0] = pabyDstBuffer;
1721 1 : size_t iDim = 0;
1722 11 : lbl_next_depth:
1723 11 : if (iDim == nDims)
1724 : {
1725 4 : GDALExtendedDataType::CopyValue(pabySrc, dt, pabyDstBufferStack[nDims],
1726 : bufferDataType);
1727 4 : pabySrc += nSrcDataTypeSize;
1728 : }
1729 : else
1730 : {
1731 7 : anStackCount[iDim] = count[iDim];
1732 : while (true)
1733 : {
1734 10 : ++iDim;
1735 10 : pabyDstBufferStack[iDim] = pabyDstBufferStack[iDim - 1];
1736 10 : goto lbl_next_depth;
1737 10 : lbl_return_to_caller_in_loop:
1738 10 : --iDim;
1739 10 : --anStackCount[iDim];
1740 10 : if (anStackCount[iDim] == 0)
1741 7 : break;
1742 3 : IncrPointer(pabyDstBufferStack[iDim], newBufferStride[iDim],
1743 : nBufferDataTypeSize);
1744 : }
1745 : }
1746 11 : if (iDim > 0)
1747 10 : goto lbl_return_to_caller_in_loop;
1748 :
1749 1 : VSIFree(pabyTemp);
1750 1 : return true;
1751 : }
1752 :
1753 : /************************************************************************/
1754 : /* IRead() */
1755 : /************************************************************************/
1756 :
1757 0 : bool HDF4SwathArray::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
1758 : const GInt64 *arrayStep,
1759 : const GPtrDiff_t *bufferStride,
1760 : const GDALExtendedDataType &bufferDataType,
1761 : void *pDstBuffer) const
1762 : {
1763 : ReadFunc readFunc;
1764 0 : readFunc.pReadField = SWreadfield;
1765 0 : return ReadPixels(arrayStartIdx, count, arrayStep, bufferStride,
1766 0 : bufferDataType, pDstBuffer, m_poShared, m_dt, m_dims,
1767 0 : m_poSwathHandle->m_handle, GetName().c_str(), readFunc);
1768 : }
1769 :
1770 : /************************************************************************/
1771 : /* GetRawNoDataValue() */
1772 : /************************************************************************/
1773 :
1774 0 : const void *HDF4SwathArray::GetRawNoDataValue() const
1775 : {
1776 0 : if (!m_abyNoData.empty())
1777 0 : return m_abyNoData.data();
1778 0 : m_abyNoData.resize(GetDataType().GetSize());
1779 :
1780 0 : auto poAttr = GetAttribute("_FillValue");
1781 0 : if (poAttr)
1782 : {
1783 0 : const double dfVal = poAttr->ReadAsDouble();
1784 0 : GDALExtendedDataType::CopyValue(
1785 0 : &dfVal, GDALExtendedDataType::Create(GDT_Float64), &m_abyNoData[0],
1786 : GetDataType());
1787 0 : return m_abyNoData.data();
1788 : }
1789 :
1790 0 : CPLMutexHolderD(&hHDF4Mutex);
1791 0 : if (SWgetfillvalue(m_poSwathHandle->m_handle, GetName().c_str(),
1792 0 : &m_abyNoData[0]) != -1)
1793 : {
1794 0 : return m_abyNoData.data();
1795 : }
1796 :
1797 0 : m_abyNoData.clear();
1798 0 : return nullptr;
1799 : }
1800 :
1801 : /************************************************************************/
1802 : /* HDF4AbstractAttribute() */
1803 : /************************************************************************/
1804 :
1805 28 : HDF4AbstractAttribute::HDF4AbstractAttribute(
1806 : const std::string &osParentName, const std::string &osName,
1807 : const std::shared_ptr<HDF4SharedResources> &poShared, int32 iNumType,
1808 0 : int32 nValues)
1809 : :
1810 : #if !defined(COMPILER_WARNS_ABOUT_ABSTRACT_VBASE_INIT)
1811 : GDALAbstractMDArray(osParentName, osName),
1812 : #endif
1813 : GDALAttribute(osParentName, osName), m_poShared(poShared),
1814 : m_dt(iNumType == DFNT_CHAR8 ? GDALExtendedDataType::CreateString()
1815 : : GDALExtendedDataType::Create(
1816 : HDF4Dataset::GetDataType(iNumType))),
1817 28 : m_nValues(nValues)
1818 : {
1819 28 : if (m_dt.GetClass() != GEDTC_STRING && m_nValues > 1)
1820 : {
1821 12 : m_dims.emplace_back(std::make_shared<GDALDimension>(
1822 18 : std::string(), "dim", std::string(), std::string(), nValues));
1823 : }
1824 28 : }
1825 :
1826 : /************************************************************************/
1827 : /* IRead() */
1828 : /************************************************************************/
1829 :
1830 13 : bool HDF4AbstractAttribute::IRead(const GUInt64 *arrayStartIdx,
1831 : const size_t *count, const GInt64 *arrayStep,
1832 : const GPtrDiff_t *bufferStride,
1833 : const GDALExtendedDataType &bufferDataType,
1834 : void *pDstBuffer) const
1835 : {
1836 26 : CPLMutexHolderD(&hHDF4Mutex);
1837 13 : if (m_dt.GetClass() == GEDTC_STRING)
1838 : {
1839 11 : if (bufferDataType.GetClass() != GEDTC_STRING)
1840 0 : return false;
1841 11 : char *pszStr = static_cast<char *>(VSIMalloc(m_nValues + 1));
1842 11 : if (pszStr == nullptr)
1843 0 : return false;
1844 11 : ReadData(pszStr);
1845 11 : pszStr[m_nValues] = 0;
1846 11 : *static_cast<char **>(pDstBuffer) = pszStr;
1847 11 : return true;
1848 : }
1849 :
1850 2 : std::vector<GByte> abyTemp(m_nValues * m_dt.GetSize());
1851 2 : ReadData(&abyTemp[0]);
1852 2 : GByte *pabyDstBuffer = static_cast<GByte *>(pDstBuffer);
1853 10 : for (size_t i = 0; i < (m_dims.empty() ? 1 : count[0]); ++i)
1854 : {
1855 : const size_t idx =
1856 8 : m_dims.empty()
1857 8 : ? 0
1858 8 : : static_cast<size_t>(arrayStartIdx[0] + i * arrayStep[0]);
1859 8 : GDALExtendedDataType::CopyValue(&abyTemp[0] + idx * m_dt.GetSize(),
1860 8 : m_dt, pabyDstBuffer, bufferDataType);
1861 8 : if (!m_dims.empty())
1862 8 : pabyDstBuffer += bufferStride[0] * bufferDataType.GetSize();
1863 : }
1864 :
1865 2 : return true;
1866 : }
1867 :
1868 : /************************************************************************/
1869 : /* GetGroupNames() */
1870 : /************************************************************************/
1871 :
1872 0 : std::vector<std::string> HDF4EOSGridsGroup::GetGroupNames(CSLConstList) const
1873 : {
1874 0 : CPLMutexHolderD(&hHDF4Mutex);
1875 0 : std::vector<std::string> res;
1876 :
1877 0 : int32 nStrBufSize = 0;
1878 0 : GDinqgrid(m_poShared->GetFilename().c_str(), nullptr, &nStrBufSize);
1879 :
1880 0 : std::string osGridList;
1881 0 : osGridList.resize(nStrBufSize);
1882 0 : GDinqgrid(m_poShared->GetFilename().c_str(), &osGridList[0], &nStrBufSize);
1883 :
1884 : CPLStringList aosGrids(
1885 0 : CSLTokenizeString2(osGridList.c_str(), ",", CSLT_HONOURSTRINGS));
1886 0 : for (int i = 0; i < aosGrids.size(); i++)
1887 0 : res.push_back(aosGrids[i]);
1888 :
1889 0 : return res;
1890 : }
1891 :
1892 : /************************************************************************/
1893 : /* OpenGroup() */
1894 : /************************************************************************/
1895 :
1896 : std::shared_ptr<GDALGroup>
1897 0 : HDF4EOSGridsGroup::OpenGroup(const std::string &osName, CSLConstList) const
1898 : {
1899 0 : CPLMutexHolderD(&hHDF4Mutex);
1900 :
1901 0 : int32 gdHandle = GDattach(m_poGDsHandle->m_handle, osName.c_str());
1902 0 : if (gdHandle < 0)
1903 : {
1904 0 : return nullptr;
1905 : }
1906 :
1907 0 : return std::make_shared<HDF4EOSGridGroup>(
1908 0 : GetFullName(), osName, m_poShared,
1909 0 : std::make_shared<HDF4GDHandle>(m_poGDsHandle, gdHandle));
1910 : }
1911 :
1912 : /************************************************************************/
1913 : /* GetDimensions() */
1914 : /************************************************************************/
1915 :
1916 : std::vector<std::shared_ptr<GDALDimension>>
1917 0 : HDF4EOSGridGroup::GetDimensions(CSLConstList) const
1918 : {
1919 0 : if (!m_dims.empty())
1920 0 : return m_dims;
1921 :
1922 0 : int32 iProjCode = 0;
1923 0 : int32 iZoneCode = 0;
1924 0 : int32 iSphereCode = 0;
1925 : double adfProjParams[15];
1926 :
1927 0 : GDprojinfo(m_poGDHandle->m_handle, &iProjCode, &iZoneCode, &iSphereCode,
1928 : adfProjParams);
1929 :
1930 0 : int32 nXSize = 0;
1931 0 : int32 nYSize = 0;
1932 : double adfUpLeft[2];
1933 : double adfLowRight[2];
1934 0 : const bool bGotGridInfo = GDgridinfo(m_poGDHandle->m_handle, &nXSize,
1935 0 : &nYSize, adfUpLeft, adfLowRight) >= 0;
1936 0 : if (bGotGridInfo)
1937 : {
1938 0 : m_dims = {std::make_shared<GDALDimensionWeakIndexingVar>(
1939 0 : GetFullName(), "YDim", GDAL_DIM_TYPE_HORIZONTAL_Y,
1940 : "NORTH", nYSize),
1941 0 : std::make_shared<GDALDimensionWeakIndexingVar>(
1942 0 : GetFullName(), "XDim", GDAL_DIM_TYPE_HORIZONTAL_X, "EAST",
1943 0 : nXSize)};
1944 :
1945 0 : if (iProjCode == 0)
1946 : {
1947 0 : adfLowRight[0] = CPLPackedDMSToDec(adfLowRight[0]);
1948 0 : adfLowRight[1] = CPLPackedDMSToDec(adfLowRight[1]);
1949 0 : adfUpLeft[0] = CPLPackedDMSToDec(adfUpLeft[0]);
1950 0 : adfUpLeft[1] = CPLPackedDMSToDec(adfUpLeft[1]);
1951 : }
1952 :
1953 0 : m_varX = GDALMDArrayRegularlySpaced::Create(
1954 0 : GetFullName(), m_dims[1]->GetName(), m_dims[1], adfUpLeft[0],
1955 0 : (adfLowRight[0] - adfUpLeft[0]) / nXSize, 0.5);
1956 0 : m_dims[1]->SetIndexingVariable(m_varX);
1957 :
1958 0 : m_varY = GDALMDArrayRegularlySpaced::Create(
1959 0 : GetFullName(), m_dims[0]->GetName(), m_dims[0], adfUpLeft[1],
1960 0 : (adfLowRight[1] - adfUpLeft[1]) / nYSize, 0.5);
1961 0 : m_dims[0]->SetIndexingVariable(m_varY);
1962 : }
1963 :
1964 : #if 0
1965 : // Dimensions seem to be never defined properly on eos_grids datasets.
1966 :
1967 : std::string dimNames;
1968 : int32 nStrBufSize = 0;
1969 : if( GDnentries( m_poGDHandle->m_handle, HDFE_NENTDIM, &nStrBufSize ) < 0
1970 : || nStrBufSize <= 0 )
1971 : {
1972 : return m_dims;
1973 : }
1974 : dimNames.resize(nStrBufSize);
1975 : int32 nDims = GDinqdims(m_poGDHandle->m_handle, &dimNames[0], nullptr);
1976 : std::vector<int32> aiDimSizes(nDims);
1977 : GDinqdims(m_poGDHandle->m_handle, &dimNames[0], &aiDimSizes[0]);
1978 : CPLStringList aosDimNames(CSLTokenizeString2(
1979 : dimNames.c_str(), ",", CSLT_HONOURSTRINGS ));
1980 : if( static_cast<size_t>(aosDimNames.size()) == aiDimSizes.size() )
1981 : {
1982 : for( int i = 0; i < aosDimNames.size(); i++ )
1983 : {
1984 : m_dims.push_back(std::make_shared<GDALDimension>(GetFullName(),
1985 : aosDimNames[i],
1986 : std::string(),
1987 : std::string(),
1988 : aiDimSizes[i]));
1989 : }
1990 : }
1991 : #endif
1992 0 : return m_dims;
1993 : }
1994 :
1995 : /************************************************************************/
1996 : /* GetMDArrayNames() */
1997 : /************************************************************************/
1998 :
1999 0 : std::vector<std::string> HDF4EOSGridGroup::GetMDArrayNames(CSLConstList) const
2000 : {
2001 0 : GetDimensions();
2002 0 : std::vector<std::string> ret;
2003 0 : if (m_varX && m_varY)
2004 : {
2005 0 : ret.push_back(m_varY->GetName());
2006 0 : ret.push_back(m_varX->GetName());
2007 : }
2008 0 : return ret;
2009 : }
2010 :
2011 : /************************************************************************/
2012 : /* OpenMDArray() */
2013 : /************************************************************************/
2014 :
2015 : std::shared_ptr<GDALMDArray>
2016 0 : HDF4EOSGridGroup::OpenMDArray(const std::string &osName, CSLConstList) const
2017 : {
2018 0 : if (m_varX && osName == m_varX->GetName())
2019 0 : return m_varX;
2020 0 : if (m_varY && osName == m_varY->GetName())
2021 0 : return m_varY;
2022 0 : return nullptr;
2023 : }
2024 :
2025 : /************************************************************************/
2026 : /* GetGroupNames() */
2027 : /************************************************************************/
2028 :
2029 0 : std::vector<std::string> HDF4EOSGridGroup::GetGroupNames(CSLConstList) const
2030 : {
2031 0 : std::vector<std::string> res;
2032 0 : res.push_back("Data Fields");
2033 0 : return res;
2034 : }
2035 :
2036 : /************************************************************************/
2037 : /* OpenGroup() */
2038 : /************************************************************************/
2039 :
2040 : std::shared_ptr<GDALGroup>
2041 0 : HDF4EOSGridGroup::OpenGroup(const std::string &osName, CSLConstList) const
2042 : {
2043 0 : if (osName == "Data Fields")
2044 : {
2045 0 : return std::make_shared<HDF4EOSGridSubGroup>(
2046 0 : GetFullName(), osName, m_poShared, m_poGDHandle, HDFE_NENTDFLD,
2047 0 : GetDimensions());
2048 : }
2049 0 : return nullptr;
2050 : }
2051 :
2052 : /************************************************************************/
2053 : /* GetAttributes() */
2054 : /************************************************************************/
2055 :
2056 : std::vector<std::shared_ptr<GDALAttribute>>
2057 0 : HDF4EOSGridGroup::GetAttributes(CSLConstList) const
2058 : {
2059 0 : CPLMutexHolderD(&hHDF4Mutex);
2060 0 : std::vector<std::shared_ptr<GDALAttribute>> ret;
2061 0 : int32 nStrBufSize = 0;
2062 0 : if (GDinqattrs(m_poGDHandle->m_handle, nullptr, &nStrBufSize) <= 0 ||
2063 0 : nStrBufSize <= 0)
2064 : {
2065 0 : return ret;
2066 : }
2067 0 : std::string osAttrs;
2068 0 : osAttrs.resize(nStrBufSize);
2069 0 : GDinqattrs(m_poGDHandle->m_handle, &osAttrs[0], &nStrBufSize);
2070 :
2071 : CPLStringList aosAttrs(
2072 0 : CSLTokenizeString2(osAttrs.c_str(), ",", CSLT_HONOURSTRINGS));
2073 0 : for (int i = 0; i < aosAttrs.size(); i++)
2074 : {
2075 0 : int32 iNumType = 0;
2076 0 : int32 nSize = 0;
2077 :
2078 0 : if (GDattrinfo(m_poGDHandle->m_handle, aosAttrs[i], &iNumType, &nSize) <
2079 : 0)
2080 0 : continue;
2081 0 : const int nDataTypeSize = HDF4Dataset::GetDataTypeSize(iNumType);
2082 0 : if (nDataTypeSize == 0)
2083 0 : continue;
2084 :
2085 0 : ret.emplace_back(std::make_shared<HDF4EOSGridAttribute>(
2086 0 : GetFullName(), aosAttrs[i], m_poShared, m_poGDHandle, iNumType,
2087 0 : nSize / nDataTypeSize));
2088 : }
2089 0 : return ret;
2090 : }
2091 :
2092 : /************************************************************************/
2093 : /* GetMDArrayNames() */
2094 : /************************************************************************/
2095 :
2096 : std::vector<std::string>
2097 0 : HDF4EOSGridSubGroup::GetMDArrayNames(CSLConstList) const
2098 : {
2099 0 : std::vector<std::string> ret;
2100 :
2101 0 : int32 nStrBufSize = 0;
2102 : const int32 nFields =
2103 0 : GDnentries(m_poGDHandle->m_handle, m_entryType, &nStrBufSize);
2104 0 : std::string osFieldList;
2105 0 : osFieldList.resize(nStrBufSize);
2106 0 : std::vector<int32> ranks(nFields);
2107 0 : std::vector<int32> numberTypes(nFields);
2108 :
2109 0 : CPLAssert(m_entryType == HDFE_NENTDFLD);
2110 0 : GDinqfields(m_poGDHandle->m_handle, &osFieldList[0], &ranks[0],
2111 0 : &numberTypes[0]);
2112 :
2113 : CPLStringList aosFields(
2114 0 : CSLTokenizeString2(osFieldList.c_str(), ",", CSLT_HONOURSTRINGS));
2115 0 : for (int i = 0; i < aosFields.size(); i++)
2116 0 : ret.push_back(aosFields[i]);
2117 :
2118 0 : return ret;
2119 : }
2120 :
2121 : /************************************************************************/
2122 : /* OpenMDArray() */
2123 : /************************************************************************/
2124 :
2125 : std::shared_ptr<GDALMDArray>
2126 0 : HDF4EOSGridSubGroup::OpenMDArray(const std::string &osName, CSLConstList) const
2127 : {
2128 0 : CPLMutexHolderD(&hHDF4Mutex);
2129 :
2130 : int32 iRank;
2131 : int32 iNumType;
2132 0 : std::vector<int32> aiDimSizes(H4_MAX_VAR_DIMS);
2133 0 : std::string dimNames;
2134 :
2135 0 : int32 nStrBufSize = 0;
2136 0 : GDnentries(m_poGDHandle->m_handle, HDFE_NENTDIM, &nStrBufSize);
2137 0 : if (nStrBufSize <= 0)
2138 0 : dimNames.resize(HDFE_DIMBUFSIZE);
2139 : else
2140 0 : dimNames.resize(nStrBufSize);
2141 0 : if (GDfieldinfo(m_poGDHandle->m_handle, osName.c_str(), &iRank,
2142 0 : &aiDimSizes[0], &iNumType, &dimNames[0]) < 0)
2143 : {
2144 0 : return nullptr;
2145 : }
2146 0 : aiDimSizes.resize(iRank);
2147 0 : dimNames.resize(strlen(dimNames.c_str()));
2148 :
2149 0 : return HDF4EOSGridArray::Create(GetFullName(), osName, m_poShared,
2150 0 : m_poGDHandle, aiDimSizes, dimNames,
2151 0 : iNumType, m_groupDims);
2152 : }
2153 :
2154 : /************************************************************************/
2155 : /* HDF4EOSGridArray() */
2156 : /************************************************************************/
2157 :
2158 0 : HDF4EOSGridArray::HDF4EOSGridArray(
2159 : const std::string &osParentName, const std::string &osName,
2160 : const std::shared_ptr<HDF4SharedResources> &poShared,
2161 : const std::shared_ptr<HDF4GDHandle> &poGDHandle,
2162 : const std::vector<int32> &aiDimSizes, const std::string &dimNames,
2163 : int32 iNumType,
2164 0 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims)
2165 : : GDALAbstractMDArray(osParentName, osName),
2166 : GDALPamMDArray(osParentName, osName, poShared->GetPAM()),
2167 : m_poShared(poShared), m_poGDHandle(poGDHandle),
2168 : m_dt(iNumType == DFNT_CHAR8 ? GDALExtendedDataType::CreateString()
2169 : : GDALExtendedDataType::Create(
2170 0 : HDF4Dataset::GetDataType(iNumType)))
2171 : {
2172 : CPLStringList aosDimNames(
2173 0 : CSLTokenizeString2(dimNames.c_str(), ",", CSLT_HONOURSTRINGS));
2174 0 : if (static_cast<size_t>(aosDimNames.size()) == aiDimSizes.size())
2175 : {
2176 0 : for (int i = 0; i < aosDimNames.size(); i++)
2177 : {
2178 0 : bool bFound = false;
2179 0 : for (const auto &poDim : groupDims)
2180 : {
2181 0 : if (poDim->GetName() == aosDimNames[i] &&
2182 0 : poDim->GetSize() == static_cast<GUInt64>(aiDimSizes[i]))
2183 : {
2184 0 : bFound = true;
2185 0 : m_dims.push_back(poDim);
2186 0 : break;
2187 : }
2188 : }
2189 0 : if (!bFound)
2190 : {
2191 0 : m_dims.push_back(std::make_shared<GDALDimension>(
2192 0 : std::string(), aosDimNames[i], std::string(), std::string(),
2193 0 : aiDimSizes[i]));
2194 : }
2195 : }
2196 : }
2197 0 : }
2198 :
2199 : /************************************************************************/
2200 : /* GetAttributes() */
2201 : /************************************************************************/
2202 :
2203 : std::vector<std::shared_ptr<GDALAttribute>>
2204 0 : HDF4EOSGridArray::GetAttributes(CSLConstList) const
2205 : {
2206 0 : CPLMutexHolderD(&hHDF4Mutex);
2207 0 : std::vector<std::shared_ptr<GDALAttribute>> ret;
2208 0 : int32 iSDS = 0;
2209 0 : if (GDsdid(m_poGDHandle->m_handle, GetName().c_str(), &iSDS) != -1)
2210 : {
2211 0 : int32 iRank = 0;
2212 0 : int32 iNumType = 0;
2213 0 : int32 nAttrs = 0;
2214 0 : std::vector<int32> aiDimSizes(H4_MAX_VAR_DIMS);
2215 :
2216 0 : if (SDgetinfo(iSDS, nullptr, &iRank, &aiDimSizes[0], &iNumType,
2217 0 : &nAttrs) == 0)
2218 : {
2219 0 : for (int32 iAttribute = 0; iAttribute < nAttrs; iAttribute++)
2220 : {
2221 0 : std::string osAttrName;
2222 0 : osAttrName.resize(H4_MAX_NC_NAME);
2223 0 : iNumType = 0;
2224 0 : int32 nValues = 0;
2225 0 : SDattrinfo(iSDS, iAttribute, &osAttrName[0], &iNumType,
2226 : &nValues);
2227 0 : osAttrName.resize(strlen(osAttrName.c_str()));
2228 0 : ret.emplace_back(std::make_shared<HDF4SDAttribute>(
2229 0 : GetFullName(), osAttrName, m_poShared, nullptr,
2230 0 : m_poGDHandle, iSDS, iAttribute, iNumType, nValues));
2231 : }
2232 : }
2233 : }
2234 0 : return ret;
2235 : }
2236 :
2237 : /************************************************************************/
2238 : /* GetRawNoDataValue() */
2239 : /************************************************************************/
2240 :
2241 0 : const void *HDF4EOSGridArray::GetRawNoDataValue() const
2242 : {
2243 0 : if (!m_abyNoData.empty())
2244 0 : return m_abyNoData.data();
2245 0 : m_abyNoData.resize(GetDataType().GetSize());
2246 :
2247 0 : auto poAttr = GetAttribute("_FillValue");
2248 0 : if (poAttr)
2249 : {
2250 0 : const double dfVal = poAttr->ReadAsDouble();
2251 0 : GDALExtendedDataType::CopyValue(
2252 0 : &dfVal, GDALExtendedDataType::Create(GDT_Float64), &m_abyNoData[0],
2253 : GetDataType());
2254 0 : return m_abyNoData.data();
2255 : }
2256 :
2257 0 : CPLMutexHolderD(&hHDF4Mutex);
2258 0 : if (GDgetfillvalue(m_poGDHandle->m_handle, GetName().c_str(),
2259 0 : &m_abyNoData[0]) != -1)
2260 : {
2261 0 : return m_abyNoData.data();
2262 : }
2263 0 : m_abyNoData.clear();
2264 0 : return nullptr;
2265 : }
2266 :
2267 : /************************************************************************/
2268 : /* GetOffsetOrScale() */
2269 : /************************************************************************/
2270 :
2271 2 : static double GetOffsetOrScale(const GDALMDArray *poArray,
2272 : const char *pszAttrName, double dfDefaultValue,
2273 : bool *pbHasVal, GDALDataType *peStorageType)
2274 : {
2275 6 : auto poAttr = poArray->GetAttribute(pszAttrName);
2276 2 : if (poAttr && (poAttr->GetDataType().GetNumericDataType() == GDT_Float32 ||
2277 2 : poAttr->GetDataType().GetNumericDataType() == GDT_Float64))
2278 : {
2279 0 : if (pbHasVal)
2280 0 : *pbHasVal = true;
2281 0 : if (peStorageType)
2282 0 : *peStorageType = poAttr->GetDataType().GetNumericDataType();
2283 0 : return poAttr->ReadAsDouble();
2284 : }
2285 2 : if (pbHasVal)
2286 2 : *pbHasVal = false;
2287 2 : return dfDefaultValue;
2288 : }
2289 :
2290 : /************************************************************************/
2291 : /* GetOffset() */
2292 : /************************************************************************/
2293 :
2294 1 : static double GetOffset(const GDALMDArray *poArray, bool *pbHasOffset,
2295 : GDALDataType *peStorageType)
2296 : {
2297 1 : return GetOffsetOrScale(poArray, "add_offset", 0, pbHasOffset,
2298 1 : peStorageType);
2299 : }
2300 :
2301 : /************************************************************************/
2302 : /* GetOffset() */
2303 : /************************************************************************/
2304 :
2305 0 : double HDF4EOSGridArray::GetOffset(bool *pbHasOffset,
2306 : GDALDataType *peStorageType) const
2307 : {
2308 0 : return ::GetOffset(this, pbHasOffset, peStorageType);
2309 : }
2310 :
2311 : /************************************************************************/
2312 : /* GetScale() */
2313 : /************************************************************************/
2314 :
2315 1 : static double GetScale(const GDALMDArray *poArray, bool *pbHasScale,
2316 : GDALDataType *peStorageType)
2317 : {
2318 1 : return GetOffsetOrScale(poArray, "scale_factor", 1, pbHasScale,
2319 1 : peStorageType);
2320 : }
2321 :
2322 : /************************************************************************/
2323 : /* GetScale() */
2324 : /************************************************************************/
2325 :
2326 0 : double HDF4EOSGridArray::GetScale(bool *pbHasScale,
2327 : GDALDataType *peStorageType) const
2328 : {
2329 0 : return ::GetScale(this, pbHasScale, peStorageType);
2330 : }
2331 :
2332 : /************************************************************************/
2333 : /* GetUnit() */
2334 : /************************************************************************/
2335 :
2336 0 : const std::string &HDF4EOSGridArray::GetUnit() const
2337 : {
2338 0 : auto poAttr = GetAttribute("units");
2339 0 : if (poAttr && poAttr->GetDataType().GetClass() == GEDTC_STRING)
2340 : {
2341 0 : const char *pszVal = poAttr->ReadAsString();
2342 0 : if (pszVal)
2343 0 : m_osUnit = pszVal;
2344 : }
2345 0 : return m_osUnit;
2346 : }
2347 :
2348 : /************************************************************************/
2349 : /* GetSpatialRef() */
2350 : /************************************************************************/
2351 :
2352 0 : std::shared_ptr<OGRSpatialReference> HDF4EOSGridArray::GetSpatialRef() const
2353 : {
2354 0 : CPLMutexHolderD(&hHDF4Mutex);
2355 0 : int32 iProjCode = 0;
2356 0 : int32 iZoneCode = 0;
2357 0 : int32 iSphereCode = 0;
2358 : double adfProjParams[15];
2359 :
2360 0 : if (GDprojinfo(m_poGDHandle->m_handle, &iProjCode, &iZoneCode, &iSphereCode,
2361 0 : adfProjParams) >= 0)
2362 : {
2363 0 : auto poSRS(std::make_shared<OGRSpatialReference>());
2364 0 : poSRS->importFromUSGS(iProjCode, iZoneCode, adfProjParams, iSphereCode,
2365 : USGS_ANGLE_RADIANS);
2366 0 : int iDimY = -1;
2367 0 : int iDimX = -1;
2368 0 : if (m_dims.size() >= 2)
2369 : {
2370 0 : iDimY = 1 + static_cast<int>(m_dims.size() - 2);
2371 0 : iDimX = 1 + static_cast<int>(m_dims.size() - 1);
2372 : }
2373 0 : if (iDimX > 0 && iDimY > 0)
2374 : {
2375 0 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2376 0 : if (poSRS->GetDataAxisToSRSAxisMapping() == std::vector<int>{2, 1})
2377 0 : poSRS->SetDataAxisToSRSAxisMapping({iDimY, iDimX});
2378 : else
2379 0 : poSRS->SetDataAxisToSRSAxisMapping({iDimX, iDimY});
2380 : }
2381 0 : return poSRS;
2382 : }
2383 0 : return nullptr;
2384 : }
2385 :
2386 : /************************************************************************/
2387 : /* IRead() */
2388 : /************************************************************************/
2389 :
2390 0 : bool HDF4EOSGridArray::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
2391 : const GInt64 *arrayStep,
2392 : const GPtrDiff_t *bufferStride,
2393 : const GDALExtendedDataType &bufferDataType,
2394 : void *pDstBuffer) const
2395 : {
2396 : ReadFunc readFunc;
2397 0 : readFunc.pReadField = GDreadfield;
2398 0 : return ReadPixels(arrayStartIdx, count, arrayStep, bufferStride,
2399 0 : bufferDataType, pDstBuffer, m_poShared, m_dt, m_dims,
2400 0 : m_poGDHandle->m_handle, GetName().c_str(), readFunc);
2401 : }
2402 :
2403 : /************************************************************************/
2404 : /* GetMDArrayNames() */
2405 : /************************************************************************/
2406 :
2407 4 : std::vector<std::string> HDF4SDSGroup::GetMDArrayNames(CSLConstList) const
2408 : {
2409 8 : CPLMutexHolderD(&hHDF4Mutex);
2410 4 : std::vector<std::string> ret;
2411 :
2412 4 : int32 nDatasets = 0;
2413 4 : int32 nAttrs = 0;
2414 4 : if (SDfileinfo(m_poShared->GetSDHandle(), &nDatasets, &nAttrs) != 0)
2415 0 : return ret;
2416 :
2417 8 : std::set<std::string> oSetNames;
2418 10 : for (int32 i = 0; i < nDatasets; i++)
2419 : {
2420 6 : const int32 iSDS = SDselect(m_poShared->GetSDHandle(), i);
2421 12 : std::string osName;
2422 6 : osName.resize(VSNAMELENMAX);
2423 6 : int32 iRank = 0;
2424 6 : int32 iNumType = 0;
2425 12 : std::vector<int32> aiDimSizes(H4_MAX_VAR_DIMS);
2426 6 : if (SDgetinfo(iSDS, &osName[0], &iRank, &aiDimSizes[0], &iNumType,
2427 6 : &nAttrs) == 0)
2428 : {
2429 6 : osName.resize(strlen(osName.c_str()));
2430 6 : int counter = 2;
2431 6 : std::string osRadix(osName);
2432 6 : while (oSetNames.find(osName) != oSetNames.end())
2433 : {
2434 0 : osName = osRadix + CPLSPrintf("_%d", counter);
2435 0 : counter++;
2436 : }
2437 6 : ret.push_back(osName);
2438 6 : m_oMapNameToSDSIdx[osName] = i;
2439 : }
2440 6 : SDendaccess(iSDS);
2441 : }
2442 :
2443 4 : if (m_bIsGDALDataset)
2444 : {
2445 2 : GetDimensions();
2446 2 : if (m_varX && m_varY)
2447 : {
2448 2 : ret.push_back(m_varX->GetName());
2449 2 : ret.push_back(m_varY->GetName());
2450 : }
2451 : }
2452 :
2453 4 : return ret;
2454 : }
2455 :
2456 : /************************************************************************/
2457 : /* OpenMDArray() */
2458 : /************************************************************************/
2459 :
2460 : std::shared_ptr<GDALMDArray>
2461 10 : HDF4SDSGroup::OpenMDArray(const std::string &osName, CSLConstList) const
2462 : {
2463 20 : CPLMutexHolderD(&hHDF4Mutex);
2464 10 : if (m_oMapNameToSDSIdx.empty())
2465 : {
2466 0 : GetMDArrayNames(nullptr);
2467 : }
2468 10 : auto oIter = m_oMapNameToSDSIdx.find(osName);
2469 10 : if (oIter == m_oMapNameToSDSIdx.end())
2470 : {
2471 2 : if (m_bIsGDALDataset)
2472 : {
2473 2 : GetDimensions();
2474 2 : if (m_varX && m_varX->GetName() == osName)
2475 : {
2476 1 : return m_varX;
2477 : }
2478 1 : if (m_varY && m_varY->GetName() == osName)
2479 : {
2480 1 : return m_varY;
2481 : }
2482 : }
2483 0 : return nullptr;
2484 : }
2485 8 : const int32 iSDS = SDselect(m_poShared->GetSDHandle(), oIter->second);
2486 :
2487 8 : int32 iRank = 0;
2488 8 : int32 iNumType = 0;
2489 8 : int32 nAttrs = 0;
2490 16 : std::vector<int32> aiDimSizes(H4_MAX_VAR_DIMS);
2491 8 : SDgetinfo(iSDS, nullptr, &iRank, &aiDimSizes[0], &iNumType, &nAttrs);
2492 8 : aiDimSizes.resize(iRank);
2493 :
2494 8 : auto ar = HDF4SDSArray::Create(GetFullName(), osName, m_poShared, iSDS,
2495 0 : aiDimSizes, GetDimensions(), iNumType,
2496 16 : nAttrs, m_bIsGDALDataset);
2497 8 : if (m_bIsGDALDataset)
2498 2 : ar->SetGlobalAttributes(m_oGlobalAttributes);
2499 8 : return ar;
2500 : }
2501 :
2502 : /************************************************************************/
2503 : /* GetDimensions() */
2504 : /************************************************************************/
2505 :
2506 : std::vector<std::shared_ptr<GDALDimension>>
2507 16 : HDF4SDSGroup::GetDimensions(CSLConstList) const
2508 : {
2509 32 : CPLMutexHolderD(&hHDF4Mutex);
2510 16 : if (m_bInGetDimensions)
2511 2 : return {};
2512 14 : if (!m_dims.empty())
2513 10 : return m_dims;
2514 4 : if (m_oMapNameToSDSIdx.empty())
2515 : {
2516 1 : m_bInGetDimensions = true;
2517 1 : GetMDArrayNames(nullptr);
2518 1 : m_bInGetDimensions = false;
2519 : }
2520 :
2521 8 : std::string osProjection;
2522 8 : std::string osTransformationMatrix;
2523 4 : if (m_bIsGDALDataset)
2524 : {
2525 8 : for (const auto &poAttr : m_oGlobalAttributes)
2526 : {
2527 8 : if (poAttr->GetName() == "Projection" &&
2528 2 : poAttr->GetDataType().GetClass() == GEDTC_STRING)
2529 : {
2530 2 : const char *pszVal = poAttr->ReadAsString();
2531 2 : if (pszVal)
2532 2 : osProjection = pszVal;
2533 : }
2534 6 : else if (poAttr->GetName() == "TransformationMatrix" &&
2535 2 : poAttr->GetDataType().GetClass() == GEDTC_STRING)
2536 : {
2537 2 : const char *pszVal = poAttr->ReadAsString();
2538 2 : if (pszVal)
2539 2 : osTransformationMatrix = pszVal;
2540 : }
2541 : }
2542 : }
2543 :
2544 : // First collect all dimension ids referenced by all datasets
2545 8 : std::map<int32, int32> oMapDimIdToDimSize;
2546 8 : std::set<std::string> oSetArrayNames;
2547 10 : for (const auto &oIter : m_oMapNameToSDSIdx)
2548 : {
2549 6 : const int32 iSDS = SDselect(m_poShared->GetSDHandle(), oIter.second);
2550 6 : int32 iRank = 0;
2551 6 : int32 iNumType = 0;
2552 6 : int32 nAttrs = 0;
2553 12 : std::vector<int32> aiDimSizes(H4_MAX_VAR_DIMS);
2554 6 : SDgetinfo(iSDS, nullptr, &iRank, &aiDimSizes[0], &iNumType, &nAttrs);
2555 17 : for (int i = 0; i < iRank; i++)
2556 : {
2557 11 : const auto dimId = SDgetdimid(iSDS, i);
2558 11 : oMapDimIdToDimSize[dimId] =
2559 11 : std::max(oMapDimIdToDimSize[dimId], aiDimSizes[i]);
2560 : }
2561 6 : oSetArrayNames.insert(oIter.first);
2562 6 : SDendaccess(iSDS);
2563 : }
2564 :
2565 : // Instantiate dimensions
2566 : std::set<std::shared_ptr<GDALDimensionWeakIndexingVar>>
2567 8 : oSetDimsWithVariable;
2568 13 : for (const auto &iter : oMapDimIdToDimSize)
2569 : {
2570 18 : std::string osName;
2571 9 : osName.resize(VSNAMELENMAX);
2572 9 : int32 iSize = 0; // can be 0 for unlimited dimension
2573 9 : int32 iNumType = 0;
2574 9 : int32 nAttrs = 0;
2575 9 : SDdiminfo(iter.first, &osName[0], &iSize, &iNumType, &nAttrs);
2576 9 : osName.resize(strlen(osName.c_str()));
2577 :
2578 18 : std::string osType;
2579 18 : std::string osDirection;
2580 9 : bool bIsIndexedDim = false;
2581 9 : if (iNumType > 0 && oSetArrayNames.find(osName) != oSetArrayNames.end())
2582 : {
2583 2 : bIsIndexedDim = true;
2584 2 : m_bInGetDimensions = true;
2585 4 : auto poArray(OpenMDArray(osName, nullptr));
2586 2 : m_bInGetDimensions = false;
2587 2 : if (poArray)
2588 : {
2589 6 : auto poAxis = poArray->GetAttribute("axis");
2590 2 : if (poAxis && poAxis->GetDataType().GetClass() == GEDTC_STRING)
2591 : {
2592 0 : const char *pszVal = poAxis->ReadAsString();
2593 0 : if (pszVal && EQUAL(pszVal, "X"))
2594 0 : osType = GDAL_DIM_TYPE_HORIZONTAL_X;
2595 0 : else if (pszVal && EQUAL(pszVal, "Y"))
2596 0 : osType = GDAL_DIM_TYPE_HORIZONTAL_Y;
2597 : }
2598 : }
2599 : }
2600 :
2601 : // Do not trust iSize which can be 0 for a unlimited dimension, but
2602 : // the size actually taken by the array(s)
2603 : auto poDim(std::make_shared<GDALDimensionWeakIndexingVar>(
2604 9 : GetFullName(), osName, osType, osDirection, iter.second));
2605 : // cppcheck-suppress knownConditionTrueFalse
2606 9 : if (bIsIndexedDim)
2607 : {
2608 2 : oSetDimsWithVariable.insert(poDim);
2609 : }
2610 9 : m_dims.push_back(poDim);
2611 : }
2612 :
2613 2 : if (m_bIsGDALDataset && (m_dims.size() == 2 || m_dims.size() == 3) &&
2614 6 : !osProjection.empty() && !osTransformationMatrix.empty())
2615 : {
2616 : CPLStringList aosCoeffs(
2617 4 : CSLTokenizeString2(osTransformationMatrix.c_str(), ",", 0));
2618 4 : if (aosCoeffs.size() == 6 && CPLAtof(aosCoeffs[2]) == 0 &&
2619 2 : CPLAtof(aosCoeffs[4]) == 0)
2620 : {
2621 : auto newDims = std::vector<std::shared_ptr<GDALDimension>>{
2622 4 : std::make_shared<GDALDimensionWeakIndexingVar>(
2623 2 : GetFullName(), "Y", GDAL_DIM_TYPE_HORIZONTAL_Y,
2624 2 : std::string(), m_dims[0]->GetSize()),
2625 4 : std::make_shared<GDALDimensionWeakIndexingVar>(
2626 2 : GetFullName(), "X", GDAL_DIM_TYPE_HORIZONTAL_X,
2627 14 : std::string(), m_dims[1]->GetSize())};
2628 2 : if (m_dims.size() == 3)
2629 : {
2630 1 : newDims.push_back(
2631 2 : std::make_shared<GDALDimensionWeakIndexingVar>(
2632 2 : GetFullName(), "Band", std::string(), std::string(),
2633 2 : m_dims[2]->GetSize()));
2634 : }
2635 2 : m_dims = std::move(newDims);
2636 :
2637 4 : m_varX = GDALMDArrayRegularlySpaced::Create(
2638 2 : GetFullName(), m_dims[1]->GetName(), m_dims[1],
2639 4 : CPLAtof(aosCoeffs[0]), CPLAtof(aosCoeffs[1]), 0.5);
2640 2 : m_dims[1]->SetIndexingVariable(m_varX);
2641 :
2642 4 : m_varY = GDALMDArrayRegularlySpaced::Create(
2643 2 : GetFullName(), m_dims[0]->GetName(), m_dims[0],
2644 4 : CPLAtof(aosCoeffs[3]), CPLAtof(aosCoeffs[5]), 0.5);
2645 2 : m_dims[0]->SetIndexingVariable(m_varY);
2646 : }
2647 : }
2648 :
2649 : // Now that we have eatablished all dimensions, we can link them to
2650 : // variables
2651 6 : for (auto &poDim : oSetDimsWithVariable)
2652 : {
2653 4 : auto poArray(OpenMDArray(poDim->GetName(), nullptr));
2654 2 : if (poArray)
2655 : {
2656 2 : m_oSetIndexingVariables.push_back(poArray);
2657 2 : poDim->SetIndexingVariable(std::move(poArray));
2658 : }
2659 : }
2660 :
2661 4 : return m_dims;
2662 : }
2663 :
2664 : /************************************************************************/
2665 : /* HDF4SDSArray() */
2666 : /************************************************************************/
2667 :
2668 8 : HDF4SDSArray::HDF4SDSArray(
2669 : const std::string &osParentName, const std::string &osName,
2670 : const std::shared_ptr<HDF4SharedResources> &poShared, int32 iSDS,
2671 : const std::vector<int32> &aiDimSizes,
2672 : const std::vector<std::shared_ptr<GDALDimension>> &groupDims,
2673 8 : int32 iNumType, int32 nAttrs, bool bIsGDALDS)
2674 : : GDALAbstractMDArray(osParentName, osName),
2675 : GDALPamMDArray(osParentName, osName, poShared->GetPAM()),
2676 : m_poShared(poShared), m_iSDS(iSDS),
2677 : m_dt(iNumType == DFNT_CHAR8 ? GDALExtendedDataType::CreateString()
2678 : : GDALExtendedDataType::Create(
2679 : HDF4Dataset::GetDataType(iNumType))),
2680 8 : m_nAttributes(nAttrs), m_bIsGDALDataset(bIsGDALDS)
2681 : {
2682 21 : for (int i = 0; i < static_cast<int>(aiDimSizes.size()); i++)
2683 : {
2684 26 : std::string osDimName;
2685 13 : osDimName.resize(VSNAMELENMAX);
2686 13 : int32 iSize = 0;
2687 13 : int32 iDimNumType = 0;
2688 13 : int32 nDimAttrs = 0;
2689 13 : int32 dimId = SDgetdimid(iSDS, i);
2690 13 : SDdiminfo(dimId, &osDimName[0], &iSize, &iDimNumType, &nDimAttrs);
2691 13 : osDimName.resize(strlen(osDimName.c_str()));
2692 13 : bool bFound = false;
2693 20 : for (const auto &poDim : groupDims)
2694 : {
2695 30 : if (poDim->GetName() == osDimName ||
2696 12 : (bIsGDALDS && i == 0 && poDim->GetName() == "Y") ||
2697 35 : (bIsGDALDS && i == 1 && poDim->GetName() == "X") ||
2698 5 : (bIsGDALDS && i == 2 && poDim->GetName() == "Band"))
2699 : {
2700 11 : bFound = true;
2701 11 : m_dims.push_back(poDim);
2702 11 : break;
2703 : }
2704 : }
2705 13 : if (!bFound)
2706 : {
2707 2 : m_dims.push_back(std::make_shared<GDALDimension>(
2708 4 : std::string(), CPLSPrintf("dim%d", i), std::string(),
2709 4 : std::string(), aiDimSizes[i]));
2710 : }
2711 : }
2712 8 : }
2713 :
2714 : /************************************************************************/
2715 : /* ~HDF4SDSArray() */
2716 : /************************************************************************/
2717 :
2718 16 : HDF4SDSArray::~HDF4SDSArray()
2719 : {
2720 16 : CPLMutexHolderD(&hHDF4Mutex);
2721 8 : SDendaccess(m_iSDS);
2722 16 : }
2723 :
2724 : /************************************************************************/
2725 : /* GetRawNoDataValue() */
2726 : /************************************************************************/
2727 :
2728 1 : const void *HDF4SDSArray::GetRawNoDataValue() const
2729 : {
2730 1 : if (!m_abyNoData.empty())
2731 0 : return m_abyNoData.data();
2732 1 : m_abyNoData.resize(GetDataType().GetSize());
2733 :
2734 3 : auto poAttr = GetAttribute("_FillValue");
2735 1 : if (poAttr)
2736 : {
2737 0 : const double dfVal = poAttr->ReadAsDouble();
2738 0 : GDALExtendedDataType::CopyValue(
2739 0 : &dfVal, GDALExtendedDataType::Create(GDT_Float64), &m_abyNoData[0],
2740 : GetDataType());
2741 0 : return m_abyNoData.data();
2742 : }
2743 :
2744 2 : CPLMutexHolderD(&hHDF4Mutex);
2745 1 : if (SDgetfillvalue(m_iSDS, &m_abyNoData[0]) != -1)
2746 : {
2747 0 : return m_abyNoData.data();
2748 : }
2749 :
2750 1 : m_abyNoData.clear();
2751 1 : return nullptr;
2752 : }
2753 :
2754 : /************************************************************************/
2755 : /* GetAttributes() */
2756 : /************************************************************************/
2757 :
2758 : std::vector<std::shared_ptr<GDALAttribute>>
2759 9 : HDF4SDSArray::GetAttributes(CSLConstList) const
2760 : {
2761 18 : CPLMutexHolderD(&hHDF4Mutex);
2762 9 : std::vector<std::shared_ptr<GDALAttribute>> ret;
2763 :
2764 13 : for (int32 iAttribute = 0; iAttribute < m_nAttributes; iAttribute++)
2765 : {
2766 4 : std::string osAttrName;
2767 4 : osAttrName.resize(H4_MAX_NC_NAME);
2768 4 : int32 iNumType = 0;
2769 4 : int32 nValues = 0;
2770 4 : SDattrinfo(m_iSDS, iAttribute, &osAttrName[0], &iNumType, &nValues);
2771 4 : osAttrName.resize(strlen(osAttrName.c_str()));
2772 8 : ret.emplace_back(std::make_shared<HDF4SDAttribute>(
2773 8 : GetFullName(), osAttrName, m_poShared, nullptr, nullptr, m_iSDS,
2774 4 : iAttribute, iNumType, nValues));
2775 : }
2776 :
2777 18 : return ret;
2778 : }
2779 :
2780 : /************************************************************************/
2781 : /* GetOffset() */
2782 : /************************************************************************/
2783 :
2784 1 : double HDF4SDSArray::GetOffset(bool *pbHasOffset,
2785 : GDALDataType *peStorageType) const
2786 : {
2787 1 : return ::GetOffset(this, pbHasOffset, peStorageType);
2788 : }
2789 :
2790 : /************************************************************************/
2791 : /* GetScale() */
2792 : /************************************************************************/
2793 :
2794 1 : double HDF4SDSArray::GetScale(bool *pbHasScale,
2795 : GDALDataType *peStorageType) const
2796 : {
2797 1 : return ::GetScale(this, pbHasScale, peStorageType);
2798 : }
2799 :
2800 : /************************************************************************/
2801 : /* GetUnit() */
2802 : /************************************************************************/
2803 :
2804 2 : const std::string &HDF4SDSArray::GetUnit() const
2805 : {
2806 4 : auto poAttr = GetAttribute("units");
2807 2 : if (poAttr && poAttr->GetDataType().GetClass() == GEDTC_STRING)
2808 : {
2809 0 : const char *pszVal = poAttr->ReadAsString();
2810 0 : if (pszVal)
2811 0 : m_osUnit = pszVal;
2812 : }
2813 4 : return m_osUnit;
2814 : }
2815 :
2816 : /************************************************************************/
2817 : /* GetSpatialRef() */
2818 : /************************************************************************/
2819 :
2820 3 : std::shared_ptr<OGRSpatialReference> HDF4SDSArray::GetSpatialRef() const
2821 : {
2822 3 : if (m_bIsGDALDataset)
2823 : {
2824 2 : std::string osProjection;
2825 6 : for (const auto &poAttr : m_oGlobalAttributes)
2826 : {
2827 8 : if (poAttr->GetName() == "Projection" &&
2828 2 : poAttr->GetDataType().GetClass() == GEDTC_STRING)
2829 : {
2830 2 : const char *pszVal = poAttr->ReadAsString();
2831 2 : if (pszVal)
2832 2 : osProjection = pszVal;
2833 2 : break;
2834 : }
2835 : }
2836 2 : if (!osProjection.empty())
2837 : {
2838 4 : auto poSRS(std::make_shared<OGRSpatialReference>());
2839 2 : poSRS->SetFromUserInput(
2840 : osProjection.c_str(),
2841 : OGRSpatialReference::SET_FROM_USER_INPUT_LIMITATIONS_get());
2842 2 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
2843 2 : if (poSRS->GetDataAxisToSRSAxisMapping() == std::vector<int>{2, 1})
2844 0 : poSRS->SetDataAxisToSRSAxisMapping({1, 2});
2845 : else
2846 2 : poSRS->SetDataAxisToSRSAxisMapping({2, 1});
2847 2 : return poSRS;
2848 : }
2849 : }
2850 1 : return nullptr;
2851 : }
2852 :
2853 : /************************************************************************/
2854 : /* IRead() */
2855 : /************************************************************************/
2856 :
2857 4 : bool HDF4SDSArray::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
2858 : const GInt64 *arrayStep,
2859 : const GPtrDiff_t *bufferStride,
2860 : const GDALExtendedDataType &bufferDataType,
2861 : void *pDstBuffer) const
2862 : {
2863 : ReadFunc readFunc;
2864 4 : readFunc.pReadData = SDreaddata;
2865 8 : return ReadPixels(arrayStartIdx, count, arrayStep, bufferStride,
2866 4 : bufferDataType, pDstBuffer, m_poShared, m_dt, m_dims,
2867 8 : m_iSDS, nullptr, readFunc);
2868 : }
2869 :
2870 : /************************************************************************/
2871 : /* GetMDArrayNames() */
2872 : /************************************************************************/
2873 :
2874 2 : std::vector<std::string> HDF4GRsGroup::GetMDArrayNames(CSLConstList) const
2875 : {
2876 4 : CPLMutexHolderD(&hHDF4Mutex);
2877 2 : std::vector<std::string> res;
2878 :
2879 2 : int32 nImages = 0;
2880 2 : int32 nAttrs = 0;
2881 2 : GRfileinfo(m_poGRsHandle->m_grHandle, &nImages, &nAttrs);
2882 4 : for (int32 i = 0; i < nImages; i++)
2883 : {
2884 2 : const int32 iGR = GRselect(m_poGRsHandle->m_grHandle, i);
2885 :
2886 4 : std::string osName;
2887 2 : osName.resize(VSNAMELENMAX);
2888 2 : int32 nBands = 0;
2889 2 : int32 iNumType = 0;
2890 2 : int32 iInterlaceMode = 0;
2891 4 : std::vector<int32> aiDimSizes(2);
2892 2 : if (GRgetiminfo(iGR, &osName[0], &nBands, &iNumType, &iInterlaceMode,
2893 4 : &aiDimSizes[0], &nAttrs) == 0)
2894 : {
2895 2 : osName.resize(strlen(osName.c_str()));
2896 2 : m_oMapNameToGRIdx[osName] = i;
2897 2 : res.push_back(osName);
2898 : }
2899 :
2900 2 : GRendaccess(iGR);
2901 : }
2902 4 : return res;
2903 : }
2904 :
2905 : /************************************************************************/
2906 : /* GetAttributes() */
2907 : /************************************************************************/
2908 :
2909 : std::vector<std::shared_ptr<GDALAttribute>>
2910 2 : HDF4GRsGroup::GetAttributes(CSLConstList) const
2911 : {
2912 4 : CPLMutexHolderD(&hHDF4Mutex);
2913 2 : std::vector<std::shared_ptr<GDALAttribute>> ret;
2914 2 : int32 nDatasets = 0;
2915 2 : int32 nAttributes = 0;
2916 2 : if (GRfileinfo(m_poGRsHandle->m_grHandle, &nDatasets, &nAttributes) != 0)
2917 0 : return ret;
2918 6 : for (int32 iAttribute = 0; iAttribute < nAttributes; iAttribute++)
2919 : {
2920 4 : int32 iNumType = 0;
2921 4 : int32 nValues = 0;
2922 :
2923 4 : std::string osAttrName;
2924 4 : osAttrName.resize(H4_MAX_NC_NAME);
2925 4 : GRattrinfo(m_poGRsHandle->m_grHandle, iAttribute, &osAttrName[0],
2926 : &iNumType, &nValues);
2927 4 : osAttrName.resize(strlen(osAttrName.c_str()));
2928 :
2929 8 : ret.emplace_back(std::make_shared<HDF4GRAttribute>(
2930 4 : GetFullName(), osAttrName, m_poShared, m_poGRsHandle, nullptr,
2931 8 : m_poGRsHandle->m_grHandle, iAttribute, iNumType, nValues));
2932 : }
2933 2 : return ret;
2934 : }
2935 :
2936 : /************************************************************************/
2937 : /* OpenMDArray() */
2938 : /************************************************************************/
2939 :
2940 : std::shared_ptr<GDALMDArray>
2941 3 : HDF4GRsGroup::OpenMDArray(const std::string &osName, CSLConstList) const
2942 : {
2943 6 : CPLMutexHolderD(&hHDF4Mutex);
2944 3 : if (m_oMapNameToGRIdx.empty())
2945 : {
2946 1 : GetMDArrayNames(nullptr);
2947 : }
2948 3 : auto oIter = m_oMapNameToGRIdx.find(osName);
2949 3 : if (oIter == m_oMapNameToGRIdx.end())
2950 : {
2951 1 : return nullptr;
2952 : }
2953 2 : const int32 iGR = GRselect(m_poGRsHandle->m_grHandle, oIter->second);
2954 :
2955 2 : int32 nBands = 0;
2956 2 : int32 iNumType = 0;
2957 2 : int32 iInterlaceMode = 0;
2958 2 : std::vector<int32> aiDimSizes(2);
2959 : int32 nAttrs;
2960 2 : GRgetiminfo(iGR, nullptr, &nBands, &iNumType, &iInterlaceMode,
2961 2 : &aiDimSizes[0], &nAttrs);
2962 :
2963 4 : return HDF4GRArray::Create(
2964 2 : GetFullName(), osName, m_poShared,
2965 4 : std::make_shared<HDF4GRHandle>(m_poGRsHandle, iGR), nBands, aiDimSizes,
2966 2 : iNumType, nAttrs);
2967 : }
2968 :
2969 : /************************************************************************/
2970 : /* HDF4GRArray() */
2971 : /************************************************************************/
2972 :
2973 2 : HDF4GRArray::HDF4GRArray(const std::string &osParentName,
2974 : const std::string &osName,
2975 : const std::shared_ptr<HDF4SharedResources> &poShared,
2976 : const std::shared_ptr<HDF4GRHandle> &poGRHandle,
2977 : int32 nBands, const std::vector<int32> &aiDimSizes,
2978 2 : int32 iNumType, int32 nAttrs)
2979 : : GDALAbstractMDArray(osParentName, osName),
2980 : GDALPamMDArray(osParentName, osName, poShared->GetPAM()),
2981 : m_poShared(poShared), m_poGRHandle(poGRHandle),
2982 : m_dt(iNumType == DFNT_CHAR8 ? GDALExtendedDataType::CreateString()
2983 : : GDALExtendedDataType::Create(
2984 : HDF4Dataset::GetDataType(iNumType))),
2985 2 : m_nAttributes(nAttrs)
2986 : {
2987 6 : for (int i = 0; i < static_cast<int>(aiDimSizes.size()); i++)
2988 : {
2989 8 : m_dims.push_back(std::make_shared<GDALDimension>(
2990 12 : std::string(), i == 0 ? "y" : "x", std::string(), std::string(),
2991 4 : aiDimSizes[i]));
2992 : }
2993 2 : m_dims.push_back(std::make_shared<GDALDimension>(
2994 4 : std::string(), "bands", std::string(), std::string(), nBands));
2995 2 : }
2996 :
2997 : /************************************************************************/
2998 : /* GetAttributes() */
2999 : /************************************************************************/
3000 :
3001 : std::vector<std::shared_ptr<GDALAttribute>>
3002 4 : HDF4GRArray::GetAttributes(CSLConstList) const
3003 : {
3004 8 : CPLMutexHolderD(&hHDF4Mutex);
3005 4 : std::vector<std::shared_ptr<GDALAttribute>> ret;
3006 10 : for (int32 iAttribute = 0; iAttribute < m_nAttributes; iAttribute++)
3007 : {
3008 6 : int32 iNumType = 0;
3009 6 : int32 nValues = 0;
3010 :
3011 6 : std::string osAttrName;
3012 6 : osAttrName.resize(H4_MAX_NC_NAME);
3013 6 : GRattrinfo(m_poGRHandle->m_iGR, iAttribute, &osAttrName[0], &iNumType,
3014 : &nValues);
3015 6 : osAttrName.resize(strlen(osAttrName.c_str()));
3016 :
3017 12 : ret.emplace_back(std::make_shared<HDF4GRAttribute>(
3018 6 : GetFullName(), osAttrName, m_poShared, nullptr, m_poGRHandle,
3019 12 : m_poGRHandle->m_iGR, iAttribute, iNumType, nValues));
3020 : }
3021 :
3022 4 : auto iPal = GRgetlutid(m_poGRHandle->m_iGR, 0);
3023 4 : if (iPal != -1)
3024 : {
3025 4 : int32 nComps = 0;
3026 4 : int32 iPalDataType = 0;
3027 4 : int32 iPalInterlaceMode = 0;
3028 4 : int32 nPalEntries = 0;
3029 4 : GRgetlutinfo(iPal, &nComps, &iPalDataType, &iPalInterlaceMode,
3030 : &nPalEntries);
3031 1 : if (nPalEntries && nComps == 3 &&
3032 1 : GDALGetDataTypeSizeBytes(HDF4Dataset::GetDataType(iPalDataType)) ==
3033 5 : 1 &&
3034 1 : nPalEntries <= 256)
3035 : {
3036 2 : ret.emplace_back(std::make_shared<HDF4GRPalette>(
3037 1 : GetFullName(), "lut", m_poShared, m_poGRHandle, iPal,
3038 1 : nPalEntries));
3039 : }
3040 : }
3041 :
3042 8 : return ret;
3043 : }
3044 :
3045 : /************************************************************************/
3046 : /* IRead() */
3047 : /************************************************************************/
3048 :
3049 4 : bool HDF4GRArray::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
3050 : const GInt64 *arrayStep, const GPtrDiff_t *bufferStride,
3051 : const GDALExtendedDataType &bufferDataType,
3052 : void *pDstBuffer) const
3053 : {
3054 8 : CPLMutexHolderD(&hHDF4Mutex);
3055 : /* -------------------------------------------------------------------- */
3056 : /* HDF files with external data files, such as some landsat */
3057 : /* products (eg. data/hdf/L1G) need to be told what directory */
3058 : /* to look in to find the external files. Normally this is the */
3059 : /* directory holding the hdf file. */
3060 : /* -------------------------------------------------------------------- */
3061 4 : HXsetdir(CPLGetPath(m_poShared->GetFilename().c_str()));
3062 :
3063 4 : const size_t nDims(m_dims.size());
3064 8 : std::vector<int32> sw_start(nDims);
3065 8 : std::vector<int32> sw_stride(nDims);
3066 8 : std::vector<int32> sw_edge(nDims);
3067 8 : std::vector<GPtrDiff_t> newBufferStride(nDims);
3068 4 : GByte *pabyDstBuffer = static_cast<GByte *>(pDstBuffer);
3069 4 : const size_t nBufferDataTypeSize = bufferDataType.GetSize();
3070 16 : for (size_t i = 0; i < nDims; i++)
3071 : {
3072 12 : sw_start[i] = static_cast<int>(arrayStartIdx[i]);
3073 12 : sw_stride[i] = static_cast<int>(arrayStep[i]);
3074 12 : sw_edge[i] = static_cast<int>(count[i]);
3075 12 : newBufferStride[i] = bufferStride[i];
3076 12 : if (sw_stride[i] < 0)
3077 : {
3078 : // GRreadimage() doesn't like negative step / array stride, so
3079 : // transform the request to a classic "left-to-right" one
3080 1 : sw_start[i] += sw_stride[i] * (sw_edge[i] - 1);
3081 1 : sw_stride[i] = -sw_stride[i];
3082 1 : pabyDstBuffer +=
3083 1 : (sw_edge[i] - 1) * newBufferStride[i] * nBufferDataTypeSize;
3084 1 : newBufferStride[i] = -newBufferStride[i];
3085 : }
3086 : }
3087 4 : size_t nExpectedStride = 1;
3088 4 : bool bContiguousStride = true;
3089 13 : for (size_t i = nDims; i > 0;)
3090 : {
3091 10 : --i;
3092 10 : if (newBufferStride[i] != static_cast<GPtrDiff_t>(nExpectedStride))
3093 : {
3094 1 : bContiguousStride = false;
3095 1 : break;
3096 : }
3097 9 : nExpectedStride *= count[i];
3098 : }
3099 10 : if (bufferDataType == m_dt && bContiguousStride && arrayStartIdx[2] == 0 &&
3100 10 : count[2] == m_dims[2]->GetSize() && arrayStep[2] == 1)
3101 : {
3102 1 : auto status = GRreadimage(m_poGRHandle->m_iGR, &sw_start[0],
3103 1 : &sw_stride[0], &sw_edge[0], pabyDstBuffer);
3104 1 : return status >= 0;
3105 : }
3106 3 : auto pabyTemp = static_cast<GByte *>(VSI_MALLOC2_VERBOSE(
3107 : m_dt.GetSize(),
3108 : count[0] * count[1] * static_cast<size_t>(m_dims[2]->GetSize())));
3109 3 : if (pabyTemp == nullptr)
3110 0 : return false;
3111 3 : auto status = GRreadimage(m_poGRHandle->m_iGR, &sw_start[0], &sw_stride[0],
3112 3 : &sw_edge[0], pabyTemp);
3113 3 : if (status < 0)
3114 : {
3115 0 : VSIFree(pabyTemp);
3116 0 : return false;
3117 : }
3118 :
3119 3 : const size_t nSrcDataTypeSize = m_dt.GetSize();
3120 6 : std::vector<size_t> anStackCount(nDims);
3121 3 : GByte *pabySrc = pabyTemp + nSrcDataTypeSize * sw_start[2];
3122 3 : std::vector<GByte *> pabyDstBufferStack(nDims + 1);
3123 3 : pabyDstBufferStack[0] = pabyDstBuffer;
3124 3 : size_t iDim = 0;
3125 54 : lbl_next_depth:
3126 54 : if (iDim == nDims)
3127 : {
3128 24 : GDALExtendedDataType::CopyValue(
3129 24 : pabySrc, m_dt, pabyDstBufferStack[nDims], bufferDataType);
3130 24 : pabySrc += nSrcDataTypeSize * sw_stride[2];
3131 : }
3132 : else
3133 : {
3134 30 : anStackCount[iDim] = count[iDim];
3135 : while (true)
3136 : {
3137 51 : ++iDim;
3138 51 : pabyDstBufferStack[iDim] = pabyDstBufferStack[iDim - 1];
3139 51 : goto lbl_next_depth;
3140 51 : lbl_return_to_caller_in_loop:
3141 51 : --iDim;
3142 51 : --anStackCount[iDim];
3143 51 : if (anStackCount[iDim] == 0)
3144 30 : break;
3145 21 : IncrPointer(pabyDstBufferStack[iDim], newBufferStride[iDim],
3146 : nBufferDataTypeSize);
3147 : }
3148 30 : if (iDim == 2)
3149 18 : pabySrc +=
3150 18 : nSrcDataTypeSize * static_cast<size_t>(m_dims[2]->GetSize() -
3151 18 : count[2] * sw_stride[2]);
3152 : }
3153 54 : if (iDim > 0)
3154 51 : goto lbl_return_to_caller_in_loop;
3155 :
3156 3 : VSIFree(pabyTemp);
3157 3 : return true;
3158 : }
3159 :
3160 : /************************************************************************/
3161 : /* HDF4GRPalette() */
3162 : /************************************************************************/
3163 :
3164 1 : HDF4GRPalette::HDF4GRPalette(
3165 : const std::string &osParentName, const std::string &osName,
3166 : const std::shared_ptr<HDF4SharedResources> &poShared,
3167 1 : const std::shared_ptr<HDF4GRHandle> &poGRHandle, int32 iPal, int32 nValues)
3168 : : GDALAbstractMDArray(osParentName, osName),
3169 : GDALAttribute(osParentName, osName), m_poShared(poShared),
3170 1 : m_poGRHandle(poGRHandle), m_iPal(iPal), m_nValues(nValues)
3171 : {
3172 1 : m_dims.push_back(std::make_shared<GDALDimension>(
3173 2 : std::string(), "index", std::string(), std::string(), nValues));
3174 1 : m_dims.push_back(std::make_shared<GDALDimension>(
3175 2 : std::string(), "component", std::string(), std::string(), 3));
3176 1 : }
3177 :
3178 : /************************************************************************/
3179 : /* IRead() */
3180 : /************************************************************************/
3181 :
3182 1 : bool HDF4GRPalette::IRead(const GUInt64 *arrayStartIdx, const size_t *count,
3183 : const GInt64 *arrayStep,
3184 : const GPtrDiff_t *bufferStride,
3185 : const GDALExtendedDataType &bufferDataType,
3186 : void *pDstBuffer) const
3187 : {
3188 2 : CPLMutexHolderD(&hHDF4Mutex);
3189 :
3190 2 : std::vector<GByte> abyValues(3 * m_nValues);
3191 1 : GRreadlut(m_iPal, &abyValues[0]);
3192 :
3193 1 : GByte *pabyDstBuffer = static_cast<GByte *>(pDstBuffer);
3194 1 : const size_t nBufferDataTypeSize = bufferDataType.GetSize();
3195 1 : const auto srcDt(GDALExtendedDataType::Create(GDT_Byte));
3196 257 : for (size_t i = 0; i < count[0]; ++i)
3197 : {
3198 256 : size_t idx = static_cast<size_t>(arrayStartIdx[0] + i * arrayStep[0]);
3199 1024 : for (size_t j = 0; j < count[1]; ++j)
3200 : {
3201 768 : size_t comp =
3202 768 : static_cast<size_t>(arrayStartIdx[1] + j * arrayStep[1]);
3203 768 : GByte *pDst =
3204 768 : pabyDstBuffer + (i * bufferStride[0] + j * bufferStride[1]) *
3205 : nBufferDataTypeSize;
3206 768 : GDALExtendedDataType::CopyValue(&abyValues[3 * idx + comp], srcDt,
3207 : pDst, bufferDataType);
3208 : }
3209 : }
3210 :
3211 2 : return true;
3212 : }
3213 :
3214 : /************************************************************************/
3215 : /* OpenMultiDim() */
3216 : /************************************************************************/
3217 :
3218 6 : void HDF4Dataset::OpenMultiDim(const char *pszFilename,
3219 : CSLConstList papszOpenOptionsIn)
3220 : {
3221 : // under hHDF4Mutex
3222 :
3223 12 : auto poShared = std::make_shared<HDF4SharedResources>(pszFilename);
3224 6 : poShared->m_hSD = hSD;
3225 6 : poShared->m_aosOpenOptions = papszOpenOptionsIn;
3226 :
3227 6 : hSD = -1;
3228 :
3229 6 : m_poRootGroup = HDF4Group::Create(std::string(), "/", poShared);
3230 :
3231 6 : SetDescription(pszFilename);
3232 :
3233 : // Setup/check for pam .aux.xml.
3234 6 : TryLoadXML();
3235 6 : }
|