LTP GCOV extension - code coverage report
Current view: directory - frmts/iso8211 - ddfmodule.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 232
Code covered: 57.8 % Executed lines: 134

       1                 : /******************************************************************************
       2                 :  * $Id: ddfmodule.cpp 17405 2009-07-17 06:13:24Z chaitanya $
       3                 :  *
       4                 :  * Project:  ISO 8211 Access
       5                 :  * Purpose:  Implements the DDFModule class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "iso8211.h"
      31                 : #include "cpl_conv.h"
      32                 : 
      33                 : CPL_CVSID("$Id: ddfmodule.cpp 17405 2009-07-17 06:13:24Z chaitanya $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                             DDFModule()                              */
      37                 : /************************************************************************/
      38                 : 
      39                 : /**
      40                 :  * The constructor.
      41                 :  */
      42                 : 
      43            9633 : DDFModule::DDFModule()
      44                 : 
      45                 : {
      46            9633 :     nFieldDefnCount = 0;
      47            9633 :     papoFieldDefns = NULL;
      48            9633 :     poRecord = NULL;
      49                 : 
      50            9633 :     papoClones = NULL;
      51            9633 :     nCloneCount = nMaxCloneCount = 0;
      52                 : 
      53            9633 :     fpDDF = NULL;
      54            9633 :     bReadOnly = TRUE;
      55                 : 
      56            9633 :     _interchangeLevel = '\0';
      57            9633 :     _inlineCodeExtensionIndicator = '\0';
      58            9633 :     _versionNumber = '\0';
      59            9633 :     _appIndicator = '\0';
      60            9633 :     _fieldControlLength = '\0';
      61            9633 :     strcpy( _extendedCharSet, " ! " );
      62                 : 
      63            9633 :     _recLength = 0;
      64            9633 :     _leaderIden = 'L';
      65            9633 :     _fieldAreaStart = 0;
      66            9633 :     _sizeFieldLength = 0;
      67            9633 :     _sizeFieldPos = 0;
      68            9633 :     _sizeFieldTag = 0;
      69            9633 : }
      70                 : 
      71                 : /************************************************************************/
      72                 : /*                             ~DDFModule()                             */
      73                 : /************************************************************************/
      74                 : 
      75                 : /**
      76                 :  * The destructor.
      77                 :  */
      78                 : 
      79            9633 : DDFModule::~DDFModule()
      80                 : 
      81                 : {
      82            9633 :     Close();
      83            9633 : }
      84                 : 
      85                 : /************************************************************************/
      86                 : /*                               Close()                                */
      87                 : /*                                                                      */
      88                 : /*      Note that closing a file also destroys essentially all other    */
      89                 : /*      module datastructures.                                          */
      90                 : /************************************************************************/
      91                 : 
      92                 : /**
      93                 :  * Close an ISO 8211 file.
      94                 :  */
      95                 : 
      96            9641 : void DDFModule::Close()
      97                 : 
      98                 : {
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Close the file.                                                 */
     101                 : /* -------------------------------------------------------------------- */
     102            9641 :     if( fpDDF != NULL )
     103                 :     {
     104              63 :         VSIFCloseL( fpDDF );
     105              63 :         fpDDF = NULL;
     106                 :     }
     107                 : 
     108                 : /* -------------------------------------------------------------------- */
     109                 : /*      Cleanup the working record.                                     */
     110                 : /* -------------------------------------------------------------------- */
     111            9641 :     if( poRecord != NULL )
     112                 :     {
     113              52 :         delete poRecord;
     114              52 :         poRecord = NULL;
     115                 :     }
     116                 : 
     117                 : /* -------------------------------------------------------------------- */
     118                 : /*      Cleanup the clones.  Deleting them will cause a callback to     */
     119                 : /*      remove them from the list.                                      */
     120                 : /* -------------------------------------------------------------------- */
     121           19674 :     while( nCloneCount > 0 )
     122             392 :         delete papoClones[0];
     123                 : 
     124            9641 :     nMaxCloneCount = 0;
     125            9641 :     CPLFree( papoClones );
     126            9641 :     papoClones = NULL;
     127                 :     
     128                 : /* -------------------------------------------------------------------- */
     129                 : /*      Cleanup the field definitions.                                  */
     130                 : /* -------------------------------------------------------------------- */
     131                 :     int i;
     132                 : 
     133           10113 :     for( i = 0; i < nFieldDefnCount; i++ )
     134             472 :         delete papoFieldDefns[i];
     135            9641 :     CPLFree( papoFieldDefns );
     136            9641 :     papoFieldDefns = NULL;
     137            9641 :     nFieldDefnCount = 0;
     138            9641 : }
     139                 : 
     140                 : /************************************************************************/
     141                 : /*                                Open()                                */
     142                 : /*                                                                      */
     143                 : /*      Open an ISO 8211 file, and read the DDR record to build the     */
     144                 : /*      field definitions.                                              */
     145                 : /************************************************************************/
     146                 : 
     147                 : /**
     148                 :  * Open a ISO 8211 (DDF) file for reading.
     149                 :  *
     150                 :  * If the open succeeds the data descriptive record (DDR) will have been
     151                 :  * read, and all the field and subfield definitions will be available.
     152                 :  *
     153                 :  * @param pszFilename   The name of the file to open.
     154                 :  * @param bFailQuietly If FALSE a CPL Error is issued for non-8211 files, 
     155                 :  * otherwise quietly return NULL.
     156                 :  *
     157                 :  * @return FALSE if the open fails or TRUE if it succeeds.  Errors messages
     158                 :  * are issued internally with CPLError().
     159                 :  */
     160                 : 
     161              66 : int DDFModule::Open( const char * pszFilename, int bFailQuietly )
     162                 : 
     163                 : {
     164                 :     static const size_t nLeaderSize = 24;
     165                 : 
     166                 : /* -------------------------------------------------------------------- */
     167                 : /*      Close the existing file if there is one.                        */
     168                 : /* -------------------------------------------------------------------- */
     169              66 :     if( fpDDF != NULL )
     170               0 :         Close();
     171                 :     
     172                 : /* -------------------------------------------------------------------- */
     173                 : /*      Open the file.                                                  */
     174                 : /* -------------------------------------------------------------------- */
     175              66 :     fpDDF = VSIFOpenL( pszFilename, "rb" );
     176                 : 
     177              66 :     if( fpDDF == NULL )
     178                 :     {
     179               3 :         if( !bFailQuietly )
     180                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     181                 :                       "Unable to open DDF file `%s'.",
     182               0 :                       pszFilename );
     183               3 :         return FALSE;
     184                 :     }
     185                 : 
     186                 : /* -------------------------------------------------------------------- */
     187                 : /*      Read the 24 byte leader.                                        */
     188                 : /* -------------------------------------------------------------------- */
     189                 :     char        achLeader[nLeaderSize];
     190                 :     
     191              63 :     if( VSIFReadL( achLeader, 1, nLeaderSize, fpDDF ) != nLeaderSize )
     192                 :     {
     193               0 :         VSIFCloseL( fpDDF );
     194               0 :         fpDDF = NULL;
     195                 : 
     196               0 :         if( !bFailQuietly )
     197                 :             CPLError( CE_Failure, CPLE_FileIO,
     198                 :                       "Leader is short on DDF file `%s'.",
     199               0 :                       pszFilename );
     200                 :         
     201               0 :         return FALSE;
     202                 :     }
     203                 : 
     204                 : /* -------------------------------------------------------------------- */
     205                 : /*      Verify that this appears to be a valid DDF file.                */
     206                 : /* -------------------------------------------------------------------- */
     207              63 :     int         i, bValid = TRUE;
     208                 : 
     209            1575 :     for( i = 0; i < (int)nLeaderSize; i++ )
     210                 :     {
     211            1512 :         if( achLeader[i] < 32 || achLeader[i] > 126 )
     212               0 :             bValid = FALSE;
     213                 :     }
     214                 : 
     215              63 :     if( achLeader[5] != '1' && achLeader[5] != '2' && achLeader[5] != '3' )
     216               0 :         bValid = FALSE;
     217                 : 
     218              63 :     if( achLeader[6] != 'L' )
     219               0 :         bValid = FALSE;
     220              63 :     if( achLeader[8] != '1' && achLeader[8] != ' ' )
     221               0 :         bValid = FALSE;
     222                 : 
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      Extract information from leader.                                */
     225                 : /* -------------------------------------------------------------------- */
     226                 : 
     227              63 :     if( bValid )
     228                 :     {
     229              63 :         _recLength                        = DDFScanInt( achLeader+0, 5 );
     230              63 :         _interchangeLevel                 = achLeader[5];
     231              63 :         _leaderIden                   = achLeader[6];
     232              63 :         _inlineCodeExtensionIndicator = achLeader[7];
     233              63 :         _versionNumber                = achLeader[8];
     234              63 :         _appIndicator                 = achLeader[9];
     235              63 :         _fieldControlLength           = DDFScanInt(achLeader+10,2);
     236              63 :         _fieldAreaStart               = DDFScanInt(achLeader+12,5);
     237              63 :         _extendedCharSet[0]           = achLeader[17];
     238              63 :         _extendedCharSet[1]           = achLeader[18];
     239              63 :         _extendedCharSet[2]           = achLeader[19];
     240              63 :         _extendedCharSet[3]           = '\0';
     241              63 :         _sizeFieldLength              = DDFScanInt(achLeader+20,1);
     242              63 :         _sizeFieldPos                 = DDFScanInt(achLeader+21,1);
     243              63 :         _sizeFieldTag                 = DDFScanInt(achLeader+23,1);
     244                 : 
     245              63 :         if( _recLength < 12 || _fieldControlLength == 0
     246                 :             || _fieldAreaStart < 24 || _sizeFieldLength == 0
     247                 :             || _sizeFieldPos == 0 || _sizeFieldTag == 0 )
     248                 :         {
     249               0 :             bValid = FALSE;
     250                 :         }
     251                 :     }
     252                 : 
     253                 : /* -------------------------------------------------------------------- */
     254                 : /*      If the header is invalid, then clean up, report the error       */
     255                 : /*      and return.                                                     */
     256                 : /* -------------------------------------------------------------------- */
     257              63 :     if( !bValid )
     258                 :     {
     259               0 :         VSIFCloseL( fpDDF );
     260               0 :         fpDDF = NULL;
     261                 : 
     262               0 :         if( !bFailQuietly )
     263                 :             CPLError( CE_Failure, CPLE_AppDefined,
     264                 :                       "File `%s' does not appear to have\n"
     265                 :                       "a valid ISO 8211 header.\n",
     266               0 :                       pszFilename );
     267               0 :         return FALSE;
     268                 :     }
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Read the whole record info memory.                              */
     272                 : /* -------------------------------------------------------------------- */
     273                 :     char        *pachRecord;
     274                 : 
     275              63 :     pachRecord = (char *) CPLMalloc(_recLength);
     276              63 :     memcpy( pachRecord, achLeader, nLeaderSize );
     277                 : 
     278              63 :     if( VSIFReadL( pachRecord+nLeaderSize, 1, _recLength-nLeaderSize, fpDDF )
     279                 :         != _recLength - nLeaderSize )
     280                 :     {
     281               0 :         if( !bFailQuietly )
     282                 :             CPLError( CE_Failure, CPLE_FileIO,
     283                 :                       "Header record is short on DDF file `%s'.",
     284               0 :                       pszFilename );
     285                 :         
     286               0 :         return FALSE;
     287                 :     }
     288                 : 
     289                 : /* -------------------------------------------------------------------- */
     290                 : /*      First make a pass counting the directory entries.               */
     291                 : /* -------------------------------------------------------------------- */
     292              63 :     int         nFieldEntryWidth, nFDCount = 0;
     293                 : 
     294              63 :     nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag;
     295                 : 
     296             535 :     for( i = nLeaderSize; i < _recLength; i += nFieldEntryWidth )
     297                 :     {
     298             535 :         if( pachRecord[i] == DDF_FIELD_TERMINATOR )
     299              63 :             break;
     300                 : 
     301             472 :         nFDCount++;
     302                 :     }
     303                 : 
     304                 : /* -------------------------------------------------------------------- */
     305                 : /*      Allocate, and read field definitions.                           */
     306                 : /* -------------------------------------------------------------------- */
     307             535 :     for( i = 0; i < nFDCount; i++ )
     308                 :     {
     309                 :         char    szTag[128];
     310             472 :         int     nEntryOffset = nLeaderSize + i*nFieldEntryWidth;
     311                 :         int     nFieldLength, nFieldPos;
     312                 :         DDFFieldDefn *poFDefn;
     313                 :         
     314             472 :         strncpy( szTag, pachRecord+nEntryOffset, _sizeFieldTag );
     315             472 :         szTag[_sizeFieldTag] = '\0';
     316                 : 
     317             472 :         nEntryOffset += _sizeFieldTag;
     318             472 :         nFieldLength = DDFScanInt( pachRecord+nEntryOffset, _sizeFieldLength );
     319                 :         
     320             472 :         nEntryOffset += _sizeFieldLength;
     321             472 :         nFieldPos = DDFScanInt( pachRecord+nEntryOffset, _sizeFieldPos );
     322                 :         
     323             472 :         poFDefn = new DDFFieldDefn();
     324             472 :         if( poFDefn->Initialize( this, szTag, nFieldLength,
     325                 :                                  pachRecord+_fieldAreaStart+nFieldPos ) )
     326             472 :             AddField( poFDefn );
     327                 :         else
     328               0 :             delete poFDefn;
     329                 :     }
     330                 : 
     331              63 :     CPLFree( pachRecord );
     332                 :     
     333                 : /* -------------------------------------------------------------------- */
     334                 : /*      Record the current file offset, the beginning of the first      */
     335                 : /*      data record.                                                    */
     336                 : /* -------------------------------------------------------------------- */
     337              63 :     nFirstRecordOffset = (long)VSIFTellL( fpDDF );
     338                 :     
     339              63 :     return TRUE;
     340                 : }
     341                 : 
     342                 : /************************************************************************/
     343                 : /*                             Initialize()                             */
     344                 : /************************************************************************/
     345                 : 
     346                 : int DDFModule::Initialize( char chInterchangeLevel,
     347                 :                            char chLeaderIden, 
     348                 :                            char chCodeExtensionIndicator,
     349                 :                            char chVersionNumber,
     350                 :                            char chAppIndicator,
     351                 :                            const char *pszExtendedCharSet,
     352                 :                            int nSizeFieldLength,
     353                 :                            int nSizeFieldPos,
     354               0 :                            int nSizeFieldTag )
     355                 : 
     356                 : {
     357               0 :     _interchangeLevel = chInterchangeLevel;
     358               0 :     _leaderIden = chLeaderIden;
     359               0 :     _inlineCodeExtensionIndicator = chCodeExtensionIndicator;
     360               0 :     _versionNumber = chVersionNumber;
     361               0 :     _appIndicator = chAppIndicator;
     362               0 :     strcpy( _extendedCharSet, pszExtendedCharSet );
     363               0 :     _sizeFieldLength = nSizeFieldLength;
     364               0 :     _sizeFieldPos = nSizeFieldPos;
     365               0 :     _sizeFieldTag = nSizeFieldTag;
     366                 : 
     367               0 :     return TRUE;
     368                 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                               Create()                               */
     372                 : /************************************************************************/
     373                 : 
     374               0 : int DDFModule::Create( const char *pszFilename )
     375                 : 
     376                 : {
     377               0 :     CPLAssert( fpDDF == NULL );
     378                 :     
     379                 : /* -------------------------------------------------------------------- */
     380                 : /*      Create the file on disk.                                        */
     381                 : /* -------------------------------------------------------------------- */
     382               0 :     fpDDF = VSIFOpenL( pszFilename, "wb+" );
     383               0 :     if( fpDDF == NULL )
     384                 :     {
     385                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     386                 :                   "Failed to create file %s, check path and permissions.",
     387               0 :                   pszFilename );
     388               0 :         return FALSE;
     389                 :     }
     390                 :     
     391               0 :     bReadOnly = FALSE;
     392                 : 
     393                 : /* -------------------------------------------------------------------- */
     394                 : /*      Prepare all the field definition information.                   */
     395                 : /* -------------------------------------------------------------------- */
     396                 :     int iField;
     397                 : 
     398               0 :     _fieldControlLength = 9;
     399                 :     _recLength = 24 
     400                 :         + nFieldDefnCount * (_sizeFieldLength+_sizeFieldPos+_sizeFieldTag) 
     401               0 :         + 1;
     402                 :     
     403               0 :     _fieldAreaStart = _recLength;
     404                 : 
     405               0 :     for( iField=0; iField < nFieldDefnCount; iField++ )
     406                 :     {
     407                 :         int nLength;
     408                 : 
     409               0 :         papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength );
     410               0 :         _recLength += nLength;
     411                 :     }
     412                 : 
     413                 : /* -------------------------------------------------------------------- */
     414                 : /*      Setup 24 byte leader.                                           */
     415                 : /* -------------------------------------------------------------------- */
     416                 :     char achLeader[25];
     417                 : 
     418               0 :     sprintf( achLeader+0, "%05d", (int) _recLength );
     419               0 :     achLeader[5] = _interchangeLevel;
     420               0 :     achLeader[6] = _leaderIden;
     421               0 :     achLeader[7] = _inlineCodeExtensionIndicator;
     422               0 :     achLeader[8] = _versionNumber;
     423               0 :     achLeader[9] = _appIndicator;
     424               0 :     sprintf( achLeader+10, "%02d", (int) _fieldControlLength );
     425               0 :     sprintf( achLeader+12, "%05d", (int) _fieldAreaStart );
     426               0 :     strncpy( achLeader+17, _extendedCharSet, 3 );
     427               0 :     sprintf( achLeader+20, "%1d", (int) _sizeFieldLength );
     428               0 :     sprintf( achLeader+21, "%1d", (int) _sizeFieldPos );
     429               0 :     achLeader[22] = '0';
     430               0 :     sprintf( achLeader+23, "%1d", (int) _sizeFieldTag );
     431               0 :     VSIFWriteL( achLeader, 24, 1, fpDDF );
     432                 : 
     433                 : /* -------------------------------------------------------------------- */
     434                 : /*      Write out directory entries.                                    */
     435                 : /* -------------------------------------------------------------------- */
     436               0 :     int nOffset = 0;
     437               0 :     for( iField=0; iField < nFieldDefnCount; iField++ )
     438                 :     {
     439                 :         char achDirEntry[12];
     440                 :         int nLength;
     441                 : 
     442               0 :         papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength );
     443                 : 
     444               0 :         strcpy( achDirEntry, papoFieldDefns[iField]->GetName() );
     445               0 :         sprintf( achDirEntry + _sizeFieldTag, "%03d", nLength );
     446                 :         sprintf( achDirEntry + _sizeFieldTag + _sizeFieldLength, 
     447               0 :                  "%04d", nOffset );
     448               0 :         nOffset += nLength;
     449                 : 
     450               0 :         VSIFWriteL( achDirEntry, 11, 1, fpDDF );
     451                 :     }
     452                 : 
     453               0 :     char chUT = DDF_FIELD_TERMINATOR;
     454               0 :     VSIFWriteL( &chUT, 1, 1, fpDDF );
     455                 : 
     456                 : /* -------------------------------------------------------------------- */
     457                 : /*      Write out the field descriptions themselves.                    */
     458                 : /* -------------------------------------------------------------------- */
     459               0 :     for( iField=0; iField < nFieldDefnCount; iField++ )
     460                 :     {
     461                 :         char *pachData;
     462                 :         int nLength;
     463                 : 
     464               0 :         papoFieldDefns[iField]->GenerateDDREntry( &pachData, &nLength );
     465               0 :         VSIFWriteL( pachData, nLength, 1, fpDDF );
     466               0 :         CPLFree( pachData );
     467                 :     }
     468                 :     
     469               0 :     return TRUE;
     470                 : }
     471                 : 
     472                 : /************************************************************************/
     473                 : /*                                Dump()                                */
     474                 : /************************************************************************/
     475                 : 
     476                 : /**
     477                 :  * Write out module info to debugging file.
     478                 :  *
     479                 :  * A variety of information about the module is written to the debugging
     480                 :  * file.  This includes all the field and subfield definitions read from
     481                 :  * the header. 
     482                 :  *
     483                 :  * @param fp The standard io file handle to write to.  ie. stderr.
     484                 :  */
     485                 : 
     486               0 : void DDFModule::Dump( FILE * fp )
     487                 : 
     488                 : {
     489               0 :     fprintf( fp, "DDFModule:\n" );
     490               0 :     fprintf( fp, "    _recLength = %ld\n", _recLength );
     491               0 :     fprintf( fp, "    _interchangeLevel = %c\n", _interchangeLevel );
     492               0 :     fprintf( fp, "    _leaderIden = %c\n", _leaderIden );
     493                 :     fprintf( fp, "    _inlineCodeExtensionIndicator = %c\n",
     494               0 :              _inlineCodeExtensionIndicator );
     495               0 :     fprintf( fp, "    _versionNumber = %c\n", _versionNumber );
     496               0 :     fprintf( fp, "    _appIndicator = %c\n", _appIndicator );
     497               0 :     fprintf( fp, "    _extendedCharSet = `%s'\n", _extendedCharSet );
     498               0 :     fprintf( fp, "    _fieldControlLength = %d\n", _fieldControlLength );
     499               0 :     fprintf( fp, "    _fieldAreaStart = %ld\n", _fieldAreaStart );
     500               0 :     fprintf( fp, "    _sizeFieldLength = %ld\n", _sizeFieldLength );
     501               0 :     fprintf( fp, "    _sizeFieldPos = %ld\n", _sizeFieldPos );
     502               0 :     fprintf( fp, "    _sizeFieldTag = %ld\n", _sizeFieldTag );
     503                 : 
     504               0 :     for( int i = 0; i < nFieldDefnCount; i++ )
     505                 :     {
     506               0 :         papoFieldDefns[i]->Dump( fp );
     507                 :     }
     508               0 : }
     509                 : 
     510                 : /************************************************************************/
     511                 : /*                           FindFieldDefn()                            */
     512                 : /************************************************************************/
     513                 : 
     514                 : /**
     515                 :  * Fetch the definition of the named field.
     516                 :  *
     517                 :  * This function will scan the DDFFieldDefn's on this module, to find
     518                 :  * one with the indicated field name.
     519                 :  *
     520                 :  * @param pszFieldName The name of the field to search for.  The comparison is
     521                 :  *                     case insensitive.
     522                 :  *
     523                 :  * @return A pointer to the request DDFFieldDefn object is returned, or NULL
     524                 :  * if none matching the name are found.  The return object remains owned by
     525                 :  * the DDFModule, and should not be deleted by application code.
     526                 :  */
     527                 : 
     528            3295 : DDFFieldDefn *DDFModule::FindFieldDefn( const char *pszFieldName )
     529                 : 
     530                 : {
     531                 :     int         i;
     532                 :     
     533                 : /* -------------------------------------------------------------------- */
     534                 : /*      This pass tries to reduce the cost of comparing strings by      */
     535                 : /*      first checking the first character, and by using strcmp()       */
     536                 : /* -------------------------------------------------------------------- */
     537           22527 :     for( i = 0; i < nFieldDefnCount; i++ )
     538                 :     {
     539           22512 :         const char *pszThisName = papoFieldDefns[i]->GetName();
     540                 :         
     541           22512 :         if( *pszThisName == *pszFieldName
     542                 :             && strcmp( pszFieldName+1, pszThisName+1) == 0 )
     543            3280 :             return papoFieldDefns[i];
     544                 :     }
     545                 : 
     546                 : /* -------------------------------------------------------------------- */
     547                 : /*      Now do a more general check.  Application code may not          */
     548                 : /*      always use the correct name case.                               */
     549                 : /* -------------------------------------------------------------------- */
     550             130 :     for( i = 0; i < nFieldDefnCount; i++ )
     551                 :     {
     552             115 :         if( EQUAL(pszFieldName, papoFieldDefns[i]->GetName()) )
     553               0 :             return papoFieldDefns[i];
     554                 :     }
     555                 : 
     556              15 :     return NULL;
     557                 : }
     558                 : 
     559                 : /************************************************************************/
     560                 : /*                             ReadRecord()                             */
     561                 : /*                                                                      */
     562                 : /*      Read one record from the file, and return to the                */
     563                 : /*      application.  The returned record is owned by the module,       */
     564                 : /*      and is reused from call to call in order to preserve headers    */
     565                 : /*      when they aren't being re-read from record to record.           */
     566                 : /************************************************************************/
     567                 : 
     568                 : /**
     569                 :  * Read one record from the file.
     570                 :  *
     571                 :  * @return A pointer to a DDFRecord object is returned, or NULL if a read
     572                 :  * error, or end of file occurs.  The returned record is owned by the
     573                 :  * module, and should not be deleted by the application.  The record is
     574                 :  * only valid untill the next ReadRecord() at which point it is overwritten.
     575                 :  */
     576                 : 
     577            1322 : DDFRecord *DDFModule::ReadRecord()
     578                 : 
     579                 : {
     580            1322 :     if( poRecord == NULL )
     581              52 :         poRecord = new DDFRecord( this );
     582                 : 
     583            1322 :     if( poRecord->Read() )
     584            1291 :         return poRecord;
     585                 :     else
     586              31 :         return NULL;
     587                 : }
     588                 : 
     589                 : /************************************************************************/
     590                 : /*                              AddField()                              */
     591                 : /************************************************************************/
     592                 : 
     593                 : /**
     594                 :  * Add new field definition.
     595                 :  *
     596                 :  * Field definitions may only be added to DDFModules being used for 
     597                 :  * writing, not those being used for reading.  Ownership of the 
     598                 :  * DDFFieldDefn object is taken by the DDFModule.
     599                 :  *
     600                 :  * @param poNewFDefn definition to be added to the module. 
     601                 :  */
     602                 : 
     603             472 : void DDFModule::AddField( DDFFieldDefn *poNewFDefn )
     604                 : 
     605                 : {
     606             472 :     nFieldDefnCount++;
     607                 :     papoFieldDefns = (DDFFieldDefn **) 
     608             472 :         CPLRealloc(papoFieldDefns, sizeof(void*)*nFieldDefnCount);
     609             472 :     papoFieldDefns[nFieldDefnCount-1] = poNewFDefn;
     610             472 : }
     611                 : 
     612                 : /************************************************************************/
     613                 : /*                              GetField()                              */
     614                 : /************************************************************************/
     615                 : 
     616                 : /**
     617                 :  * Fetch a field definition by index.
     618                 :  *
     619                 :  * @param i (from 0 to GetFieldCount() - 1.
     620                 :  * @return the returned field pointer or NULL if the index is out of range.
     621                 :  */
     622                 : 
     623               0 : DDFFieldDefn *DDFModule::GetField(int i)
     624                 : 
     625                 : {
     626               0 :     if( i < 0 || i >= nFieldDefnCount )
     627               0 :         return NULL;
     628                 :     else
     629               0 :         return papoFieldDefns[i];
     630                 : }
     631                 :     
     632                 : /************************************************************************/
     633                 : /*                           AddCloneRecord()                           */
     634                 : /*                                                                      */
     635                 : /*      We want to keep track of cloned records, so we can clean        */
     636                 : /*      them up when the module is destroyed.                           */
     637                 : /************************************************************************/
     638                 : 
     639             750 : void DDFModule::AddCloneRecord( DDFRecord * poRecord )
     640                 : 
     641                 : {
     642                 : /* -------------------------------------------------------------------- */
     643                 : /*      Do we need to grow the container array?                         */
     644                 : /* -------------------------------------------------------------------- */
     645             750 :     if( nCloneCount == nMaxCloneCount )
     646                 :     {
     647              16 :         nMaxCloneCount = nCloneCount*2 + 20;
     648                 :         papoClones = (DDFRecord **) CPLRealloc(papoClones,
     649              16 :                                                nMaxCloneCount * sizeof(void*));
     650                 :     }
     651                 : 
     652                 : /* -------------------------------------------------------------------- */
     653                 : /*      Add to the list.                                                */
     654                 : /* -------------------------------------------------------------------- */
     655             750 :     papoClones[nCloneCount++] = poRecord;
     656             750 : }
     657                 : 
     658                 : /************************************************************************/
     659                 : /*                         RemoveCloneRecord()                          */
     660                 : /************************************************************************/
     661                 : 
     662             750 : void DDFModule::RemoveCloneRecord( DDFRecord * poRecord )
     663                 : 
     664                 : {
     665                 :     int         i;
     666                 :  
     667            7394 :     for( i = 0; i < nCloneCount; i++ )
     668                 :     {
     669            7394 :         if( papoClones[i] == poRecord )
     670                 :         {
     671             750 :             papoClones[i] = papoClones[nCloneCount-1];
     672             750 :             nCloneCount--;
     673             750 :             return;
     674                 :         }
     675                 :     }
     676                 : 
     677               0 :     CPLAssert( FALSE );
     678                 : }
     679                 : 
     680                 : /************************************************************************/
     681                 : /*                               Rewind()                               */
     682                 : /************************************************************************/
     683                 : 
     684                 : /**
     685                 :  * Return to first record.
     686                 :  * 
     687                 :  * The next call to ReadRecord() will read the first data record in the file.
     688                 :  *
     689                 :  * @param nOffset the offset in the file to return to.  By default this is
     690                 :  * -1, a special value indicating that reading should return to the first
     691                 :  * data record.  Otherwise it is an absolute byte offset in the file.
     692                 :  */
     693                 : 
     694              24 : void DDFModule::Rewind( long nOffset )
     695                 : 
     696                 : {
     697              24 :     if( nOffset == -1 )
     698              24 :         nOffset = nFirstRecordOffset;
     699                 : 
     700              24 :     if( fpDDF == NULL )
     701               0 :         return;
     702                 :     
     703              24 :     VSIFSeekL( fpDDF, nOffset, SEEK_SET );
     704                 : 
     705              24 :     if( nOffset == nFirstRecordOffset && poRecord != NULL )
     706              16 :         poRecord->Clear();
     707                 :         
     708                 : }

Generated by: LTP GCOV extension version 1.5