LTP GCOV extension - code coverage report
Current view: directory - frmts/hfa - hfaentry.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 345
Code covered: 82.6 % Executed lines: 285

       1                 : /******************************************************************************
       2                 :  * $Id: hfaentry.cpp 18895 2010-02-23 19:30:01Z warmerdam $
       3                 :  *
       4                 :  * Project:  Erdas Imagine (.img) Translator
       5                 :  * Purpose:  Implementation of the HFAEntry class for reading and relating
       6                 :  *           one node in the HFA object tree structure. 
       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                 :  * hfaentry.cpp
      32                 :  *
      33                 :  * Implementation of the HFAEntry class.
      34                 :  *
      35                 :  */
      36                 : 
      37                 : #include "hfa_p.h"
      38                 : #include "cpl_conv.h"
      39                 : 
      40                 : CPL_CVSID("$Id: hfaentry.cpp 18895 2010-02-23 19:30:01Z warmerdam $");
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                              HFAEntry()                              */
      44                 : /*                                                                      */
      45                 : /*      Construct an HFAEntry from the source file.                     */
      46                 : /************************************************************************/
      47                 : 
      48                 : HFAEntry::HFAEntry( HFAInfo_t * psHFAIn, GUInt32 nPos,
      49            3086 :                     HFAEntry * poParentIn, HFAEntry * poPrevIn )
      50                 : 
      51                 : {
      52            3086 :     psHFA = psHFAIn;
      53                 :     
      54            3086 :     nFilePos = nPos;
      55            3086 :     bDirty = FALSE;
      56            3086 :     bIsMIFObject = FALSE;
      57                 : 
      58            3086 :     poParent = poParentIn;
      59            3086 :     poPrev = poPrevIn;
      60                 : 
      61                 : /* -------------------------------------------------------------------- */
      62                 : /*      Initialize fields to null values in case there is a read        */
      63                 : /*      error, so the entry will be in a harmless state.                */
      64                 : /* -------------------------------------------------------------------- */
      65            3086 :     poNext = poChild = NULL;
      66                 : 
      67            3086 :     nDataPos = nDataSize = 0;
      68            3086 :     nNextPos = nChildPos = 0;
      69                 : 
      70            3086 :     szName[0] = szType[0] = '\0';
      71                 : 
      72            3086 :     pabyData = NULL;
      73                 : 
      74            3086 :     poType = NULL;
      75                 : 
      76                 : /* -------------------------------------------------------------------- */
      77                 : /*      Read the entry information from the file.                       */
      78                 : /* -------------------------------------------------------------------- */
      79                 :     GInt32  anEntryNums[6];
      80                 :     int   i;
      81                 : 
      82            3086 :     if( VSIFSeekL( psHFA->fp, nFilePos, SEEK_SET ) == -1
      83                 :         || VSIFReadL( anEntryNums, sizeof(GInt32), 6, psHFA->fp ) < 1 )
      84                 :     {
      85                 :         CPLError( CE_Failure, CPLE_FileIO,
      86                 :                   "VSIFReadL(%p,6*4) @ %d failed in HFAEntry().\n%s",
      87               0 :                   psHFA->fp, nFilePos, VSIStrerror( errno ) );
      88               0 :         return;
      89                 :     }
      90                 : 
      91            3086 :     for( i = 0; i < 6; i++ )
      92                 :         HFAStandard( 4, anEntryNums + i );
      93                 : 
      94            3086 :     nNextPos = anEntryNums[0];
      95            3086 :     nChildPos = anEntryNums[3];
      96            3086 :     nDataPos = anEntryNums[4];
      97            3086 :     nDataSize = anEntryNums[5];
      98                 : 
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Read the name, and type.                                        */
     101                 : /* -------------------------------------------------------------------- */
     102            3086 :     if( VSIFReadL( szName, 1, 64, psHFA->fp ) < 1
     103                 :         || VSIFReadL( szType, 1, 32, psHFA->fp ) < 1 )
     104                 :     {
     105                 :         CPLError( CE_Failure, CPLE_FileIO,
     106               0 :                   "VSIFReadL() failed in HFAEntry()." );
     107               0 :         return;
     108                 :     }
     109                 : }
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                              HFAEntry()                              */
     113                 : /*                                                                      */
     114                 : /*      Construct an HFAEntry in memory, with the intention that it     */
     115                 : /*      would be written to disk later.                                 */
     116                 : /************************************************************************/
     117                 : 
     118                 : HFAEntry::HFAEntry( HFAInfo_t * psHFAIn, 
     119                 :                     const char * pszNodeName, 
     120                 :                     const char * pszTypeName,
     121            1277 :                     HFAEntry * poParentIn )
     122                 : 
     123                 : {
     124                 : /* -------------------------------------------------------------------- */
     125                 : /*      Initialize Entry                                                */
     126                 : /* -------------------------------------------------------------------- */
     127            1277 :     psHFA = psHFAIn;
     128                 :     
     129            1277 :     nFilePos = 0;
     130            1277 :     bIsMIFObject = FALSE;
     131                 : 
     132            1277 :     poParent = poParentIn;
     133            1277 :     poPrev = poNext = poChild = NULL;
     134                 : 
     135            1277 :     nDataPos = nDataSize = 0;
     136            1277 :     nNextPos = nChildPos = 0;
     137                 : 
     138            1277 :     SetName( pszNodeName );
     139            1277 :     memset( szType, 0, sizeof(szType) );
     140            1277 :     strncpy( szType, pszTypeName, sizeof(szType) );
     141            1277 :     szType[sizeof(szType)-1] = '\0';
     142                 : 
     143            1277 :     pabyData = NULL;
     144            1277 :     poType = NULL;
     145                 : 
     146                 : /* -------------------------------------------------------------------- */
     147                 : /*      Update the previous or parent node to refer to this one.        */
     148                 : /* -------------------------------------------------------------------- */
     149            1277 :     if( poParent == NULL )
     150                 :     {
     151                 :         /* do nothing */
     152                 :     }
     153            1172 :     else if( poParent->poChild == NULL )
     154                 :     {
     155             419 :         poParent->poChild = this;
     156             419 :         poParent->MarkDirty();
     157                 :     }
     158                 :     else
     159                 :     {
     160             753 :         poPrev = poParent->poChild;
     161            2326 :         while( poPrev->poNext != NULL )
     162             820 :             poPrev = poPrev->poNext;
     163                 : 
     164             753 :         poPrev->poNext = this;
     165             753 :         poPrev->MarkDirty();
     166                 :     }
     167                 : 
     168            1277 :     MarkDirty();
     169            1277 : }
     170                 : 
     171                 : /************************************************************************/
     172                 : /*                      BuildEntryFromMIFObject()                       */
     173                 : /*                                                                      */
     174                 : /*      Create a pseudo-HFAEntry wrapping a MIFObject.                  */
     175                 : /************************************************************************/
     176                 : 
     177               2 : HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer, const char *pszMIFObjectPath )
     178                 : {
     179                 :     const char* pszField;
     180               2 :     CPLString osFieldName;
     181                 : 
     182               2 :     osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFDictionary" );
     183               2 :     pszField = poContainer->GetStringField( osFieldName.c_str() );
     184               2 :     if (pszField == NULL)
     185                 :     {
     186                 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry",
     187               0 :                  osFieldName.c_str());
     188               0 :         return NULL;
     189                 :     }
     190               2 :     CPLString osDictionnary = pszField;
     191                 : 
     192               2 :     osFieldName.Printf("%s.%s", pszMIFObjectPath, "type.string" );
     193               2 :     pszField = poContainer->GetStringField( osFieldName.c_str() );
     194               2 :     if (pszField == NULL)
     195                 :     {
     196                 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry",
     197               0 :                  osFieldName.c_str());
     198               0 :         return NULL;
     199                 :     }
     200               2 :     CPLString osType = pszField;
     201                 : 
     202               2 :     osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFObject" );
     203               2 :     int nRemainingDataSize = 0;
     204                 :     pszField = poContainer->GetStringField( osFieldName.c_str(),
     205               2 :                                             NULL, &nRemainingDataSize );
     206               2 :     if (pszField == NULL)
     207                 :     {
     208                 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry",
     209               0 :                  osFieldName.c_str());
     210               0 :         return NULL;
     211                 :     }
     212                 : 
     213                 :     GInt32 nMIFObjectSize;
     214                 :     // we rudely look before the field data to get at the pointer/size info
     215               2 :     memcpy( &nMIFObjectSize, pszField-8, 4 );
     216                 :     HFAStandard( 4, &nMIFObjectSize );
     217               2 :     if (nMIFObjectSize <= 0)
     218                 :     {
     219                 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid MIF object size (%d)",
     220               0 :                  nMIFObjectSize);
     221               0 :         return NULL;
     222                 :     }
     223                 : 
     224                 :     // check that we won't copy more bytes than available in the buffer
     225               2 :     if (nMIFObjectSize > nRemainingDataSize)
     226                 :     {
     227                 :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid MIF object size (%d > %d)",
     228               0 :                  nMIFObjectSize, nRemainingDataSize);
     229               0 :         return NULL;
     230                 :     }
     231                 : 
     232               2 :     GByte* pabyData = (GByte *) VSIMalloc(nMIFObjectSize);
     233               2 :     if (pabyData == NULL)
     234               0 :         return NULL;
     235                 : 
     236               2 :     memcpy( pabyData, pszField, nMIFObjectSize );
     237                 : 
     238                 :     return new HFAEntry(poContainer, pszMIFObjectPath,
     239                 :                         osDictionnary, osType,
     240               2 :                         nMIFObjectSize, pabyData);
     241                 : 
     242                 : }
     243                 : 
     244                 : /************************************************************************/
     245                 : /*                              HFAEntry()                              */
     246                 : /*                                                                      */
     247                 : /*      Create a pseudo-HFAEntry wrapping a MIFObject.                  */
     248                 : /************************************************************************/
     249                 : 
     250                 : HFAEntry::HFAEntry( HFAEntry * poContainer,
     251                 :                     const char *pszMIFObjectPath,
     252                 :                     const char * pszDictionnary, 
     253                 :                     const char * pszTypeName,
     254                 :                     int nDataSizeIn,
     255               2 :                     GByte* pabyDataIn )
     256                 : 
     257                 : {
     258                 : /* -------------------------------------------------------------------- */
     259                 : /*      Initialize Entry                                                */
     260                 : /* -------------------------------------------------------------------- */
     261               2 :     nFilePos = 0;
     262                 : 
     263               2 :     poParent = poPrev = poNext = poChild = NULL;
     264                 : 
     265               2 :     bIsMIFObject = TRUE;
     266                 : 
     267               2 :     nDataPos = nDataSize = 0;
     268               2 :     nNextPos = nChildPos = 0;
     269                 : 
     270               2 :     memset( szName, 0, sizeof(szName) );
     271                 : 
     272                 : /* -------------------------------------------------------------------- */
     273                 : /*      Create a dummy HFAInfo_t.                                       */
     274                 : /* -------------------------------------------------------------------- */
     275               2 :     psHFA = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
     276                 : 
     277               2 :     psHFA->eAccess = HFA_ReadOnly;
     278               2 :     psHFA->bTreeDirty = FALSE;
     279               2 :     psHFA->poRoot = this;
     280                 : 
     281               2 :     psHFA->poDictionary = new HFADictionary( pszDictionnary );
     282                 : 
     283                 : /* -------------------------------------------------------------------- */
     284                 : /*      Work out the type for this MIFObject.                           */
     285                 : /* -------------------------------------------------------------------- */
     286               2 :     memset( szType, 0, sizeof(szType) );
     287               2 :     strncpy( szType, pszTypeName, sizeof(szType) );
     288               2 :     szType[sizeof(szType)-1] = '\0';
     289                 :     
     290               2 :     poType = psHFA->poDictionary->FindType( szType );
     291                 : 
     292               2 :     nDataSize = nDataSizeIn;
     293               2 :     pabyData = pabyDataIn;
     294               2 : }
     295                 : 
     296                 : /************************************************************************/
     297                 : /*                             ~HFAEntry()                              */
     298                 : /*                                                                      */
     299                 : /*      Ensure that children are cleaned up when this node is           */
     300                 : /*      cleaned up.                                                     */
     301                 : /************************************************************************/
     302                 : 
     303            4365 : HFAEntry::~HFAEntry()
     304                 : 
     305                 : {
     306            4365 :     CPLFree( pabyData );
     307                 :     
     308            4365 :     if( poNext != NULL )
     309            2548 :         delete poNext;
     310                 : 
     311            4365 :     if( poChild != NULL )
     312            1384 :         delete poChild;
     313                 : 
     314            4365 :     if( bIsMIFObject )
     315                 :     {
     316               2 :         delete psHFA->poDictionary;
     317               2 :         CPLFree( psHFA );
     318                 :     }
     319            4365 : }
     320                 : 
     321                 : /************************************************************************/
     322                 : /*                          RemoveAndDestroy()                          */
     323                 : /*                                                                      */
     324                 : /*      Removes this entry, and it's children from the current          */
     325                 : /*      tree.  The parent and/or siblings are appropriately updated     */
     326                 : /*      so that they will be flushed back to disk without the           */
     327                 : /*      reference to this node.                                         */
     328                 : /************************************************************************/
     329                 : 
     330               9 : CPLErr HFAEntry::RemoveAndDestroy()
     331                 : 
     332                 : {
     333               9 :     if( poPrev != NULL )
     334                 :     {
     335               9 :         poPrev->poNext = poNext;
     336               9 :         if( poNext != NULL )
     337               7 :             poPrev->nNextPos = poNext->nFilePos;
     338                 :         else
     339               2 :             poPrev->nNextPos = 0;
     340               9 :         poPrev->MarkDirty();
     341                 :     }
     342               9 :     if( poParent != NULL && poParent->poChild == this )
     343                 :     {
     344               0 :         poParent->poChild = poNext;
     345               0 :         if( poNext )
     346               0 :             poParent->nChildPos = poNext->nFilePos;
     347                 :         else
     348               0 :             poParent->nChildPos = 0;
     349               0 :         poParent->MarkDirty();
     350                 :     }
     351                 : 
     352               9 :     if( poNext != NULL )
     353                 :     {
     354               7 :         poNext->poPrev = poPrev;
     355                 :     }
     356                 :     
     357               9 :     poNext = NULL;
     358               9 :     poPrev = NULL;
     359               9 :     poParent = NULL;
     360                 : 
     361               9 :     delete this;
     362                 : 
     363               9 :     return CE_None;
     364                 : }
     365                 : 
     366                 : /************************************************************************/
     367                 : /*                              SetName()                               */
     368                 : /*                                                                      */
     369                 : /*    Changes the name assigned to this node                            */
     370                 : /************************************************************************/
     371                 : 
     372            1280 : void HFAEntry::SetName( const char *pszNodeName )
     373                 : {
     374            1280 :   memset( szName, 0, sizeof(szName) );
     375            1280 :   strncpy( szName, pszNodeName, sizeof(szName) );
     376            1280 :   szName[sizeof(szName)-1] = '\0';
     377                 : 
     378            1280 :   MarkDirty();
     379            1280 : }
     380                 : 
     381                 : /************************************************************************/
     382                 : /*                              GetChild()                              */
     383                 : /************************************************************************/
     384                 : 
     385           13944 : HFAEntry *HFAEntry::GetChild()
     386                 : 
     387                 : {
     388                 : /* -------------------------------------------------------------------- */
     389                 : /*      Do we need to create the child node?                            */
     390                 : /* -------------------------------------------------------------------- */
     391           13944 :     if( poChild == NULL && nChildPos != 0 )
     392                 :     {
     393             965 :         poChild = new HFAEntry( psHFA, nChildPos, this, NULL );
     394                 :     }
     395                 : 
     396           13944 :     return( poChild );
     397                 : }
     398                 : 
     399                 : /************************************************************************/
     400                 : /*                              GetNext()                               */
     401                 : /************************************************************************/
     402                 : 
     403           37268 : HFAEntry *HFAEntry::GetNext()
     404                 : 
     405                 : {
     406                 : /* -------------------------------------------------------------------- */
     407                 : /*      Do we need to create the next node?                             */
     408                 : /* -------------------------------------------------------------------- */
     409           37268 :     if( poNext == NULL && nNextPos != 0 )
     410                 :     {
     411                 :         // Check if we have a loop on the next node in this sibling chain.
     412                 :         HFAEntry *poPast;
     413                 : 
     414            1805 :         for( poPast = this; 
     415                 :              poPast != NULL && poPast->nFilePos != nNextPos; 
     416                 :              poPast = poPast->poPrev ) {}
     417                 : 
     418            1805 :         if( poPast != NULL )
     419                 :         {
     420                 :             CPLError( CE_Warning, CPLE_AppDefined,
     421                 :                       "Corrupt (looping) entry in %s, ignoring some entries after %s.",
     422                 :                       psHFA->pszFilename, 
     423               1 :                       szName );
     424               1 :             nNextPos = 0;
     425               1 :             return NULL;
     426                 :         }
     427                 :              
     428            1804 :         poNext = new HFAEntry( psHFA, nNextPos, poParent, this );
     429                 :     }
     430                 : 
     431           37267 :     return( poNext );
     432                 : }
     433                 : 
     434                 : /************************************************************************/
     435                 : /*                              LoadData()                              */
     436                 : /*                                                                      */
     437                 : /*      Load the data for this entry, and build up the field            */
     438                 : /*      information for it.                                             */
     439                 : /************************************************************************/
     440                 : 
     441           19937 : void HFAEntry::LoadData()
     442                 : 
     443                 : {
     444           19937 :     if( pabyData != NULL || nDataSize == 0 )
     445           18288 :         return;
     446                 : 
     447                 : /* -------------------------------------------------------------------- */
     448                 : /*      Allocate buffer, and read data.                                 */
     449                 : /* -------------------------------------------------------------------- */
     450            1649 :     pabyData = (GByte *) VSIMalloc(nDataSize + 1);
     451            1649 :     if (pabyData == NULL)
     452                 :     {
     453                 :         CPLError( CE_Failure, CPLE_OutOfMemory,
     454               0 :                   "VSIMalloc() failed in HFAEntry::LoadData()." );
     455               0 :         return;
     456                 :     }
     457                 :     
     458            1649 :     if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) < 0 )
     459                 :     {
     460                 :         CPLError( CE_Failure, CPLE_FileIO,
     461               0 :                   "VSIFSeekL() failed in HFAEntry::LoadData()." );
     462               0 :         return;
     463                 :     }
     464                 : 
     465            1649 :     if( VSIFReadL( pabyData, 1, nDataSize, psHFA->fp ) < 1 )
     466                 :     {
     467                 :         CPLError( CE_Failure, CPLE_FileIO,
     468               0 :                   "VSIFReadL() failed in HFAEntry::LoadData()." );
     469               0 :         return;
     470                 :     }
     471                 : 
     472                 :     /* Make sure the buffer is always null terminated to avoid */
     473                 :     /* issues when extracting strings from a corrupted file */
     474            1649 :     pabyData[nDataSize] = '\0';
     475                 : 
     476                 : /* -------------------------------------------------------------------- */
     477                 : /*      Get the type corresponding to this entry.                       */
     478                 : /* -------------------------------------------------------------------- */
     479            1649 :     poType = psHFA->poDictionary->FindType( szType );
     480            1649 :     if( poType == NULL )
     481            1649 :         return;
     482                 : }
     483                 : 
     484                 : /************************************************************************/
     485                 : /*                           GetTypeObject()                            */
     486                 : /************************************************************************/
     487                 : 
     488              93 : HFAType *HFAEntry::GetTypeObject()
     489                 : 
     490                 : {
     491              93 :     if( poType == NULL )
     492              93 :         poType = psHFA->poDictionary->FindType( szType );
     493                 : 
     494              93 :     return poType;
     495                 : }
     496                 : 
     497                 : /************************************************************************/
     498                 : /*                              MakeData()                              */
     499                 : /*                                                                      */
     500                 : /*      Create a data block on the this HFAEntry in memory.  By         */
     501                 : /*      default it will create the data the correct size for fixed      */
     502                 : /*      sized types, or do nothing for variable length types.           */
     503                 : /*      However, the caller can supply a desired size for variable      */
     504                 : /*      sized fields.                                                   */
     505                 : /************************************************************************/
     506                 : 
     507            8076 : GByte *HFAEntry::MakeData( int nSize )
     508                 : 
     509                 : {
     510            8076 :     if( poType == NULL )
     511                 :     {
     512            1079 :         poType = psHFA->poDictionary->FindType( szType );
     513            1079 :         if( poType == NULL )
     514               0 :             return NULL;
     515                 :     }
     516                 : 
     517            8076 :     if( nSize == 0 && poType->nBytes > 0 )
     518            2055 :         nSize = poType->nBytes;
     519                 : 
     520            8076 :     if( (int) nDataSize < nSize && nSize > 0 )
     521                 :     {
     522            1172 :         pabyData = (GByte *) CPLRealloc(pabyData, nSize);
     523            1172 :         memset( pabyData + nDataSize, 0, nSize - nDataSize );
     524            1172 :         nDataSize = nSize;
     525                 : 
     526            1172 :         MarkDirty();
     527                 : 
     528                 : /* -------------------------------------------------------------------- */
     529                 : /*      If the data already had a file position, we now need to         */
     530                 : /*      clear that, forcing it to be rewritten at the end of the        */
     531                 : /*      file.  Referencing nodes will need to be marked dirty so        */
     532                 : /*      they are rewritten.                                             */
     533                 : /* -------------------------------------------------------------------- */
     534            1172 :         if( nFilePos != 0 )
     535                 :         {
     536               1 :             nFilePos = 0;
     537               1 :             nDataPos = 0;
     538               1 :             if (poPrev != NULL) poPrev->MarkDirty(); 
     539               1 :             if (poNext != NULL) poNext->MarkDirty(); 
     540               1 :             if (poChild != NULL) poChild->MarkDirty(); 
     541               1 :             if (poParent != NULL) poParent->MarkDirty(); 
     542                 :         }
     543                 :     }
     544                 : 
     545            8076 :     return pabyData;
     546                 : }
     547                 : 
     548                 : 
     549                 : /************************************************************************/
     550                 : /*                          DumpFieldValues()                           */
     551                 : /************************************************************************/
     552                 : 
     553               0 : void HFAEntry::DumpFieldValues( FILE * fp, const char * pszPrefix )
     554                 : 
     555                 : {
     556               0 :     if( pszPrefix == NULL )
     557               0 :         pszPrefix = "";
     558                 : 
     559               0 :     LoadData();
     560                 : 
     561               0 :     if( pabyData == NULL || poType == NULL )
     562               0 :         return;
     563                 : 
     564                 :     poType->DumpInstValue( fp,
     565                 :                            pabyData, nDataPos, nDataSize,
     566               0 :                            pszPrefix );
     567                 : }
     568                 : 
     569                 : /************************************************************************/
     570                 : /*                           GetNamedChild()                            */
     571                 : /************************************************************************/
     572                 : 
     573           12231 : HFAEntry *HFAEntry::GetNamedChild( const char * pszName )
     574                 : 
     575                 : {
     576                 :     int   nNameLen;
     577                 :     HFAEntry  *poEntry;
     578                 : 
     579                 : /* -------------------------------------------------------------------- */
     580                 : /*      Establish how much of this name path is for the next child.     */
     581                 : /*      Up to the '.' or end of estring.                                */
     582                 : /* -------------------------------------------------------------------- */
     583           12231 :     for( nNameLen = 0;
     584                 :          pszName[nNameLen] != '.'
     585                 :              && pszName[nNameLen] != '\0'
     586                 :              && pszName[nNameLen] != ':';
     587                 :          nNameLen++ ) {}
     588                 : 
     589                 : /* -------------------------------------------------------------------- */
     590                 : /*      Scan children looking for this name.                            */
     591                 : /* -------------------------------------------------------------------- */
     592           44785 :     for( poEntry = GetChild(); poEntry != NULL; poEntry = poEntry->GetNext() )
     593                 :     {
     594           34466 :         if( EQUALN(poEntry->GetName(),pszName,nNameLen)
     595                 :             && (int) strlen(poEntry->GetName()) == nNameLen )
     596                 :         {
     597            1990 :             if( pszName[nNameLen] == '.' )
     598                 :             {
     599                 :                 HFAEntry *poResult;
     600                 : 
     601             209 :                 poResult = poEntry->GetNamedChild( pszName+nNameLen+1 );
     602             209 :                 if( poResult != NULL )
     603             131 :                     return poResult;
     604                 :             }
     605                 :             else
     606            1781 :                 return poEntry;
     607                 :         }
     608                 :     }
     609                 : 
     610           10319 :     return NULL;
     611                 : }
     612                 : 
     613                 : /************************************************************************/
     614                 : /*                           GetFieldValue()                            */
     615                 : /************************************************************************/
     616                 :         
     617                 : int HFAEntry::GetFieldValue( const char * pszFieldPath,
     618                 :                              char chReqType, void *pReqReturn,
     619           12174 :                              int *pnRemainingDataSize)
     620                 : 
     621                 : {
     622           12174 :     HFAEntry  *poEntry = this;
     623                 :     
     624                 : /* -------------------------------------------------------------------- */
     625                 : /*      Is there a node path in this string?                            */
     626                 : /* -------------------------------------------------------------------- */
     627           12174 :     if( strchr(pszFieldPath,':') != NULL )
     628                 :     {
     629               0 :         poEntry = GetNamedChild( pszFieldPath );
     630               0 :         if( poEntry == NULL )
     631               0 :             return FALSE;
     632                 :         
     633               0 :         pszFieldPath = strchr(pszFieldPath,':') + 1;
     634                 :     }
     635                 : 
     636                 : /* -------------------------------------------------------------------- */
     637                 : /*      Do we have the data and type for this node?                     */
     638                 : /* -------------------------------------------------------------------- */
     639           12174 :     LoadData();
     640                 : 
     641           12174 :     if( pabyData == NULL )
     642               3 :         return FALSE;
     643                 :     
     644           12171 :     if( poType == NULL )
     645               0 :         return FALSE;
     646                 : 
     647                 : /* -------------------------------------------------------------------- */
     648                 : /*      Extract the instance information.                               */
     649                 : /* -------------------------------------------------------------------- */
     650                 : 
     651                 : 
     652                 :     return( poType->ExtractInstValue( pszFieldPath,
     653                 :                                       pabyData, nDataPos, nDataSize,
     654           12171 :                                       chReqType, pReqReturn, pnRemainingDataSize ) );
     655                 : }
     656                 : 
     657                 : /************************************************************************/
     658                 : /*                           GetFieldCount()                            */
     659                 : /************************************************************************/
     660                 : 
     661             426 : int HFAEntry::GetFieldCount( const char * pszFieldPath, CPLErr *peErr )
     662                 : 
     663                 : {
     664             426 :     HFAEntry  *poEntry = this;
     665                 :     
     666                 : /* -------------------------------------------------------------------- */
     667                 : /*      Is there a node path in this string?                            */
     668                 : /* -------------------------------------------------------------------- */
     669             426 :     if( strchr(pszFieldPath,':') != NULL )
     670                 :     {
     671               0 :         poEntry = GetNamedChild( pszFieldPath );
     672               0 :         if( poEntry == NULL )
     673               0 :             return -1;
     674                 :         
     675               0 :         pszFieldPath = strchr(pszFieldPath,':') + 1;
     676                 :     }
     677                 : 
     678                 : /* -------------------------------------------------------------------- */
     679                 : /*      Do we have the data and type for this node?                     */
     680                 : /* -------------------------------------------------------------------- */
     681             426 :     LoadData();
     682                 : 
     683             426 :     if( pabyData == NULL )
     684               0 :         return -1;
     685                 :     
     686             426 :     if( poType == NULL )
     687               0 :         return -1;
     688                 : 
     689                 : /* -------------------------------------------------------------------- */
     690                 : /*      Extract the instance information.                               */
     691                 : /* -------------------------------------------------------------------- */
     692                 : 
     693                 :     return( poType->GetInstCount( pszFieldPath,
     694             426 :                                   pabyData, nDataPos, nDataSize ) );
     695                 : }
     696                 : 
     697                 : /************************************************************************/
     698                 : /*                            GetIntField()                             */
     699                 : /************************************************************************/
     700                 : 
     701            8670 : GInt32 HFAEntry::GetIntField( const char * pszFieldPath, CPLErr *peErr )
     702                 : 
     703                 : {
     704                 :     GInt32  nIntValue;
     705                 : 
     706            8670 :     if( !GetFieldValue( pszFieldPath, 'i', &nIntValue, NULL ) )
     707                 :     {
     708              13 :         if( peErr != NULL )
     709               9 :             *peErr = CE_Failure;
     710                 : 
     711              13 :         return 0;
     712                 :     }
     713                 :     else
     714                 :     {
     715            8657 :         if( peErr != NULL )
     716              96 :             *peErr = CE_None;
     717                 : 
     718            8657 :         return nIntValue;
     719                 :     }
     720                 : }
     721                 : 
     722                 : /************************************************************************/
     723                 : /*                           GetBigIntField()                           */
     724                 : /*                                                                      */
     725                 : /*      This is just a helper method that reads two ULONG array         */
     726                 : /*      entries as a GBigInt.  The passed name should be the name of    */
     727                 : /*      the array with no array index.  Array indexes 0 and 1 will      */
     728                 : /*      be concatenated.                                                */
     729                 : /************************************************************************/
     730                 : 
     731              50 : GIntBig HFAEntry::GetBigIntField( const char *pszFieldPath, CPLErr *peErr )
     732                 : 
     733                 : {
     734                 :     GUInt32 nLower, nUpper;
     735                 :     char szFullFieldPath[1024];
     736                 : 
     737              50 :     sprintf( szFullFieldPath, "%s[0]", pszFieldPath );
     738              50 :     nLower = GetIntField( szFullFieldPath, peErr );
     739              50 :     if( peErr != NULL && *peErr != CE_None )
     740               0 :         return 0;
     741                 : 
     742              50 :     sprintf( szFullFieldPath, "%s[1]", pszFieldPath );
     743              50 :     nUpper = GetIntField( szFullFieldPath, peErr );
     744              50 :     if( peErr != NULL && *peErr != CE_None )
     745               0 :         return 0;
     746                 : 
     747              50 :     return nLower + (((GIntBig) nUpper) << 32);
     748                 : }
     749                 : 
     750                 : /************************************************************************/
     751                 : /*                           GetDoubleField()                           */
     752                 : /************************************************************************/
     753                 : 
     754            2153 : double HFAEntry::GetDoubleField( const char * pszFieldPath, CPLErr *peErr )
     755                 : 
     756                 : {
     757                 :     double dfDoubleValue;
     758                 : 
     759            2153 :     if( !GetFieldValue( pszFieldPath, 'd', &dfDoubleValue, NULL ) )
     760                 :     {
     761             138 :         if( peErr != NULL )
     762              18 :             *peErr = CE_Failure;
     763                 : 
     764             138 :         return 0.0;
     765                 :     }
     766                 :     else
     767                 :     {
     768            2015 :         if( peErr != NULL )
     769             533 :             *peErr = CE_None;
     770                 : 
     771            2015 :         return dfDoubleValue;
     772                 :     }
     773                 : }
     774                 : 
     775                 : /************************************************************************/
     776                 : /*                           GetStringField()                           */
     777                 : /************************************************************************/
     778                 : 
     779                 : const char *HFAEntry::GetStringField( const char * pszFieldPath, CPLErr *peErr,
     780            1351 :                                       int *pnRemainingDataSize)
     781                 : 
     782                 : {
     783            1351 :     char *pszResult = NULL;
     784                 : 
     785            1351 :     if( !GetFieldValue( pszFieldPath, 's', &pszResult, pnRemainingDataSize ) )
     786                 :     {
     787              63 :         if( peErr != NULL )
     788              11 :             *peErr = CE_Failure;
     789                 : 
     790              63 :         return NULL;
     791                 :     }
     792                 :     else
     793                 :     {
     794            1288 :         if( peErr != NULL )
     795             495 :             *peErr = CE_None;
     796                 : 
     797            1288 :         return pszResult;
     798                 :     }
     799                 : }
     800                 : 
     801                 : /************************************************************************/
     802                 : /*                           SetFieldValue()                            */
     803                 : /************************************************************************/
     804                 :         
     805                 : CPLErr HFAEntry::SetFieldValue( const char * pszFieldPath,
     806            7177 :                                 char chReqType, void *pValue )
     807                 : 
     808                 : {
     809            7177 :     HFAEntry  *poEntry = this;
     810                 :     
     811                 : /* -------------------------------------------------------------------- */
     812                 : /*      Is there a node path in this string?                            */
     813                 : /* -------------------------------------------------------------------- */
     814            7177 :     if( strchr(pszFieldPath,':') != NULL )
     815                 :     {
     816               0 :         poEntry = GetNamedChild( pszFieldPath );
     817               0 :         if( poEntry == NULL )
     818               0 :             return CE_Failure;
     819                 :         
     820               0 :         pszFieldPath = strchr(pszFieldPath,':') + 1;
     821                 :     }
     822                 : 
     823                 : /* -------------------------------------------------------------------- */
     824                 : /*      Do we have the data and type for this node?  Try loading        */
     825                 : /*      from a file, or instantiating a new node.                       */
     826                 : /* -------------------------------------------------------------------- */
     827            7177 :     LoadData();
     828            7177 :     if( MakeData() == NULL 
     829                 :         || pabyData == NULL
     830                 :         || poType == NULL )
     831                 :     {
     832               0 :         CPLAssert( FALSE );
     833               0 :         return CE_Failure;
     834                 :     }
     835                 : 
     836                 : /* -------------------------------------------------------------------- */
     837                 : /*      Extract the instance information.                               */
     838                 : /* -------------------------------------------------------------------- */
     839            7177 :     MarkDirty();
     840                 : 
     841                 :     return( poType->SetInstValue( pszFieldPath,
     842                 :                                   pabyData, nDataPos, nDataSize,
     843            7177 :                                   chReqType, pValue ) );
     844                 : }
     845                 : 
     846                 : /************************************************************************/
     847                 : /*                           SetStringField()                           */
     848                 : /************************************************************************/
     849                 : 
     850                 : CPLErr HFAEntry::SetStringField( const char * pszFieldPath, 
     851            1691 :                                  const char * pszValue )
     852                 : 
     853                 : {
     854            1691 :     return SetFieldValue( pszFieldPath, 's', (void *) pszValue );
     855                 : }
     856                 : 
     857                 : /************************************************************************/
     858                 : /*                            SetIntField()                             */
     859                 : /************************************************************************/
     860                 : 
     861            2399 : CPLErr HFAEntry::SetIntField( const char * pszFieldPath, int nValue )
     862                 : 
     863                 : {
     864            2399 :     return SetFieldValue( pszFieldPath, 'i', &nValue );
     865                 : }
     866                 : 
     867                 : /************************************************************************/
     868                 : /*                           SetDoubleField()                           */
     869                 : /************************************************************************/
     870                 : 
     871                 : CPLErr HFAEntry::SetDoubleField( const char * pszFieldPath,
     872            3087 :                                  double dfValue )
     873                 : 
     874                 : {
     875            3087 :     return SetFieldValue( pszFieldPath, 'd', &dfValue );
     876                 : }
     877                 : 
     878                 : /************************************************************************/
     879                 : /*                            SetPosition()                             */
     880                 : /*                                                                      */
     881                 : /*      Set the disk position for this entry, and recursively apply     */
     882                 : /*      to any children of this node.  The parent will take care of     */
     883                 : /*      our siblings.                                                   */
     884                 : /************************************************************************/
     885                 : 
     886            2749 : void HFAEntry::SetPosition()
     887                 : 
     888                 : {
     889                 : /* -------------------------------------------------------------------- */
     890                 : /*      Establish the location of this entry, and it's data.            */
     891                 : /* -------------------------------------------------------------------- */
     892            2749 :     if( nFilePos == 0 )
     893                 :     {
     894                 :         nFilePos = HFAAllocateSpace( psHFA, 
     895                 :                                      psHFA->nEntryHeaderLength 
     896            1278 :                                      + nDataSize );
     897                 : 
     898            1278 :         if( nDataSize > 0 )
     899            1172 :             nDataPos = nFilePos + psHFA->nEntryHeaderLength;
     900                 :     }
     901                 : 
     902                 : /* -------------------------------------------------------------------- */
     903                 : /*      Force all children to set their position.                       */
     904                 : /* -------------------------------------------------------------------- */
     905            4559 :     for( HFAEntry *poThisChild = poChild; 
     906                 :          poThisChild != NULL;
     907                 :          poThisChild = poThisChild->poNext )
     908                 :     {
     909            1810 :         poThisChild->SetPosition();
     910                 :     }
     911            2749 : }
     912                 : 
     913                 : /************************************************************************/
     914                 : /*                            FlushToDisk()                             */
     915                 : /*                                                                      */
     916                 : /*      Write this entry, and it's data to disk if the entries          */
     917                 : /*      information is dirty.  Also force children to do the same.      */
     918                 : /************************************************************************/
     919                 : 
     920            2019 : CPLErr HFAEntry::FlushToDisk()
     921                 : 
     922                 : {
     923            2019 :     CPLErr  eErr = CE_None;
     924                 : 
     925                 : /* -------------------------------------------------------------------- */
     926                 : /*      If we are the root node, call SetPosition() on the whole        */
     927                 : /*      tree to ensure that all entries have an allocated position.     */
     928                 : /* -------------------------------------------------------------------- */
     929            2019 :     if( poParent == NULL )
     930             209 :         SetPosition();
     931                 : 
     932                 : /* ==================================================================== */
     933                 : /*      Only write this node out if it is dirty.                        */
     934                 : /* ==================================================================== */
     935            2019 :     if( bDirty )
     936                 :     {
     937                 : /* -------------------------------------------------------------------- */
     938                 : /*      Ensure we know where the relative entries are located.          */
     939                 : /* -------------------------------------------------------------------- */
     940            1527 :         if( poNext != NULL )
     941             841 :             nNextPos = poNext->nFilePos;
     942                 :         else
     943             686 :             nNextPos = 0;
     944                 : 
     945            1527 :         if( poChild != NULL )
     946             469 :             nChildPos = poChild->nFilePos;
     947                 :         else
     948            1058 :             nChildPos = 0;
     949                 : 
     950                 : /* -------------------------------------------------------------------- */
     951                 : /*      Write the Ehfa_Entry fields.                                    */
     952                 : /* -------------------------------------------------------------------- */
     953                 :         GUInt32   nLong;
     954                 : 
     955                 :         //VSIFFlushL( psHFA->fp );
     956            1527 :         if( VSIFSeekL( psHFA->fp, nFilePos, SEEK_SET ) != 0 )
     957                 :         {
     958                 :             CPLError( CE_Failure, CPLE_FileIO, 
     959                 :                       "Failed to seek to %d for writing, out of disk space?",
     960               0 :                       nFilePos );
     961               0 :             return CE_Failure;
     962                 :         }
     963                 : 
     964            1527 :         nLong = nNextPos;
     965                 :         HFAStandard( 4, &nLong );
     966            1527 :         VSIFWriteL( &nLong, 4, 1, psHFA->fp );
     967                 : 
     968            1527 :         if( poPrev != NULL )
     969             916 :             nLong = poPrev->nFilePos;
     970                 :         else
     971             611 :             nLong = 0;
     972                 :         HFAStandard( 4, &nLong );
     973            1527 :         VSIFWriteL( &nLong, 4, 1, psHFA->fp );
     974                 : 
     975            1527 :         if( poParent != NULL )
     976            1422 :             nLong = poParent->nFilePos;
     977                 :         else
     978             105 :             nLong = 0;
     979                 :         HFAStandard( 4, &nLong );
     980            1527 :         VSIFWriteL( &nLong, 4, 1, psHFA->fp );
     981                 : 
     982            1527 :         nLong = nChildPos;
     983                 :         HFAStandard( 4, &nLong );
     984            1527 :         VSIFWriteL( &nLong, 4, 1, psHFA->fp );
     985                 : 
     986                 :         
     987            1527 :         nLong = nDataPos;
     988                 :         HFAStandard( 4, &nLong );
     989            1527 :         VSIFWriteL( &nLong, 4, 1, psHFA->fp );
     990                 : 
     991            1527 :         nLong = nDataSize;
     992                 :         HFAStandard( 4, &nLong );
     993            1527 :         VSIFWriteL( &nLong, 4, 1, psHFA->fp );
     994                 : 
     995            1527 :         VSIFWriteL( szName, 1, 64, psHFA->fp );
     996            1527 :         VSIFWriteL( szType, 1, 32, psHFA->fp );
     997                 : 
     998            1527 :         nLong = 0; /* Should we keep the time, or set it more reasonably? */
     999            1527 :         if( VSIFWriteL( &nLong, 4, 1, psHFA->fp ) != 1 )
    1000                 :         {
    1001                 :             CPLError( CE_Failure, CPLE_FileIO, 
    1002                 :                       "Failed to write HFAEntry %s(%s), out of disk space?",
    1003               0 :                       szName, szType );
    1004               0 :             return CE_Failure;
    1005                 :         }
    1006                 : 
    1007                 : /* -------------------------------------------------------------------- */
    1008                 : /*      Write out the data.                                             */
    1009                 : /* -------------------------------------------------------------------- */
    1010                 :         //VSIFFlushL( psHFA->fp );
    1011            1527 :         if( nDataSize > 0 && pabyData != NULL )
    1012                 :         {
    1013            1311 :             if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) != 0 
    1014                 :                 || VSIFWriteL( pabyData, nDataSize, 1, psHFA->fp ) != 1 )
    1015                 :             {
    1016                 :                 CPLError( CE_Failure, CPLE_FileIO, 
    1017                 :                           "Failed to write %d bytes HFAEntry %s(%s) data,\n"
    1018                 :                           "out of disk space?",
    1019               0 :                           nDataSize, szName, szType );
    1020               0 :                 return CE_Failure;
    1021                 :             }
    1022                 :         }
    1023                 : 
    1024                 :         //VSIFFlushL( psHFA->fp );
    1025                 :     }
    1026                 : 
    1027                 : /* -------------------------------------------------------------------- */
    1028                 : /*      Process all the children of this node                           */
    1029                 : /* -------------------------------------------------------------------- */
    1030            3829 :     for( HFAEntry *poThisChild = poChild; 
    1031                 :          poThisChild != NULL;
    1032                 :          poThisChild = poThisChild->poNext )
    1033                 :     {
    1034            1810 :         eErr = poThisChild->FlushToDisk();
    1035            1810 :         if( eErr != CE_None )
    1036               0 :             return eErr;
    1037                 :     }
    1038                 : 
    1039            2019 :     bDirty = FALSE;
    1040                 : 
    1041            2019 :     return CE_None;
    1042                 : }
    1043                 : 
    1044                 : /************************************************************************/
    1045                 : /*                             MarkDirty()                              */
    1046                 : /*                                                                      */
    1047                 : /*      Mark this node as dirty (in need of writing to disk), and       */
    1048                 : /*      also mark the tree as a whole as being dirty.                   */
    1049                 : /************************************************************************/
    1050                 : 
    1051           12374 : void HFAEntry::MarkDirty()
    1052                 : 
    1053                 : {
    1054           12374 :     bDirty = TRUE;
    1055           12374 :     psHFA->bTreeDirty = TRUE;
    1056           12374 : }
    1057                 : 

Generated by: LTP GCOV extension version 1.5