Coverage Report

Created: 2025-07-23 09:13

/src/gdal/frmts/hfa/hfadictionary.cpp
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 *
3
 * Project:  Erdas Imagine (.img) Translator
4
 * Purpose:  Implementation of the HFADictionary class for managing the
5
 *           dictionary read from the HFA file.  Most work done by the
6
 *           HFAType, and HFAField classes.
7
 * Author:   Frank Warmerdam, warmerdam@pobox.com
8
 *
9
 ******************************************************************************
10
 * Copyright (c) 1999, Intergraph Corporation
11
 *
12
 * SPDX-License-Identifier: MIT
13
 ****************************************************************************/
14
15
#include "cpl_port.h"
16
#include "hfa_p.h"
17
18
#include <cstdio>
19
#include <cstring>
20
#include <string>
21
22
#include "cpl_conv.h"
23
#include "cpl_error.h"
24
#include "cpl_string.h"
25
#include "cpl_vsi.h"
26
27
static const char *const apszDefDefn[] = {
28
    "Edsc_Table",
29
    "{1:lnumrows,}Edsc_Table",
30
31
    "Edsc_Column",
32
    "{1:lnumRows,1:LcolumnDataPtr,1:e4:integer,real,complex,string,dataType,1:"
33
    "lmaxNumChars,}Edsc_Column",
34
35
    "Eprj_Size",
36
    "{1:dwidth,1:dheight,}Eprj_Size",
37
38
    "Eprj_Coordinate",
39
    "{1:dx,1:dy,}Eprj_Coordinate",
40
41
    "Eprj_MapInfo",
42
    "{0:pcproName,1:*oEprj_Coordinate,upperLeftCenter,1:*oEprj_Coordinate,"
43
    "lowerRightCenter,1:*oEprj_Size,pixelSize,0:pcunits,}Eprj_MapInfo",
44
45
    "Eimg_StatisticsParameters830",
46
    "{0:poEmif_String,LayerNames,1:*bExcludedValues,1:oEmif_String,AOIname,1:"
47
    "lSkipFactorX,1:lSkipFactorY,1:*oEdsc_BinFunction,BinFunction,}Eimg_"
48
    "StatisticsParameters830",
49
50
    "Esta_Statistics",
51
    "{1:dminimum,1:dmaximum,1:dmean,1:dmedian,1:dmode,1:dstddev,}Esta_"
52
    "Statistics",
53
54
    "Edsc_BinFunction",
55
    "{1:lnumBins,1:e4:direct,linear,logarithmic,explicit,binFunctionType,1:"
56
    "dminLimit,1:dmaxLimit,1:*bbinLimits,}Edsc_BinFunction",
57
58
    "Eimg_NonInitializedValue",
59
    "{1:*bvalueBD,}Eimg_NonInitializedValue",
60
61
    "Eprj_MapProjection842",
62
    "{1:x{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,"
63
    "MIFDictionary,0:pCMIFObject,}Emif_MIFObject,projection,1:x{0:pcstring,}"
64
    "Emif_String,title,}Eprj_MapProjection842",
65
66
    "Emif_MIFObject",
67
    "{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,"
68
    "MIFDictionary,0:pCMIFObject,}Emif_MIFObject",
69
70
    "Eprj_ProParameters",
71
    "{1:e2:EPRJ_INTERNAL,EPRJ_EXTERNAL,proType,1:lproNumber,0:pcproExeName,0:"
72
    "pcproName,1:lproZone,0:pdproParams,1:*oEprj_Spheroid,proSpheroid,}Eprj_"
73
    "ProParameters",
74
75
    "Eprj_Datum",
76
    "{0:pcdatumname,1:e3:EPRJ_DATUM_PARAMETRIC,EPRJ_DATUM_GRID,EPRJ_DATUM_"
77
    "REGRESSION,type,0:pdparams,0:pcgridname,}Eprj_Datum",
78
79
    "Eprj_Spheroid",
80
    "{0:pcsphereName,1:da,1:db,1:deSquared,1:dradius,}Eprj_Spheroid",
81
82
    nullptr,
83
    nullptr};
84
85
/************************************************************************/
86
/* ==================================================================== */
87
/*                             HFADictionary                            */
88
/* ==================================================================== */
89
/************************************************************************/
90
91
/************************************************************************/
92
/*                           HFADictionary()                            */
93
/************************************************************************/
94
95
HFADictionary::HFADictionary(const char *pszString)
96
15.1k
    : nTypes(0), nTypesMax(0), papoTypes(nullptr), osDictionaryText(pszString),
97
15.1k
      bDictionaryTextDirty(false)
