Coverage Report

Created: 2025-11-15 08:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/frmts/hfa/hfa_p.h
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  Erdas Imagine (.img) Translator
4
 * Purpose:  Private class declarations for the HFA classes used to read
5
 *           Erdas Imagine (.img) files.  Public (C callable) declarations
6
 *           are in hfa.h.
7
 * Author:   Frank Warmerdam, warmerdam@pobox.com
8
 *
9
 ******************************************************************************
10
 * Copyright (c) 1999, Intergraph Corporation
11
 *
12
 * SPDX-License-Identifier: MIT
13
 ****************************************************************************/
14
15
#ifndef HFA_P_H_INCLUDED
16
#define HFA_P_H_INCLUDED
17
18
#include "cpl_port.h"
19
#include "hfa.h"
20
21
#include <cstdio>
22
#include <memory>
23
#include <vector>
24
#include <set>
25
26
#include "cpl_error.h"
27
#include "cpl_vsi.h"
28
#include "ogr_spatialref.h"
29
30
#ifdef CPL_LSB
31
#define HFAStandard(n, p)                                                      \
32
13.0M
    {                                                                          \
33
13.0M
    }
34
#else
35
void HFAStandard(int, void *);
36
#endif
37
38
#include "hfa.h"
39
40
class HFABand;
41
class HFADictionary;
42
class HFAEntry;
43
class HFASpillFile;
44
class HFAType;
45
46
/************************************************************************/
47
/*      Flag indicating read/write, or read-only access to data.        */
48
/************************************************************************/
49
typedef enum
50
{
51
    /*! Read only (no update) access */ HFA_ReadOnly = 0,
52
    /*! Read/write access. */ HFA_Update = 1
53
} HFAAccess;
54
55
/************************************************************************/
56
/*                              HFAInfo_t                               */
57
/*                                                                      */
58
/*      This is just a structure, and used hold info about the whole    */
59
/*      dataset within hfaopen.cpp                                      */
60
/************************************************************************/
61
struct hfainfo
62
{
63
    VSILFILE *fp;
64
65
    char *pszPath;
66
    char *pszFilename;     // Sans path.
67
    char *pszIGEFilename;  // Sans path.
68
69
    HFAAccess eAccess;
70
71
    GUInt32 nEndOfFile;
72
    GUInt32 nRootPos;
73
    GUInt32 nDictionaryPos;
74
75
    GInt16 nEntryHeaderLength;
76
    GInt32 nVersion;
77
78
    bool bTreeDirty;
79
    HFAEntry *poRoot;
80
81
    HFADictionary *poDictionary;
82
    char *pszDictionary;
83
84
    int nXSize;
85
    int nYSize;
86
87
    int nBands;
88
    HFABand **papoBand;
89
90
    void *pMapInfo;
91
    void *pDatum;
92
    void *pProParameters;
93
94
    struct hfainfo *psDependent;
95
};
96
97
typedef struct hfainfo HFAInfo_t;
98
99
GUInt32 HFAAllocateSpace(HFAInfo_t *, GUInt32);
100
CPLErr HFAParseBandInfo(HFAInfo_t *);
101
HFAInfo_t *HFAGetDependent(HFAInfo_t *, const char *);
102
HFAInfo_t *HFACreateDependent(HFAInfo_t *psBase);
103
bool HFACreateSpillStack(HFAInfo_t *, int nXSize, int nYSize, int nLayers,
104
                         int nBlockSize, EPTType eDataType,
105
                         GIntBig *pnValidFlagsOffset, GIntBig *pnDataOffset);
106
107
const char *const *GetHFAAuxMetaDataList();
108
109
double *HFAReadBFUniqueBins(HFAEntry *poBinFunc, int nPCTColors);
110
111
int CPL_DLL HFACreateLayer(HFAHandle psInfo, HFAEntry *poParent,
112
                           const char *pszLayerName, int bOverview,
113
                           int nBlockSize, int bCreateCompressed,
114
                           int bCreateLargeRaster, int bDependentLayer,
115
                           int nXSize, int nYSize, EPTType eDataType,
116
                           char **papszOptions,
117
118
                           // These are only related to external (large) files.
119
                           GIntBig nStackValidFlagsOffset,
120
                           GIntBig nStackDataOffset, int nStackCount,
121
                           int nStackIndex);
122
123
std::unique_ptr<OGRSpatialReference>
124
HFAPCSStructToOSR(const Eprj_Datum *psDatum, const Eprj_ProParameters *psPro,
125
                  const Eprj_MapInfo *psMapInfo, HFAEntry *poMapInformation);
