Line data Source code
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 948 : HFADictionary::HFADictionary(const char *pszString)
96 : : nTypes(0), nTypesMax(0), papoTypes(nullptr), osDictionaryText(pszString),
97 948 : bDictionaryTextDirty(false)
98 : {
99 : // Read all the types.
100 : // TODO(schwehr): Refactor this approach to be more obvious.
101 28338 : while (pszString != nullptr && *pszString != '.')
102 : {
103 27390 : HFAType *poNewType = new HFAType();
104 27390 : pszString = poNewType->Initialize(pszString);
105 :
106 27390 : if (pszString != nullptr)
107 27389 : AddType(poNewType);
108 : else
109 1 : delete poNewType;
110 : }
111 :
112 : // Complete the definitions.
113 28337 : for (int i = 0; i < nTypes; i++)
114 : {
115 27389 : papoTypes[i]->CompleteDefn(this);
116 : }
117 948 : }
118 :
119 : /************************************************************************/
120 : /* ~HFADictionary() */
121 : /************************************************************************/
122 :
123 948 : HFADictionary::~HFADictionary()
124 :
125 : {
126 28342 : for (int i = 0; i < nTypes; i++)
127 27394 : delete papoTypes[i];
128 :
129 948 : CPLFree(papoTypes);
130 948 : }
131 :
132 : /************************************************************************/
133 : /* AddType() */
134 : /************************************************************************/
135 :
136 27394 : void HFADictionary::AddType(HFAType *poType)
137 :
138 : {
139 27394 : if (nTypes == nTypesMax
140 : #ifdef DEBUG
141 : // To please Coverity.
142 24990 : || papoTypes == nullptr
143 : #endif
144 : )
145 : {
146 2404 : nTypesMax = nTypes * 2 + 10;
147 2404 : papoTypes = static_cast<HFAType **>(
148 2404 : CPLRealloc(papoTypes, sizeof(void *) * nTypesMax));
149 : }
150 :
151 27394 : papoTypes[nTypes++] = poType;
152 27394 : }
153 :
154 : /************************************************************************/
155 : /* FindType() */
156 : /************************************************************************/
157 :
158 19965 : HFAType *HFADictionary::FindType(const char *pszName)
159 :
160 : {
161 331142 : for (int i = 0; i < nTypes; i++)
162 : {
163 331134 : if (papoTypes[i]->pszTypeName != nullptr &&
164 331134 : strcmp(pszName, papoTypes[i]->pszTypeName) == 0)
165 19957 : return papoTypes[i];
166 : }
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 47 : for (int i = 0; apszDefDefn[i] != nullptr; i += 2)
172 : {
173 45 : if (strcmp(pszName, apszDefDefn[i]) == 0)
174 : {
175 6 : HFAType *poNewType = new HFAType();
176 :
177 6 : poNewType->Initialize(apszDefDefn[i + 1]);
178 6 : if (!poNewType->CompleteDefn(this))
179 : {
180 1 : delete poNewType;
181 1 : return nullptr;
182 : }
183 5 : AddType(poNewType);
184 :
185 5 : if (!osDictionaryText.empty())
186 5 : osDictionaryText.erase(osDictionaryText.size() - 1, 1);
187 5 : osDictionaryText += apszDefDefn[i + 1];
188 5 : osDictionaryText += ",.";
189 :
190 5 : bDictionaryTextDirty = true;
191 :
192 5 : return poNewType;
193 : }
194 : }
195 :
196 2 : return nullptr;
197 : }
198 :
199 : /************************************************************************/
200 : /* GetItemSize() */
201 : /* */
202 : /* Get the size of a basic (atomic) item. */
203 : /************************************************************************/
204 :
205 152633 : int HFADictionary::GetItemSize(char chType)
206 :
207 : {
208 152633 : switch (chType)
209 : {
210 71499 : case '1':
211 : case '2':
212 : case '4':
213 : case 'c':
214 : case 'C':
215 71499 : return 1;
216 :
217 15604 : case 'e':
218 : case 's':
219 : case 'S':
220 15604 : return 2;
221 :
222 41996 : case 't':
223 : case 'l':
224 : case 'L':
225 : case 'f':
226 41996 : return 4;
227 :
228 18899 : case 'd':
229 : case 'm':
230 18899 : return 8;
231 :
232 0 : case 'M':
233 0 : return 16;
234 :
235 4632 : case 'b':
236 4632 : return -1;
237 :
238 3 : case 'o':
239 : case 'x':
240 3 : return 0;
241 :
242 0 : default:
243 0 : CPLAssert(false);
244 : }
245 :
246 : return 0;
247 : }
248 :
249 : /************************************************************************/
250 : /* Dump() */
251 : /************************************************************************/
252 :
253 0 : void HFADictionary::Dump(FILE *fp)
254 :
255 : {
256 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "\nHFADictionary:\n"));
257 :
258 0 : for (int i = 0; i < nTypes; i++)
259 : {
260 0 : papoTypes[i]->Dump(fp);
261 : }
262 0 : }
|