98
15.1k
{
99
    // Read all the types.
100
    // TODO(schwehr): Refactor this approach to be more obvious.
101
635k
    while (pszString != nullptr && *pszString != '.')
102
620k
    {
103
620k
        HFAType *poNewType = new HFAType();
104
620k
        pszString = poNewType->Initialize(pszString);
105
106
620k
        if (pszString != nullptr)
107
608k
            AddType(poNewType);
108
11.8k
        else
109
11.8k
            delete poNewType;
110
620k
    }
111
112
    // Complete the definitions.
113
624k
    for (int i = 0; i < nTypes; i++)
114
608k
    {
115
608k
        papoTypes[i]->CompleteDefn(this);
116
608k
    }
117
15.1k
}
118
119
/************************************************************************/
120
/*                           ~HFADictionary()                           */
121
/************************************************************************/
122
123
HFADictionary::~HFADictionary()
124
125
15.1k
{
126
642k
    for (int i = 0; i < nTypes; i++)
127
627k
        delete papoTypes[i];
128
129
15.1k
    CPLFree(papoTypes);
130
15.1k
}
131
132
/************************************************************************/
133
/*                              AddType()                               */
134
/************************************************************************/
135
136
void HFADictionary::AddType(HFAType *poType)
137
138
627k
{
139
627k
    if (nTypes == nTypesMax
140
#ifdef DEBUG
141
        // To please Coverity.
142
        || papoTypes == nullptr
143
#endif
144
627k
    )
145
25.1k
    {
146
25.1k
        nTypesMax = nTypes * 2 + 10;
147
25.1k
        papoTypes = static_cast<HFAType **>(
148
25.1k
            CPLRealloc(papoTypes, sizeof(void *) * nTypesMax));
149
25.1k
    }
150
151
627k
    papoTypes[nTypes++] = poType;
152
627k
}
153
154
/************************************************************************/
155
/*                              FindType()                              */
156
/************************************************************************/
157
158
HFAType *HFADictionary::FindType(const char *pszName)
159
160
1.13M
{
161
864M
    for (int i = 0; i < nTypes; i++)
162
864M
    {
163
864M
        if (papoTypes[i]->pszTypeName != nullptr &&
164
864M
            strcmp(pszName, papoTypes[i]->pszTypeName) == 0)
165
963k
            return papoTypes[i];
166
864M
    }
167
168
    // Check if this is a type have other knowledge of.  If so, add
169
    // it to the dictionary now.  I'm not sure how some files end
170
    // up being distributed using types not in the dictionary.
171
2.36M
    for (int i = 0; apszDefDefn[i] != nullptr; i += 2)
172
2.22M
    {
173
2.22M
        if (strcmp(pszName, apszDefDefn[i]) == 0)
174
24.1k
        {
175
24.1k
            HFAType *poNewType = new HFAType();
176
177
24.1k
            poNewType->Initialize(apszDefDefn[i + 1]);
178
24.1k
            if (!poNewType->CompleteDefn(this))
179
5.21k
            {
180
5.21k
                delete poNewType;
181
5.21k
                return nullptr;
182
5.21k
            }
183
18.9k
            AddType(poNewType);
184
185
18.9k
            if (!osDictionaryText.empty())
186
18.9k
                osDictionaryText.erase(osDictionaryText.size() - 1, 1);
187
18.9k
            osDictionaryText += apszDefDefn[i + 1];
188
18.9k
            osDictionaryText += ",.";
189
190
18.9k
            bDictionaryTextDirty = true;
191
192
18.9k
            return poNewType;
193
24.1k
        }
194
2.22M
    }
195
196
143k
    return nullptr;
197
167k
}
198
199
/************************************************************************/
200
/*                            GetItemSize()                             */
201
/*                                                                      */
202
/*      Get the size of a basic (atomic) item.                          */
203
/************************************************************************/
204
205
int HFADictionary::GetItemSize(char chType)
206
207
5.56M
{
208
5.56M
    switch (chType)
209
5.56M
    {
210
24.0k
        case '1':
211
32.1k
        case '2':
212
33.9k
        case '4':
213
3.55M
        case 'c':
214
3.59M
        case 'C':
215
3.59M
            return 1;
216
217
121k
        case 'e':
218
144k
        case 's':
219
213k
        case 'S':
220
213k
            return 2;
221
222
23.1k
        case 't':
223
264k
        case 'l':
224
404k
        case 'L':
225
419k
        case 'f':
226
419k
            return 4;
227
228
264k
        case 'd':
229
287k
        case 'm':
230
287k
            return 8;
231
232
5.61k
        case 'M':
233
5.61k
            return 16;
234
235
870k
        case 'b':
236
870k
            return -1;
237
238
151k
        case 'o':
239
172k
        case 'x':
240
172k
            return 0;
241
242
0
        default:
243
0
            CPLAssert(false);
244
5.56M
    }
245
246
0
    return 0;
247
5.56M
}
248
249
/************************************************************************/
250
/*                                Dump()                                */
251
/************************************************************************/
252
253
void HFADictionary::Dump(FILE *fp)
254
255
0
{
256
0
    CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "\nHFADictionary:\n"));
257
258
0
    for (int i = 0; i < nTypes; i++)
259
0
    {
260
0
        papoTypes[i]->Dump(fp);
261
0
    }
262
0
}