LCOV - code coverage report
Current view: directory - frmts/hfa - hfaentry.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 319 244 76.5 %
Date: 2010-01-09 Functions: 27 25 92.6 %

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

Generated by: LCOV version 1.7