LCOV - code coverage report
Current view: directory - frmts/hfa - hfatype.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 167 126 75.4 %
Date: 2010-01-09 Functions: 10 8 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: hfatype.cpp 16382 2009-02-22 15:29:49Z rouault $
       3                 :  *
       4                 :  * Project:  Erdas Imagine (.img) Translator
       5                 :  * Purpose:  Implementation of the HFAType class, for managing one type
       6                 :  *           defined in the HFA data dictionary.  Managed by HFADictionary.
       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: hfatype.cpp 16382 2009-02-22 15:29:49Z rouault $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /* ==================================================================== */
      37                 : /*                 HFAType          */
      38                 : /* ==================================================================== */
      39                 : /************************************************************************/
      40                 : 
      41                 : /************************************************************************/
      42                 : /*                              HFAType()                               */
      43                 : /************************************************************************/
      44                 : 
      45           13803 : HFAType::HFAType()
      46                 : 
      47                 : {
      48           13803 :     nBytes = 0;
      49           13803 :     nFields = 0;
      50           13803 :     papoFields = NULL;
      51           13803 :     pszTypeName = NULL;
      52           13803 : }
      53                 : 
      54                 : /************************************************************************/
      55                 : /*                              ~HFAType()                              */
      56                 : /************************************************************************/
      57                 : 
      58           13803 : HFAType::~HFAType()
      59                 : 
      60                 : {
      61                 :     int   i;
      62                 : 
      63           66052 :     for( i = 0; i < nFields; i++ )
      64                 :     {
      65           52249 :         delete papoFields[i];
      66                 :     }
      67                 : 
      68           13803 :     CPLFree( papoFields );
      69                 : 
      70           13803 :     CPLFree( pszTypeName );
      71           13803 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                             Initialize()                             */
      75                 : /************************************************************************/
      76                 : 
      77           13803 : const char *HFAType::Initialize( const char * pszInput )
      78                 : 
      79                 : {
      80                 :     int   i;
      81                 :     
      82                 :     
      83           13803 :     if( *pszInput != '{' )
      84                 :     {
      85               0 :         if( *pszInput != '\0' )
      86                 :             CPLDebug( "HFAType", "Initialize(%60.60s) - unexpected input.",
      87               0 :                       pszInput );
      88                 : 
      89               0 :         while( *pszInput != '{' && *pszInput != '\0' )
      90               0 :             pszInput++;
      91                 : 
      92               0 :         if( *pszInput == '\0' )
      93               0 :             return NULL;
      94                 :     }
      95                 : 
      96           13803 :     pszInput++;
      97                 : 
      98                 : /* -------------------------------------------------------------------- */
      99                 : /*      Read the field definitions.                                     */
     100                 : /* -------------------------------------------------------------------- */
     101           79855 :     while( pszInput != NULL && *pszInput != '}' )
     102                 :     {
     103           52249 :         HFAField  *poNewField = new HFAField();
     104                 : 
     105           52249 :         pszInput = poNewField->Initialize( pszInput );
     106           52249 :         if( pszInput != NULL )
     107                 :         {
     108                 :             papoFields = (HFAField **)
     109           52249 :                 CPLRealloc(papoFields, sizeof(void*) * (nFields+1) );
     110           52249 :             papoFields[nFields++] = poNewField;
     111                 :         }
     112                 :         else
     113               0 :             delete poNewField;
     114                 :     }
     115                 : 
     116           13803 :     if( pszInput == NULL )
     117               0 :         return NULL;
     118                 : 
     119                 : /* -------------------------------------------------------------------- */
     120                 : /*      Collect the name.                                               */
     121                 : /* -------------------------------------------------------------------- */
     122           13803 :     pszInput++; /* skip `}' */
     123                 : 
     124           13803 :     for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
     125                 : 
     126           13803 :     pszTypeName = (char *) CPLMalloc(i+1);
     127           13803 :     strncpy( pszTypeName, pszInput, i );
     128           13803 :     pszTypeName[i] = '\0';
     129                 :     
     130           13803 :     pszInput += i+1;
     131                 : 
     132           13803 :     return( pszInput );
     133                 : }
     134                 : 
     135                 : /************************************************************************/
     136                 : /*                            CompleteDefn()                            */
     137                 : /************************************************************************/
     138                 : 
     139           19685 : void HFAType::CompleteDefn( HFADictionary * poDict )
     140                 : 
     141                 : {
     142                 :     int   i;
     143                 : 
     144                 : /* -------------------------------------------------------------------- */
     145                 : /*      This may already be done, if an earlier object required this    */
     146                 : /*      object (as a field), and forced an early computation of the     */
     147                 : /*      size.                                                           */
     148                 : /* -------------------------------------------------------------------- */
     149           19685 :     if( nBytes != 0 )
     150            5882 :         return;
     151                 :     
     152                 : /* -------------------------------------------------------------------- */
     153                 : /*      Complete each of the fields, totaling up the sizes.  This       */
     154                 : /*      isn't really accurate for object with variable sized            */
     155                 : /*      subobjects.                                                     */
     156                 : /* -------------------------------------------------------------------- */
     157           66052 :     for( i = 0; i < nFields; i++ )
     158                 :     {
     159           52249 :         papoFields[i]->CompleteDefn( poDict );
     160           74862 :         if( papoFields[i]->nBytes < 0 || nBytes == -1 )
     161           22613 :             nBytes = -1;
     162                 :         else
     163           29636 :             nBytes += papoFields[i]->nBytes;
     164                 :     }
     165                 : }
     166                 : 
     167                 : /************************************************************************/
     168                 : /*                                Dump()                                */
     169                 : /************************************************************************/
     170                 : 
     171               0 : void HFAType::Dump( FILE * fp )
     172                 : 
     173                 : {
     174                 :     int   i;
     175                 :     
     176               0 :     VSIFPrintf( fp, "HFAType %s/%d bytes\n", pszTypeName, nBytes );
     177                 : 
     178               0 :     for( i = 0; i < nFields; i++ )
     179                 :     {
     180               0 :         papoFields[i]->Dump( fp );
     181                 :     }
     182                 : 
     183               0 :     VSIFPrintf( fp, "\n" );
     184               0 : }
     185                 : 
     186                 : /************************************************************************/
     187                 : /*                            SetInstValue()                            */
     188                 : /************************************************************************/
     189                 : 
     190                 : CPLErr 
     191            5624 : HFAType::SetInstValue( const char * pszFieldPath,
     192                 :                        GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
     193                 :                        char chReqType, void *pValue )
     194                 : 
     195                 : {
     196            5624 :     int   nArrayIndex = 0, nNameLen, iField, nByteOffset;
     197                 :     const char  *pszRemainder;
     198                 : 
     199                 : /* -------------------------------------------------------------------- */
     200                 : /*      Parse end of field name, possible index value and               */
     201                 : /*      establish where the remaining fields (if any) would start.      */
     202                 : /* -------------------------------------------------------------------- */
     203            5624 :     if( strchr(pszFieldPath,'[') != NULL )
     204                 :     {
     205            1168 :         const char  *pszEnd = strchr(pszFieldPath,'[');
     206                 :         
     207            1168 :         nArrayIndex = atoi(pszEnd+1);
     208            1168 :         nNameLen = pszEnd - pszFieldPath;
     209                 : 
     210            1168 :         pszRemainder = strchr(pszFieldPath,'.');
     211            1168 :         if( pszRemainder != NULL )
     212             136 :             pszRemainder++;
     213                 :     }
     214                 : 
     215            4456 :     else if( strchr(pszFieldPath,'.') != NULL )
     216                 :     {
     217             810 :         const char  *pszEnd = strchr(pszFieldPath,'.');
     218                 :         
     219             810 :         nNameLen = pszEnd - pszFieldPath;
     220                 : 
     221             810 :         pszRemainder = pszEnd + 1;
     222                 :     }
     223                 : 
     224                 :     else
     225                 :     {
     226            3646 :         nNameLen = strlen(pszFieldPath);
     227            3646 :         pszRemainder = pszFieldPath/*NULL*/;
     228                 :     }
     229                 :     
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Find this field within this type, if possible.                  */
     232                 : /* -------------------------------------------------------------------- */
     233            5624 :     nByteOffset = 0;
     234           18189 :     for( iField = 0; iField < nFields && nByteOffset < nDataSize; iField++ )
     235                 :     {
     236           29389 :         if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
     237           11246 :             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
     238                 :         {
     239            5578 :             break;
     240                 :         }
     241                 : 
     242           12565 :         int nInc = papoFields[iField]->GetInstBytes( pabyData+nByteOffset,
     243           25130 :                                               nDataSize - nByteOffset );
     244                 : 
     245           12565 :         if (nInc < 0 || nByteOffset > INT_MAX - nInc)
     246                 :         {
     247               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
     248               0 :             return CE_Failure;
     249                 :         }
     250                 : 
     251           12565 :         nByteOffset += nInc;
     252                 :     }
     253                 : 
     254            5624 :     if( iField == nFields || nByteOffset >= nDataSize )
     255              46 :         return CE_Failure;
     256                 : 
     257                 : /* -------------------------------------------------------------------- */
     258                 : /*      Extract this field value, and return.                           */
     259                 : /* -------------------------------------------------------------------- */
     260            5578 :     return( papoFields[iField]->SetInstValue( pszRemainder, nArrayIndex,
     261                 :                                               pabyData + nByteOffset,
     262                 :                                               nDataOffset + nByteOffset,
     263                 :                                               nDataSize - nByteOffset,
     264           11156 :                                               chReqType, pValue ) );
     265                 : }
     266                 : 
     267                 : /************************************************************************/
     268                 : /*                            GetInstCount()                            */
     269                 : /************************************************************************/
     270                 : 
     271                 : int
     272             377 : HFAType::GetInstCount( const char * pszFieldPath,
     273                 :                        GByte *pabyData, GUInt32 nDataOffset, int nDataSize )
     274                 : 
     275                 : {
     276             377 :     int   nArrayIndex = 0, nNameLen, iField, nByteOffset;
     277                 :     const char  *pszRemainder;
     278                 : 
     279                 : /* -------------------------------------------------------------------- */
     280                 : /*      Parse end of field name, possible index value and               */
     281                 : /*      establish where the remaining fields (if any) would start.      */
     282                 : /* -------------------------------------------------------------------- */
     283             377 :     if( strchr(pszFieldPath,'[') != NULL )
     284                 :     {
     285               0 :         const char  *pszEnd = strchr(pszFieldPath,'[');
     286                 :         
     287               0 :         nArrayIndex = atoi(pszEnd+1);
     288               0 :         nNameLen = pszEnd - pszFieldPath;
     289                 : 
     290               0 :         pszRemainder = strchr(pszFieldPath,'.');
     291               0 :         if( pszRemainder != NULL )
     292               0 :             pszRemainder++;
     293                 :     }
     294                 : 
     295             377 :     else if( strchr(pszFieldPath,'.') != NULL )
     296                 :     {
     297              93 :         const char  *pszEnd = strchr(pszFieldPath,'.');
     298                 :         
     299              93 :         nNameLen = pszEnd - pszFieldPath;
     300                 : 
     301              93 :         pszRemainder = pszEnd + 1;
     302                 :     }
     303                 : 
     304                 :     else
     305                 :     {
     306             284 :         nNameLen = strlen(pszFieldPath);
     307             284 :         pszRemainder = NULL;
     308                 :     }
     309                 :     
     310                 : /* -------------------------------------------------------------------- */
     311                 : /*      Find this field within this type, if possible.                  */
     312                 : /* -------------------------------------------------------------------- */
     313             377 :     nByteOffset = 0;
     314            1560 :     for( iField = 0; iField < nFields && nByteOffset < nDataSize; iField++ )
     315                 :     {
     316            2314 :         if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
     317             754 :             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
     318                 :         {
     319             377 :             break;
     320                 :         }
     321                 : 
     322            1183 :         int nInc = papoFields[iField]->GetInstBytes( pabyData+nByteOffset,
     323            2366 :                                               nDataSize - nByteOffset );
     324                 : 
     325            1183 :         if (nInc < 0 || nByteOffset > INT_MAX - nInc)
     326                 :         {
     327               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
     328               0 :             return -1;
     329                 :         }
     330                 : 
     331            1183 :         nByteOffset += nInc;
     332                 :     }
     333                 : 
     334             377 :     if( iField == nFields || nByteOffset >= nDataSize )
     335               0 :         return -1;
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Extract this field value, and return.                           */
     339                 : /* -------------------------------------------------------------------- */
     340             377 :     return( papoFields[iField]->GetInstCount( pabyData + nByteOffset,
     341             754 :                                               nDataSize - nByteOffset ) );
     342                 : }
     343                 : 
     344                 : /************************************************************************/
     345                 : /*                          ExtractInstValue()                          */
     346                 : /*                                                                      */
     347                 : /*      Extract the value of a field instance within this type.         */
     348                 : /*      Most of the work is done by the ExtractInstValue() for the      */
     349                 : /*      HFAField, but this methond does the field name parsing.         */
     350                 : /*                                                                      */
     351                 : /*      field names have the form:                                      */
     352                 : /*                                                                      */
     353                 : /*        fieldname{[index]}{.fieldname...}                             */
     354                 : /*                                                                      */
     355                 : /*      eg.                                                             */
     356                 : /*        abc                                   - field abc[0]          */
     357                 : /*        abc[3]                                - field abc[3]          */
     358                 : /*        abc[2].def                            - field def[0] of       */
     359                 : /*                                                the third abc struct. */
     360                 : /************************************************************************/
     361                 : 
     362                 : int
     363           12794 : HFAType::ExtractInstValue( const char * pszFieldPath,
     364                 :                            GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
     365                 :                            char chReqType, void *pReqReturn )
     366                 : 
     367                 : {
     368           12794 :     int   nArrayIndex = 0, nNameLen, iField, nByteOffset;
     369                 :     const char  *pszRemainder;
     370                 : 
     371                 : /* -------------------------------------------------------------------- */
     372                 : /*      Parse end of field name, possible index value and               */
     373                 : /*      establish where the remaining fields (if any) would start.      */
     374                 : /* -------------------------------------------------------------------- */
     375           12794 :     const char *pszFirstArray = strchr(pszFieldPath,'[');
     376           12794 :     const char *pszFirstDot = strchr(pszFieldPath,'.');
     377                 : 
     378           15306 :     if( pszFirstArray != NULL
     379                 :         && (pszFirstDot == NULL
     380                 :             || pszFirstDot > pszFirstArray) )
     381                 :     {
     382            2512 :         const char  *pszEnd = pszFirstArray;
     383                 :         
     384            2512 :         nArrayIndex = atoi(pszEnd+1);
     385            2512 :         nNameLen = pszEnd - pszFieldPath;
     386                 : 
     387            2512 :         pszRemainder = strchr(pszFieldPath,'.');
     388            2512 :         if( pszRemainder != NULL )
     389            1273 :             pszRemainder++;
     390                 :     }
     391                 : 
     392           10282 :     else if( pszFirstDot != NULL )
     393                 :     {
     394            1160 :         const char  *pszEnd = pszFirstDot;
     395                 :         
     396            1160 :         nNameLen = pszEnd - pszFieldPath;
     397                 : 
     398            1160 :         pszRemainder = pszEnd + 1;
     399                 :     }
     400                 : 
     401                 :     else
     402                 :     {
     403            9122 :         nNameLen = strlen(pszFieldPath);
     404            9122 :         pszRemainder = NULL;
     405                 :     }
     406                 :     
     407                 : /* -------------------------------------------------------------------- */
     408                 : /*      Find this field within this type, if possible.                  */
     409                 : /* -------------------------------------------------------------------- */
     410           12794 :     nByteOffset = 0;
     411           41017 :     for( iField = 0; iField < nFields && nByteOffset < nDataSize; iField++ )
     412                 :     {
     413           66524 :         if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
     414           25534 :             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
     415                 :         {
     416           12767 :             break;
     417                 :         }
     418                 : 
     419           28223 :         int nInc = papoFields[iField]->GetInstBytes( pabyData+nByteOffset,
     420           56446 :                                               nDataSize - nByteOffset );
     421                 : 
     422           28223 :         if (nInc < 0 || nByteOffset > INT_MAX - nInc)
     423                 :         {
     424               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
     425               0 :             return FALSE;
     426                 :         }
     427                 : 
     428           28223 :         nByteOffset += nInc;
     429                 :     }
     430                 : 
     431           12794 :     if( iField == nFields || nByteOffset >= nDataSize )
     432              27 :         return FALSE;
     433                 : 
     434                 : /* -------------------------------------------------------------------- */
     435                 : /*      Extract this field value, and return.                           */
     436                 : /* -------------------------------------------------------------------- */
     437           12767 :     return( papoFields[iField]->
     438                 :             ExtractInstValue( pszRemainder, nArrayIndex,
     439                 :                               pabyData + nByteOffset,
     440                 :                               nDataOffset + nByteOffset,
     441                 :                               nDataSize - nByteOffset,
     442           25534 :                               chReqType, pReqReturn ) );
     443                 : }
     444                 : 
     445                 : 
     446                 : /************************************************************************/
     447                 : /*                           DumpInstValue()                            */
     448                 : /************************************************************************/
     449                 : 
     450               0 : void HFAType::DumpInstValue( FILE * fpOut,
     451                 :                              GByte *pabyData, GUInt32 nDataOffset,
     452                 :                              int nDataSize, const char * pszPrefix )
     453                 : 
     454                 : {
     455                 :     int   iField;
     456                 :     
     457               0 :     for ( iField = 0; iField < nFields && nDataSize > 0; iField++ )
     458                 :     {
     459               0 :         HFAField  *poField = papoFields[iField];
     460                 :         int   nInstBytes;
     461                 :         
     462                 :         poField->DumpInstValue( fpOut, pabyData, nDataOffset,
     463               0 :                                 nDataSize, pszPrefix );
     464                 : 
     465               0 :         nInstBytes = poField->GetInstBytes( pabyData, nDataSize );
     466               0 :         if (nInstBytes < 0 || nDataOffset > UINT_MAX - nInstBytes)
     467                 :         {
     468               0 :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
     469               0 :             return;
     470                 :         }
     471                 : 
     472               0 :         pabyData += nInstBytes;
     473               0 :         nDataOffset += nInstBytes;
     474               0 :         nDataSize -= nInstBytes;
     475                 :     }    
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                            GetInstBytes()                            */
     480                 : /*                                                                      */
     481                 : /*      How many bytes in this particular instance of this type?        */
     482                 : /************************************************************************/
     483                 : 
     484             902 : int HFAType::GetInstBytes( GByte *pabyData, int nDataSize )
     485                 : 
     486                 : {
     487             902 :     if( nBytes >= 0 )
     488               0 :         return( nBytes );
     489                 :     else
     490                 :     {
     491             902 :         int nTotal = 0;
     492                 :         int iField;
     493                 :     
     494            2040 :         for( iField = 0; iField < nFields && nTotal < nDataSize; iField++ )
     495                 :         {
     496            1138 :             HFAField  *poField = papoFields[iField];
     497                 : 
     498                 :             int nInstBytes = poField->GetInstBytes( pabyData,
     499            1138 :                                                     nDataSize - nTotal );
     500            1138 :             if (nInstBytes < 0 || nTotal > INT_MAX - nInstBytes)
     501                 :             {
     502               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
     503               0 :                 return -1;
     504                 :             }
     505                 : 
     506            1138 :             pabyData += nInstBytes;
     507            1138 :             nTotal += nInstBytes;
     508                 :         }
     509                 : 
     510             902 :         return( nTotal );
     511                 :     }
     512                 : }

Generated by: LCOV version 1.7