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 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_port.h"
32 : #include "hfa_p.h"
33 :
34 : #include <cstdio>
35 : #include <cstring>
36 : #include <string>
37 :
38 : #include "cpl_conv.h"
39 : #include "cpl_error.h"
40 : #include "cpl_string.h"
41 : #include "cpl_vsi.h"
42 :
43 : static const char *const apszDefDefn[] = {
44 : "Edsc_Table",
45 : "{1:lnumrows,}Edsc_Table",
46 :
47 : "Edsc_Column",
48 : "{1:lnumRows,1:LcolumnDataPtr,1:e4:integer,real,complex,string,dataType,1:"
49 : "lmaxNumChars,}Edsc_Column",
50 :
51 : "Eprj_Size",
52 : "{1:dwidth,1:dheight,}Eprj_Size",
53 :
54 : "Eprj_Coordinate",
55 : "{1:dx,1:dy,}Eprj_Coordinate",
56 :
57 : "Eprj_MapInfo",
58 : "{0:pcproName,1:*oEprj_Coordinate,upperLeftCenter,1:*oEprj_Coordinate,"
59 : "lowerRightCenter,1:*oEprj_Size,pixelSize,0:pcunits,}Eprj_MapInfo",
60 :
61 : "Eimg_StatisticsParameters830",
62 : "{0:poEmif_String,LayerNames,1:*bExcludedValues,1:oEmif_String,AOIname,1:"
63 : "lSkipFactorX,1:lSkipFactorY,1:*oEdsc_BinFunction,BinFunction,}Eimg_"
64 : "StatisticsParameters830",
65 :
66 : "Esta_Statistics",
67 : "{1:dminimum,1:dmaximum,1:dmean,1:dmedian,1:dmode,1:dstddev,}Esta_"
68 : "Statistics",
69 :
70 : "Edsc_BinFunction",
71 : "{1:lnumBins,1:e4:direct,linear,logarithmic,explicit,binFunctionType,1:"
72 : "dminLimit,1:dmaxLimit,1:*bbinLimits,}Edsc_BinFunction",
73 :
74 : "Eimg_NonInitializedValue",
75 : "{1:*bvalueBD,}Eimg_NonInitializedValue",
76 :
77 : "Eprj_MapProjection842",
78 : "{1:x{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,"
79 : "MIFDictionary,0:pCMIFObject,}Emif_MIFObject,projection,1:x{0:pcstring,}"
80 : "Emif_String,title,}Eprj_MapProjection842",
81 :
82 : "Emif_MIFObject",
83 : "{1:x{0:pcstring,}Emif_String,type,1:x{0:pcstring,}Emif_String,"
84 : "MIFDictionary,0:pCMIFObject,}Emif_MIFObject",
85 :
86 : "Eprj_ProParameters",
87 : "{1:e2:EPRJ_INTERNAL,EPRJ_EXTERNAL,proType,1:lproNumber,0:pcproExeName,0:"
88 : "pcproName,1:lproZone,0:pdproParams,1:*oEprj_Spheroid,proSpheroid,}Eprj_"
89 : "ProParameters",
90 :
91 : "Eprj_Datum",
92 : "{0:pcdatumname,1:e3:EPRJ_DATUM_PARAMETRIC,EPRJ_DATUM_GRID,EPRJ_DATUM_"
93 : "REGRESSION,type,0:pdparams,0:pcgridname,}Eprj_Datum",
94 :
95 : "Eprj_Spheroid",
96 : "{0:pcsphereName,1:da,1:db,1:deSquared,1:dradius,}Eprj_Spheroid",
97 :
98 : nullptr,
99 : nullptr};
100 :
101 : /************************************************************************/
102 : /* ==================================================================== */
103 : /* HFADictionary */
104 : /* ==================================================================== */
105 : /************************************************************************/
106 :
107 : /************************************************************************/
108 : /* HFADictionary() */
109 : /************************************************************************/
110 :
111 946 : HFADictionary::HFADictionary(const char *pszString)
112 : : nTypes(0), nTypesMax(0), papoTypes(nullptr), osDictionaryText(pszString),
113 946 : bDictionaryTextDirty(false)
114 : {
115 : // Read all the types.
116 : // TODO(schwehr): Refactor this approach to be more obvious.
117 28301 : while (pszString != nullptr && *pszString != '.')
118 : {
119 27355 : HFAType *poNewType = new HFAType();
120 27355 : pszString = poNewType->Initialize(pszString);
121 :
122 27355 : if (pszString != nullptr)
123 27354 : AddType(poNewType);
124 : else
125 1 : delete poNewType;
126 : }
127 :
128 : // Complete the definitions.
129 28300 : for (int i = 0; i < nTypes; i++)
130 : {
131 27354 : papoTypes[i]->CompleteDefn(this);
132 : }
133 946 : }
134 :
135 : /************************************************************************/
136 : /* ~HFADictionary() */
137 : /************************************************************************/
138 :
139 946 : HFADictionary::~HFADictionary()
140 :
141 : {
142 28305 : for (int i = 0; i < nTypes; i++)
143 27359 : delete papoTypes[i];
144 :
145 946 : CPLFree(papoTypes);
146 946 : }
147 :
148 : /************************************************************************/
149 : /* AddType() */
150 : /************************************************************************/
151 :
152 27359 : void HFADictionary::AddType(HFAType *poType)
153 :
154 : {
155 27359 : if (nTypes == nTypesMax
156 : #ifdef DEBUG
157 : // To please Coverity.
158 24959 : || papoTypes == nullptr
159 : #endif
160 : )
161 : {
162 2400 : nTypesMax = nTypes * 2 + 10;
163 2400 : papoTypes = static_cast<HFAType **>(
164 2400 : CPLRealloc(papoTypes, sizeof(void *) * nTypesMax));
165 : }
166 :
167 27359 : papoTypes[nTypes++] = poType;
168 27359 : }
169 :
170 : /************************************************************************/
171 : /* FindType() */
172 : /************************************************************************/
173 :
174 19983 : HFAType *HFADictionary::FindType(const char *pszName)
175 :
176 : {
177 332320 : for (int i = 0; i < nTypes; i++)
178 : {
179 332312 : if (papoTypes[i]->pszTypeName != nullptr &&
180 332312 : strcmp(pszName, papoTypes[i]->pszTypeName) == 0)
181 19975 : return papoTypes[i];
182 : }
183 :
184 : // Check if this is a type have other knowledge of. If so, add
185 : // it to the dictionary now. I'm not sure how some files end
186 : // up being distributed using types not in the dictionary.
187 47 : for (int i = 0; apszDefDefn[i] != nullptr; i += 2)
188 : {
189 45 : if (strcmp(pszName, apszDefDefn[i]) == 0)
190 : {
191 6 : HFAType *poNewType = new HFAType();
192 :
193 6 : poNewType->Initialize(apszDefDefn[i + 1]);
194 6 : if (!poNewType->CompleteDefn(this))
195 : {
196 1 : delete poNewType;
197 1 : return nullptr;
198 : }
199 5 : AddType(poNewType);
200 :
201 5 : if (!osDictionaryText.empty())
202 5 : osDictionaryText.erase(osDictionaryText.size() - 1, 1);
203 5 : osDictionaryText += apszDefDefn[i + 1];
204 5 : osDictionaryText += ",.";
205 :
206 5 : bDictionaryTextDirty = true;
207 :
208 5 : return poNewType;
209 : }
210 : }
211 :
212 2 : return nullptr;
213 : }
214 :
215 : /************************************************************************/
216 : /* GetItemSize() */
217 : /* */
218 : /* Get the size of a basic (atomic) item. */
219 : /************************************************************************/
220 :
221 152465 : int HFADictionary::GetItemSize(char chType)
222 :
223 : {
224 152465 : switch (chType)
225 : {
226 71419 : case '1':
227 : case '2':
228 : case '4':
229 : case 'c':
230 : case 'C':
231 71419 : return 1;
232 :
233 15588 : case 'e':
234 : case 's':
235 : case 'S':
236 15588 : return 2;
237 :
238 41939 : case 't':
239 : case 'l':
240 : case 'L':
241 : case 'f':
242 41939 : return 4;
243 :
244 18889 : case 'd':
245 : case 'm':
246 18889 : return 8;
247 :
248 0 : case 'M':
249 0 : return 16;
250 :
251 4627 : case 'b':
252 4627 : return -1;
253 :
254 3 : case 'o':
255 : case 'x':
256 3 : return 0;
257 :
258 0 : default:
259 0 : CPLAssert(false);
260 : }
261 :
262 : return 0;
263 : }
264 :
265 : /************************************************************************/
266 : /* Dump() */
267 : /************************************************************************/
268 :
269 0 : void HFADictionary::Dump(FILE *fp)
270 :
271 : {
272 0 : CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "\nHFADictionary:\n"));
273 :
274 0 : for (int i = 0; i < nTypes; i++)
275 : {
276 0 : papoTypes[i]->Dump(fp);
277 : }
278 0 : }
|