Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PDS 4 Driver; Planetary Data System Format
4 : * Purpose: Implementation of PDS4Dataset
5 : * Author: Even Rouault, even.rouault at spatialys.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2019, Hobu Inc
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #pragma once
14 :
15 : #include "cpl_string.h"
16 : #include "gdal_priv.h"
17 : #include "gdal_proxy.h"
18 : #include "ogreditablelayer.h"
19 : #include "rawdataset.h"
20 : #include "ogr_spatialref.h"
21 :
22 : #include <array>
23 : #include <vector>
24 :
25 : class PDS4Dataset;
26 :
27 240 : class PDS4TableLayerInterface CPL_NON_FINAL
28 : {
29 : public:
30 : virtual ~PDS4TableLayerInterface();
31 :
32 : virtual const char *GetFileName() const = 0;
33 :
34 : virtual bool IsDirtyHeader() const = 0;
35 :
36 : virtual int GetRawFieldCount() const = 0;
37 :
38 : virtual char **GetFileList() const = 0;
39 :
40 : virtual void RefreshFileAreaObservational(CPLXMLNode *psFAO) = 0;
41 :
42 : virtual GIntBig GetFeatureCount(int bForce) = 0;
43 :
44 : virtual void SetSpatialRef(OGRSpatialReference *poSRS) = 0;
45 :
46 : virtual const char *GetName() const = 0;
47 :
48 : virtual OGRwkbGeometryType GetGeomType() const = 0;
49 : };
50 :
51 : /************************************************************************/
52 : /* ==================================================================== */
53 : /* PDS4TableBaseLayer */
54 : /* ==================================================================== */
55 : /************************************************************************/
56 :
57 : class PDS4TableBaseLayer CPL_NON_FINAL : public OGRLayer,
58 : public PDS4TableLayerInterface
59 : {
60 : protected:
61 : bool m_bUpdate = false;
62 : PDS4Dataset *m_poDS = nullptr;
63 : OGRFeatureDefn *m_poRawFeatureDefn = nullptr;
64 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
65 : CPLString m_osFilename{};
66 : int m_iLatField = -1;
67 : int m_iLongField = -1;
68 : int m_iAltField = -1;
69 : int m_iWKT = -1;
70 : bool m_bKeepGeomColmuns = false;
71 : bool m_bDirtyHeader = false;
72 : VSILFILE *m_fp = nullptr;
73 : GIntBig m_nFeatureCount = -1;
74 : GIntBig m_nFID = 1;
75 : vsi_l_offset m_nOffset = 0;
76 : CPLStringList m_aosLCO{};
77 : std::string m_osLineEnding{};
78 :
79 : void SetupGeomField();
80 : OGRFeature *AddGeometryFromFields(OGRFeature *poFeature);
81 : OGRFeature *AddFieldsFromGeometry(OGRFeature *poFeature);
82 : void MarkHeaderDirty();
83 : CPLXMLNode *RefreshFileAreaObservationalBeginningCommon(
84 : CPLXMLNode *psFAO, const CPLString &osPrefix,
85 : const char *pszTableEltName, CPLString &osDescription);
86 : void ParseLineEndingOption(CSLConstList papszOptions);
87 :
88 : CPL_DISALLOW_COPY_ASSIGN(PDS4TableBaseLayer)
89 :
90 : public:
91 : PDS4TableBaseLayer(PDS4Dataset *poDS, const char *pszName,
92 : const char *pszFilename, bool bUpdate);
93 : ~PDS4TableBaseLayer() override;
94 :
95 : using OGRLayer::GetLayerDefn;
96 :
97 289 : const char *GetName() const override
98 : {
99 289 : return GetDescription();
100 : }
101 :
102 1976 : const OGRFeatureDefn *GetLayerDefn() const override
103 : {
104 1976 : return m_poFeatureDefn;
105 : }
106 :
107 : GIntBig GetFeatureCount(int bForce) override;
108 :
109 136 : const char *GetFileName() const override
110 : {
111 136 : return m_osFilename.c_str();
112 : }
113 :
114 72 : bool IsDirtyHeader() const override
115 : {
116 72 : return m_bDirtyHeader;
117 : }
118 :
119 69 : int GetRawFieldCount() const override
120 : {
121 69 : return m_poRawFeatureDefn->GetFieldCount();
122 : }
123 :
124 165 : OGRwkbGeometryType GetGeomType() const override
125 : {
126 165 : return OGRLayer::GetGeomType();
127 : }
128 :
129 : void SetSpatialRef(OGRSpatialReference *poSRS) override;
130 :
131 : bool RenameFileTo(const char *pszNewName);
132 : char **GetFileList() const override;
133 :
134 : GDALDataset *GetDataset() override;
135 : };
136 :
137 : /************************************************************************/
138 : /* ==================================================================== */
139 : /* PDS4FixedWidthTable */
140 : /* ==================================================================== */
141 : /************************************************************************/
142 :
143 : template <class T> class PDS4EditableSynchronizer;
144 :
145 : class PDS4FixedWidthTable CPL_NON_FINAL : public PDS4TableBaseLayer
146 : {
147 : friend class PDS4EditableSynchronizer<PDS4FixedWidthTable>;
148 :
149 : protected:
150 : int m_nRecordSize = 0;
151 : CPLString m_osBuffer{};
152 :
153 : struct Field
154 : {
155 : int m_nOffset = 0; // in XML 1-based, here 0-based
156 : int m_nLength = 0;
157 : CPLString m_osDataType{};
158 : CPLString m_osUnit{};
159 : CPLString m_osDescription{};
160 : CPLString m_osSpecialConstantsXML{};
161 : };
162 :
163 : std::vector<Field> m_aoFields{};
164 :
165 : virtual CPLString GetSubType() const = 0;
166 :
167 : virtual bool CreateFieldInternal(OGRFieldType eType,
168 : OGRFieldSubType eSubType, int nWidth,
169 : Field &f) = 0;
170 :
171 : bool ReadFields(const CPLXMLNode *psParent, int nBaseOffset,
172 : const CPLString &osSuffixFieldName);
173 :
174 : public:
175 : PDS4FixedWidthTable(PDS4Dataset *poDS, const char *pszName,
176 : const char *pszFilename, bool bUpdate);
177 :
178 : void ResetReading() override;
179 : OGRFeature *GetFeature(GIntBig nFID) override;
180 : OGRFeature *GetNextFeature() override;
181 : bool TestCapability(const char *) const override;
182 : OGRErr ISetFeature(OGRFeature *poFeature) override;
183 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
184 : OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override;
185 :
186 : bool ReadTableDef(const CPLXMLNode *psTable);
187 :
188 : bool InitializeNewLayer(const OGRSpatialReference *poSRS,
189 : bool bForceGeographic, OGRwkbGeometryType eGType,
190 : const char *const *papszOptions);
191 :
192 : virtual PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS,
193 : const char *pszName,
194 : const char *pszFilename) = 0;
195 :
196 : void RefreshFileAreaObservational(CPLXMLNode *psFAO) override;
197 : };
198 :
199 : /************************************************************************/
200 : /* ==================================================================== */
201 : /* PDS4TableCharacter */
202 : /* ==================================================================== */
203 : /************************************************************************/
204 :
205 : class PDS4TableCharacter final : public PDS4FixedWidthTable
206 : {
207 565 : CPLString GetSubType() const override
208 : {
209 565 : return "Character";
210 : }
211 :
212 : bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType,
213 : int nWidth, Field &f) override;
214 :
215 : public:
216 : PDS4TableCharacter(PDS4Dataset *poDS, const char *pszName,
217 : const char *pszFilename, bool bUpdate);
218 :
219 2 : PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
220 : const char *pszFilename) override
221 : {
222 2 : return new PDS4TableCharacter(poDS, pszName, pszFilename, true);
223 : }
224 : };
225 :
226 : /************************************************************************/
227 : /* ==================================================================== */
228 : /* PDS4TableBinary */
229 : /* ==================================================================== */
230 : /************************************************************************/
231 :
232 : class PDS4TableBinary final : public PDS4FixedWidthTable
233 : {
234 3258 : CPLString GetSubType() const override
235 : {
236 3258 : return "Binary";
237 : }
238 :
239 : bool CreateFieldInternal(OGRFieldType eType, OGRFieldSubType eSubType,
240 : int nWidth, Field &f) override;
241 :
242 : public:
243 : PDS4TableBinary(PDS4Dataset *poDS, const char *pszName,
244 : const char *pszFilename, bool bUpdate);
245 :
246 0 : PDS4FixedWidthTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
247 : const char *pszFilename) override
248 : {
249 0 : return new PDS4TableBinary(poDS, pszName, pszFilename, true);
250 : }
251 : };
252 :
253 : /************************************************************************/
254 : /* ==================================================================== */
255 : /* PDS4DelimitedTable */
256 : /* ==================================================================== */
257 : /************************************************************************/
258 :
259 : class PDS4DelimitedTable CPL_NON_FINAL : public PDS4TableBaseLayer
260 : {
261 : friend class PDS4EditableSynchronizer<PDS4DelimitedTable>;
262 :
263 : protected:
264 : bool m_bCreation = false;
265 : char m_chFieldDelimiter = ',';
266 : bool m_bAddWKTColumnPending = false;
267 :
268 : struct Field
269 : {
270 : CPLString m_osDataType{};
271 : CPLString m_osUnit{};
272 : CPLString m_osDescription{};
273 : CPLString m_osSpecialConstantsXML{};
274 : CPLString m_osMissingConstant{}; // included in above potentially
275 : };
276 :
277 : std::vector<Field> m_aoFields{};
278 :
279 : OGRFeature *GetNextFeatureRaw();
280 : CPLString QuoteIfNeeded(const char *pszVal);
281 : void GenerateVRT();
282 :
283 : bool ReadFields(const CPLXMLNode *psParent,
284 : const CPLString &osSuffixFieldName);
285 :
286 : public:
287 : PDS4DelimitedTable(PDS4Dataset *poDS, const char *pszName,
288 : const char *pszFilename, bool bUpdate);
289 : ~PDS4DelimitedTable() override;
290 :
291 : void ResetReading() override;
292 : OGRFeature *GetNextFeature() override;
293 : bool TestCapability(const char *) const override;
294 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
295 : OGRErr CreateField(const OGRFieldDefn *poFieldIn, int) override;
296 :
297 : bool ReadTableDef(const CPLXMLNode *psTable);
298 :
299 : bool InitializeNewLayer(const OGRSpatialReference *poSRS,
300 : bool bForceGeographic, OGRwkbGeometryType eGType,
301 : const char *const *papszOptions);
302 :
303 : void RefreshFileAreaObservational(CPLXMLNode *psFAO) override;
304 : char **GetFileList() const override;
305 :
306 1 : PDS4DelimitedTable *NewLayer(PDS4Dataset *poDS, const char *pszName,
307 : const char *pszFilename)
308 : {
309 1 : return new PDS4DelimitedTable(poDS, pszName, pszFilename, true);
310 : }
311 : };
312 :
313 : /************************************************************************/
314 : /* ==================================================================== */
315 : /* PDS4EditableLayer */
316 : /* ==================================================================== */
317 : /************************************************************************/
318 :
319 148 : class PDS4EditableLayer final : public OGREditableLayer,
320 : public PDS4TableLayerInterface
321 : {
322 : PDS4TableBaseLayer *GetBaseLayer() const;
323 :
324 : public:
325 : explicit PDS4EditableLayer(
326 : std::unique_ptr<PDS4FixedWidthTable> poBaseLayer);
327 : explicit PDS4EditableLayer(std::unique_ptr<PDS4DelimitedTable> poBaseLayer);
328 : ~PDS4EditableLayer() override;
329 :
330 69 : void RefreshFileAreaObservational(CPLXMLNode *psFAO) override
331 : {
332 69 : GetBaseLayer()->RefreshFileAreaObservational(psFAO);
333 69 : }
334 :
335 69 : const char *GetFileName() const override
336 : {
337 69 : return GetBaseLayer()->GetFileName();
338 : }
339 :
340 72 : bool IsDirtyHeader() const override
341 : {
342 72 : return GetBaseLayer()->IsDirtyHeader();
343 : }
344 :
345 69 : int GetRawFieldCount() const override
346 : {
347 69 : return GetBaseLayer()->GetRawFieldCount();
348 : }
349 :
350 : void SetSpatialRef(OGRSpatialReference *poSRS) override;
351 :
352 2 : char **GetFileList() const override
353 : {
354 2 : return GetBaseLayer()->GetFileList();
355 : }
356 :
357 107 : GIntBig GetFeatureCount(int bForce) override
358 : {
359 107 : return OGREditableLayer::GetFeatureCount(bForce);
360 : }
361 :
362 122 : const char *GetName() const override
363 : {
364 122 : return GetBaseLayer()->GetName();
365 : }
366 :
367 101 : OGRwkbGeometryType GetGeomType() const override
368 : {
369 101 : return GetBaseLayer()->GetGeomType();
370 : }
371 : };
372 :
373 : /************************************************************************/
374 : /* PDS4Dataset */
375 : /************************************************************************/
376 :
377 : class PDS4Dataset final : public RawDataset
378 : {
379 : friend class PDS4RawRasterBand;
380 : friend class PDS4WrapperRasterBand;
381 :
382 : VSILFILE *m_fpImage = nullptr;
383 : vsi_l_offset m_nBaseOffset = 0;
384 : GDALDataset *m_poExternalDS = nullptr; // external dataset (GeoTIFF)
385 : OGRSpatialReference m_oSRS{};
386 : bool m_bGotTransform = false;
387 : GDALGeoTransform m_gt{};
388 : CPLString m_osXMLFilename{};
389 : CPLString m_osImageFilename{};
390 : CPLString m_osUnits{};
391 : bool m_bCreatedFromExistingBinaryFile = false;
392 :
393 : std::vector<std::unique_ptr<PDS4TableLayerInterface>> m_apoLayers{};
394 :
395 : // Write dedicated parameters
396 : bool m_bMustInitImageFile = false;
397 : bool m_bUseSrcLabel = true;
398 : bool m_bDirtyHeader = false;
399 : bool m_bCreateHeader = false;
400 : bool m_bStripFileAreaObservationalFromTemplate = false;
401 : bool m_bIsLSB = true;
402 : CPLString m_osHeaderParsingStandard{};
403 : CPLString m_osInterleave{};
404 : char **m_papszCreationOptions = nullptr;
405 : CPLString m_osXMLPDS4{};
406 :
407 : void CreateHeader(CPLXMLNode *psProduct, const char *pszCARTVersion);
408 : void WriteHeader();
409 : void WriteHeaderAppendCase();
410 : void WriteVectorLayers(CPLXMLNode *psProduct);
411 : void WriteArray(const CPLString &osPrefix, CPLXMLNode *psFAO,
412 : const char *pszLocalIdentifier,
413 : CPLXMLNode *psTemplateSpecialConstants);
414 : void WriteGeoreferencing(CPLXMLNode *psCart, const char *pszCARTVersion);
415 : void ReadGeoreferencing(CPLXMLNode *psProduct);
416 : bool InitImageFile();
417 :
418 : void SubstituteVariables(CPLXMLNode *psNode, char **papszDict);
419 :
420 : bool OpenTableCharacter(const char *pszFilename, const CPLXMLNode *psTable);
421 :
422 : bool OpenTableBinary(const char *pszFilename, const CPLXMLNode *psTable);
423 :
424 : bool OpenTableDelimited(const char *pszFilename, const CPLXMLNode *psTable);
425 :
426 : static std::unique_ptr<PDS4Dataset>
427 : CreateInternal(const char *pszFilename, GDALDataset *poSrcDS, int nXSize,
428 : int nYSize, int nBands, GDALDataType eType,
429 : const char *const *papszOptions);
430 :
431 : CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override;
432 :
433 : static std::unique_ptr<PDS4Dataset> OpenBrowse(GDALOpenInfo *,
434 : const CPLXMLNode *);
435 :
436 : CPL_DISALLOW_COPY_ASSIGN(PDS4Dataset)
437 :
438 : public:
439 : PDS4Dataset();
440 : ~PDS4Dataset() override;
441 :
442 : int CloseDependentDatasets() override;
443 :
444 : const OGRSpatialReference *GetSpatialRef() const override;
445 : CPLErr SetSpatialRef(const OGRSpatialReference *poSRS) override;
446 : CPLErr GetGeoTransform(GDALGeoTransform >) const override;
447 : CPLErr SetGeoTransform(const GDALGeoTransform >) override;
448 : char **GetFileList() override;
449 : CPLErr SetMetadata(CSLConstList papszMD,
450 : const char *pszDomain = "") override;
451 :
452 1136 : int GetLayerCount() const override
453 : {
454 1136 : return static_cast<int>(m_apoLayers.size());
455 : }
456 :
457 : using GDALDataset::GetLayer;
458 : const OGRLayer *GetLayer(int) const override;
459 :
460 : OGRLayer *ICreateLayer(const char *pszName,
461 : const OGRGeomFieldDefn *poGeomFieldDefn,
462 : CSLConstList papszOptions) override;
463 :
464 : bool TestCapability(const char *pszCap) const override;
465 :
466 : bool GetRawBinaryLayout(GDALDataset::RawBinaryLayout &) override;
467 :
468 : static std::unique_ptr<PDS4Dataset> OpenInternal(GDALOpenInfo *);
469 :
470 189 : static GDALDataset *Open(GDALOpenInfo *poOpenInfo)
471 : {
472 189 : return OpenInternal(poOpenInfo).release();
473 : }
474 :
475 : static GDALDataset *Create(const char *pszFilename, int nXSize, int nYSize,
476 : int nBands, GDALDataType eType,
477 : CSLConstList papszOptions);
478 : static GDALDataset *CreateCopy(const char *pszFilename,
479 : GDALDataset *poSrcDS, int bStrict,
480 : CSLConstList papszOptions,
481 : GDALProgressFunc pfnProgress,
482 : void *pProgressData);
483 : static CPLErr Delete(const char *pszName);
484 :
485 263 : const char *const *GetOpenOptions() const
486 : {
487 263 : return papszOpenOptions;
488 : }
489 :
490 338 : void MarkHeaderDirty()
491 : {
492 338 : m_bDirtyHeader = true;
493 338 : }
494 : };
495 :
496 : /************************************************************************/
497 : /* ==================================================================== */
498 : /* PDS4RawRasterBand */
499 : /* ==================================================================== */
500 : /************************************************************************/
501 :
502 : class PDS4RawRasterBand final : public RawRasterBand
503 : {
504 : friend class PDS4Dataset;
505 :
506 : bool m_bHasOffset{};
507 : bool m_bHasScale{};
508 : bool m_bHasNoData{};
509 : bool m_bHasNoDataInt64{};
510 : bool m_bHasNoDataUInt64{};
511 : double m_dfOffset{};
512 : double m_dfScale{};
513 : double m_dfNoData{};
514 : int64_t m_nNoDataInt64{};
515 : uint64_t m_nNoDataUInt64{};
516 :
517 : public:
518 : PDS4RawRasterBand(GDALDataset *l_poDS, int l_nBand, VSILFILE *l_fpRaw,
519 : vsi_l_offset l_nImgOffset, int l_nPixelOffset,
520 : int l_nLineOffset, GDALDataType l_eDataType,
521 : RawRasterBand::ByteOrder eByteOrderIn);
522 :
523 : CPLErr IWriteBlock(int, int, void *) override;
524 :
525 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
526 : GDALDataType, GSpacing nPixelSpace, GSpacing nLineSpace,
527 : GDALRasterIOExtraArg *psExtraArg) override;
528 :
529 : double GetOffset(int *pbSuccess = nullptr) override;
530 : double GetScale(int *pbSuccess = nullptr) override;
531 : CPLErr SetOffset(double dfNewOffset) override;
532 : CPLErr SetScale(double dfNewScale) override;
533 : double GetNoDataValue(int *pbSuccess = nullptr) override;
534 : CPLErr SetNoDataValue(double dfNewNoData) override;
535 : int64_t GetNoDataValueAsInt64(int *pbSuccess = nullptr) override;
536 : uint64_t GetNoDataValueAsUInt64(int *pbSuccess = nullptr) override;
537 : CPLErr SetNoDataValueAsInt64(int64_t nNoData) override;
538 : CPLErr SetNoDataValueAsUInt64(uint64_t nNoData) override;
539 :
540 125 : const char *GetUnitType() override
541 : {
542 125 : return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
543 : }
544 :
545 67 : CPLErr SetUnitType(const char *pszUnits) override
546 : {
547 67 : static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
548 67 : return CE_None;
549 : }
550 :
551 : void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
552 : };
553 :
554 : /************************************************************************/
555 : /* ==================================================================== */
556 : /* PDS4BrowseImageProxyRasterBand */
557 : /* */
558 : /* proxy for bands stored in browse images */
559 : /* ==================================================================== */
560 : /************************************************************************/
561 : class PDS4BrowseImageProxyRasterBand final : public GDALProxyRasterBand
562 : {
563 : friend class PDS4Dataset;
564 :
565 : GDALRasterBand *m_poBaseBand{};
566 :
567 : CPL_DISALLOW_COPY_ASSIGN(PDS4BrowseImageProxyRasterBand)
568 :
569 : protected:
570 : GDALRasterBand *RefUnderlyingRasterBand(bool /*bForceOpen*/) const override;
571 :
572 : public:
573 : explicit PDS4BrowseImageProxyRasterBand(GDALRasterBand *poBaseBandIn);
574 : };
575 :
576 : /************************************************************************/
577 : /* ==================================================================== */
578 : /* PDS4WrapperRasterBand */
579 : /* */
580 : /* proxy for bands stored in other formats. */
581 : /* ==================================================================== */
582 : /************************************************************************/
583 : class PDS4WrapperRasterBand final : public GDALProxyRasterBand
584 : {
585 : friend class PDS4Dataset;
586 :
587 : GDALRasterBand *m_poBaseBand{};
588 : bool m_bHasOffset{};
589 : bool m_bHasScale{};
590 : bool m_bHasNoData{};
591 : bool m_bHasNoDataInt64{};
592 : bool m_bHasNoDataUInt64{};
593 : double m_dfOffset{};
594 : double m_dfScale{1};
595 : double m_dfNoData{};
596 : int64_t m_nNoDataInt64{};
597 : uint64_t m_nNoDataUInt64{};
598 :
599 : CPL_DISALLOW_COPY_ASSIGN(PDS4WrapperRasterBand)
600 :
601 : protected:
602 : virtual GDALRasterBand *
603 161 : RefUnderlyingRasterBand(bool /*bForceOpen*/) const override
604 : {
605 161 : return m_poBaseBand;
606 : }
607 :
608 : public:
609 : explicit PDS4WrapperRasterBand(GDALRasterBand *poBaseBandIn);
610 :
611 : virtual CPLErr Fill(double dfRealValue,
612 : double dfImaginaryValue = 0) override;
613 : CPLErr IWriteBlock(int, int, void *) override;
614 :
615 : CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *, int, int,
616 : GDALDataType, GSpacing nPixelSpace, GSpacing nLineSpace,
617 : GDALRasterIOExtraArg *psExtraArg) override;
618 :
619 : double GetOffset(int *pbSuccess = nullptr) override;
620 : double GetScale(int *pbSuccess = nullptr) override;
621 : CPLErr SetOffset(double dfNewOffset) override;
622 : CPLErr SetScale(double dfNewScale) override;
623 : double GetNoDataValue(int *pbSuccess = nullptr) override;
624 : CPLErr SetNoDataValue(double dfNewNoData) override;
625 : int64_t GetNoDataValueAsInt64(int *pbSuccess = nullptr) override;
626 : uint64_t GetNoDataValueAsUInt64(int *pbSuccess = nullptr) override;
627 : CPLErr SetNoDataValueAsInt64(int64_t nNoData) override;
628 : CPLErr SetNoDataValueAsUInt64(uint64_t nNoData) override;
629 :
630 18 : const char *GetUnitType() override
631 : {
632 18 : return static_cast<PDS4Dataset *>(poDS)->m_osUnits.c_str();
633 : }
634 :
635 15 : CPLErr SetUnitType(const char *pszUnits) override
636 : {
637 15 : static_cast<PDS4Dataset *>(poDS)->m_osUnits = pszUnits;
638 15 : return CE_None;
639 : }
640 :
641 0 : int GetMaskFlags() override
642 : {
643 0 : return nMaskFlags;
644 : }
645 :
646 0 : GDALRasterBand *GetMaskBand() override
647 : {
648 0 : return poMask;
649 : }
650 :
651 : void SetMaskBand(std::unique_ptr<GDALRasterBand> poMaskBand);
652 : };
653 :
654 : /************************************************************************/
655 : /* ==================================================================== */
656 : /* PDS4MaskBand */
657 : /* ==================================================================== */
658 :
659 : class PDS4MaskBand final : public GDALRasterBand
660 : {
661 : GDALRasterBand *m_poBaseBand{};
662 : void *m_pBuffer{};
663 : std::vector<double> m_adfConstants{};
664 :
665 : CPL_DISALLOW_COPY_ASSIGN(PDS4MaskBand)
666 :
667 : public:
668 : PDS4MaskBand(GDALRasterBand *poBaseBand,
669 : const std::vector<double> &adfConstants);
670 : ~PDS4MaskBand() override;
671 :
672 : CPLErr IReadBlock(int, int, void *) override;
673 : };
|