LCOV - code coverage report
Current view: directory - frmts/hfa - hfatype.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 175 132 75.4 %
Date: 2012-12-26 Functions: 12 8 66.7 %

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

Generated by: LCOV version 1.7