126
127
const char *const *HFAGetDatumMap();
128
const char *const *HFAGetUnitMap();
129
130
/************************************************************************/
131
/*                               HFABand                                */
132
/************************************************************************/
133
134
class HFABand final
135
{
136
    int nBlocks;
137
138
    // Used for single-file modification.
139
    vsi_l_offset *panBlockStart;
140
    int *panBlockSize;
141
    int *panBlockFlag;
142
143
    // Used for spill-file modification.
144
    vsi_l_offset nBlockStart;
145
    vsi_l_offset nBlockSize;
146
    int nLayerStackCount;
147
    int nLayerStackIndex;
148
149
146k
#define BFLG_VALID 0x01
150
143k
#define BFLG_COMPRESSED 0x02
151
152
    int nPCTColors;
153
    double *apadfPCT[4];
154
    double *padfPCTBins;
155
156
    CPLErr LoadBlockInfo();
157
    CPLErr LoadExternalBlockInfo();
158
159
    void ReAllocBlock(int iBlock, int nSize);
160
    void NullBlock(void *);
161
162
    CPLString osOverName;
163
164
    CPL_DISALLOW_COPY_ASSIGN(HFABand)
165
166
  public:
167
    HFABand(HFAInfo_t *, HFAEntry *);
168
    ~HFABand();
169
170
    HFAInfo_t *psInfo;
171
172
    VSILFILE *fpExternal;
173
174
    EPTType eDataType;
175
    HFAEntry *poNode;
176
177
    int nBlockXSize;
178
    int nBlockYSize;
179
180
    int nWidth;
181
    int nHeight;
182
183
    int nBlocksPerRow;
184
    int nBlocksPerColumn;
185
186
    bool bNoDataSet;
187
    double dfNoData;
188
189
    bool bOverviewsPending;
190
    int nOverviews;
191
    HFABand **papoOverviews;
192
193
    CPLErr GetRasterBlock(int nXBlock, int nYBlock, void *pData, int nDataSize);
194
    CPLErr SetRasterBlock(int nXBlock, int nYBlock, void *pData);
195
196
    const char *GetBandName();
197
    void SetBandName(const char *pszName);
198
199
    CPLErr SetNoDataValue(double dfValue);
200
201
    CPLErr GetPCT(int *, double **, double **, double **, double **, double **);
202
    CPLErr SetPCT(int, const double *, const double *, const double *,
203
                  const double *);
204
205
    int CreateOverview(int nOverviewLevel, const char *pszResampling);
206
    CPLErr CleanOverviews();
207
208
    CPLErr LoadOverviews();
209
};
210
211
/************************************************************************/
212
/*                               HFAEntry                               */
213
/*                                                                      */
214
/*      Base class for all entry types.  Most entry types do not        */
215
/*      have a subclass, and are just handled generically with this     */
216
/*      class.                                                          */
217
/************************************************************************/
218
class HFAEntry final
219
{
220
    bool bDirty;
221
    GUInt32 nFilePos;
222
223
    HFAInfo_t *psHFA;
224
    HFAEntry *poParent;
225
    HFAEntry *poPrev;
226
227
    GUInt32 nNextPos;
228
    HFAEntry *poNext;
229
230
    GUInt32 nChildPos;
231
    HFAEntry *poChild;
232
233
    char szName[64];
234
    char szType[32];
235
236
    HFAType *poType;
237
238
    GUInt32 nDataPos;
239
    GUInt32 nDataSize;
240
    GByte *pabyData;
241
242
    void LoadData();
243
244
    bool GetFieldValue(const char *, char, void *, int *pnRemainingDataSize);
245
    CPLErr SetFieldValue(const char *, char, void *);
246
247
    bool bIsMIFObject;
248
249
    HFAEntry();
250
    HFAEntry(const char *pszDictionary, const char *pszTypeName,
251
             int nDataSizeIn, GByte *pabyDataIn);
252
    std::vector<HFAEntry *> FindChildren(const char *pszName,
253
                                         const char *pszType, int nRecLevel,
254
                                         int *pbErrorDetected);
255
256
    CPL_DISALLOW_COPY_ASSIGN(HFAEntry)
257
258
  public:
259
    static HFAEntry *New(HFAInfo_t *psHFA, GUInt32 nPos, HFAEntry *poParent,
260
                         HFAEntry *poPrev) CPL_WARN_UNUSED_RESULT;
261
262
    HFAEntry(HFAInfo_t *psHFA, const char *pszNodeName, const char *pszTypeName,
263
             HFAEntry *poParent);
264
265
    static HFAEntry *New(HFAInfo_t *psHFA, const char *pszNodeName,
266
                         const char *pszTypeName,
267
                         HFAEntry *poParent) CPL_WARN_UNUSED_RESULT;
268
269
    ~HFAEntry();
270
271
    static HFAEntry *BuildEntryFromMIFObject(HFAEntry *poContainer,
272
                                             const char *pszMIFObjectPath)
273
        CPL_WARN_UNUSED_RESULT;
274
275
    CPLErr RemoveAndDestroy();
276
277
    GUInt32 GetFilePos() const CPL_WARN_UNUSED_RESULT
278
367
    {
279
367
        return nFilePos;
280
367
    }
281
282
    const char *GetName() const CPL_WARN_UNUSED_RESULT
283
2.78M
    {
284
2.78M
        return szName;
285
2.78M
    }
286
287
    void SetName(const char *pszNodeName);
288
289
    const char *GetType() const CPL_WARN_UNUSED_RESULT
290
995k
    {
291
995k
        return szType;
292
995k
    }
293
294
    HFAType *GetTypeObject() CPL_WARN_UNUSED_RESULT;
295
296
    GByte *GetData() CPL_WARN_UNUSED_RESULT
297
18.7k
    {
298
18.7k
        LoadData();
299
18.7k
        return pabyData;
300
18.7k
    }
301
302
    GUInt32 GetDataPos() const CPL_WARN_UNUSED_RESULT
303
18.9k
    {
304
18.9k
        return nDataPos;
305
18.9k
    }
306
307
    GUInt32 GetDataSize() const CPL_WARN_UNUSED_RESULT
308
18.7k
    {
309
18.7k
        return nDataSize;
310
18.7k
    }
311
312
    HFAEntry *GetChild() CPL_WARN_UNUSED_RESULT;
313
    HFAEntry *GetNext() CPL_WARN_UNUSED_RESULT;
314
    HFAEntry *GetNamedChild(const char *) CPL_WARN_UNUSED_RESULT;
315
    std::vector<HFAEntry *>
316
    FindChildren(const char *pszName,
317
                 const char *pszType) CPL_WARN_UNUSED_RESULT;
318
319
    GInt32 GetIntField(const char *, CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
320
    double GetDoubleField(const char *,
321
                          CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
322
    const char *
323
    GetStringField(const char *, CPLErr * = nullptr,
324
                   int *pnRemainingDataSize = nullptr) CPL_WARN_UNUSED_RESULT;
325
    GIntBig GetBigIntField(const char *,
326
                           CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
327
    int GetFieldCount(const char *, CPLErr * = nullptr) CPL_WARN_UNUSED_RESULT;
328
329
    CPLErr SetIntField(const char *, int);
330
    CPLErr SetDoubleField(const char *, double);
331
    CPLErr SetStringField(const char *, const char *);
332
333
    void DumpFieldValues(FILE *, const char * = nullptr);
334
335
    void SetPosition();
336
    CPLErr FlushToDisk();
337
338
    void MarkDirty();
339
    GByte *MakeData(int nSize = 0);
340
};
341
342
/************************************************************************/
343
/*                               HFAField                               */
344
/*                                                                      */
345
/*      A field in a HFAType in the dictionary.                         */
346
/************************************************************************/
347
348
class HFAField final
349
{
350
  public:
351
    int nBytes;
352
353
    int nItemCount;
354
    // TODO(schwehr): Rename chPointer to something more meaningful.
355
    // It's not a pointer.
356
    char chPointer;   // '\0', '*' or 'p'
357
    char chItemType;  // 1|2|4|e|...
358
359
    char *pszItemObjectType;  // if chItemType == 'o'
360
    HFAType *poItemObjectType;
361
362
    char **papszEnumNames;  // Normally NULL if not an enum.
363
364
    char *pszFieldName;
365
366
    char szNumberString[36];  // Buffer used to return int as a string.
367
368
    HFAField();
369
    ~HFAField();
370
371
    const char *Initialize(const char *);
372
373
    bool CompleteDefn(HFADictionary *);
374
375
    void Dump(FILE *);
376
377
    bool ExtractInstValue(const char *pszField, int nIndexValue,
378
                          GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
379
                          char chReqType, void *pReqReturn,
380
                          int *pnRemainingDataSize = nullptr);
381
382
    CPLErr SetInstValue(const char *pszField, int nIndexValue, GByte *pabyData,
383
                        GUInt32 nDataOffset, int nDataSize, char chReqType,
384
                        void *pValue);
385
386
    void DumpInstValue(FILE *fpOut, GByte *pabyData, GUInt32 nDataOffset,
387
                       int nDataSize, const char *pszPrefix = nullptr);
388
389
    int GetInstBytes(GByte *, int, std::set<HFAField *> &oVisitedFields);
390
    int GetInstCount(GByte *pabyData, int nDataSize) const;
391
};
392
393
/************************************************************************/
394
/*                               HFAType                                */
395
/*                                                                      */
396
/*      A type in the dictionary.                                       */
397
/************************************************************************/
398
399
class HFAType
400
{
401
    bool bInCompleteDefn;
402
403
  public:
404
    int nBytes;
405
406
    std::vector<std::unique_ptr<HFAField>> apoFields;
407
408
    char *pszTypeName;
409
410
    HFAType();
411
    ~HFAType();
412
413
    const char *Initialize(const char *);
414
415
    bool CompleteDefn(HFADictionary *);
416
417
    void Dump(FILE *);
418
419
    int GetInstBytes(GByte *, int, std::set<HFAField *> &oVisitedFields) const;
420
    int GetInstCount(const char *pszField, GByte *pabyData, GUInt32 nDataOffset,
421
                     int nDataSize);
422
    bool ExtractInstValue(const char *pszField, GByte *pabyData,
423
                          GUInt32 nDataOffset, int nDataSize, char chReqType,
424
                          void *pReqReturn, int *pnRemainingDataSize);
425
    CPLErr SetInstValue(const char *pszField, GByte *pabyData,
426
                        GUInt32 nDataOffset, int nDataSize, char chReqType,
427
                        void *pValue);
428
    void DumpInstValue(FILE *fpOut, GByte *pabyData, GUInt32 nDataOffset,
429
                       int nDataSize, const char *pszPrefix = nullptr) const;
430
};
431
432
/************************************************************************/
433
/*                            HFADictionary                             */
434
/************************************************************************/
435
436
class HFADictionary
437
{
438
  public:
439
    explicit HFADictionary(const char *pszDict);
440
    ~HFADictionary();
441
442
    HFAType *FindType(const char *);
443
    void AddType(HFAType *);
444
445
    static int GetItemSize(char);
446
447
    void Dump(FILE *);
448
449
  private:
450
    int nTypes;
451
    int nTypesMax;
452
    HFAType **papoTypes;
453
454
    CPL_DISALLOW_COPY_ASSIGN(HFADictionary)
455
456
  public:
457
    // TODO(schwehr): Make these members private.
458
    CPLString osDictionaryText;
459
    bool bDictionaryTextDirty;
460
};
461
462
/************************************************************************/
463
/*                             HFACompress                              */
464
/*                                                                      */
465
/*      Class that given a block of memory compresses the contents      */
466
/*      using run length encoding (RLE) as used by Imagine.             */
467
/************************************************************************/
468
469
class HFACompress
470
{
471
  public:
472
    HFACompress(void *pData, GUInt32 nBlockSize, EPTType eDataType);
473
    ~HFACompress();
474
475
    // This is the method that does the work.
476
    bool compressBlock();
477
478
    // Static method to allow us to query whether HFA type supported.
479
    static bool QueryDataTypeSupported(EPTType eHFADataType);
480
481
    // Get methods - only valid after compressBlock has been called.
482
    GByte *getCounts() const
483
8
    {
484
8
        return m_pCounts;
485
8
    }
486
487
    GUInt32 getCountSize() const
488
4
    {
489
4
        return m_nSizeCounts;
490
4
    }
491
492
    GByte *getValues() const
493
8
    {
494
8
        return m_pValues;
495
8
    }
496
497
    GUInt32 getValueSize() const
498
4
    {
499
4
        return m_nSizeValues;
500
4
    }
501
502
    GUInt32 getMin() const
503
4
    {
504
4
        return m_nMin;
505
4
    }
506
507
    GUInt32 getNumRuns() const
508
4
    {
509
4
        return m_nNumRuns;
510
4
    }
511
512
    GByte getNumBits() const
513
4
    {
514
4
        return m_nNumBits;
515
4
    }
516
517
  private:
518
    static void makeCount(GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount);
519
    GUInt32 findMin(GByte *pNumBits);
520
    GUInt32 valueAsUInt32(GUInt32 index);
521
    void encodeValue(GUInt32 val, GUInt32 repeat);
522
523
    void *m_pData;
524
    GUInt32 m_nBlockSize;
525
    GUInt32 m_nBlockCount;
526
    EPTType m_eDataType;
527
    // The number of bits the datatype we are trying to compress takes.
528
    int m_nDataTypeNumBits;
529
530
    GByte *m_pCounts;
531
    GByte *m_pCurrCount;
532
    GUInt32 m_nSizeCounts;
533
534
    GByte *m_pValues;
535
    GByte *m_pCurrValues;
536
    GUInt32 m_nSizeValues;
537
538
    GUInt32 m_nMin;
539
    GUInt32 m_nNumRuns;
540
    // The number of bits needed to compress the range of values in the block.
541
    GByte m_nNumBits;
542
};
543
544
#endif /* ndef HFA_P_H_INCLUDED */