LCOV - code coverage report
Current view: directory - frmts/iso8211 - ddffield.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 83 48 57.8 %
Date: 2012-04-28 Functions: 5 4 80.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ddffield.cpp 10645 2007-01-18 02:22:39Z warmerdam $
       3                 :  *
       4                 :  * Project:  ISO 8211 Access
       5                 :  * Purpose:  Implements the DDFField 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: ddffield.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
      34                 : 
      35                 : // Note, we implement no constructor for this class to make instantiation
      36                 : // cheaper.  It is required that the Initialize() be called before anything
      37                 : // else.
      38                 : 
      39                 : /************************************************************************/
      40                 : /*                             Initialize()                             */
      41                 : /************************************************************************/
      42                 : 
      43          357600 : void DDFField::Initialize( DDFFieldDefn *poDefnIn, const char * pachDataIn,
      44                 :                            int nDataSizeIn )
      45                 : 
      46                 : {
      47          357600 :     pachData = pachDataIn;
      48          357600 :     nDataSize = nDataSizeIn;
      49          357600 :     poDefn = poDefnIn;
      50          357600 : }
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                                Dump()                                */
      54                 : /************************************************************************/
      55                 : 
      56                 : /**
      57                 :  * Write out field contents to debugging file.
      58                 :  *
      59                 :  * A variety of information about this field, and all it's
      60                 :  * subfields is written to the given debugging file handle.  Note that
      61                 :  * field definition information (ala DDFFieldDefn) isn't written.
      62                 :  *
      63                 :  * @param fp The standard io file handle to write to.  ie. stderr
      64                 :  */
      65                 : 
      66               0 : void DDFField::Dump( FILE * fp )
      67                 : 
      68                 : {
      69               0 :     int         nMaxRepeat = 8;
      70                 : 
      71               0 :     if( getenv("DDF_MAXDUMP") != NULL )
      72               0 :         nMaxRepeat = atoi(getenv("DDF_MAXDUMP"));
      73                 : 
      74               0 :     fprintf( fp, "  DDFField:\n" );
      75               0 :     fprintf( fp, "      Tag = `%s'\n", poDefn->GetName() );
      76               0 :     fprintf( fp, "      DataSize = %d\n", nDataSize );
      77                 : 
      78               0 :     fprintf( fp, "      Data = `" );
      79               0 :     for( int i = 0; i < MIN(nDataSize,40); i++ )
      80                 :     {
      81               0 :         if( pachData[i] < 32 || pachData[i] > 126 )
      82               0 :             fprintf( fp, "\\%02X", ((unsigned char *) pachData)[i] );
      83                 :         else
      84               0 :             fprintf( fp, "%c", pachData[i] );
      85                 :     }
      86                 : 
      87               0 :     if( nDataSize > 40 )
      88               0 :         fprintf( fp, "..." );
      89               0 :     fprintf( fp, "'\n" );
      90                 : 
      91                 : /* -------------------------------------------------------------------- */
      92                 : /*      dump the data of the subfields.                                 */
      93                 : /* -------------------------------------------------------------------- */
      94               0 :     int         iOffset = 0, nLoopCount;
      95                 : 
      96               0 :     for( nLoopCount = 0; nLoopCount < GetRepeatCount(); nLoopCount++ )
      97                 :     {
      98               0 :         if( nLoopCount > nMaxRepeat )
      99                 :         {
     100               0 :             fprintf( fp, "      ...\n" );
     101               0 :             break;
     102                 :         }
     103                 :         
     104               0 :         for( int i = 0; i < poDefn->GetSubfieldCount(); i++ )
     105                 :         {
     106                 :             int         nBytesConsumed;
     107                 : 
     108                 :             poDefn->GetSubfield(i)->DumpData( pachData + iOffset,
     109               0 :                                               nDataSize - iOffset, fp );
     110                 :         
     111                 :             poDefn->GetSubfield(i)->GetDataLength( pachData + iOffset,
     112                 :                                                    nDataSize - iOffset,
     113               0 :                                                    &nBytesConsumed );
     114                 : 
     115               0 :             iOffset += nBytesConsumed;
     116                 :         }
     117                 :     }
     118               0 : }
     119                 : 
     120                 : /************************************************************************/
     121                 : /*                          GetSubfieldData()                           */
     122                 : /************************************************************************/
     123                 : 
     124                 : /**
     125                 :  * Fetch raw data pointer for a particular subfield of this field.
     126                 :  *
     127                 :  * The passed DDFSubfieldDefn (poSFDefn) should be acquired from the
     128                 :  * DDFFieldDefn corresponding with this field.  This is normally done
     129                 :  * once before reading any records.  This method involves a series of
     130                 :  * calls to DDFSubfield::GetDataLength() in order to track through the
     131                 :  * DDFField data to that belonging to the requested subfield.  This can
     132                 :  * be relatively expensive.<p>
     133                 :  *
     134                 :  * @param poSFDefn The definition of the subfield for which the raw
     135                 :  * data pointer is desired.
     136                 :  * @param pnMaxBytes The maximum number of bytes that can be accessed from
     137                 :  * the returned data pointer is placed in this int, unless it is NULL.
     138                 :  * @param iSubfieldIndex The instance of this subfield to fetch.  Use zero
     139                 :  * (the default) for the first instance.
     140                 :  *
     141                 :  * @return A pointer into the DDFField's data that belongs to the subfield.
     142                 :  * This returned pointer is invalidated by the next record read
     143                 :  * (DDFRecord::ReadRecord()) and the returned pointer should not be freed
     144                 :  * by the application.
     145                 :  */
     146                 : 
     147          105644 : const char *DDFField::GetSubfieldData( DDFSubfieldDefn *poSFDefn,
     148                 :                                        int *pnMaxBytes, int iSubfieldIndex )
     149                 : 
     150                 : {
     151          105644 :     int         iOffset = 0;
     152                 :     
     153          105644 :     if( poSFDefn == NULL )
     154               0 :         return NULL;
     155                 : 
     156          105644 :     if( iSubfieldIndex > 0 && poDefn->GetFixedWidth() > 0 )
     157                 :     {
     158             308 :         iOffset = poDefn->GetFixedWidth() * iSubfieldIndex;
     159             308 :         iSubfieldIndex = 0;
     160                 :     }
     161                 : 
     162          211362 :     while( iSubfieldIndex >= 0 )
     163                 :     {
     164          272610 :         for( int iSF = 0; iSF < poDefn->GetSubfieldCount(); iSF++ )
     165                 :         {
     166                 :             int nBytesConsumed;
     167          272536 :             DDFSubfieldDefn * poThisSFDefn = poDefn->GetSubfield( iSF );
     168                 :             
     169          272536 :             if( poThisSFDefn == poSFDefn && iSubfieldIndex == 0 )
     170                 :             {
     171          105644 :                 if( pnMaxBytes != NULL )
     172          104952 :                     *pnMaxBytes = nDataSize - iOffset;
     173                 :                 
     174          105644 :                 return pachData + iOffset;
     175                 :             }
     176                 :             
     177                 :             poThisSFDefn->GetDataLength( pachData+iOffset, nDataSize - iOffset,
     178          166892 :                                          &nBytesConsumed);
     179          166892 :             iOffset += nBytesConsumed;
     180                 :         }
     181                 : 
     182              74 :         iSubfieldIndex--;
     183                 :     }
     184                 : 
     185                 :     // We didn't find our target subfield or instance!
     186               0 :     return NULL;
     187                 : }
     188                 : 
     189                 : /************************************************************************/
     190                 : /*                           GetRepeatCount()                           */
     191                 : /************************************************************************/
     192                 : 
     193                 : /**
     194                 :  * How many times do the subfields of this record repeat?  This    
     195                 :  * will always be one for non-repeating fields.
     196                 :  *
     197                 :  * @return The number of times that the subfields of this record occur
     198                 :  * in this record.  This will be one for non-repeating fields.
     199                 :  *
     200                 :  * @see <a href="example.html">8211view example program</a>
     201                 :  * for demonstation of handling repeated fields properly.
     202                 :  */
     203                 : 
     204             252 : int DDFField::GetRepeatCount()
     205                 : 
     206                 : {
     207             252 :     if( !poDefn->IsRepeating() )
     208               0 :         return 1;
     209                 : 
     210                 : /* -------------------------------------------------------------------- */
     211                 : /*      The occurance count depends on how many copies of this          */
     212                 : /*      field's list of subfields can fit into the data space.          */
     213                 : /* -------------------------------------------------------------------- */
     214             252 :     if( poDefn->GetFixedWidth() )
     215                 :     {
     216             236 :         return nDataSize / poDefn->GetFixedWidth();
     217                 :     }
     218                 : 
     219                 : /* -------------------------------------------------------------------- */
     220                 : /*      Note that it may be legal to have repeating variable width      */
     221                 : /*      subfields, but I don't have any samples, so I ignore it for     */
     222                 : /*      now.                                                            */
     223                 : /*                                                                      */
     224                 : /*      The file data/cape_royal_AZ_DEM/1183XREF.DDF has a repeating    */
     225                 : /*      variable length field, but the count is one, so it isn't        */
     226                 : /*      much value for testing.                                         */
     227                 : /* -------------------------------------------------------------------- */
     228              16 :     int         iOffset = 0, iRepeatCount = 1;
     229                 :     
     230              20 :     while( TRUE )
     231                 :     {
     232             112 :         for( int iSF = 0; iSF < poDefn->GetSubfieldCount(); iSF++ )
     233                 :         {
     234                 :             int nBytesConsumed;
     235              76 :             DDFSubfieldDefn * poThisSFDefn = poDefn->GetSubfield( iSF );
     236                 : 
     237              76 :             if( poThisSFDefn->GetWidth() > nDataSize - iOffset )
     238               0 :                 nBytesConsumed = poThisSFDefn->GetWidth();
     239                 :             else
     240                 :                 poThisSFDefn->GetDataLength( pachData+iOffset, 
     241                 :                                              nDataSize - iOffset,
     242              76 :                                              &nBytesConsumed);
     243                 : 
     244              76 :             iOffset += nBytesConsumed;
     245              76 :             if( iOffset > nDataSize )
     246               0 :                 return iRepeatCount - 1;
     247                 :         }
     248                 : 
     249              36 :         if( iOffset > nDataSize - 2 )
     250              16 :             return iRepeatCount;
     251                 : 
     252              20 :         iRepeatCount++;
     253                 :     }
     254                 : }
     255                 : 
     256                 : /************************************************************************/
     257                 : /*                          GetInstanceData()                           */
     258                 : /************************************************************************/
     259                 : 
     260                 : /**
     261                 :  * Get field instance data and size.
     262                 :  *
     263                 :  * The returned data pointer and size values are suitable for use with
     264                 :  * DDFRecord::SetFieldRaw(). 
     265                 :  *
     266                 :  * @param nInstance a value from 0 to GetRepeatCount()-1.  
     267                 :  * @param pnInstanceSize a location to put the size (in bytes) of the
     268                 :  * field instance data returned.  This size will include the unit terminator
     269                 :  * (if any), but not the field terminator.  This size pointer may be NULL
     270                 :  * if not needed.
     271                 :  *
     272                 :  * @return the data pointer, or NULL on error. 
     273                 :  */
     274                 : 
     275              16 : const char *DDFField::GetInstanceData( int nInstance, 
     276                 :                                        int *pnInstanceSize )
     277                 : 
     278                 : {
     279              16 :     int nRepeatCount = GetRepeatCount();
     280                 :     const char *pachWrkData;
     281                 : 
     282              16 :     if( nInstance < 0 || nInstance >= nRepeatCount )
     283               0 :         return NULL;
     284                 : 
     285                 : /* -------------------------------------------------------------------- */
     286                 : /*      Special case for fields without subfields (like "0001").  We    */
     287                 : /*      don't currently handle repeating simple fields.                 */
     288                 : /* -------------------------------------------------------------------- */
     289              16 :     if( poDefn->GetSubfieldCount() == 0 )
     290                 :     {
     291               0 :         pachWrkData = GetData();
     292               0 :         if( pnInstanceSize != 0 )
     293               0 :             *pnInstanceSize = GetDataSize();
     294               0 :         return pachWrkData;
     295                 :     }
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Get a pointer to the start of the existing data for this        */
     299                 : /*      iteration of the field.                                         */
     300                 : /* -------------------------------------------------------------------- */
     301                 :     int         nBytesRemaining1, nBytesRemaining2;
     302                 :     DDFSubfieldDefn *poFirstSubfield;
     303                 : 
     304              16 :     poFirstSubfield = poDefn->GetSubfield(0);
     305                 : 
     306                 :     pachWrkData = GetSubfieldData(poFirstSubfield, &nBytesRemaining1,
     307              16 :                                nInstance);
     308                 : 
     309                 : /* -------------------------------------------------------------------- */
     310                 : /*      Figure out the size of the entire field instance, including     */
     311                 : /*      unit terminators, but not any trailing field terminator.        */
     312                 : /* -------------------------------------------------------------------- */
     313              16 :     if( pnInstanceSize != NULL )
     314                 :     {
     315                 :         DDFSubfieldDefn *poLastSubfield;
     316                 :         int              nLastSubfieldWidth;
     317                 :         const char          *pachLastData;
     318                 :         
     319              16 :         poLastSubfield = poDefn->GetSubfield(poDefn->GetSubfieldCount()-1);
     320                 :         
     321                 :         pachLastData = GetSubfieldData( poLastSubfield, &nBytesRemaining2, 
     322              16 :                                         nInstance );
     323                 :         poLastSubfield->GetDataLength( pachLastData, nBytesRemaining2, 
     324              16 :                                        &nLastSubfieldWidth );
     325                 :         
     326                 :         *pnInstanceSize = 
     327              16 :             nBytesRemaining1 - (nBytesRemaining2 - nLastSubfieldWidth);
     328                 :     }
     329                 : 
     330              16 :     return pachWrkData;
     331                 : }

Generated by: LCOV version 1.7