1 : /******************************************************************************
2 : * $Id: hfafield.cpp 18895 2010-02-23 19:30:01Z warmerdam $
3 : *
4 : * Project: Erdas Imagine (.img) Translator
5 : * Purpose: Implementation of the HFAField class for managing information
6 : * about one field in a HFA dictionary type. Managed by HFAType.
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 "hfa_p.h"
32 :
33 : CPL_CVSID("$Id: hfafield.cpp 18895 2010-02-23 19:30:01Z warmerdam $");
34 :
35 : #define MAX_ENTRY_REPORT 16
36 :
37 : /************************************************************************/
38 : /* ==================================================================== */
39 : /* HFAField */
40 : /* ==================================================================== */
41 : /************************************************************************/
42 :
43 : /************************************************************************/
44 : /* HFAField() */
45 : /************************************************************************/
46 :
47 58736 : HFAField::HFAField()
48 :
49 : {
50 58736 : nBytes = 0;
51 :
52 58736 : nItemCount = 0;
53 58736 : chPointer = '\0';
54 58736 : chItemType = '\0';
55 :
56 58736 : pszItemObjectType = NULL;
57 58736 : poItemObjectType = NULL;
58 :
59 58736 : papszEnumNames = NULL;
60 :
61 58736 : pszFieldName = NULL;
62 58736 : }
63 :
64 : /************************************************************************/
65 : /* ~HFAField() */
66 : /************************************************************************/
67 :
68 58736 : HFAField::~HFAField()
69 :
70 : {
71 58736 : CPLFree( pszItemObjectType );
72 58736 : CSLDestroy( papszEnumNames );
73 58736 : CPLFree( pszFieldName );
74 58736 : }
75 :
76 : /************************************************************************/
77 : /* Initialize() */
78 : /************************************************************************/
79 :
80 58736 : const char *HFAField::Initialize( const char * pszInput )
81 :
82 : {
83 : int i;
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Read the number. */
87 : /* -------------------------------------------------------------------- */
88 58736 : nItemCount = atoi(pszInput);
89 :
90 177474 : while( *pszInput != '\0' && *pszInput != ':' )
91 60002 : pszInput++;
92 :
93 58736 : if( *pszInput == '\0' )
94 0 : return NULL;
95 :
96 58736 : pszInput++;
97 :
98 : /* -------------------------------------------------------------------- */
99 : /* Is this a pointer? */
100 : /* -------------------------------------------------------------------- */
101 58736 : if( *pszInput == 'p' || *pszInput == '*' )
102 13493 : chPointer = *(pszInput++);
103 :
104 : /* -------------------------------------------------------------------- */
105 : /* Get the general type */
106 : /* -------------------------------------------------------------------- */
107 58736 : if( *pszInput == '\0' )
108 0 : return NULL;
109 :
110 58736 : chItemType = *(pszInput++);
111 :
112 58736 : if ( strchr( "124cCesStlLfdmMbox", chItemType) == NULL )
113 : {
114 : CPLError(CE_Failure, CPLE_AppDefined,
115 0 : "Unrecognized item type : %c", chItemType);
116 0 : return NULL;
117 : }
118 :
119 : /* -------------------------------------------------------------------- */
120 : /* If this is an object, we extract the type of the object. */
121 : /* -------------------------------------------------------------------- */
122 58736 : if( chItemType == 'o' )
123 : {
124 7074 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
125 7074 : if (pszInput[i] == '\0')
126 0 : return NULL;
127 :
128 7074 : pszItemObjectType = (char *) CPLMalloc(i+1);
129 7074 : strncpy( pszItemObjectType, pszInput, i );
130 7074 : pszItemObjectType[i] = '\0';
131 :
132 7074 : pszInput += i+1;
133 : }
134 :
135 : /* -------------------------------------------------------------------- */
136 : /* If this is an inline object, we need to skip past the */
137 : /* definition, and then extract the object class name. */
138 : /* */
139 : /* We ignore the actual definition, so if the object type isn't */
140 : /* already defined, things will not work properly. See the */
141 : /* file lceugr250_00_pct.aux for an example of inline defs. */
142 : /* -------------------------------------------------------------------- */
143 58736 : if( chItemType == 'x' && *pszInput == '{' )
144 : {
145 1615 : int nBraceDepth = 1;
146 1615 : pszInput++;
147 :
148 : // Skip past the definition.
149 54278 : while( nBraceDepth > 0 && *pszInput != '\0' )
150 : {
151 51048 : if( *pszInput == '{' )
152 807 : nBraceDepth++;
153 50241 : else if( *pszInput == '}' )
154 2422 : nBraceDepth--;
155 :
156 51048 : pszInput++;
157 : }
158 1615 : if (*pszInput == '\0')
159 0 : return NULL;
160 :
161 1615 : chItemType = 'o';
162 :
163 : // find the comma terminating the type name.
164 1615 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
165 1615 : if (pszInput[i] == '\0')
166 0 : return NULL;
167 :
168 1615 : pszItemObjectType = (char *) CPLMalloc(i+1);
169 1615 : strncpy( pszItemObjectType, pszInput, i );
170 1615 : pszItemObjectType[i] = '\0';
171 :
172 1615 : pszInput += i+1;
173 : }
174 :
175 : /* -------------------------------------------------------------------- */
176 : /* If this is an enumeration we have to extract all the */
177 : /* enumeration values. */
178 : /* -------------------------------------------------------------------- */
179 58736 : if( chItemType == 'e' )
180 : {
181 7903 : int nEnumCount = atoi(pszInput);
182 : int iEnum;
183 :
184 7903 : pszInput = strchr(pszInput,':');
185 7903 : if( pszInput == NULL )
186 0 : return NULL;
187 :
188 7903 : pszInput++;
189 :
190 7903 : papszEnumNames = (char **) CPLCalloc(sizeof(char *), nEnumCount+1);
191 :
192 44009 : for( iEnum = 0; iEnum < nEnumCount; iEnum++ )
193 : {
194 : char *pszToken;
195 :
196 36106 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
197 :
198 36106 : if( pszInput[i] != ',' )
199 0 : return NULL;
200 :
201 36106 : pszToken = (char *) CPLMalloc(i+1);
202 36106 : strncpy( pszToken, pszInput, i );
203 36106 : pszToken[i] = '\0';
204 :
205 36106 : papszEnumNames[iEnum] = pszToken;
206 :
207 36106 : pszInput += i+1;
208 : }
209 : }
210 :
211 : /* -------------------------------------------------------------------- */
212 : /* Extract the field name. */
213 : /* -------------------------------------------------------------------- */
214 58736 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
215 58736 : if (pszInput[i] == '\0')
216 0 : return NULL;
217 :
218 58736 : pszFieldName = (char *) CPLMalloc(i+1);
219 58736 : strncpy( pszFieldName, pszInput, i );
220 58736 : pszFieldName[i] = '\0';
221 :
222 58736 : pszInput += i+1;
223 :
224 58736 : return( pszInput );
225 : }
226 :
227 : /************************************************************************/
228 : /* CompleteDefn() */
229 : /* */
230 : /* Establish size, and pointers to component types. */
231 : /************************************************************************/
232 :
233 58736 : void HFAField::CompleteDefn( HFADictionary * poDict )
234 :
235 : {
236 : /* -------------------------------------------------------------------- */
237 : /* Get a reference to the type object if we have a type name */
238 : /* for this field (not a built in). */
239 : /* -------------------------------------------------------------------- */
240 58736 : if( pszItemObjectType != NULL )
241 8689 : poItemObjectType = poDict->FindType( pszItemObjectType );
242 :
243 : /* -------------------------------------------------------------------- */
244 : /* Figure out the size. */
245 : /* -------------------------------------------------------------------- */
246 58736 : if( chPointer == 'p' )
247 : {
248 9343 : nBytes = -1; /* we can't know the instance size */
249 : }
250 49393 : else if( poItemObjectType != NULL )
251 : {
252 6617 : poItemObjectType->CompleteDefn( poDict );
253 6617 : if( poItemObjectType->nBytes == -1 )
254 5381 : nBytes = -1;
255 : else
256 1236 : nBytes = poItemObjectType->nBytes * nItemCount;
257 :
258 6617 : if( chPointer == '*' && nBytes != -1 )
259 1236 : nBytes += 8; /* count, and offset */
260 : }
261 : else
262 : {
263 42776 : nBytes = poDict->GetItemSize( chItemType ) * nItemCount;
264 : }
265 58736 : }
266 :
267 : /************************************************************************/
268 : /* Dump() */
269 : /************************************************************************/
270 :
271 0 : void HFAField::Dump( FILE * fp )
272 :
273 : {
274 : const char *pszTypeName;
275 :
276 0 : switch( chItemType )
277 : {
278 : case '1':
279 0 : pszTypeName = "U1";
280 0 : break;
281 :
282 : case '2':
283 0 : pszTypeName = "U2";
284 0 : break;
285 :
286 : case '4':
287 0 : pszTypeName = "U4";
288 0 : break;
289 :
290 : case 'c':
291 0 : pszTypeName = "UCHAR";
292 0 : break;
293 :
294 : case 'C':
295 0 : pszTypeName = "CHAR";
296 0 : break;
297 :
298 : case 'e':
299 0 : pszTypeName = "ENUM";
300 0 : break;
301 :
302 : case 's':
303 0 : pszTypeName = "USHORT";
304 0 : break;
305 :
306 : case 'S':
307 0 : pszTypeName = "SHORT";
308 0 : break;
309 :
310 : case 't':
311 0 : pszTypeName = "TIME";
312 0 : break;
313 :
314 : case 'l':
315 0 : pszTypeName = "ULONG";
316 0 : break;
317 :
318 : case 'L':
319 0 : pszTypeName = "LONG";
320 0 : break;
321 :
322 : case 'f':
323 0 : pszTypeName = "FLOAT";
324 0 : break;
325 :
326 : case 'd':
327 0 : pszTypeName = "DOUBLE";
328 0 : break;
329 :
330 : case 'm':
331 0 : pszTypeName = "COMPLEX";
332 0 : break;
333 :
334 : case 'M':
335 0 : pszTypeName = "DCOMPLEX";
336 0 : break;
337 :
338 : case 'b':
339 0 : pszTypeName = "BASEDATA";
340 0 : break;
341 :
342 : case 'o':
343 0 : pszTypeName = pszItemObjectType;
344 0 : break;
345 :
346 : case 'x':
347 0 : pszTypeName = "InlineType";
348 0 : break;
349 :
350 : default:
351 0 : CPLAssert( FALSE );
352 0 : pszTypeName = "Unknown";
353 : }
354 :
355 : VSIFPrintf( fp, " %-19s %c %s[%d];\n",
356 : pszTypeName,
357 : chPointer ? chPointer : ' ',
358 0 : pszFieldName, nItemCount );
359 :
360 0 : if( papszEnumNames != NULL )
361 : {
362 : int i;
363 :
364 0 : for( i = 0; papszEnumNames[i] != NULL; i++ )
365 : {
366 : VSIFPrintf( fp, " %s=%d\n",
367 0 : papszEnumNames[i], i );
368 : }
369 : }
370 0 : }
371 :
372 : /************************************************************************/
373 : /* SetInstValue() */
374 : /************************************************************************/
375 :
376 : CPLErr
377 : HFAField::SetInstValue( const char * pszField, int nIndexValue,
378 : GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
379 8841 : char chReqType, void *pValue )
380 :
381 : {
382 : /* -------------------------------------------------------------------- */
383 : /* If this field contains a pointer, then we will adjust the */
384 : /* data offset relative to it. */
385 : /* -------------------------------------------------------------------- */
386 8841 : if( chPointer != '\0' )
387 : {
388 : GUInt32 nCount;
389 : GUInt32 nOffset;
390 :
391 : /* set the count for fixed sized arrays */
392 4215 : if( nBytes > -1 )
393 624 : nCount = nItemCount;
394 :
395 : // The count returned for BASEDATA's are the contents,
396 : // but here we really want to mark it as one BASEDATA instance
397 : // (see #2144)
398 4215 : if( chItemType == 'b' )
399 40 : nCount = 1;
400 :
401 : /* Set the size from string length */
402 5142 : else if( chReqType == 's' && (chItemType == 'c' || chItemType == 'C'))
403 : {
404 967 : if( pValue == NULL )
405 161 : nCount = 0;
406 : else
407 806 : nCount = strlen((char *) pValue) + 1;
408 : }
409 :
410 : /* set size based on index ... assumes in-order setting of array */
411 : else
412 3208 : nCount = nIndexValue+1;
413 :
414 4215 : if( (int) nCount + 8 > nDataSize )
415 : {
416 : CPLError( CE_Failure, CPLE_AppDefined,
417 : "Attempt to extend field %s in node past end of data,\n"
418 : "not currently supported.",
419 0 : pszField );
420 0 : return CE_Failure;
421 : }
422 :
423 : // we will update the object count iff we are writing beyond the end
424 4215 : memcpy( &nOffset, pabyData, 4 );
425 : HFAStandard( 4, &nOffset );
426 4215 : if( nOffset < nCount )
427 : {
428 3212 : nOffset = nCount;
429 : HFAStandard( 4, &nOffset );
430 3212 : memcpy( pabyData, &nOffset, 4 );
431 : }
432 :
433 4215 : if( pValue == NULL )
434 161 : nOffset = 0;
435 : else
436 4054 : nOffset = nDataOffset + 8;
437 : HFAStandard( 4, &nOffset );
438 4215 : memcpy( pabyData+4, &nOffset, 4 );
439 :
440 4215 : pabyData += 8;
441 :
442 4215 : nDataOffset += 8;
443 4215 : nDataSize -= 8;
444 : }
445 :
446 : /* -------------------------------------------------------------------- */
447 : /* pointers to char or uchar arrays requested as strings are */
448 : /* handled as a special case. */
449 : /* -------------------------------------------------------------------- */
450 8841 : if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' )
451 : {
452 : int nBytesToCopy;
453 :
454 967 : if( nBytes == -1 )
455 : {
456 967 : if( pValue == NULL )
457 161 : nBytesToCopy = 0;
458 : else
459 806 : nBytesToCopy = strlen((char *) pValue) + 1;
460 : }
461 : else
462 0 : nBytesToCopy = nBytes;
463 :
464 967 : if( nBytesToCopy > nDataSize )
465 : {
466 : CPLError( CE_Failure, CPLE_AppDefined,
467 : "Attempt to extend field %s in node past end of data,\n"
468 : "not currently supported.",
469 0 : pszField );
470 0 : return CE_Failure;
471 : }
472 :
473 967 : memset( pabyData, 0, nBytesToCopy );
474 :
475 967 : if( pValue != NULL )
476 806 : strncpy( (char *) pabyData, (char *) pValue, nBytesToCopy );
477 :
478 967 : return CE_None;
479 : }
480 :
481 : /* -------------------------------------------------------------------- */
482 : /* Translate the passed type into different representations. */
483 : /* -------------------------------------------------------------------- */
484 : int nIntValue;
485 : double dfDoubleValue;
486 :
487 7874 : if( chReqType == 's' )
488 : {
489 1372 : nIntValue = atoi((char *) pValue);
490 1372 : dfDoubleValue = atof((char *) pValue);
491 : }
492 6502 : else if( chReqType == 'd' )
493 : {
494 4075 : dfDoubleValue = *((double *) pValue);
495 4075 : nIntValue = (int) dfDoubleValue;
496 : }
497 2427 : else if( chReqType == 'i' )
498 : {
499 2427 : dfDoubleValue = *((int *) pValue);
500 2427 : nIntValue = *((int *) pValue);
501 : }
502 0 : else if( chReqType == 'p' )
503 : {
504 : CPLError( CE_Failure, CPLE_NotSupported,
505 0 : "HFAField::SetInstValue() not supported yet for pointer values." );
506 :
507 0 : return CE_Failure;
508 : }
509 : else
510 : {
511 0 : CPLAssert( FALSE );
512 0 : return CE_Failure;
513 : }
514 :
515 : /* -------------------------------------------------------------------- */
516 : /* Handle by type. */
517 : /* -------------------------------------------------------------------- */
518 7874 : switch( chItemType )
519 : {
520 : case 'c':
521 : case 'C':
522 0 : if( nIndexValue + 1 > nDataSize )
523 : {
524 : CPLError( CE_Failure, CPLE_AppDefined,
525 : "Attempt to extend field %s in node past end of data,\n"
526 : "not currently supported.",
527 0 : pszField );
528 0 : return CE_Failure;
529 : }
530 :
531 0 : if( chReqType == 's' )
532 0 : pabyData[nIndexValue] = ((char *) pValue)[0];
533 : else
534 0 : pabyData[nIndexValue] = (char) nIntValue;
535 0 : break;
536 :
537 : case 'e':
538 : case 's':
539 : {
540 1038 : if( chItemType == 'e' && chReqType == 's' )
541 : {
542 678 : nIntValue = CSLFindString( papszEnumNames, (char *) pValue );
543 678 : if( nIntValue == -1 )
544 : {
545 : CPLError( CE_Failure, CPLE_AppDefined,
546 : "Attempt to set enumerated field with unknown"
547 : " value `%s'.",
548 0 : (char *) pValue );
549 0 : return CE_Failure;
550 : }
551 : }
552 :
553 1038 : unsigned short nNumber = (unsigned short) nIntValue;
554 :
555 1038 : if( nIndexValue*2 + 2 > nDataSize )
556 : {
557 : CPLError( CE_Failure, CPLE_AppDefined,
558 : "Attempt to extend field %s in node past end of data,\n"
559 : "not currently supported.",
560 0 : pszField );
561 0 : return CE_Failure;
562 : }
563 :
564 : HFAStandard( 2, &nNumber );
565 1038 : memcpy( pabyData + nIndexValue*2, &nNumber, 2 );
566 : }
567 1038 : break;
568 :
569 : case 'S':
570 : {
571 : short nNumber;
572 :
573 0 : if( nIndexValue*2 + 2 > nDataSize )
574 : {
575 : CPLError( CE_Failure, CPLE_AppDefined,
576 : "Attempt to extend field %s in node past end of data,\n"
577 : "not currently supported.",
578 0 : pszField );
579 0 : return CE_Failure;
580 : }
581 :
582 0 : nNumber = (short) nIntValue;
583 : HFAStandard( 2, &nNumber );
584 0 : memcpy( pabyData + nIndexValue*2, &nNumber, 2 );
585 : }
586 0 : break;
587 :
588 : case 't':
589 : case 'l':
590 : {
591 1594 : GUInt32 nNumber = nIntValue;
592 :
593 1594 : if( nIndexValue*4 + 4 > nDataSize )
594 : {
595 : CPLError( CE_Failure, CPLE_AppDefined,
596 : "Attempt to extend field %s in node past end of data,\n"
597 : "not currently supported.",
598 0 : pszField );
599 0 : return CE_Failure;
600 : }
601 :
602 : HFAStandard( 4, &nNumber );
603 1594 : memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
604 : }
605 1594 : break;
606 :
607 : case 'L':
608 : {
609 418 : GInt32 nNumber = nIntValue;
610 :
611 418 : if( nIndexValue*4 + 4 > nDataSize )
612 : {
613 : CPLError( CE_Failure, CPLE_AppDefined,
614 : "Attempt to extend field %s in node past end of data,\n"
615 : "not currently supported.",
616 0 : pszField );
617 0 : return CE_Failure;
618 : }
619 :
620 : HFAStandard( 4, &nNumber );
621 418 : memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
622 : }
623 418 : break;
624 :
625 : case 'f':
626 : {
627 0 : float fNumber = (float) dfDoubleValue;
628 :
629 0 : if( nIndexValue*4 + 4 > nDataSize )
630 : {
631 : CPLError( CE_Failure, CPLE_AppDefined,
632 : "Attempt to extend field %s in node past end of data,\n"
633 : "not currently supported.",
634 0 : pszField );
635 0 : return CE_Failure;
636 : }
637 :
638 : HFAStandard( 4, &fNumber );
639 0 : memcpy( pabyData + nIndexValue*4, &fNumber, 4 );
640 : }
641 0 : break;
642 :
643 : case 'd':
644 : {
645 3074 : double dfNumber = dfDoubleValue;
646 :
647 3074 : if( nIndexValue*8 + 8 > nDataSize )
648 : {
649 : CPLError( CE_Failure, CPLE_AppDefined,
650 : "Attempt to extend field %s in node past end of data,\n"
651 : "not currently supported.",
652 0 : pszField );
653 0 : return CE_Failure;
654 : }
655 :
656 : HFAStandard( 8, &dfNumber );
657 3074 : memcpy( pabyData + nIndexValue*8, &dfNumber, 8 );
658 : }
659 3074 : break;
660 :
661 : case 'b':
662 : {
663 40 : GInt32 nRows = 1;
664 40 : GInt32 nColumns = 1;
665 : GInt16 nBaseItemType;
666 :
667 : // Extract existing rows, columns, and datatype.
668 40 : memcpy( &nRows, pabyData, 4 );
669 : HFAStandard( 4, &nRows );
670 40 : memcpy( &nColumns, pabyData+4, 4 );
671 : HFAStandard( 4, &nColumns );
672 40 : memcpy( &nBaseItemType, pabyData+8, 2 );
673 : HFAStandard( 2, &nBaseItemType );
674 :
675 : // Are we using special index values to update the rows, columnrs
676 : // or type?
677 :
678 40 : if( nIndexValue == -3 )
679 9 : nBaseItemType = nIntValue;
680 31 : else if( nIndexValue == -2 )
681 9 : nColumns = nIntValue;
682 22 : else if( nIndexValue == -1 )
683 9 : nRows = nIntValue;
684 :
685 40 : if( nIndexValue < -3 || nIndexValue >= nRows * nColumns )
686 0 : return CE_Failure;
687 :
688 : // Write back the rows, columns and basedatatype.
689 : HFAStandard( 4, &nRows );
690 40 : memcpy( pabyData, &nRows, 4 );
691 : HFAStandard( 4, &nColumns );
692 40 : memcpy( pabyData+4, &nColumns, 4 );
693 : HFAStandard( 2, &nBaseItemType );
694 40 : memcpy ( pabyData + 8, &nBaseItemType, 2 );
695 : HFAStandard( 2, &nBaseItemType ); // swap back for our use.
696 :
697 : // We ignore the 2 byte objecttype value.
698 :
699 40 : nDataSize -= 12;
700 :
701 40 : if( nIndexValue >= 0 )
702 : {
703 13 : if( (nIndexValue+1) * (HFAGetDataTypeBits(nBaseItemType)/8)
704 : > nDataSize )
705 : {
706 : CPLError( CE_Failure, CPLE_AppDefined,
707 : "Attempt to extend field %s in node past end of data,\n"
708 : "not currently supported.",
709 0 : pszField );
710 0 : return CE_Failure;
711 : }
712 :
713 13 : if( nBaseItemType == EPT_f64 )
714 : {
715 13 : double dfNumber = dfDoubleValue;
716 :
717 : HFAStandard( 8, &dfNumber );
718 13 : memcpy( pabyData + 12 + nIndexValue * 8, &dfNumber, 8 );
719 : }
720 : else
721 : {
722 : CPLError( CE_Failure, CPLE_AppDefined,
723 : "Setting basedata field %s with type %s not currently supported.",
724 0 : pszField, HFAGetDataTypeName( nBaseItemType ) );
725 0 : return CE_Failure;
726 : }
727 : }
728 : }
729 40 : break;
730 :
731 : case 'o':
732 1710 : if( poItemObjectType != NULL )
733 : {
734 1710 : int nExtraOffset = 0;
735 : int iIndexCounter;
736 :
737 1710 : if( poItemObjectType->nBytes > 0 )
738 : {
739 756 : if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue)
740 0 : return CE_Failure;
741 756 : nExtraOffset = poItemObjectType->nBytes * nIndexValue;
742 : }
743 : else
744 : {
745 959 : for( iIndexCounter = 0;
746 : iIndexCounter < nIndexValue && nExtraOffset < nDataSize;
747 : iIndexCounter++ )
748 : {
749 : int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset,
750 5 : nDataSize - nExtraOffset);
751 5 : if (nInc < 0 || nExtraOffset > INT_MAX - nInc)
752 : {
753 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
754 0 : return CE_Failure;
755 : }
756 :
757 5 : nExtraOffset += nInc;
758 : }
759 : }
760 :
761 1710 : if (nExtraOffset >= nDataSize)
762 1 : return CE_Failure;
763 :
764 1709 : if( pszField != NULL && strlen(pszField) > 0 )
765 : {
766 : return( poItemObjectType->
767 : SetInstValue( pszField, pabyData + nExtraOffset,
768 : nDataOffset + nExtraOffset,
769 : nDataSize - nExtraOffset,
770 1709 : chReqType, pValue ) );
771 : }
772 : else
773 : {
774 0 : CPLAssert( FALSE );
775 0 : return CE_Failure;
776 : }
777 : }
778 0 : break;
779 :
780 : default:
781 0 : CPLAssert( FALSE );
782 0 : return CE_Failure;
783 : break;
784 : }
785 :
786 6164 : return CE_None;
787 : }
788 :
789 : /************************************************************************/
790 : /* ExtractInstValue() */
791 : /* */
792 : /* Extract the value of an instance of a field. */
793 : /* */
794 : /* pszField should be NULL if this field is not a */
795 : /* substructure. */
796 : /************************************************************************/
797 :
798 : int
799 : HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
800 : GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
801 14984 : char chReqType, void *pReqReturn, int *pnRemainingDataSize )
802 :
803 : {
804 14984 : char *pszStringRet = NULL;
805 14984 : int nIntRet = 0;
806 14984 : double dfDoubleRet = 0.0;
807 14984 : int nInstItemCount = GetInstCount( pabyData, nDataSize );
808 14984 : GByte *pabyRawData = NULL;
809 :
810 14984 : if (pnRemainingDataSize)
811 4 : *pnRemainingDataSize = -1;
812 :
813 : /* -------------------------------------------------------------------- */
814 : /* Check the index value is valid. */
815 : /* */
816 : /* Eventually this will have to account for variable fields. */
817 : /* -------------------------------------------------------------------- */
818 14984 : if( nIndexValue < 0 || nIndexValue >= nInstItemCount )
819 : {
820 183 : if( chItemType == 'b' && nIndexValue >= -3 && nIndexValue < 0 )
821 : /* ok - special index values */;
822 : else
823 183 : return FALSE;
824 : }
825 :
826 : /* -------------------------------------------------------------------- */
827 : /* If this field contains a pointer, then we will adjust the */
828 : /* data offset relative to it. */
829 : /* -------------------------------------------------------------------- */
830 14801 : if( chPointer != '\0' )
831 : {
832 : GUInt32 nOffset;
833 :
834 3903 : if (nDataSize < 8)
835 : {
836 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
837 0 : return FALSE;
838 : }
839 :
840 3903 : memcpy( &nOffset, pabyData+4, 4 );
841 : HFAStandard( 4, &nOffset );
842 :
843 3903 : if( nOffset != (GUInt32) (nDataOffset + 8) )
844 : {
845 : #ifdef notdef
846 : CPLError( CE_Warning, CPLE_AppDefined,
847 : "%s.%s points at %d, not %d as expected\n",
848 : pszFieldName, pszField ? pszField : "",
849 : nOffset, nDataOffset+8 );
850 : #endif
851 : }
852 :
853 3903 : pabyData += 8;
854 :
855 3903 : nDataOffset += 8;
856 3903 : nDataSize -= 8;
857 : }
858 :
859 : /* -------------------------------------------------------------------- */
860 : /* pointers to char or uchar arrays requested as strings are */
861 : /* handled as a special case. */
862 : /* -------------------------------------------------------------------- */
863 14801 : if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' )
864 : {
865 595 : *((GByte **)pReqReturn) = pabyData;
866 595 : if (pnRemainingDataSize)
867 2 : *pnRemainingDataSize = nDataSize;
868 595 : return( pabyData != NULL );
869 : }
870 :
871 : /* -------------------------------------------------------------------- */
872 : /* Handle by type. */
873 : /* -------------------------------------------------------------------- */
874 14206 : switch( chItemType )
875 : {
876 : case 'c':
877 : case 'C':
878 0 : if (nIndexValue >= nDataSize)
879 : {
880 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
881 0 : return FALSE;
882 : }
883 0 : nIntRet = pabyData[nIndexValue];
884 0 : dfDoubleRet = nIntRet;
885 0 : break;
886 :
887 : case 'e':
888 : case 's':
889 : {
890 : unsigned short nNumber;
891 2537 : if (nIndexValue*2 + 2 > nDataSize)
892 : {
893 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
894 0 : return FALSE;
895 : }
896 2537 : memcpy( &nNumber, pabyData + nIndexValue*2, 2 );
897 : HFAStandard( 2, &nNumber );
898 2537 : nIntRet = nNumber;
899 2537 : dfDoubleRet = nIntRet;
900 :
901 2537 : if( chItemType == 'e'
902 : && nIntRet >= 0 && nIntRet < CSLCount(papszEnumNames) )
903 : {
904 2536 : pszStringRet = papszEnumNames[nIntRet];
905 : }
906 : }
907 2537 : break;
908 :
909 : case 'S':
910 : {
911 : short nNumber;
912 0 : if (nIndexValue*2 + 2 > nDataSize)
913 : {
914 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
915 0 : return FALSE;
916 : }
917 0 : memcpy( &nNumber, pabyData + nIndexValue*2, 2 );
918 : HFAStandard( 2, &nNumber );
919 0 : nIntRet = nNumber;
920 0 : dfDoubleRet = nIntRet;
921 : }
922 0 : break;
923 :
924 : case 't':
925 : case 'l':
926 : {
927 : GUInt32 nNumber;
928 6095 : if (nIndexValue*4 + 4 > nDataSize)
929 : {
930 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
931 0 : return FALSE;
932 : }
933 6095 : memcpy( &nNumber, pabyData + nIndexValue*4, 4 );
934 : HFAStandard( 4, &nNumber );
935 6095 : nIntRet = nNumber;
936 6095 : dfDoubleRet = nIntRet;
937 : }
938 6095 : break;
939 :
940 : case 'L':
941 : {
942 : GInt32 nNumber;
943 679 : if (nIndexValue*4 + 4 > nDataSize)
944 : {
945 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
946 0 : return FALSE;
947 : }
948 679 : memcpy( &nNumber, pabyData + nIndexValue*4, 4 );
949 : HFAStandard( 4, &nNumber );
950 679 : nIntRet = nNumber;
951 679 : dfDoubleRet = nIntRet;
952 : }
953 679 : break;
954 :
955 : case 'f':
956 : {
957 : float fNumber;
958 0 : if (nIndexValue*4 + 4 > nDataSize)
959 : {
960 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
961 0 : return FALSE;
962 : }
963 0 : memcpy( &fNumber, pabyData + nIndexValue*4, 4 );
964 : HFAStandard( 4, &fNumber );
965 0 : dfDoubleRet = fNumber;
966 0 : nIntRet = (int) fNumber;
967 : }
968 0 : break;
969 :
970 : case 'd':
971 : {
972 : double dfNumber;
973 1941 : if (nIndexValue*8 + 8 > nDataSize)
974 : {
975 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
976 0 : return FALSE;
977 : }
978 1941 : memcpy( &dfNumber, pabyData + nIndexValue*8, 8 );
979 : HFAStandard( 8, &dfNumber );
980 1941 : dfDoubleRet = dfNumber;
981 1941 : nIntRet = (int) dfNumber;
982 : }
983 1941 : break;
984 :
985 : case 'b':
986 : {
987 : GInt32 nRows, nColumns;
988 : GInt16 nBaseItemType;
989 :
990 113 : if( nDataSize < 12 )
991 0 : return FALSE;
992 :
993 113 : memcpy( &nRows, pabyData, 4 );
994 : HFAStandard( 4, &nRows );
995 113 : memcpy( &nColumns, pabyData+4, 4 );
996 : HFAStandard( 4, &nColumns );
997 113 : memcpy( &nBaseItemType, pabyData+8, 2 );
998 : HFAStandard( 2, &nBaseItemType );
999 : // We ignore the 2 byte objecttype value.
1000 :
1001 113 : if( nIndexValue < -3 || nIndexValue >= nRows * nColumns )
1002 0 : return FALSE;
1003 :
1004 113 : pabyData += 12;
1005 113 : nDataSize -= 12;
1006 :
1007 113 : if( nIndexValue == -3 )
1008 : {
1009 0 : dfDoubleRet = nIntRet = nBaseItemType;
1010 : }
1011 113 : else if( nIndexValue == -2 )
1012 : {
1013 0 : dfDoubleRet = nIntRet = nColumns;
1014 : }
1015 113 : else if( nIndexValue == -1 )
1016 : {
1017 0 : dfDoubleRet = nIntRet = nRows;
1018 : }
1019 113 : else if( nBaseItemType == EPT_u8 )
1020 : {
1021 6 : if (nIndexValue >= nDataSize)
1022 : {
1023 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1024 0 : return FALSE;
1025 : }
1026 6 : dfDoubleRet = pabyData[nIndexValue];
1027 6 : nIntRet = pabyData[nIndexValue];
1028 : }
1029 107 : else if( nBaseItemType == EPT_s16 )
1030 : {
1031 : GInt16 nValue;
1032 0 : if (nIndexValue*2 + 2 > nDataSize)
1033 : {
1034 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1035 0 : return FALSE;
1036 : }
1037 0 : memcpy( &nValue, pabyData + 2*nIndexValue, 2 );
1038 : HFAStandard( 2, &nValue );
1039 :
1040 0 : dfDoubleRet = nValue;
1041 0 : nIntRet = nValue;
1042 : }
1043 107 : else if( nBaseItemType == EPT_u16 )
1044 : {
1045 : GUInt16 nValue;
1046 0 : if (nIndexValue*2 + 2 > nDataSize)
1047 : {
1048 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1049 0 : return FALSE;
1050 : }
1051 0 : memcpy( &nValue, pabyData + 2*nIndexValue, 2 );
1052 : HFAStandard( 2, &nValue );
1053 :
1054 0 : dfDoubleRet = nValue;
1055 0 : nIntRet = nValue;
1056 : }
1057 107 : else if( nBaseItemType == EPT_s32 )
1058 : {
1059 : GInt32 nValue;
1060 0 : if (nIndexValue*4 + 4 > nDataSize)
1061 : {
1062 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1063 0 : return FALSE;
1064 : }
1065 0 : memcpy( &nValue, pabyData + 4*nIndexValue, 4 );
1066 : HFAStandard( 4, &nValue );
1067 :
1068 0 : dfDoubleRet = nValue;
1069 0 : nIntRet = nValue;
1070 : }
1071 107 : else if( nBaseItemType == EPT_u32 )
1072 : {
1073 : GUInt32 nValue;
1074 0 : if (nIndexValue*4 + 4 > nDataSize)
1075 : {
1076 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1077 0 : return FALSE;
1078 : }
1079 0 : memcpy( &nValue, pabyData + 4*nIndexValue, 4 );
1080 : HFAStandard( 4, &nValue );
1081 :
1082 0 : dfDoubleRet = nValue;
1083 0 : nIntRet = nValue;
1084 : }
1085 107 : else if( nBaseItemType == EPT_f32 )
1086 : {
1087 : float fValue;
1088 0 : if (nIndexValue*4 + 4 > nDataSize)
1089 : {
1090 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1091 0 : return FALSE;
1092 : }
1093 0 : memcpy( &fValue, pabyData + 4*nIndexValue, 4 );
1094 : HFAStandard( 4, &fValue );
1095 :
1096 0 : dfDoubleRet = fValue;
1097 0 : nIntRet = (int) fValue;
1098 : }
1099 107 : else if( nBaseItemType == EPT_f64 )
1100 : {
1101 : double dfValue;
1102 107 : if (nIndexValue*8 + 8 > nDataSize)
1103 : {
1104 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1105 0 : return FALSE;
1106 : }
1107 107 : memcpy( &dfValue, pabyData+8*nIndexValue, 8 );
1108 : HFAStandard( 8, &dfValue );
1109 :
1110 107 : dfDoubleRet = dfValue;
1111 107 : nIntRet = (int) dfValue;
1112 : }
1113 : else
1114 : {
1115 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unknown base item type : %d", nBaseItemType);
1116 0 : return FALSE;
1117 : }
1118 : }
1119 113 : break;
1120 :
1121 : case 'o':
1122 2841 : if( poItemObjectType != NULL )
1123 : {
1124 2841 : int nExtraOffset = 0;
1125 : int iIndexCounter;
1126 :
1127 2841 : if( poItemObjectType->nBytes > 0 )
1128 : {
1129 2120 : if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue)
1130 0 : return CE_Failure;
1131 2120 : nExtraOffset = poItemObjectType->nBytes * nIndexValue;
1132 : }
1133 : else
1134 : {
1135 725 : for( iIndexCounter = 0;
1136 : iIndexCounter < nIndexValue && nExtraOffset < nDataSize;
1137 : iIndexCounter++ )
1138 : {
1139 : int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset,
1140 4 : nDataSize - nExtraOffset);
1141 4 : if (nInc < 0 || nExtraOffset > INT_MAX - nInc)
1142 : {
1143 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
1144 0 : return CE_Failure;
1145 : }
1146 :
1147 4 : nExtraOffset += nInc;
1148 : }
1149 : }
1150 :
1151 2841 : if (nExtraOffset >= nDataSize)
1152 0 : return CE_Failure;
1153 :
1154 2841 : pabyRawData = pabyData + nExtraOffset;
1155 :
1156 2841 : if( pszField != NULL && strlen(pszField) > 0 )
1157 : {
1158 : return( poItemObjectType->
1159 : ExtractInstValue( pszField, pabyRawData,
1160 : nDataOffset + nExtraOffset,
1161 : nDataSize - nExtraOffset,
1162 2841 : chReqType, pReqReturn, pnRemainingDataSize ) );
1163 : }
1164 : }
1165 0 : break;
1166 :
1167 : default:
1168 0 : return FALSE;
1169 : break;
1170 : }
1171 :
1172 : /* -------------------------------------------------------------------- */
1173 : /* Return the appropriate representation. */
1174 : /* -------------------------------------------------------------------- */
1175 11365 : if( chReqType == 's' )
1176 : {
1177 693 : if( pszStringRet == NULL )
1178 : {
1179 : /* HFAEntry:: BuildEntryFromMIFObject() expects to have always */
1180 : /* 8 bytes before the data. In normal situations, it should */
1181 : /* not go here, but that can happen if the file is corrupted */
1182 : /* so reserve the first 8 bytes before the string to contain null bytes */
1183 39 : memset(szNumberString, 0, 8);
1184 39 : sprintf( szNumberString + 8, "%.14g", dfDoubleRet );
1185 39 : pszStringRet = szNumberString + 8;
1186 : }
1187 :
1188 693 : *((char **) pReqReturn) = pszStringRet;
1189 693 : return( TRUE );
1190 : }
1191 10672 : else if( chReqType == 'd' )
1192 : {
1193 2015 : *((double *)pReqReturn) = dfDoubleRet;
1194 2015 : return( TRUE );
1195 : }
1196 8657 : else if( chReqType == 'i' )
1197 : {
1198 8657 : *((int *) pReqReturn) = nIntRet;
1199 8657 : return( TRUE );
1200 : }
1201 0 : else if( chReqType == 'p' )
1202 : {
1203 0 : *((GByte **) pReqReturn) = pabyRawData;
1204 0 : return( TRUE );
1205 : }
1206 : else
1207 : {
1208 0 : CPLAssert( FALSE );
1209 0 : return FALSE;
1210 : }
1211 : }
1212 :
1213 : /************************************************************************/
1214 : /* GetInstBytes() */
1215 : /* */
1216 : /* Get the number of bytes in a particular instance of a */
1217 : /* field. This will normally be the fixed internal nBytes */
1218 : /* value, but for pointer objects will include the variable */
1219 : /* portion. */
1220 : /************************************************************************/
1221 :
1222 56938 : int HFAField::GetInstBytes( GByte *pabyData, int nDataSize )
1223 :
1224 : {
1225 : int nCount;
1226 56938 : int nInstBytes = 0;
1227 :
1228 56938 : if( nBytes > -1 )
1229 43920 : return nBytes;
1230 :
1231 13018 : if( chPointer != '\0' )
1232 : {
1233 11894 : if (nDataSize < 4)
1234 : {
1235 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1236 0 : return -1;
1237 : }
1238 :
1239 11894 : memcpy( &nCount, pabyData, 4 );
1240 : HFAStandard( 4, &nCount );
1241 :
1242 11894 : pabyData += 8;
1243 11894 : nInstBytes += 8;
1244 : }
1245 : else
1246 1124 : nCount = 1;
1247 :
1248 13335 : if( chItemType == 'b' && nCount != 0 ) // BASEDATA
1249 : {
1250 317 : if (nDataSize - nInstBytes < 4+4+2)
1251 : {
1252 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1253 0 : return -1;
1254 : }
1255 :
1256 : GInt32 nRows, nColumns;
1257 : GInt16 nBaseItemType;
1258 :
1259 317 : memcpy( &nRows, pabyData, 4 );
1260 : HFAStandard( 4, &nRows );
1261 317 : memcpy( &nColumns, pabyData+4, 4 );
1262 : HFAStandard( 4, &nColumns );
1263 317 : memcpy( &nBaseItemType, pabyData+8, 2 );
1264 : HFAStandard( 2, &nBaseItemType );
1265 :
1266 317 : nInstBytes += 12;
1267 :
1268 317 : if (nRows < 0 || nColumns < 0)
1269 0 : return -1;
1270 317 : if (nColumns != 0 && nRows > INT_MAX / nColumns)
1271 0 : return -1;
1272 317 : if (nColumns != 0 && ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows > INT_MAX / nColumns)
1273 0 : return -1;
1274 317 : if (((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns > INT_MAX - nInstBytes)
1275 0 : return -1;
1276 :
1277 : nInstBytes +=
1278 317 : ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns;
1279 : }
1280 12701 : else if( poItemObjectType == NULL )
1281 : {
1282 11084 : if (nCount != 0 && HFADictionary::GetItemSize(chItemType) > INT_MAX / nCount)
1283 0 : return -1;
1284 11084 : nInstBytes += nCount * HFADictionary::GetItemSize(chItemType);
1285 : }
1286 : else
1287 : {
1288 : int i;
1289 :
1290 2792 : for( i = 0; i < nCount &&
1291 : nInstBytes < nDataSize &&
1292 : nInstBytes >= 0; i++ )
1293 : {
1294 : int nThisBytes;
1295 :
1296 : nThisBytes =
1297 : poItemObjectType->GetInstBytes( pabyData,
1298 1175 : nDataSize - nInstBytes );
1299 1175 : if (nThisBytes < 0 || nInstBytes > INT_MAX - nThisBytes)
1300 : {
1301 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
1302 0 : return -1;
1303 : }
1304 :
1305 1175 : nInstBytes += nThisBytes;
1306 1175 : pabyData += nThisBytes;
1307 : }
1308 : }
1309 :
1310 13018 : return( nInstBytes );
1311 : }
1312 :
1313 : /************************************************************************/
1314 : /* GetInstCount() */
1315 : /* */
1316 : /* Get the count for a particular instance of a field. This */
1317 : /* will normally be the built in value, but for variable fields */
1318 : /* this is extracted from the data itself. */
1319 : /************************************************************************/
1320 :
1321 15410 : int HFAField::GetInstCount( GByte * pabyData, int nDataSize )
1322 :
1323 : {
1324 15410 : if( chPointer == '\0' )
1325 11205 : return nItemCount;
1326 4205 : else if( chItemType == 'b' )
1327 : {
1328 : GInt32 nRows, nColumns;
1329 :
1330 148 : if( nDataSize < 20 )
1331 0 : return 0;
1332 :
1333 148 : memcpy( &nRows, pabyData+8, 4 );
1334 : HFAStandard( 4, &nRows );
1335 148 : memcpy( &nColumns, pabyData+12, 4 );
1336 : HFAStandard( 4, &nColumns );
1337 :
1338 148 : if (nRows < 0 || nColumns < 0)
1339 0 : return 0;
1340 148 : if (nColumns != 0 && nRows > INT_MAX / nColumns)
1341 0 : return 0;
1342 :
1343 148 : return nRows * nColumns;
1344 : }
1345 : else
1346 : {
1347 : GInt32 nCount;
1348 :
1349 4057 : if( nDataSize < 4 )
1350 0 : return 0;
1351 :
1352 4057 : memcpy( &nCount, pabyData, 4 );
1353 : HFAStandard( 4, &nCount );
1354 4057 : return nCount;
1355 : }
1356 : }
1357 :
1358 : /************************************************************************/
1359 : /* DumpInstValue() */
1360 : /************************************************************************/
1361 :
1362 : void HFAField::DumpInstValue( FILE *fpOut,
1363 : GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
1364 0 : const char *pszPrefix )
1365 :
1366 : {
1367 : int iEntry, nEntries;
1368 : void *pReturn;
1369 : char szLongFieldName[256];
1370 :
1371 0 : nEntries = GetInstCount( pabyData, nDataSize );
1372 :
1373 : /* -------------------------------------------------------------------- */
1374 : /* Special case for arrays of chars or uchars which are printed */
1375 : /* as a string. */
1376 : /* -------------------------------------------------------------------- */
1377 0 : if( (chItemType == 'c' || chItemType == 'C') && nEntries > 0 )
1378 : {
1379 0 : if( ExtractInstValue( NULL, 0,
1380 : pabyData, nDataOffset, nDataSize,
1381 : 's', &pReturn ) )
1382 : VSIFPrintf( fpOut, "%s%s = `%s'\n",
1383 : pszPrefix, pszFieldName,
1384 0 : (char *) pReturn );
1385 : else
1386 : VSIFPrintf( fpOut, "%s%s = (access failed)\n",
1387 0 : pszPrefix, pszFieldName );
1388 :
1389 0 : return;
1390 : }
1391 :
1392 : /* -------------------------------------------------------------------- */
1393 : /* For BASEDATA objects, we want to first dump their dimension */
1394 : /* and type. */
1395 : /* -------------------------------------------------------------------- */
1396 0 : if( chItemType == 'b' )
1397 : {
1398 : int nDataType, nRows, nColumns;
1399 : int bSuccess = ExtractInstValue( NULL, -3, pabyData, nDataOffset,
1400 0 : nDataSize, 'i', &nDataType );
1401 0 : if (bSuccess)
1402 : {
1403 : ExtractInstValue( NULL, -2, pabyData, nDataOffset,
1404 0 : nDataSize, 'i', &nColumns );
1405 : ExtractInstValue( NULL, -1, pabyData, nDataOffset,
1406 0 : nDataSize, 'i', &nRows );
1407 : VSIFPrintf( fpOut, "%sBASEDATA(%s): %dx%d of %s\n",
1408 : pszPrefix, pszFieldName,
1409 0 : nColumns, nRows, HFAGetDataTypeName( nDataType ) );
1410 : }
1411 : else
1412 : {
1413 : VSIFPrintf( fpOut, "%sBASEDATA(%s): empty\n",
1414 0 : pszPrefix, pszFieldName );
1415 : }
1416 : }
1417 :
1418 : /* -------------------------------------------------------------------- */
1419 : /* Dump each entry in the field array. */
1420 : /* -------------------------------------------------------------------- */
1421 0 : for( iEntry = 0; iEntry < MIN(MAX_ENTRY_REPORT,nEntries); iEntry++ )
1422 : {
1423 0 : if( nEntries == 1 )
1424 0 : VSIFPrintf( fpOut, "%s%s = ", pszPrefix, pszFieldName );
1425 : else
1426 : VSIFPrintf( fpOut, "%s%s[%d] = ",
1427 0 : pszPrefix, pszFieldName, iEntry );
1428 :
1429 0 : switch( chItemType )
1430 : {
1431 : case 'f':
1432 : case 'd':
1433 : {
1434 : double dfValue;
1435 0 : if( ExtractInstValue( NULL, iEntry,
1436 : pabyData, nDataOffset, nDataSize,
1437 : 'd', &dfValue ) )
1438 0 : VSIFPrintf( fpOut, "%f\n", dfValue );
1439 : else
1440 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1441 : }
1442 0 : break;
1443 :
1444 : case 'b':
1445 : {
1446 : double dfValue;
1447 :
1448 0 : if( ExtractInstValue( NULL, iEntry,
1449 : pabyData, nDataOffset, nDataSize,
1450 : 'd', &dfValue ) )
1451 0 : VSIFPrintf( fpOut, "%s%.15g\n", pszPrefix, dfValue );
1452 : else
1453 0 : VSIFPrintf( fpOut, "%s(access failed)\n", pszPrefix );
1454 : }
1455 0 : break;
1456 :
1457 : case 'e':
1458 0 : if( ExtractInstValue( NULL, iEntry,
1459 : pabyData, nDataOffset, nDataSize,
1460 : 's', &pReturn ) )
1461 0 : VSIFPrintf( fpOut, "%s\n", (char *) pReturn );
1462 : else
1463 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1464 0 : break;
1465 :
1466 : case 'o':
1467 0 : if( !ExtractInstValue( NULL, iEntry,
1468 : pabyData, nDataOffset, nDataSize,
1469 : 'p', &pReturn ) )
1470 : {
1471 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1472 : }
1473 : else
1474 : {
1475 : int nByteOffset;
1476 :
1477 0 : VSIFPrintf( fpOut, "\n" );
1478 :
1479 0 : nByteOffset = ((GByte *) pReturn) - pabyData;
1480 :
1481 0 : sprintf( szLongFieldName, "%s ", pszPrefix );
1482 :
1483 : poItemObjectType->DumpInstValue( fpOut,
1484 : pabyData + nByteOffset,
1485 : nDataOffset + nByteOffset,
1486 : nDataSize - nByteOffset,
1487 0 : szLongFieldName );
1488 : }
1489 0 : break;
1490 :
1491 : default:
1492 : {
1493 : GInt32 nIntValue;
1494 :
1495 0 : if( ExtractInstValue( NULL, iEntry,
1496 : pabyData, nDataOffset, nDataSize,
1497 : 'i', &nIntValue ) )
1498 0 : VSIFPrintf( fpOut, "%d\n", nIntValue );
1499 : else
1500 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1501 : }
1502 : break;
1503 : }
1504 : }
1505 :
1506 0 : if( nEntries > MAX_ENTRY_REPORT )
1507 0 : printf( "%s ... remaining instances omitted ...\n", pszPrefix );
1508 :
1509 0 : if( nEntries == 0 )
1510 0 : VSIFPrintf( fpOut, "%s%s = (no values)\n", pszPrefix, pszFieldName );
1511 :
1512 : }
|