LCOV - code coverage report
Current view: directory - frmts/hfa - hfaentry.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 369 303 82.1 %
Date: 2011-12-18 Functions: 33 27 81.8 %

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

Generated by: LCOV version 1.7