LCOV - code coverage report
Current view: directory - frmts/iso8211 - ddfmodule.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 237 135 57.0 %
Date: 2012-12-26 Functions: 16 10 62.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ddfmodule.cpp 23595 2011-12-18 22:58:47Z rouault $
       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 23595 2011-12-18 22:58:47Z rouault $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                             DDFModule()                              */
      37                 : /************************************************************************/
      38                 : 
      39                 : /**
      40                 :  * The constructor.
      41                 :  */
      42                 : 
      43           11889 : DDFModule::DDFModule()
      44                 : 
      45                 : {
      46           11889 :     nFieldDefnCount = 0;
      47           11889 :     papoFieldDefns = NULL;
      48           11889 :     poRecord = NULL;
      49                 : 
      50           11889 :     papoClones = NULL;
      51           11889 :     nCloneCount = nMaxCloneCount = 0;
      52                 : 
      53           11889 :     fpDDF = NULL;
      54           11889 :     bReadOnly = TRUE;
      55                 : 
      56           11889 :     _interchangeLevel = '\0';
      57           11889 :     _inlineCodeExtensionIndicator = '\0';
      58           11889 :     _versionNumber = '\0';
      59           11889 :     _appIndicator = '\0';
      60           11889 :     _fieldControlLength = '\0';
      61           11889 :     strcpy( _extendedCharSet, " ! " );
      62                 : 
      63           11889 :     _recLength = 0;
      64           11889 :     _leaderIden = 'L';
      65           11889 :     _fieldAreaStart = 0;
      66           11889 :     _sizeFieldLength = 0;
      67           11889 :     _sizeFieldPos = 0;
      68           11889 :     _sizeFieldTag = 0;
      69           11889 : }
      70                 : 
      71                 : /************************************************************************/
      72                 : /*                             ~DDFModule()                             */
      73                 : /************************************************************************/
      74                 : 
      75                 : /**
      76                 :  * The destructor.
      77                 :  */
      78                 : 
      79           11889 : DDFModule::~DDFModule()
      80                 : 
      81                 : {
      82           11889 :     Close();
      83           11889 : }
      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           11897 : void DDFModule::Close()
      97                 : 
      98                 : {
      99                 : /* -------------------------------------------------------------------- */
     100                 : /*      Close the file.                                                 */
     101                 : /* -------------------------------------------------------------------- */
     102           11897 :     if( fpDDF != NULL )
     103                 :     {
     104              85 :         VSIFCloseL( fpDDF );
     105              85 :         fpDDF = NULL;
     106                 :     }
     107                 : 
     108                 : /* -------------------------------------------------------------------- */
     109                 : /*      Cleanup the working record.                                     */
     110                 : /* -------------------------------------------------------------------- */
     111           11897 :     if( poRecord != NULL )
     112                 :     {
     113              68 :         delete poRecord;
     114              68 :         poRecord = NULL;
     115                 :     }
     116                 : 
     117                 : /* -------------------------------------------------------------------- */
     118                 : /*      Cleanup the clones.  Deleting them will cause a callback to     */
     119                 : /*      remove them from the list.                                      */
     120                 : /* -------------------------------------------------------------------- */
     121           47371 :     while( nCloneCount > 0 )
     122           23577 :         delete papoClones[0];
     123                 : 
     124           11897 :     nMaxCloneCount = 0;
     125           11897 :     CPLFree( papoClones );
     126           11897 :     papoClones = NULL;
     127                 :     
     128                 : /* -------------------------------------------------------------------- */
     129                 : /*      Cleanup the field definitions.                                  */
     130                 : /* -------------------------------------------------------------------- */
     131                 :     int i;
     132                 : 
     133           12575 :     for( i = 0; i < nFieldDefnCount; i++ )
     134             678 :         delete papoFieldDefns[i];
     135           11897 :     CPLFree( papoFieldDefns );
     136           11897 :     papoFieldDefns = NULL;
     137           11897 :     nFieldDefnCount = 0;
     138           11897 : }
     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              91 : int DDFModule::Open( const char * pszFilename, int bFailQuietly )
     162                 : 
     163                 : {
     164                 :     static const int nLeaderSize = 24;
     165                 : 
     166                 : /* -------------------------------------------------------------------- */
     167                 : /*      Close the existing file if there is one.                        */
     168                 : /* -------------------------------------------------------------------- */
     169              91 :     if( fpDDF != NULL )
     170               0 :         Close();
     171                 :     
     172                 : /* -------------------------------------------------------------------- */
     173                 : /*      Open the file.                                                  */
     174                 : /* -------------------------------------------------------------------- */
     175              91 :     fpDDF = VSIFOpenL( pszFilename, "rb" );
     176                 : 
     177              91 :     if( fpDDF == NULL )
     178                 :     {
     179               6 :         if( !bFailQuietly )
     180                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     181                 :                       "Unable to open DDF file `%s'.",
     182               0 :                       pszFilename );
     183               6 :         return FALSE;
     184                 :     }
     185                 : 
     186                 : /* -------------------------------------------------------------------- */
     187                 : /*      Read the 24 byte leader.                                        */
     188                 : /* -------------------------------------------------------------------- */
     189                 :     char        achLeader[nLeaderSize];
     190                 :     
     191              85 :     if( (int)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              85 :     int         i, bValid = TRUE;
     208                 : 
     209            2125 :     for( i = 0; i < nLeaderSize; i++ )
     210                 :     {
     211            2040 :         if( achLeader[i] < 32 || achLeader[i] > 126 )
     212               0 :             bValid = FALSE;
     213                 :     }
     214                 : 
     215              85 :     if( achLeader[5] != '1' && achLeader[5] != '2' && achLeader[5] != '3' )
     216               0 :         bValid = FALSE;
     217                 : 
     218              85 :     if( achLeader[6] != 'L' )
     219               0 :         bValid = FALSE;
     220              85 :     if( achLeader[8] != '1' && achLeader[8] != ' ' )
     221               0 :         bValid = FALSE;
     222                 : 
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      Extract information from leader.                                */
     225                 : /* -------------------------------------------------------------------- */
     226                 : 
     227              85 :     if( bValid )
     228                 :     {
     229              85 :         _recLength                        = DDFScanInt( achLeader+0, 5 );
     230              85 :         _interchangeLevel                 = achLeader[5];
     231              85 :         _leaderIden                   = achLeader[6];
     232              85 :         _inlineCodeExtensionIndicator = achLeader[7];
     233              85 :         _versionNumber                = achLeader[8];
     234              85 :         _appIndicator                 = achLeader[9];
     235              85 :         _fieldControlLength           = DDFScanInt(achLeader+10,2);
     236              85 :         _fieldAreaStart               = DDFScanInt(achLeader+12,5);
     237              85 :         _extendedCharSet[0]           = achLeader[17];
     238              85 :         _extendedCharSet[1]           = achLeader[18];
     239              85 :         _extendedCharSet[2]           = achLeader[19];
     240              85 :         _extendedCharSet[3]           = '\0';
     241              85 :         _sizeFieldLength              = DDFScanInt(achLeader+20,1);
     242              85 :         _sizeFieldPos                 = DDFScanInt(achLeader+21,1);
     243              85 :         _sizeFieldTag                 = DDFScanInt(achLeader+23,1);
     244                 : 
     245              85 :         if( _recLength < nLeaderSize || _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              85 :     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              85 :     pachRecord = (char *) CPLMalloc(_recLength);
     276              85 :     memcpy( pachRecord, achLeader, nLeaderSize );
     277                 : 
     278              85 :     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              85 :     int         nFieldEntryWidth, nFDCount = 0;
     293                 : 
     294              85 :     nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag;
     295                 : 
     296             763 :     for( i = nLeaderSize; i < _recLength; i += nFieldEntryWidth )
     297                 :     {
     298             763 :         if( pachRecord[i] == DDF_FIELD_TERMINATOR )
     299              85 :             break;
     300                 : 
     301             678 :         nFDCount++;
     302                 :     }
     303                 : 
     304                 : /* -------------------------------------------------------------------- */
     305                 : /*      Allocate, and read field definitions.                           */
     306                 : /* -------------------------------------------------------------------- */
     307             763 :     for( i = 0; i < nFDCount; i++ )
     308                 :     {
     309                 :         char    szTag[128];
     310             678 :         int     nEntryOffset = nLeaderSize + i*nFieldEntryWidth;
     311                 :         int     nFieldLength, nFieldPos;
     312                 :         DDFFieldDefn *poFDefn;
     313                 :         
     314             678 :         strncpy( szTag, pachRecord+nEntryOffset, _sizeFieldTag );
     315             678 :         szTag[_sizeFieldTag] = '\0';
     316                 : 
     317             678 :         nEntryOffset += _sizeFieldTag;
     318             678 :         nFieldLength = DDFScanInt( pachRecord+nEntryOffset, _sizeFieldLength );
     319                 :         
     320             678 :         nEntryOffset += _sizeFieldLength;
     321             678 :         nFieldPos = DDFScanInt( pachRecord+nEntryOffset, _sizeFieldPos );
     322                 : 
     323             678 :         if (_fieldAreaStart+nFieldPos < 0 ||
     324                 :             _recLength - (_fieldAreaStart+nFieldPos) < nFieldLength)
     325                 :         {
     326               0 :             if( !bFailQuietly )
     327                 :                 CPLError( CE_Failure, CPLE_FileIO,
     328                 :                         "Header record invalid on DDF file `%s'.",
     329               0 :                         pszFilename );
     330                 : 
     331               0 :             CPLFree( pachRecord );
     332               0 :             return FALSE;
     333                 :         }
     334                 :         
     335             678 :         poFDefn = new DDFFieldDefn();
     336             678 :         if( poFDefn->Initialize( this, szTag, nFieldLength,
     337                 :                                  pachRecord+_fieldAreaStart+nFieldPos ) )
     338             678 :             AddField( poFDefn );
     339                 :         else
     340               0 :             delete poFDefn;
     341                 :     }
     342                 : 
     343              85 :     CPLFree( pachRecord );
     344                 :     
     345                 : /* -------------------------------------------------------------------- */
     346                 : /*      Record the current file offset, the beginning of the first      */
     347                 : /*      data record.                                                    */
     348                 : /* -------------------------------------------------------------------- */
     349              85 :     nFirstRecordOffset = (long)VSIFTellL( fpDDF );
     350                 :     
     351              85 :     return TRUE;
     352                 : }
     353                 : 
     354                 : /************************************************************************/
     355                 : /*                             Initialize()                             */
     356                 : /************************************************************************/
     357                 : 
     358               0 : int DDFModule::Initialize( char chInterchangeLevel,
     359                 :                            char chLeaderIden, 
     360                 :                            char chCodeExtensionIndicator,
     361                 :                            char chVersionNumber,
     362                 :                            char chAppIndicator,
     363                 :                            const char *pszExtendedCharSet,
     364                 :                            int nSizeFieldLength,
     365                 :                            int nSizeFieldPos,
     366                 :                            int nSizeFieldTag )
     367                 : 
     368                 : {
     369               0 :     _interchangeLevel = chInterchangeLevel;
     370               0 :     _leaderIden = chLeaderIden;
     371               0 :     _inlineCodeExtensionIndicator = chCodeExtensionIndicator;
     372               0 :     _versionNumber = chVersionNumber;
     373               0 :     _appIndicator = chAppIndicator;
     374               0 :     strcpy( _extendedCharSet, pszExtendedCharSet );
     375               0 :     _sizeFieldLength = nSizeFieldLength;
     376               0 :     _sizeFieldPos = nSizeFieldPos;
     377               0 :     _sizeFieldTag = nSizeFieldTag;
     378                 : 
     379               0 :     return TRUE;
     380                 : }
     381                 : 
     382                 : /************************************************************************/
     383                 : /*                               Create()                               */
     384                 : /************************************************************************/
     385                 : 
     386               0 : int DDFModule::Create( const char *pszFilename )
     387                 : 
     388                 : {
     389               0 :     CPLAssert( fpDDF == NULL );
     390                 :     
     391                 : /* -------------------------------------------------------------------- */
     392                 : /*      Create the file on disk.                                        */
     393                 : /* -------------------------------------------------------------------- */
     394               0 :     fpDDF = VSIFOpenL( pszFilename, "wb+" );
     395               0 :     if( fpDDF == NULL )
     396                 :     {
     397                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     398                 :                   "Failed to create file %s, check path and permissions.",
     399               0 :                   pszFilename );
     400               0 :         return FALSE;
     401                 :     }
     402                 :     
     403               0 :     bReadOnly = FALSE;
     404                 : 
     405                 : /* -------------------------------------------------------------------- */
     406                 : /*      Prepare all the field definition information.                   */
     407                 : /* -------------------------------------------------------------------- */
     408                 :     int iField;
     409                 : 
     410               0 :     _fieldControlLength = 9;
     411                 :     _recLength = 24 
     412                 :         + nFieldDefnCount * (_sizeFieldLength+_sizeFieldPos+_sizeFieldTag) 
     413               0 :         + 1;
     414                 :     
     415               0 :     _fieldAreaStart = _recLength;
     416                 : 
     417               0 :     for( iField=0; iField < nFieldDefnCount; iField++ )
     418                 :     {
     419                 :         int nLength;
     420                 : 
     421               0 :         papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength );
     422               0 :         _recLength += nLength;
     423                 :     }
     424                 : 
     425                 : /* -------------------------------------------------------------------- */
     426                 : /*      Setup 24 byte leader.                                           */
     427                 : /* -------------------------------------------------------------------- */
     428                 :     char achLeader[25];
     429                 : 
     430               0 :     sprintf( achLeader+0, "%05d", (int) _recLength );
     431               0 :     achLeader[5] = _interchangeLevel;
     432               0 :     achLeader[6] = _leaderIden;
     433               0 :     achLeader[7] = _inlineCodeExtensionIndicator;
     434               0 :     achLeader[8] = _versionNumber;
     435               0 :     achLeader[9] = _appIndicator;
     436               0 :     sprintf( achLeader+10, "%02d", (int) _fieldControlLength );
     437               0 :     sprintf( achLeader+12, "%05d", (int) _fieldAreaStart );
     438               0 :     strncpy( achLeader+17, _extendedCharSet, 3 );
     439               0 :     sprintf( achLeader+20, "%1d", (int) _sizeFieldLength );
     440               0 :     sprintf( achLeader+21, "%1d", (int) _sizeFieldPos );
     441               0 :     achLeader[22] = '0';
     442               0 :     sprintf( achLeader+23, "%1d", (int) _sizeFieldTag );
     443               0 :     VSIFWriteL( achLeader, 24, 1, fpDDF );
     444                 : 
     445                 : /* -------------------------------------------------------------------- */
     446                 : /*      Write out directory entries.                                    */
     447                 : /* -------------------------------------------------------------------- */
     448               0 :     int nOffset = 0;
     449               0 :     for( iField=0; iField < nFieldDefnCount; iField++ )
     450                 :     {
     451                 :         char achDirEntry[12];
     452                 :         int nLength;
     453                 : 
     454               0 :         papoFieldDefns[iField]->GenerateDDREntry( NULL, &nLength );
     455                 : 
     456               0 :         strcpy( achDirEntry, papoFieldDefns[iField]->GetName() );
     457               0 :         sprintf( achDirEntry + _sizeFieldTag, "%03d", nLength );
     458                 :         sprintf( achDirEntry + _sizeFieldTag + _sizeFieldLength, 
     459               0 :                  "%04d", nOffset );
     460               0 :         nOffset += nLength;
     461                 : 
     462               0 :         VSIFWriteL( achDirEntry, 11, 1, fpDDF );
     463                 :     }
     464                 : 
     465               0 :     char chUT = DDF_FIELD_TERMINATOR;
     466               0 :     VSIFWriteL( &chUT, 1, 1, fpDDF );
     467                 : 
     468                 : /* -------------------------------------------------------------------- */
     469                 : /*      Write out the field descriptions themselves.                    */
     470                 : /* -------------------------------------------------------------------- */
     471               0 :     for( iField=0; iField < nFieldDefnCount; iField++ )
     472                 :     {
     473                 :         char *pachData;
     474                 :         int nLength;
     475                 : 
     476               0 :         papoFieldDefns[iField]->GenerateDDREntry( &pachData, &nLength );
     477               0 :         VSIFWriteL( pachData, nLength, 1, fpDDF );
     478               0 :         CPLFree( pachData );
     479                 :     }
     480                 :     
     481               0 :     return TRUE;
     482                 : }
     483                 : 
     484                 : /************************************************************************/
     485                 : /*                                Dump()                                */
     486                 : /************************************************************************/
     487                 : 
     488                 : /**
     489                 :  * Write out module info to debugging file.
     490                 :  *
     491                 :  * A variety of information about the module is written to the debugging
     492                 :  * file.  This includes all the field and subfield definitions read from
     493                 :  * the header. 
     494                 :  *
     495                 :  * @param fp The standard io file handle to write to.  ie. stderr.
     496                 :  */
     497                 : 
     498               0 : void DDFModule::Dump( FILE * fp )
     499                 : 
     500                 : {
     501               0 :     fprintf( fp, "DDFModule:\n" );
     502               0 :     fprintf( fp, "    _recLength = %ld\n", _recLength );
     503               0 :     fprintf( fp, "    _interchangeLevel = %c\n", _interchangeLevel );
     504               0 :     fprintf( fp, "    _leaderIden = %c\n", _leaderIden );
     505                 :     fprintf( fp, "    _inlineCodeExtensionIndicator = %c\n",
     506               0 :              _inlineCodeExtensionIndicator );
     507               0 :     fprintf( fp, "    _versionNumber = %c\n", _versionNumber );
     508               0 :     fprintf( fp, "    _appIndicator = %c\n", _appIndicator );
     509               0 :     fprintf( fp, "    _extendedCharSet = `%s'\n", _extendedCharSet );
     510               0 :     fprintf( fp, "    _fieldControlLength = %d\n", _fieldControlLength );
     511               0 :     fprintf( fp, "    _fieldAreaStart = %ld\n", _fieldAreaStart );
     512               0 :     fprintf( fp, "    _sizeFieldLength = %ld\n", _sizeFieldLength );
     513               0 :     fprintf( fp, "    _sizeFieldPos = %ld\n", _sizeFieldPos );
     514               0 :     fprintf( fp, "    _sizeFieldTag = %ld\n", _sizeFieldTag );
     515                 : 
     516               0 :     for( int i = 0; i < nFieldDefnCount; i++ )
     517                 :     {
     518               0 :         papoFieldDefns[i]->Dump( fp );
     519                 :     }
     520               0 : }
     521                 : 
     522                 : /************************************************************************/
     523                 : /*                           FindFieldDefn()                            */
     524                 : /************************************************************************/
     525                 : 
     526                 : /**
     527                 :  * Fetch the definition of the named field.
     528                 :  *
     529                 :  * This function will scan the DDFFieldDefn's on this module, to find
     530                 :  * one with the indicated field name.
     531                 :  *
     532                 :  * @param pszFieldName The name of the field to search for.  The comparison is
     533                 :  *                     case insensitive.
     534                 :  *
     535                 :  * @return A pointer to the request DDFFieldDefn object is returned, or NULL
     536                 :  * if none matching the name are found.  The return object remains owned by
     537                 :  * the DDFModule, and should not be deleted by application code.
     538                 :  */
     539                 : 
     540           89958 : DDFFieldDefn *DDFModule::FindFieldDefn( const char *pszFieldName )
     541                 : 
     542                 : {
     543                 :     int         i;
     544                 :     
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      This pass tries to reduce the cost of comparing strings by      */
     547                 : /*      first checking the first character, and by using strcmp()       */
     548                 : /* -------------------------------------------------------------------- */
     549          873840 :     for( i = 0; i < nFieldDefnCount; i++ )
     550                 :     {
     551          873819 :         const char *pszThisName = papoFieldDefns[i]->GetName();
     552                 :         
     553          873819 :         if( *pszThisName == *pszFieldName
     554                 :             && strcmp( pszFieldName+1, pszThisName+1) == 0 )
     555           89937 :             return papoFieldDefns[i];
     556                 :     }
     557                 : 
     558                 : /* -------------------------------------------------------------------- */
     559                 : /*      Now do a more general check.  Application code may not          */
     560                 : /*      always use the correct name case.                               */
     561                 : /* -------------------------------------------------------------------- */
     562             160 :     for( i = 0; i < nFieldDefnCount; i++ )
     563                 :     {
     564             139 :         if( EQUAL(pszFieldName, papoFieldDefns[i]->GetName()) )
     565               0 :             return papoFieldDefns[i];
     566                 :     }
     567                 : 
     568              21 :     return NULL;
     569                 : }
     570                 : 
     571                 : /************************************************************************/
     572                 : /*                             ReadRecord()                             */
     573                 : /*                                                                      */
     574                 : /*      Read one record from the file, and return to the                */
     575                 : /*      application.  The returned record is owned by the module,       */
     576                 : /*      and is reused from call to call in order to preserve headers    */
     577                 : /*      when they aren't being re-read from record to record.           */
     578                 : /************************************************************************/
     579                 : 
     580                 : /**
     581                 :  * Read one record from the file.
     582                 :  *
     583                 :  * @return A pointer to a DDFRecord object is returned, or NULL if a read
     584                 :  * error, or end of file occurs.  The returned record is owned by the
     585                 :  * module, and should not be deleted by the application.  The record is
     586                 :  * only valid untill the next ReadRecord() at which point it is overwritten.
     587                 :  */
     588                 : 
     589           24554 : DDFRecord *DDFModule::ReadRecord()
     590                 : 
     591                 : {
     592           24554 :     if( poRecord == NULL )
     593              68 :         poRecord = new DDFRecord( this );
     594                 : 
     595           24554 :     if( poRecord->Read() )
     596           24519 :         return poRecord;
     597                 :     else
     598              35 :         return NULL;
     599                 : }
     600                 : 
     601                 : /************************************************************************/
     602                 : /*                              AddField()                              */
     603                 : /************************************************************************/
     604                 : 
     605                 : /**
     606                 :  * Add new field definition.
     607                 :  *
     608                 :  * Field definitions may only be added to DDFModules being used for 
     609                 :  * writing, not those being used for reading.  Ownership of the 
     610                 :  * DDFFieldDefn object is taken by the DDFModule.
     611                 :  *
     612                 :  * @param poNewFDefn definition to be added to the module. 
     613                 :  */
     614                 : 
     615             678 : void DDFModule::AddField( DDFFieldDefn *poNewFDefn )
     616                 : 
     617                 : {
     618             678 :     nFieldDefnCount++;
     619                 :     papoFieldDefns = (DDFFieldDefn **) 
     620             678 :         CPLRealloc(papoFieldDefns, sizeof(void*)*nFieldDefnCount);
     621             678 :     papoFieldDefns[nFieldDefnCount-1] = poNewFDefn;
     622             678 : }
     623                 : 
     624                 : /************************************************************************/
     625                 : /*                              GetField()                              */
     626                 : /************************************************************************/
     627                 : 
     628                 : /**
     629                 :  * Fetch a field definition by index.
     630                 :  *
     631                 :  * @param i (from 0 to GetFieldCount() - 1.
     632                 :  * @return the returned field pointer or NULL if the index is out of range.
     633                 :  */
     634                 : 
     635               0 : DDFFieldDefn *DDFModule::GetField(int i)
     636                 : 
     637                 : {
     638               0 :     if( i < 0 || i >= nFieldDefnCount )
     639               0 :         return NULL;
     640                 :     else
     641               0 :         return papoFieldDefns[i];
     642                 : }
     643                 :     
     644                 : /************************************************************************/
     645                 : /*                           AddCloneRecord()                           */
     646                 : /*                                                                      */
     647                 : /*      We want to keep track of cloned records, so we can clean        */
     648                 : /*      them up when the module is destroyed.                           */
     649                 : /************************************************************************/
     650                 : 
     651           23967 : void DDFModule::AddCloneRecord( DDFRecord * poRecord )
     652                 : 
     653                 : {
     654                 : /* -------------------------------------------------------------------- */
     655                 : /*      Do we need to grow the container array?                         */
     656                 : /* -------------------------------------------------------------------- */
     657           23967 :     if( nCloneCount == nMaxCloneCount )
     658                 :     {
     659              43 :         nMaxCloneCount = nCloneCount*2 + 20;
     660                 :         papoClones = (DDFRecord **) CPLRealloc(papoClones,
     661              43 :                                                nMaxCloneCount * sizeof(void*));
     662                 :     }
     663                 : 
     664                 : /* -------------------------------------------------------------------- */
     665                 : /*      Add to the list.                                                */
     666                 : /* -------------------------------------------------------------------- */
     667           23967 :     papoClones[nCloneCount++] = poRecord;
     668           23967 : }
     669                 : 
     670                 : /************************************************************************/
     671                 : /*                         RemoveCloneRecord()                          */
     672                 : /************************************************************************/
     673                 : 
     674           23967 : void DDFModule::RemoveCloneRecord( DDFRecord * poRecord )
     675                 : 
     676                 : {
     677                 :     int         i;
     678                 :  
     679           31396 :     for( i = 0; i < nCloneCount; i++ )
     680                 :     {
     681           31396 :         if( papoClones[i] == poRecord )
     682                 :         {
     683           23967 :             papoClones[i] = papoClones[nCloneCount-1];
     684           23967 :             nCloneCount--;
     685           23967 :             return;
     686                 :         }
     687                 :     }
     688                 : 
     689               0 :     CPLAssert( FALSE );
     690                 : }
     691                 : 
     692                 : /************************************************************************/
     693                 : /*                               Rewind()                               */
     694                 : /************************************************************************/
     695                 : 
     696                 : /**
     697                 :  * Return to first record.
     698                 :  * 
     699                 :  * The next call to ReadRecord() will read the first data record in the file.
     700                 :  *
     701                 :  * @param nOffset the offset in the file to return to.  By default this is
     702                 :  * -1, a special value indicating that reading should return to the first
     703                 :  * data record.  Otherwise it is an absolute byte offset in the file.
     704                 :  */
     705                 : 
     706              24 : void DDFModule::Rewind( long nOffset )
     707                 : 
     708                 : {
     709              24 :     if( nOffset == -1 )
     710              24 :         nOffset = nFirstRecordOffset;
     711                 : 
     712              24 :     if( fpDDF == NULL )
     713               0 :         return;
     714                 :     
     715              24 :     VSIFSeekL( fpDDF, nOffset, SEEK_SET );
     716                 : 
     717              24 :     if( nOffset == nFirstRecordOffset && poRecord != NULL )
     718              16 :         poRecord->Clear();
     719                 :         
     720                 : }

Generated by: LCOV version 1.7