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