LTP GCOV extension - code coverage report
Current view: directory - frmts/hfa - hfafield.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 572
Code covered: 56.5 % Executed lines: 323

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

Generated by: LTP GCOV extension version 1.5