LCOV - code coverage report
Current view: directory - frmts/hfa - hfafield.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 583 326 55.9 %
Date: 2011-12-18 Functions: 12 8 66.7 %

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

Generated by: LCOV version 1.7