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