1 : /******************************************************************************
2 : * $Id: hfafield.cpp 24044 2012-03-01 18:45:30Z 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 24044 2012-03-01 18:45:30Z warmerdam $");
34 :
35 : #define MAX_ENTRY_REPORT 16
36 :
37 : /************************************************************************/
38 : /* ==================================================================== */
39 : /* HFAField */
40 : /* ==================================================================== */
41 : /************************************************************************/
42 :
43 : /************************************************************************/
44 : /* HFAField() */
45 : /************************************************************************/
46 :
47 75592 : HFAField::HFAField()
48 :
49 : {
50 75592 : nBytes = 0;
51 :
52 75592 : nItemCount = 0;
53 75592 : chPointer = '\0';
54 75592 : chItemType = '\0';
55 :
56 75592 : pszItemObjectType = NULL;
57 75592 : poItemObjectType = NULL;
58 :
59 75592 : papszEnumNames = NULL;
60 :
61 75592 : pszFieldName = NULL;
62 75592 : }
63 :
64 : /************************************************************************/
65 : /* ~HFAField() */
66 : /************************************************************************/
67 :
68 75592 : HFAField::~HFAField()
69 :
70 : {
71 75592 : CPLFree( pszItemObjectType );
72 75592 : CSLDestroy( papszEnumNames );
73 75592 : CPLFree( pszFieldName );
74 75592 : }
75 :
76 : /************************************************************************/
77 : /* Initialize() */
78 : /************************************************************************/
79 :
80 75592 : const char *HFAField::Initialize( const char * pszInput )
81 :
82 : {
83 : int i;
84 :
85 : /* -------------------------------------------------------------------- */
86 : /* Read the number. */
87 : /* -------------------------------------------------------------------- */
88 75592 : nItemCount = atoi(pszInput);
89 :
90 228402 : while( *pszInput != '\0' && *pszInput != ':' )
91 77218 : pszInput++;
92 :
93 75592 : if( *pszInput == '\0' )
94 0 : return NULL;
95 :
96 75592 : pszInput++;
97 :
98 : /* -------------------------------------------------------------------- */
99 : /* Is this a pointer? */
100 : /* -------------------------------------------------------------------- */
101 75592 : if( *pszInput == 'p' || *pszInput == '*' )
102 17413 : chPointer = *(pszInput++);
103 :
104 : /* -------------------------------------------------------------------- */
105 : /* Get the general type */
106 : /* -------------------------------------------------------------------- */
107 75592 : if( *pszInput == '\0' )
108 0 : return NULL;
109 :
110 75592 : chItemType = *(pszInput++);
111 :
112 75592 : 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 75592 : if( chItemType == 'o' )
123 : {
124 9104 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
125 9104 : if (pszInput[i] == '\0')
126 0 : return NULL;
127 :
128 9104 : pszItemObjectType = (char *) CPLMalloc(i+1);
129 9104 : strncpy( pszItemObjectType, pszInput, i );
130 9104 : pszItemObjectType[i] = '\0';
131 :
132 9104 : 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 75592 : if( chItemType == 'x' && *pszInput == '{' )
144 : {
145 2089 : int nBraceDepth = 1;
146 2089 : pszInput++;
147 :
148 : // Skip past the definition.
149 70148 : while( nBraceDepth > 0 && *pszInput != '\0' )
150 : {
151 65970 : if( *pszInput == '{' )
152 1043 : nBraceDepth++;
153 64927 : else if( *pszInput == '}' )
154 3132 : nBraceDepth--;
155 :
156 65970 : pszInput++;
157 : }
158 2089 : if (*pszInput == '\0')
159 0 : return NULL;
160 :
161 2089 : chItemType = 'o';
162 :
163 : // find the comma terminating the type name.
164 2089 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
165 2089 : if (pszInput[i] == '\0')
166 0 : return NULL;
167 :
168 2089 : pszItemObjectType = (char *) CPLMalloc(i+1);
169 2089 : strncpy( pszItemObjectType, pszInput, i );
170 2089 : pszItemObjectType[i] = '\0';
171 :
172 2089 : pszInput += i+1;
173 : }
174 :
175 : /* -------------------------------------------------------------------- */
176 : /* If this is an enumeration we have to extract all the */
177 : /* enumeration values. */
178 : /* -------------------------------------------------------------------- */
179 75592 : if( chItemType == 'e' )
180 : {
181 10174 : int nEnumCount = atoi(pszInput);
182 : int iEnum;
183 :
184 10174 : if (nEnumCount < 0 || nEnumCount > 100000)
185 0 : return NULL;
186 :
187 10174 : pszInput = strchr(pszInput,':');
188 10174 : if( pszInput == NULL )
189 0 : return NULL;
190 :
191 10174 : pszInput++;
192 :
193 10174 : papszEnumNames = (char **) VSICalloc(sizeof(char *), nEnumCount+1);
194 10174 : if (papszEnumNames == NULL)
195 0 : return NULL;
196 :
197 56516 : for( iEnum = 0; iEnum < nEnumCount; iEnum++ )
198 : {
199 : char *pszToken;
200 :
201 46342 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
202 :
203 46342 : if( pszInput[i] != ',' )
204 0 : return NULL;
205 :
206 46342 : pszToken = (char *) CPLMalloc(i+1);
207 46342 : strncpy( pszToken, pszInput, i );
208 46342 : pszToken[i] = '\0';
209 :
210 46342 : papszEnumNames[iEnum] = pszToken;
211 :
212 46342 : pszInput += i+1;
213 : }
214 : }
215 :
216 : /* -------------------------------------------------------------------- */
217 : /* Extract the field name. */
218 : /* -------------------------------------------------------------------- */
219 75592 : for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
220 75592 : if (pszInput[i] == '\0')
221 0 : return NULL;
222 :
223 75592 : pszFieldName = (char *) CPLMalloc(i+1);
224 75592 : strncpy( pszFieldName, pszInput, i );
225 75592 : pszFieldName[i] = '\0';
226 :
227 75592 : pszInput += i+1;
228 :
229 75592 : return( pszInput );
230 : }
231 :
232 : /************************************************************************/
233 : /* CompleteDefn() */
234 : /* */
235 : /* Establish size, and pointers to component types. */
236 : /************************************************************************/
237 :
238 75592 : 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 75592 : if( pszItemObjectType != NULL )
246 11193 : poItemObjectType = poDict->FindType( pszItemObjectType );
247 :
248 : /* -------------------------------------------------------------------- */
249 : /* Figure out the size. */
250 : /* -------------------------------------------------------------------- */
251 75592 : if( chPointer == 'p' )
252 : {
253 12069 : nBytes = -1; /* we can't know the instance size */
254 : }
255 63523 : else if( poItemObjectType != NULL )
256 : {
257 8524 : poItemObjectType->CompleteDefn( poDict );
258 8524 : if( poItemObjectType->nBytes == -1 )
259 6931 : nBytes = -1;
260 : else
261 1593 : nBytes = poItemObjectType->nBytes * nItemCount;
262 :
263 8524 : if( chPointer == '*' && nBytes != -1 )
264 1593 : nBytes += 8; /* count, and offset */
265 : }
266 : else
267 : {
268 54999 : nBytes = poDict->GetItemSize( chItemType ) * nItemCount;
269 : }
270 75592 : }
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 10038 : 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 10038 : if( chPointer != '\0' )
392 : {
393 : GUInt32 nCount;
394 : GUInt32 nOffset;
395 :
396 : /* set the count for fixed sized arrays */
397 4959 : 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 4959 : if( chItemType == 'b' )
404 44 : nCount = 1;
405 :
406 : /* Set the size from string length */
407 6083 : else if( chReqType == 's' && (chItemType == 'c' || chItemType == 'C'))
408 : {
409 1168 : if( pValue == NULL )
410 186 : nCount = 0;
411 : else
412 982 : nCount = strlen((char *) pValue) + 1;
413 : }
414 :
415 : /* set size based on index ... assumes in-order setting of array */
416 : else
417 3747 : nCount = nIndexValue+1;
418 :
419 4959 : 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 4959 : memcpy( &nOffset, pabyData, 4 );
430 : HFAStandard( 4, &nOffset );
431 4959 : if( nOffset < nCount )
432 : {
433 3810 : nOffset = nCount;
434 : HFAStandard( 4, &nOffset );
435 3810 : memcpy( pabyData, &nOffset, 4 );
436 : }
437 :
438 4959 : if( pValue == NULL )
439 186 : nOffset = 0;
440 : else
441 4773 : nOffset = nDataOffset + 8;
442 : HFAStandard( 4, &nOffset );
443 4959 : memcpy( pabyData+4, &nOffset, 4 );
444 :
445 4959 : pabyData += 8;
446 :
447 4959 : nDataOffset += 8;
448 4959 : nDataSize -= 8;
449 : }
450 :
451 : /* -------------------------------------------------------------------- */
452 : /* pointers to char or uchar arrays requested as strings are */
453 : /* handled as a special case. */
454 : /* -------------------------------------------------------------------- */
455 10038 : if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' )
456 : {
457 : int nBytesToCopy;
458 :
459 1168 : if( nBytes == -1 )
460 : {
461 1168 : if( pValue == NULL )
462 186 : nBytesToCopy = 0;
463 : else
464 982 : nBytesToCopy = strlen((char *) pValue) + 1;
465 : }
466 : else
467 0 : nBytesToCopy = nBytes;
468 :
469 1168 : 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 1168 : memset( pabyData, 0, nBytesToCopy );
479 :
480 1168 : if( pValue != NULL )
481 982 : strncpy( (char *) pabyData, (char *) pValue, nBytesToCopy );
482 :
483 1168 : return CE_None;
484 : }
485 :
486 : /* -------------------------------------------------------------------- */
487 : /* Translate the passed type into different representations. */
488 : /* -------------------------------------------------------------------- */
489 : int nIntValue;
490 : double dfDoubleValue;
491 :
492 8870 : if( chReqType == 's' )
493 : {
494 1522 : nIntValue = atoi((char *) pValue);
495 1522 : dfDoubleValue = atof((char *) pValue);
496 : }
497 7348 : else if( chReqType == 'd' )
498 : {
499 4834 : dfDoubleValue = *((double *) pValue);
500 4834 : nIntValue = (int) dfDoubleValue;
501 : }
502 2514 : else if( chReqType == 'i' )
503 : {
504 2514 : dfDoubleValue = *((int *) pValue);
505 2514 : 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 8870 : 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 1075 : if( chItemType == 'e' && chReqType == 's' )
546 : {
547 689 : nIntValue = CSLFindString( papszEnumNames, (char *) pValue );
548 689 : 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 1075 : unsigned short nNumber = (unsigned short) nIntValue;
559 :
560 1075 : 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 1075 : memcpy( pabyData + nIndexValue*2, &nNumber, 2 );
571 : }
572 1075 : 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 1650 : GUInt32 nNumber = nIntValue;
597 :
598 1650 : 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 1650 : memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
609 : }
610 1650 : break;
611 :
612 : case 'L':
613 : {
614 432 : GInt32 nNumber = nIntValue;
615 :
616 432 : 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 432 : memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
627 : }
628 432 : 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 3630 : double dfNumber = dfDoubleValue;
651 :
652 3630 : 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 3630 : memcpy( pabyData + nIndexValue*8, &dfNumber, 8 );
663 : }
664 3630 : break;
665 :
666 : case 'b':
667 : {
668 44 : GInt32 nRows = 1;
669 44 : GInt32 nColumns = 1;
670 : GInt16 nBaseItemType;
671 :
672 : // Extract existing rows, columns, and datatype.
673 44 : memcpy( &nRows, pabyData, 4 );
674 : HFAStandard( 4, &nRows );
675 44 : memcpy( &nColumns, pabyData+4, 4 );
676 : HFAStandard( 4, &nColumns );
677 44 : 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 44 : if( nIndexValue == -3 )
684 10 : nBaseItemType = (GInt16) nIntValue;
685 34 : else if( nIndexValue == -2 )
686 10 : nColumns = nIntValue;
687 24 : else if( nIndexValue == -1 )
688 10 : nRows = nIntValue;
689 :
690 44 : 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 44 : memcpy( pabyData, &nRows, 4 );
696 : HFAStandard( 4, &nColumns );
697 44 : memcpy( pabyData+4, &nColumns, 4 );
698 : HFAStandard( 2, &nBaseItemType );
699 44 : 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 44 : nDataSize -= 12;
705 :
706 44 : if( nIndexValue >= 0 )
707 : {
708 14 : 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 14 : if( nBaseItemType == EPT_f64 )
719 : {
720 14 : double dfNumber = dfDoubleValue;
721 :
722 : HFAStandard( 8, &dfNumber );
723 14 : 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 44 : break;
735 :
736 : case 'o':
737 2039 : if( poItemObjectType != NULL )
738 : {
739 2039 : int nExtraOffset = 0;
740 : int iIndexCounter;
741 :
742 2039 : if( poItemObjectType->nBytes > 0 )
743 : {
744 876 : if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue)
745 0 : return CE_Failure;
746 876 : nExtraOffset = poItemObjectType->nBytes * nIndexValue;
747 : }
748 : else
749 : {
750 1172 : for( iIndexCounter = 0;
751 : iIndexCounter < nIndexValue && nExtraOffset < nDataSize;
752 : iIndexCounter++ )
753 : {
754 : int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset,
755 9 : nDataSize - nExtraOffset);
756 9 : 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 9 : nExtraOffset += nInc;
763 : }
764 : }
765 :
766 2039 : if (nExtraOffset >= nDataSize)
767 1 : return CE_Failure;
768 :
769 2038 : if( pszField != NULL && strlen(pszField) > 0 )
770 : {
771 : return( poItemObjectType->
772 : SetInstValue( pszField, pabyData + nExtraOffset,
773 : nDataOffset + nExtraOffset,
774 : nDataSize - nExtraOffset,
775 2038 : 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 6831 : 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 16327 : HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
805 : GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
806 : char chReqType, void *pReqReturn, int *pnRemainingDataSize )
807 :
808 : {
809 16327 : char *pszStringRet = NULL;
810 16327 : int nIntRet = 0;
811 16327 : double dfDoubleRet = 0.0;
812 16327 : int nInstItemCount = GetInstCount( pabyData, nDataSize );
813 16327 : GByte *pabyRawData = NULL;
814 :
815 16327 : 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 16327 : if( nIndexValue < 0 || nIndexValue >= nInstItemCount )
824 : {
825 221 : if( chItemType == 'b' && nIndexValue >= -3 && nIndexValue < 0 )
826 : /* ok - special index values */;
827 : else
828 221 : 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 16106 : if( chPointer != '\0' )
836 : {
837 : GUInt32 nOffset;
838 :
839 4511 : if (nDataSize < 8)
840 : {
841 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
842 0 : return FALSE;
843 : }
844 :
845 4511 : memcpy( &nOffset, pabyData+4, 4 );
846 : HFAStandard( 4, &nOffset );
847 :
848 4511 : 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 4511 : pabyData += 8;
859 :
860 4511 : nDataOffset += 8;
861 4511 : nDataSize -= 8;
862 : }
863 :
864 : /* -------------------------------------------------------------------- */
865 : /* pointers to char or uchar arrays requested as strings are */
866 : /* handled as a special case. */
867 : /* -------------------------------------------------------------------- */
868 16106 : if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' )
869 : {
870 789 : *((GByte **)pReqReturn) = pabyData;
871 789 : if (pnRemainingDataSize)
872 2 : *pnRemainingDataSize = nDataSize;
873 789 : return( pabyData != NULL );
874 : }
875 :
876 : /* -------------------------------------------------------------------- */
877 : /* Handle by type. */
878 : /* -------------------------------------------------------------------- */
879 15317 : 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 2627 : if (nIndexValue*2 + 2 > nDataSize)
897 : {
898 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
899 0 : return FALSE;
900 : }
901 2627 : memcpy( &nNumber, pabyData + nIndexValue*2, 2 );
902 : HFAStandard( 2, &nNumber );
903 2627 : nIntRet = nNumber;
904 2627 : dfDoubleRet = nIntRet;
905 :
906 2627 : if( chItemType == 'e'
907 : && nIntRet >= 0 && nIntRet < CSLCount(papszEnumNames) )
908 : {
909 2626 : pszStringRet = papszEnumNames[nIntRet];
910 : }
911 : }
912 2627 : 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 6210 : if (nIndexValue*4 + 4 > nDataSize)
934 : {
935 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
936 0 : return FALSE;
937 : }
938 6210 : memcpy( &nNumber, pabyData + nIndexValue*4, 4 );
939 : HFAStandard( 4, &nNumber );
940 6210 : nIntRet = nNumber;
941 6210 : dfDoubleRet = nIntRet;
942 : }
943 6210 : break;
944 :
945 : case 'L':
946 : {
947 : GInt32 nNumber;
948 728 : if (nIndexValue*4 + 4 > nDataSize)
949 : {
950 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
951 0 : return FALSE;
952 : }
953 728 : memcpy( &nNumber, pabyData + nIndexValue*4, 4 );
954 : HFAStandard( 4, &nNumber );
955 728 : nIntRet = nNumber;
956 728 : dfDoubleRet = nIntRet;
957 : }
958 728 : 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 2301 : if (nIndexValue*8 + 8 > nDataSize)
979 : {
980 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
981 0 : return FALSE;
982 : }
983 2301 : memcpy( &dfNumber, pabyData + nIndexValue*8, 8 );
984 : HFAStandard( 8, &dfNumber );
985 2301 : dfDoubleRet = dfNumber;
986 2301 : nIntRet = (int) dfNumber;
987 : }
988 2301 : break;
989 :
990 : case 'b':
991 : {
992 : GInt32 nRows, nColumns;
993 : GInt16 nBaseItemType;
994 :
995 117 : if( nDataSize < 12 )
996 0 : return FALSE;
997 :
998 117 : memcpy( &nRows, pabyData, 4 );
999 : HFAStandard( 4, &nRows );
1000 117 : memcpy( &nColumns, pabyData+4, 4 );
1001 : HFAStandard( 4, &nColumns );
1002 117 : memcpy( &nBaseItemType, pabyData+8, 2 );
1003 : HFAStandard( 2, &nBaseItemType );
1004 : // We ignore the 2 byte objecttype value.
1005 :
1006 117 : if( nIndexValue < -3 || nIndexValue >= nRows * nColumns )
1007 0 : return FALSE;
1008 :
1009 117 : pabyData += 12;
1010 117 : nDataSize -= 12;
1011 :
1012 117 : if( nIndexValue == -3 )
1013 : {
1014 0 : dfDoubleRet = nIntRet = nBaseItemType;
1015 : }
1016 117 : else if( nIndexValue == -2 )
1017 : {
1018 0 : dfDoubleRet = nIntRet = nColumns;
1019 : }
1020 117 : else if( nIndexValue == -1 )
1021 : {
1022 0 : dfDoubleRet = nIntRet = nRows;
1023 : }
1024 117 : else if( nBaseItemType == EPT_u1 )
1025 : {
1026 0 : if (nIndexValue*8 >= nDataSize)
1027 : {
1028 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1029 0 : return FALSE;
1030 : }
1031 :
1032 0 : if( pabyData[nIndexValue>>3] & (1 << (nIndexValue & 0x7)) )
1033 : {
1034 0 : dfDoubleRet = 1;
1035 0 : nIntRet = 1;
1036 : }
1037 : else
1038 : {
1039 0 : dfDoubleRet = 0.0;
1040 0 : nIntRet = 0;
1041 : }
1042 : }
1043 117 : else if( nBaseItemType == EPT_u8 )
1044 : {
1045 6 : if (nIndexValue >= nDataSize)
1046 : {
1047 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1048 0 : return FALSE;
1049 : }
1050 6 : dfDoubleRet = pabyData[nIndexValue];
1051 6 : nIntRet = pabyData[nIndexValue];
1052 : }
1053 111 : else if( nBaseItemType == EPT_s8 )
1054 : {
1055 0 : if (nIndexValue >= nDataSize)
1056 : {
1057 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1058 0 : return FALSE;
1059 : }
1060 0 : dfDoubleRet = ((signed char *)pabyData)[nIndexValue];
1061 0 : nIntRet = ((signed char *)pabyData)[nIndexValue];
1062 : }
1063 111 : else if( nBaseItemType == EPT_s16 )
1064 : {
1065 : GInt16 nValue;
1066 0 : if (nIndexValue*2 + 2 > nDataSize)
1067 : {
1068 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1069 0 : return FALSE;
1070 : }
1071 0 : memcpy( &nValue, pabyData + 2*nIndexValue, 2 );
1072 : HFAStandard( 2, &nValue );
1073 :
1074 0 : dfDoubleRet = nValue;
1075 0 : nIntRet = nValue;
1076 : }
1077 111 : else if( nBaseItemType == EPT_u16 )
1078 : {
1079 : GUInt16 nValue;
1080 0 : if (nIndexValue*2 + 2 > nDataSize)
1081 : {
1082 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1083 0 : return FALSE;
1084 : }
1085 0 : memcpy( &nValue, pabyData + 2*nIndexValue, 2 );
1086 : HFAStandard( 2, &nValue );
1087 :
1088 0 : dfDoubleRet = nValue;
1089 0 : nIntRet = nValue;
1090 : }
1091 111 : else if( nBaseItemType == EPT_s32 )
1092 : {
1093 : GInt32 nValue;
1094 0 : if (nIndexValue*4 + 4 > nDataSize)
1095 : {
1096 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1097 0 : return FALSE;
1098 : }
1099 0 : memcpy( &nValue, pabyData + 4*nIndexValue, 4 );
1100 : HFAStandard( 4, &nValue );
1101 :
1102 0 : dfDoubleRet = nValue;
1103 0 : nIntRet = nValue;
1104 : }
1105 111 : else if( nBaseItemType == EPT_u32 )
1106 : {
1107 : GUInt32 nValue;
1108 0 : if (nIndexValue*4 + 4 > nDataSize)
1109 : {
1110 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1111 0 : return FALSE;
1112 : }
1113 0 : memcpy( &nValue, pabyData + 4*nIndexValue, 4 );
1114 : HFAStandard( 4, &nValue );
1115 :
1116 0 : dfDoubleRet = nValue;
1117 0 : nIntRet = nValue;
1118 : }
1119 111 : else if( nBaseItemType == EPT_f32 )
1120 : {
1121 : float fValue;
1122 0 : if (nIndexValue*4 + 4 > nDataSize)
1123 : {
1124 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1125 0 : return FALSE;
1126 : }
1127 0 : memcpy( &fValue, pabyData + 4*nIndexValue, 4 );
1128 : HFAStandard( 4, &fValue );
1129 :
1130 0 : dfDoubleRet = fValue;
1131 0 : nIntRet = (int) fValue;
1132 : }
1133 111 : else if( nBaseItemType == EPT_f64 )
1134 : {
1135 : double dfValue;
1136 111 : if (nIndexValue*8 + 8 > nDataSize)
1137 : {
1138 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1139 0 : return FALSE;
1140 : }
1141 111 : memcpy( &dfValue, pabyData+8*nIndexValue, 8 );
1142 : HFAStandard( 8, &dfValue );
1143 :
1144 111 : dfDoubleRet = dfValue;
1145 111 : nIntRet = (int) dfValue;
1146 : }
1147 : else
1148 : {
1149 0 : CPLError(CE_Failure, CPLE_AppDefined, "Unknown base item type : %d", nBaseItemType);
1150 0 : return FALSE;
1151 : }
1152 : }
1153 117 : break;
1154 :
1155 : case 'o':
1156 3334 : if( poItemObjectType != NULL )
1157 : {
1158 3334 : int nExtraOffset = 0;
1159 : int iIndexCounter;
1160 :
1161 3334 : if( poItemObjectType->nBytes > 0 )
1162 : {
1163 2428 : if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue)
1164 0 : return CE_Failure;
1165 2428 : nExtraOffset = poItemObjectType->nBytes * nIndexValue;
1166 : }
1167 : else
1168 : {
1169 927 : for( iIndexCounter = 0;
1170 : iIndexCounter < nIndexValue && nExtraOffset < nDataSize;
1171 : iIndexCounter++ )
1172 : {
1173 : int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset,
1174 21 : nDataSize - nExtraOffset);
1175 21 : if (nInc < 0 || nExtraOffset > INT_MAX - nInc)
1176 : {
1177 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
1178 0 : return CE_Failure;
1179 : }
1180 :
1181 21 : nExtraOffset += nInc;
1182 : }
1183 : }
1184 :
1185 3334 : if (nExtraOffset >= nDataSize)
1186 0 : return CE_Failure;
1187 :
1188 3334 : pabyRawData = pabyData + nExtraOffset;
1189 :
1190 3334 : if( pszField != NULL && strlen(pszField) > 0 )
1191 : {
1192 : return( poItemObjectType->
1193 : ExtractInstValue( pszField, pabyRawData,
1194 : nDataOffset + nExtraOffset,
1195 : nDataSize - nExtraOffset,
1196 3334 : chReqType, pReqReturn, pnRemainingDataSize ) );
1197 : }
1198 : }
1199 0 : break;
1200 :
1201 : default:
1202 0 : return FALSE;
1203 : break;
1204 : }
1205 :
1206 : /* -------------------------------------------------------------------- */
1207 : /* Return the appropriate representation. */
1208 : /* -------------------------------------------------------------------- */
1209 11983 : if( chReqType == 's' )
1210 : {
1211 725 : if( pszStringRet == NULL )
1212 : {
1213 : /* HFAEntry:: BuildEntryFromMIFObject() expects to have always */
1214 : /* 8 bytes before the data. In normal situations, it should */
1215 : /* not go here, but that can happen if the file is corrupted */
1216 : /* so reserve the first 8 bytes before the string to contain null bytes */
1217 39 : memset(szNumberString, 0, 8);
1218 39 : sprintf( szNumberString + 8, "%.14g", dfDoubleRet );
1219 39 : pszStringRet = szNumberString + 8;
1220 : }
1221 :
1222 725 : *((char **) pReqReturn) = pszStringRet;
1223 725 : return( TRUE );
1224 : }
1225 11258 : else if( chReqType == 'd' )
1226 : {
1227 2379 : *((double *)pReqReturn) = dfDoubleRet;
1228 2379 : return( TRUE );
1229 : }
1230 8879 : else if( chReqType == 'i' )
1231 : {
1232 8879 : *((int *) pReqReturn) = nIntRet;
1233 8879 : return( TRUE );
1234 : }
1235 0 : else if( chReqType == 'p' )
1236 : {
1237 0 : *((GByte **) pReqReturn) = pabyRawData;
1238 0 : return( TRUE );
1239 : }
1240 : else
1241 : {
1242 0 : CPLAssert( FALSE );
1243 0 : return FALSE;
1244 : }
1245 : }
1246 :
1247 : /************************************************************************/
1248 : /* GetInstBytes() */
1249 : /* */
1250 : /* Get the number of bytes in a particular instance of a */
1251 : /* field. This will normally be the fixed internal nBytes */
1252 : /* value, but for pointer objects will include the variable */
1253 : /* portion. */
1254 : /************************************************************************/
1255 :
1256 62679 : int HFAField::GetInstBytes( GByte *pabyData, int nDataSize )
1257 :
1258 : {
1259 : int nCount;
1260 62679 : int nInstBytes = 0;
1261 :
1262 62679 : if( nBytes > -1 )
1263 47434 : return nBytes;
1264 :
1265 15245 : if( chPointer != '\0' )
1266 : {
1267 13880 : if (nDataSize < 4)
1268 : {
1269 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1270 0 : return -1;
1271 : }
1272 :
1273 13880 : memcpy( &nCount, pabyData, 4 );
1274 : HFAStandard( 4, &nCount );
1275 :
1276 13880 : pabyData += 8;
1277 13880 : nInstBytes += 8;
1278 : }
1279 : else
1280 1365 : nCount = 1;
1281 :
1282 15582 : if( chItemType == 'b' && nCount != 0 ) // BASEDATA
1283 : {
1284 337 : if (nDataSize - nInstBytes < 4+4+2)
1285 : {
1286 0 : CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
1287 0 : return -1;
1288 : }
1289 :
1290 : GInt32 nRows, nColumns;
1291 : GInt16 nBaseItemType;
1292 :
1293 337 : memcpy( &nRows, pabyData, 4 );
1294 : HFAStandard( 4, &nRows );
1295 337 : memcpy( &nColumns, pabyData+4, 4 );
1296 : HFAStandard( 4, &nColumns );
1297 337 : memcpy( &nBaseItemType, pabyData+8, 2 );
1298 : HFAStandard( 2, &nBaseItemType );
1299 :
1300 337 : nInstBytes += 12;
1301 :
1302 337 : if (nRows < 0 || nColumns < 0)
1303 0 : return -1;
1304 337 : if (nColumns != 0 && nRows > INT_MAX / nColumns)
1305 0 : return -1;
1306 337 : if (nColumns != 0 && ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows > INT_MAX / nColumns)
1307 0 : return -1;
1308 337 : if (((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns > INT_MAX - nInstBytes)
1309 0 : return -1;
1310 :
1311 : nInstBytes +=
1312 337 : ((HFAGetDataTypeBits(nBaseItemType) + 7) / 8) * nRows * nColumns;
1313 : }
1314 14908 : else if( poItemObjectType == NULL )
1315 : {
1316 12927 : if (nCount != 0 && HFADictionary::GetItemSize(chItemType) > INT_MAX / nCount)
1317 0 : return -1;
1318 12927 : nInstBytes += nCount * HFADictionary::GetItemSize(chItemType);
1319 : }
1320 : else
1321 : {
1322 : int i;
1323 :
1324 3397 : for( i = 0; i < nCount &&
1325 : nInstBytes < nDataSize &&
1326 : nInstBytes >= 0; i++ )
1327 : {
1328 : int nThisBytes;
1329 :
1330 : nThisBytes =
1331 : poItemObjectType->GetInstBytes( pabyData,
1332 1416 : nDataSize - nInstBytes );
1333 1416 : if (nThisBytes < 0 || nInstBytes > INT_MAX - nThisBytes)
1334 : {
1335 0 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
1336 0 : return -1;
1337 : }
1338 :
1339 1416 : nInstBytes += nThisBytes;
1340 1416 : pabyData += nThisBytes;
1341 : }
1342 : }
1343 :
1344 15245 : return( nInstBytes );
1345 : }
1346 :
1347 : /************************************************************************/
1348 : /* GetInstCount() */
1349 : /* */
1350 : /* Get the count for a particular instance of a field. This */
1351 : /* will normally be the built in value, but for variable fields */
1352 : /* this is extracted from the data itself. */
1353 : /************************************************************************/
1354 :
1355 16879 : int HFAField::GetInstCount( GByte * pabyData, int nDataSize )
1356 :
1357 : {
1358 16879 : if( chPointer == '\0' )
1359 11993 : return nItemCount;
1360 4886 : else if( chItemType == 'b' )
1361 : {
1362 : GInt32 nRows, nColumns;
1363 :
1364 163 : if( nDataSize < 20 )
1365 0 : return 0;
1366 :
1367 163 : memcpy( &nRows, pabyData+8, 4 );
1368 : HFAStandard( 4, &nRows );
1369 163 : memcpy( &nColumns, pabyData+12, 4 );
1370 : HFAStandard( 4, &nColumns );
1371 :
1372 163 : if (nRows < 0 || nColumns < 0)
1373 0 : return 0;
1374 163 : if (nColumns != 0 && nRows > INT_MAX / nColumns)
1375 0 : return 0;
1376 :
1377 163 : return nRows * nColumns;
1378 : }
1379 : else
1380 : {
1381 : GInt32 nCount;
1382 :
1383 4723 : if( nDataSize < 4 )
1384 0 : return 0;
1385 :
1386 4723 : memcpy( &nCount, pabyData, 4 );
1387 : HFAStandard( 4, &nCount );
1388 4723 : return nCount;
1389 : }
1390 : }
1391 :
1392 : /************************************************************************/
1393 : /* DumpInstValue() */
1394 : /************************************************************************/
1395 :
1396 0 : void HFAField::DumpInstValue( FILE *fpOut,
1397 : GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
1398 : const char *pszPrefix )
1399 :
1400 : {
1401 : int iEntry, nEntries;
1402 : void *pReturn;
1403 : char szLongFieldName[256];
1404 :
1405 0 : nEntries = GetInstCount( pabyData, nDataSize );
1406 :
1407 : /* -------------------------------------------------------------------- */
1408 : /* Special case for arrays of chars or uchars which are printed */
1409 : /* as a string. */
1410 : /* -------------------------------------------------------------------- */
1411 0 : if( (chItemType == 'c' || chItemType == 'C') && nEntries > 0 )
1412 : {
1413 0 : if( ExtractInstValue( NULL, 0,
1414 : pabyData, nDataOffset, nDataSize,
1415 : 's', &pReturn ) )
1416 : VSIFPrintf( fpOut, "%s%s = `%s'\n",
1417 : pszPrefix, pszFieldName,
1418 0 : (char *) pReturn );
1419 : else
1420 : VSIFPrintf( fpOut, "%s%s = (access failed)\n",
1421 0 : pszPrefix, pszFieldName );
1422 :
1423 0 : return;
1424 : }
1425 :
1426 : /* -------------------------------------------------------------------- */
1427 : /* For BASEDATA objects, we want to first dump their dimension */
1428 : /* and type. */
1429 : /* -------------------------------------------------------------------- */
1430 0 : if( chItemType == 'b' )
1431 : {
1432 : int nDataType, nRows, nColumns;
1433 : int bSuccess = ExtractInstValue( NULL, -3, pabyData, nDataOffset,
1434 0 : nDataSize, 'i', &nDataType );
1435 0 : if (bSuccess)
1436 : {
1437 : ExtractInstValue( NULL, -2, pabyData, nDataOffset,
1438 0 : nDataSize, 'i', &nColumns );
1439 : ExtractInstValue( NULL, -1, pabyData, nDataOffset,
1440 0 : nDataSize, 'i', &nRows );
1441 : VSIFPrintf( fpOut, "%sBASEDATA(%s): %dx%d of %s\n",
1442 : pszPrefix, pszFieldName,
1443 0 : nColumns, nRows, HFAGetDataTypeName( nDataType ) );
1444 : }
1445 : else
1446 : {
1447 : VSIFPrintf( fpOut, "%sBASEDATA(%s): empty\n",
1448 0 : pszPrefix, pszFieldName );
1449 : }
1450 : }
1451 :
1452 : /* -------------------------------------------------------------------- */
1453 : /* Dump each entry in the field array. */
1454 : /* -------------------------------------------------------------------- */
1455 0 : for( iEntry = 0; iEntry < MIN(MAX_ENTRY_REPORT,nEntries); iEntry++ )
1456 : {
1457 0 : if( nEntries == 1 )
1458 0 : VSIFPrintf( fpOut, "%s%s = ", pszPrefix, pszFieldName );
1459 : else
1460 : VSIFPrintf( fpOut, "%s%s[%d] = ",
1461 0 : pszPrefix, pszFieldName, iEntry );
1462 :
1463 0 : switch( chItemType )
1464 : {
1465 : case 'f':
1466 : case 'd':
1467 : {
1468 : double dfValue;
1469 0 : if( ExtractInstValue( NULL, iEntry,
1470 : pabyData, nDataOffset, nDataSize,
1471 : 'd', &dfValue ) )
1472 0 : VSIFPrintf( fpOut, "%f\n", dfValue );
1473 : else
1474 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1475 : }
1476 0 : break;
1477 :
1478 : case 'b':
1479 : {
1480 : double dfValue;
1481 :
1482 0 : if( ExtractInstValue( NULL, iEntry,
1483 : pabyData, nDataOffset, nDataSize,
1484 : 'd', &dfValue ) )
1485 0 : VSIFPrintf( fpOut, "%s%.15g\n", pszPrefix, dfValue );
1486 : else
1487 0 : VSIFPrintf( fpOut, "%s(access failed)\n", pszPrefix );
1488 : }
1489 0 : break;
1490 :
1491 : case 'e':
1492 0 : if( ExtractInstValue( NULL, iEntry,
1493 : pabyData, nDataOffset, nDataSize,
1494 : 's', &pReturn ) )
1495 0 : VSIFPrintf( fpOut, "%s\n", (char *) pReturn );
1496 : else
1497 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1498 0 : break;
1499 :
1500 : case 'o':
1501 0 : if( !ExtractInstValue( NULL, iEntry,
1502 : pabyData, nDataOffset, nDataSize,
1503 : 'p', &pReturn ) )
1504 : {
1505 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1506 : }
1507 : else
1508 : {
1509 : int nByteOffset;
1510 :
1511 0 : VSIFPrintf( fpOut, "\n" );
1512 :
1513 0 : nByteOffset = ((GByte *) pReturn) - pabyData;
1514 :
1515 0 : sprintf( szLongFieldName, "%s ", pszPrefix );
1516 :
1517 0 : if( poItemObjectType )
1518 : poItemObjectType->DumpInstValue( fpOut,
1519 : pabyData + nByteOffset,
1520 : nDataOffset + nByteOffset,
1521 : nDataSize - nByteOffset,
1522 0 : szLongFieldName );
1523 : }
1524 0 : break;
1525 :
1526 : default:
1527 : {
1528 : GInt32 nIntValue;
1529 :
1530 0 : if( ExtractInstValue( NULL, iEntry,
1531 : pabyData, nDataOffset, nDataSize,
1532 : 'i', &nIntValue ) )
1533 0 : VSIFPrintf( fpOut, "%d\n", nIntValue );
1534 : else
1535 0 : VSIFPrintf( fpOut, "(access failed)\n" );
1536 : }
1537 : break;
1538 : }
1539 : }
1540 :
1541 0 : if( nEntries > MAX_ENTRY_REPORT )
1542 0 : printf( "%s ... remaining instances omitted ...\n", pszPrefix );
1543 :
1544 0 : if( nEntries == 0 )
1545 0 : VSIFPrintf( fpOut, "%s%s = (no values)\n", pszPrefix, pszFieldName );
1546 :
1547 : }
|