LCOV - code coverage report
Current view: directory - frmts/iso8211 - ddfsubfielddefn.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 295 111 37.6 %
Date: 2011-12-18 Functions: 16 8 50.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ddfsubfielddefn.cpp 17405 2009-07-17 06:13:24Z chaitanya $
       3                 :  *
       4                 :  * Project:  ISO 8211 Access
       5                 :  * Purpose:  Implements the DDFSubfieldDefn 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: ddfsubfielddefn.cpp 17405 2009-07-17 06:13:24Z chaitanya $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                          DDFSubfieldDefn()                           */
      37                 : /************************************************************************/
      38                 : 
      39            2662 : DDFSubfieldDefn::DDFSubfieldDefn()
      40                 : 
      41                 : {
      42            2662 :     pszName = NULL;
      43                 :     
      44            2662 :     bIsVariable = TRUE;
      45            2662 :     nFormatWidth = 0;
      46            2662 :     chFormatDelimeter = DDF_UNIT_TERMINATOR;
      47            2662 :     eBinaryFormat = NotBinary;
      48            2662 :     eType = DDFString;
      49                 :     
      50            2662 :     pszFormatString = CPLStrdup("");
      51                 : 
      52            2662 :     nMaxBufChars = 0;
      53            2662 :     pachBuffer = NULL;
      54            2662 : }
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                          ~DDFSubfieldDefn()                          */
      58                 : /************************************************************************/
      59                 : 
      60            2662 : DDFSubfieldDefn::~DDFSubfieldDefn()
      61                 : 
      62                 : {
      63            2662 :     CPLFree( pszName );
      64            2662 :     CPLFree( pszFormatString );
      65            2662 :     CPLFree( pachBuffer );
      66            2662 : }
      67                 : 
      68                 : /************************************************************************/
      69                 : /*                              SetName()                               */
      70                 : /************************************************************************/
      71                 : 
      72            2662 : void DDFSubfieldDefn::SetName( const char * pszNewName )
      73                 : 
      74                 : {
      75                 :     int         i;
      76                 :     
      77            2662 :     CPLFree( pszName );
      78                 : 
      79            2662 :     pszName = CPLStrdup( pszNewName );
      80                 : 
      81            2956 :     for( i = strlen(pszName)-1; i > 0 && pszName[i] == ' '; i-- )
      82             294 :         pszName[i] = '\0';
      83            2662 : }
      84                 : 
      85                 : /************************************************************************/
      86                 : /*                             SetFormat()                              */
      87                 : /*                                                                      */
      88                 : /*      While interpreting the format string we don't support:          */
      89                 : /*                                                                      */
      90                 : /*       o Passing an explicit terminator for variable length field.    */
      91                 : /*       o 'X' for unused data ... this should really be filtered       */
      92                 : /*         out by DDFFieldDefn::ApplyFormats(), but isn't.              */
      93                 : /*       o 'B' bitstrings that aren't a multiple of eight.              */
      94                 : /************************************************************************/
      95                 : 
      96            2662 : int DDFSubfieldDefn::SetFormat( const char * pszFormat )
      97                 : 
      98                 : {
      99            2662 :     CPLFree( pszFormatString );
     100            2662 :     pszFormatString = CPLStrdup( pszFormat );
     101                 : 
     102                 : /* -------------------------------------------------------------------- */
     103                 : /*      These values will likely be used.                               */
     104                 : /* -------------------------------------------------------------------- */
     105            2662 :     if( pszFormatString[1] == '(' )
     106                 :     {
     107            1888 :         nFormatWidth = atoi(pszFormatString+2);
     108            1888 :         bIsVariable = nFormatWidth == 0;
     109                 :     }
     110                 :     else
     111             774 :         bIsVariable = TRUE;
     112                 :     
     113                 : /* -------------------------------------------------------------------- */
     114                 : /*      Interpret the format string.                                    */
     115                 : /* -------------------------------------------------------------------- */
     116            2662 :     switch( pszFormatString[0] )
     117                 :     {
     118                 :       case 'A':
     119                 :       case 'C':         // It isn't clear to me how this is different than 'A'
     120             987 :         eType = DDFString;
     121             987 :         break;
     122                 : 
     123                 :       case 'R':
     124             140 :         eType = DDFFloat;
     125             140 :         break;
     126                 :         
     127                 :       case 'I':
     128                 :       case 'S':
     129            1012 :         eType = DDFInt;
     130            1012 :         break;
     131                 : 
     132                 :       case 'B':
     133                 :       case 'b':
     134                 :         // Is the width expressed in bits? (is it a bitstring)
     135             523 :         bIsVariable = FALSE;
     136             523 :         if( pszFormatString[1] == '(' )
     137                 :         {
     138              31 :             CPLAssert( atoi(pszFormatString+2) % 8 == 0 );
     139                 :             
     140              31 :             nFormatWidth = atoi(pszFormatString+2) / 8;
     141              31 :             eBinaryFormat = SInt; // good default, works for SDTS.
     142                 : 
     143              31 :             if( nFormatWidth < 5 )
     144              10 :                 eType = DDFInt;
     145                 :             else
     146              21 :                 eType = DDFBinaryString;
     147                 :         }
     148                 :         
     149                 :         // or do we have a binary type indicator? (is it binary)
     150                 :         else
     151                 :         {
     152             492 :             eBinaryFormat = (DDFBinaryFormat) (pszFormatString[1] - '0');
     153             492 :             nFormatWidth = atoi(pszFormatString+2);
     154                 : 
     155             984 :             if( eBinaryFormat == SInt || eBinaryFormat == UInt )
     156             492 :                 eType = DDFInt;
     157                 :             else
     158               0 :                 eType = DDFFloat;
     159                 :         }
     160             523 :         break;
     161                 : 
     162                 :       case 'X':
     163                 :         // 'X' is extra space, and shouldn't be directly assigned to a
     164                 :         // subfield ... I haven't encountered it in use yet though.
     165                 :         CPLError( CE_Failure, CPLE_AppDefined,
     166                 :                   "Format type of `%c' not supported.\n",
     167               0 :                   pszFormatString[0] );
     168                 :         
     169               0 :         CPLAssert( FALSE );
     170               0 :         return FALSE;
     171                 :         
     172                 :       default:
     173                 :         CPLError( CE_Failure, CPLE_AppDefined,
     174                 :                   "Format type of `%c' not recognised.\n",
     175               0 :                   pszFormatString[0] );
     176                 :         
     177               0 :         CPLAssert( FALSE );
     178               0 :         return FALSE;
     179                 :     }
     180                 :     
     181            2662 :     return TRUE;
     182                 : }
     183                 : 
     184                 : /************************************************************************/
     185                 : /*                                Dump()                                */
     186                 : /************************************************************************/
     187                 : 
     188                 : /**
     189                 :  * Write out subfield definition info to debugging file.
     190                 :  *
     191                 :  * A variety of information about this field definition is written to the
     192                 :  * give debugging file handle.
     193                 :  *
     194                 :  * @param fp The standard io file handle to write to.  ie. stderr
     195                 :  */
     196                 : 
     197               0 : void DDFSubfieldDefn::Dump( FILE * fp )
     198                 : 
     199                 : {
     200               0 :     fprintf( fp, "    DDFSubfieldDefn:\n" );
     201               0 :     fprintf( fp, "        Label = `%s'\n", pszName );
     202               0 :     fprintf( fp, "        FormatString = `%s'\n", pszFormatString );
     203               0 : }
     204                 : 
     205                 : /************************************************************************/
     206                 : /*                           GetDataLength()                            */
     207                 : /*                                                                      */
     208                 : /*      This method will scan for the end of a variable field.          */
     209                 : /************************************************************************/
     210                 : 
     211                 : /**
     212                 :  * Scan for the end of variable length data.  Given a pointer to the data
     213                 :  * for this subfield (from within a DDFRecord) this method will return the
     214                 :  * number of bytes which are data for this subfield.  The number of bytes
     215                 :  * consumed as part of this field can also be fetched.  This number may
     216                 :  * be one longer than the length if there is a terminator character
     217                 :  * used.<p>
     218                 :  *
     219                 :  * This method is mainly for internal use, or for applications which
     220                 :  * want the raw binary data to interpret themselves.  Otherwise use one
     221                 :  * of ExtractStringData(), ExtractIntData() or ExtractFloatData().
     222                 :  *
     223                 :  * @param pachSourceData The pointer to the raw data for this field.  This
     224                 :  * may have come from DDFRecord::GetData(), taking into account skip factors
     225                 :  * over previous subfields data.
     226                 :  * @param nMaxBytes The maximum number of bytes that are accessable after
     227                 :  * pachSourceData.
     228                 :  * @param pnConsumedBytes Pointer to an integer into which the number of
     229                 :  * bytes consumed by this field should be written.  May be NULL to ignore.
     230                 :  *
     231                 :  * @return The number of bytes at pachSourceData which are actual data for
     232                 :  * this record (not including unit, or field terminator).  
     233                 :  */
     234                 : 
     235           87285 : int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
     236                 :                                     int nMaxBytes, int * pnConsumedBytes )
     237                 : 
     238                 : {
     239           87285 :     if( !bIsVariable )
     240                 :     {
     241           85429 :         if( nFormatWidth > nMaxBytes )
     242                 :         {
     243                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     244                 :                       "Only %d bytes available for subfield %s with\n"
     245                 :                       "format string %s ... returning shortened data.",
     246               0 :                       nMaxBytes, pszName, pszFormatString );
     247                 : 
     248               0 :             if( pnConsumedBytes != NULL )
     249               0 :                 *pnConsumedBytes = nMaxBytes;
     250                 : 
     251               0 :             return nMaxBytes;
     252                 :         }
     253                 :         else
     254                 :         {
     255           85429 :             if( pnConsumedBytes != NULL )
     256           82088 :                 *pnConsumedBytes = nFormatWidth;
     257                 : 
     258           85429 :             return nFormatWidth;
     259                 :         }
     260                 :     }
     261                 :     else
     262                 :     {
     263            1856 :         int     nLength = 0;
     264            1856 :         int     bAsciiField = TRUE;
     265            1856 :         int     extraConsumedBytes = 0;
     266                 : 
     267                 :         /* We only check for the field terminator because of some buggy 
     268                 :          * datasets with missing format terminators.  However, we have found
     269                 :          * the field terminator and unit terminators are legal characters 
     270                 :          * within the fields of some extended datasets (such as JP34NC94.000).
     271                 :          * So we don't check for the field terminator and unit terminators as 
     272                 :          * a single byte if the field appears to be multi-byte which we 
     273                 :          * establish by checking for the buffer ending with 0x1e 0x00 (a
     274                 :          * two byte field terminator). 
     275                 :          *
     276                 :          * In the case of S57, the subfield ATVL of the NATF field can be 
     277                 :          * encoded in lexical level 2 (see S57 specification, Edition 3.1, 
     278                 :          * paragraph 2.4 and 2.5). In that case the Unit Terminator and Field 
     279                 :          * Terminator are followed by the NULL character.
     280                 :          * A better fix would be to read the NALL tag in the DSSI to check 
     281                 :          * that the lexical level is 2, instead of relying on the value of 
     282                 :          * the first byte as we are doing - but that is not information
     283                 :          * that is available at the libiso8211 level (bug #1526)
     284                 :          */
     285                 : 
     286                 :         // If the whole field ends with 0x1e 0x00 then we assume this
     287                 :         // field is a double byte character set.
     288            5570 :         if( nMaxBytes > 1 
     289            1856 :             && (pachSourceData[nMaxBytes-2] == chFormatDelimeter
     290            1734 :                 || pachSourceData[nMaxBytes-2] == DDF_FIELD_TERMINATOR) 
     291             124 :             && pachSourceData[nMaxBytes-1] == 0x00 )
     292               2 :             bAsciiField = FALSE;
     293                 : 
     294                 : //        if( !bAsciiField )
     295                 : //            CPLDebug( "ISO8211", "Non-ASCII field detected." );
     296                 : 
     297           18695 :         while( nLength < nMaxBytes)
     298                 :         {
     299           16839 :             if (bAsciiField)
     300                 :             {
     301           31320 :                 if (pachSourceData[nLength] == chFormatDelimeter ||
     302           14741 :                     pachSourceData[nLength] == DDF_FIELD_TERMINATOR)
     303            1854 :                     break;
     304                 :             }
     305                 :             else
     306                 :             {
     307             776 :                 if (nLength > 0 
     308             258 :                     && (pachSourceData[nLength-1] == chFormatDelimeter 
     309             254 :                         || pachSourceData[nLength-1] == DDF_FIELD_TERMINATOR) 
     310               4 :                     && pachSourceData[nLength] == 0)
     311                 :                 {
     312                 :                     // Suck up the field terminator if one follows
     313                 :                     // or else it will be interpreted as a new subfield.
     314                 :                     // This is a pretty ugly counter-intuitive hack!
     315               4 :                     if (nLength+1 < nMaxBytes &&
     316               2 :                         pachSourceData[nLength+1] == DDF_FIELD_TERMINATOR)
     317               2 :                         extraConsumedBytes++;
     318               2 :                     break;
     319                 :                 } 
     320                 :             }
     321                 :             
     322           14983 :             nLength++;
     323                 :         }
     324                 : 
     325            1856 :         if( pnConsumedBytes != NULL )
     326                 :         {
     327            1467 :             if( nMaxBytes == 0 )
     328               0 :                 *pnConsumedBytes = nLength + extraConsumedBytes;
     329                 :             else
     330            1467 :                 *pnConsumedBytes = nLength + extraConsumedBytes + 1;
     331                 :         }
     332                 :         
     333            1856 :         return nLength;
     334                 :     }
     335                 : }
     336                 : 
     337                 : /************************************************************************/
     338                 : /*                         ExtractStringData()                          */
     339                 : /************************************************************************/
     340                 : 
     341                 : /**
     342                 :  * Extract a zero terminated string containing the data for this subfield.
     343                 :  * Given a pointer to the data
     344                 :  * for this subfield (from within a DDFRecord) this method will return the
     345                 :  * data for this subfield.  The number of bytes
     346                 :  * consumed as part of this field can also be fetched.  This number may
     347                 :  * be one longer than the string length if there is a terminator character
     348                 :  * used.<p>
     349                 :  *
     350                 :  * This function will return the raw binary data of a subfield for
     351                 :  * types other than DDFString, including data past zero chars.  This is
     352                 :  * the standard way of extracting DDFBinaryString subfields for instance.<p>
     353                 :  *
     354                 :  * @param pachSourceData The pointer to the raw data for this field.  This
     355                 :  * may have come from DDFRecord::GetData(), taking into account skip factors
     356                 :  * over previous subfields data.
     357                 :  * @param nMaxBytes The maximum number of bytes that are accessable after
     358                 :  * pachSourceData.
     359                 :  * @param pnConsumedBytes Pointer to an integer into which the number of
     360                 :  * bytes consumed by this field should be written.  May be NULL to ignore.
     361                 :  * This is used as a skip factor to increment pachSourceData to point to the
     362                 :  * next subfields data.
     363                 :  *
     364                 :  * @return A pointer to a buffer containing the data for this field.  The
     365                 :  * returned pointer is to an internal buffer which is invalidated on the
     366                 :  * next ExtractStringData() call on this DDFSubfieldDefn().  It should not
     367                 :  * be freed by the application.
     368                 :  *
     369                 :  * @see ExtractIntData(), ExtractFloatData()
     370                 :  */
     371                 : 
     372                 : const char *
     373            3793 : DDFSubfieldDefn::ExtractStringData( const char * pachSourceData,
     374                 :                                     int nMaxBytes, int * pnConsumedBytes )
     375                 : 
     376                 : {
     377                 :     int         nLength = GetDataLength( pachSourceData, nMaxBytes,
     378            3793 :                                          pnConsumedBytes );
     379                 : 
     380                 : /* -------------------------------------------------------------------- */
     381                 : /*      Do we need to grow the buffer.                                  */
     382                 : /* -------------------------------------------------------------------- */
     383            3793 :     if( nMaxBufChars < nLength+1 )
     384                 :     {
     385             385 :         CPLFree( pachBuffer );
     386                 :         
     387             385 :         nMaxBufChars = nLength+1;
     388             385 :         pachBuffer = (char *) CPLMalloc(nMaxBufChars);
     389                 :     }
     390                 : 
     391                 : /* -------------------------------------------------------------------- */
     392                 : /*      Copy the data to the buffer.  We use memcpy() so that it        */
     393                 : /*      will work for binary data.                                      */
     394                 : /* -------------------------------------------------------------------- */
     395            3793 :     memcpy( pachBuffer, pachSourceData, nLength );
     396            3793 :     pachBuffer[nLength] = '\0';
     397                 : 
     398            3793 :     return pachBuffer;
     399                 : }
     400                 : 
     401                 : /************************************************************************/
     402                 : /*                          ExtractFloatData()                          */
     403                 : /************************************************************************/
     404                 : 
     405                 : /**
     406                 :  * Extract a subfield value as a float.  Given a pointer to the data
     407                 :  * for this subfield (from within a DDFRecord) this method will return the
     408                 :  * floating point data for this subfield.  The number of bytes
     409                 :  * consumed as part of this field can also be fetched.  This method may be
     410                 :  * called for any type of subfield, and will return zero if the subfield is
     411                 :  * not numeric.
     412                 :  *
     413                 :  * @param pachSourceData The pointer to the raw data for this field.  This
     414                 :  * may have come from DDFRecord::GetData(), taking into account skip factors
     415                 :  * over previous subfields data.
     416                 :  * @param nMaxBytes The maximum number of bytes that are accessable after
     417                 :  * pachSourceData.
     418                 :  * @param pnConsumedBytes Pointer to an integer into which the number of
     419                 :  * bytes consumed by this field should be written.  May be NULL to ignore.
     420                 :  * This is used as a skip factor to increment pachSourceData to point to the
     421                 :  * next subfields data.
     422                 :  *
     423                 :  * @return The subfield's numeric value (or zero if it isn't numeric).
     424                 :  *
     425                 :  * @see ExtractIntData(), ExtractStringData()
     426                 :  */
     427                 : 
     428                 : double
     429              58 : DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
     430                 :                                    int nMaxBytes, int * pnConsumedBytes )
     431                 : 
     432                 : {
     433              58 :     switch( pszFormatString[0] )
     434                 :     {
     435                 :       case 'A':
     436                 :       case 'I':
     437                 :       case 'R':
     438                 :       case 'S':
     439                 :       case 'C':
     440                 :         return atof(ExtractStringData(pachSourceData, nMaxBytes,
     441              58 :                                       pnConsumedBytes));
     442                 : 
     443                 :       case 'B':
     444                 :       case 'b':
     445                 :       {
     446                 :           unsigned char   abyData[8];
     447                 : 
     448               0 :           CPLAssert( nFormatWidth <= nMaxBytes );
     449               0 :           if( pnConsumedBytes != NULL )
     450               0 :               *pnConsumedBytes = nFormatWidth;
     451                 : 
     452                 :           // Byte swap the data if it isn't in machine native format.
     453                 :           // In any event we copy it into our buffer to ensure it is
     454                 :           // word aligned.
     455                 : #ifdef CPL_LSB
     456               0 :           if( pszFormatString[0] == 'B' )
     457                 : #else            
     458                 :               if( pszFormatString[0] == 'b' )
     459                 : #endif            
     460                 :               {
     461               0 :                   for( int i = 0; i < nFormatWidth; i++ )
     462               0 :                       abyData[nFormatWidth-i-1] = pachSourceData[i];
     463                 :               }
     464                 :               else
     465                 :               {
     466               0 :                   memcpy( abyData, pachSourceData, nFormatWidth );
     467                 :               }
     468                 : 
     469                 :           // Interpret the bytes of data.
     470               0 :           switch( eBinaryFormat )
     471                 :           {
     472                 :             case UInt:
     473               0 :               if( nFormatWidth == 1 )
     474               0 :                   return( abyData[0] );
     475               0 :               else if( nFormatWidth == 2 )
     476               0 :                   return( *((GUInt16 *) abyData) );
     477               0 :               else if( nFormatWidth == 4 )
     478               0 :                   return( *((GUInt32 *) abyData) );
     479                 :               else
     480                 :               {
     481               0 :                   CPLAssert( FALSE );
     482               0 :                   return 0.0;
     483                 :               }
     484                 :             
     485                 :             case SInt:
     486               0 :               if( nFormatWidth == 1 )
     487               0 :                   return( *((signed char *) abyData) );
     488               0 :               else if( nFormatWidth == 2 )
     489               0 :                   return( *((GInt16 *) abyData) );
     490               0 :               else if( nFormatWidth == 4 )
     491               0 :                   return( *((GInt32 *) abyData) );
     492                 :               else
     493                 :               {
     494               0 :                   CPLAssert( FALSE );
     495               0 :                   return 0.0;
     496                 :               }
     497                 :             
     498                 :             case FloatReal:
     499               0 :               if( nFormatWidth == 4 )
     500               0 :                   return( *((float *) abyData) );
     501               0 :               else if( nFormatWidth == 8 )
     502               0 :                   return( *((double *) abyData) );
     503                 :               else
     504                 :               {
     505               0 :                   CPLAssert( FALSE );
     506               0 :                   return 0.0;
     507                 :               }
     508                 : 
     509                 :             case NotBinary:            
     510                 :             case FPReal:
     511                 :             case FloatComplex:
     512               0 :               CPLAssert( FALSE );
     513               0 :               return 0.0;
     514                 :           }
     515                 :           break;
     516                 :           // end of 'b'/'B' case.
     517                 :       }
     518                 : 
     519                 :       default:
     520               0 :         CPLAssert( FALSE );
     521               0 :         return 0.0;
     522                 :     }
     523                 : 
     524               0 :     CPLAssert( FALSE );
     525               0 :     return 0.0;
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                           ExtractIntData()                           */
     530                 : /************************************************************************/
     531                 : 
     532                 : /**
     533                 :  * Extract a subfield value as an integer.  Given a pointer to the data
     534                 :  * for this subfield (from within a DDFRecord) this method will return the
     535                 :  * int data for this subfield.  The number of bytes
     536                 :  * consumed as part of this field can also be fetched.  This method may be
     537                 :  * called for any type of subfield, and will return zero if the subfield is
     538                 :  * not numeric.
     539                 :  *
     540                 :  * @param pachSourceData The pointer to the raw data for this field.  This
     541                 :  * may have come from DDFRecord::GetData(), taking into account skip factors
     542                 :  * over previous subfields data.
     543                 :  * @param nMaxBytes The maximum number of bytes that are accessable after
     544                 :  * pachSourceData.
     545                 :  * @param pnConsumedBytes Pointer to an integer into which the number of
     546                 :  * bytes consumed by this field should be written.  May be NULL to ignore.
     547                 :  * This is used as a skip factor to increment pachSourceData to point to the
     548                 :  * next subfields data.
     549                 :  *
     550                 :  * @return The subfield's numeric value (or zero if it isn't numeric).
     551                 :  *
     552                 :  * @see ExtractFloatData(), ExtractStringData()
     553                 :  */
     554                 : 
     555                 : int
     556           49394 : DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
     557                 :                                  int nMaxBytes, int * pnConsumedBytes )
     558                 : 
     559                 : {
     560           49394 :     switch( pszFormatString[0] )
     561                 :     {
     562                 :       case 'A':
     563                 :       case 'I':
     564                 :       case 'R':
     565                 :       case 'S':
     566                 :       case 'C':
     567                 :         return atoi(ExtractStringData(pachSourceData, nMaxBytes,
     568             483 :                                       pnConsumedBytes));
     569                 : 
     570                 :       case 'B':
     571                 :       case 'b':
     572                 :       {
     573                 :           unsigned char   abyData[8];
     574                 : 
     575           48911 :           if( nFormatWidth > nMaxBytes )
     576                 :           {
     577                 :               CPLError( CE_Warning, CPLE_AppDefined, 
     578                 :                         "Attempt to extract int subfield %s with format %s\n"
     579                 :                         "failed as only %d bytes available.  Using zero.",
     580               0 :                         pszName, pszFormatString, nMaxBytes );
     581               0 :               return 0;
     582                 :           }
     583                 : 
     584           48911 :           if( pnConsumedBytes != NULL )
     585           48781 :               *pnConsumedBytes = nFormatWidth;
     586                 : 
     587                 :           // Byte swap the data if it isn't in machine native format.
     588                 :           // In any event we copy it into our buffer to ensure it is
     589                 :           // word aligned.
     590                 : #ifdef CPL_LSB
     591           48911 :           if( pszFormatString[0] == 'B' )
     592                 : #else            
     593                 :               if( pszFormatString[0] == 'b' )
     594                 : #endif            
     595                 :               {
     596               0 :                   for( int i = 0; i < nFormatWidth; i++ )
     597               0 :                       abyData[nFormatWidth-i-1] = pachSourceData[i];
     598                 :               }
     599                 :               else
     600                 :               {
     601           48911 :                   memcpy( abyData, pachSourceData, nFormatWidth );
     602                 :               }
     603                 : 
     604                 :           // Interpret the bytes of data.
     605           48911 :           switch( eBinaryFormat )
     606                 :           {
     607                 :             case UInt:
     608           48667 :               if( nFormatWidth == 4 )
     609           23650 :                   return( (int) *((GUInt32 *) abyData) );
     610           25017 :               else if( nFormatWidth == 1 )
     611           16499 :                   return( abyData[0] );
     612            8518 :               else if( nFormatWidth == 2 )
     613            8518 :                   return( *((GUInt16 *) abyData) );
     614                 :               else
     615                 :               {
     616               0 :                   CPLAssert( FALSE );
     617               0 :                   return 0;
     618                 :               }
     619                 :             
     620                 :             case SInt:
     621             244 :               if( nFormatWidth == 4 )
     622             244 :                   return( *((GInt32 *) abyData) );
     623               0 :               else if( nFormatWidth == 1 )
     624               0 :                   return( *((signed char *) abyData) );
     625               0 :               else if( nFormatWidth == 2 )
     626               0 :                   return( *((GInt16 *) abyData) );
     627                 :               else
     628                 :               {
     629               0 :                   CPLAssert( FALSE );
     630               0 :                   return 0;
     631                 :               }
     632                 :             
     633                 :             case FloatReal:
     634               0 :               if( nFormatWidth == 4 )
     635               0 :                   return( (int) *((float *) abyData) );
     636               0 :               else if( nFormatWidth == 8 )
     637               0 :                   return( (int) *((double *) abyData) );
     638                 :               else
     639                 :               {
     640               0 :                   CPLAssert( FALSE );
     641               0 :                   return 0;
     642                 :               }
     643                 : 
     644                 :             case NotBinary:            
     645                 :             case FPReal:
     646                 :             case FloatComplex:
     647               0 :               CPLAssert( FALSE );
     648               0 :               return 0;
     649                 :           }
     650                 :           break;
     651                 :           // end of 'b'/'B' case.
     652                 :       }
     653                 : 
     654                 :       default:
     655               0 :         CPLAssert( FALSE );
     656               0 :         return 0;
     657                 :     }
     658                 : 
     659               0 :     CPLAssert( FALSE );
     660               0 :     return 0;
     661                 : }
     662                 : 
     663                 : /************************************************************************/
     664                 : /*                              DumpData()                              */
     665                 : /*                                                                      */
     666                 : /*      Dump the instance data for this subfield from a data            */
     667                 : /*      record.  This fits into the output dump stream of a DDFField.   */
     668                 : /************************************************************************/
     669                 : 
     670                 : /**
     671                 :  * Dump subfield value to debugging file.
     672                 :  *
     673                 :  * @param pachData Pointer to data for this subfield.
     674                 :  * @param nMaxBytes Maximum number of bytes available in pachData.
     675                 :  * @param fp File to write report to.
     676                 :  */
     677                 : 
     678               0 : void DDFSubfieldDefn::DumpData( const char * pachData, int nMaxBytes,
     679                 :                                 FILE * fp )
     680                 : 
     681                 : {
     682               0 :     if( eType == DDFFloat )
     683                 :         fprintf( fp, "      Subfield `%s' = %f\n",
     684                 :                  pszName,
     685               0 :                  ExtractFloatData( pachData, nMaxBytes, NULL ) );
     686               0 :     else if( eType == DDFInt )
     687                 :         fprintf( fp, "      Subfield `%s' = %d\n",
     688                 :                  pszName,
     689               0 :                  ExtractIntData( pachData, nMaxBytes, NULL ) );
     690               0 :     else if( eType == DDFBinaryString )
     691                 :     {
     692                 :         int     nBytes, i;
     693               0 :         GByte   *pabyBString = (GByte *) ExtractStringData( pachData, nMaxBytes, &nBytes );
     694                 : 
     695               0 :         fprintf( fp, "      Subfield `%s' = 0x", pszName );
     696               0 :         for( i = 0; i < MIN(nBytes,24); i++ )
     697               0 :             fprintf( fp, "%02X", pabyBString[i] );
     698                 : 
     699               0 :         if( nBytes > 24 )
     700               0 :             fprintf( fp, "%s", "..." );
     701                 : 
     702               0 :         fprintf( fp, "\n" );
     703                 :     }
     704                 :     else
     705                 :         fprintf( fp, "      Subfield `%s' = `%s'\n",
     706                 :                  pszName,
     707               0 :                  ExtractStringData( pachData, nMaxBytes, NULL ) );
     708               0 : }
     709                 : 
     710                 : /************************************************************************/
     711                 : /*                          GetDefaultValue()                           */
     712                 : /************************************************************************/
     713                 : 
     714                 : /**
     715                 :  * Get default data. 
     716                 :  *
     717                 :  * Returns the default subfield data contents for this subfield definition.
     718                 :  * For variable length numbers this will normally be "0<unit-terminator>". 
     719                 :  * For variable length strings it will be "<unit-terminator>".  For fixed
     720                 :  * length numbers it is zero filled.  For fixed length strings it is space
     721                 :  * filled.  For binary numbers it is binary zero filled. 
     722                 :  *
     723                 :  * @param pachData the buffer into which the returned default will be placed.
     724                 :  * May be NULL if just querying default size.
     725                 :  * @param nBytesAvailable the size of pachData in bytes. 
     726                 :  * @param pnBytesUsed will receive the size of the subfield default data in
     727                 :  * bytes.
     728                 :  *
     729                 :  * @return TRUE on success or FALSE on failure or if the passed buffer is too
     730                 :  * small to hold the default.
     731                 :  */
     732                 : 
     733               0 : int DDFSubfieldDefn::GetDefaultValue( char *pachData, int nBytesAvailable, 
     734                 :                                       int *pnBytesUsed )
     735                 : 
     736                 : {
     737                 :     int nDefaultSize;
     738                 : 
     739               0 :     if( !bIsVariable )
     740               0 :         nDefaultSize = nFormatWidth;
     741                 :     else
     742               0 :         nDefaultSize = 1;
     743                 : 
     744               0 :     if( pnBytesUsed != NULL )
     745               0 :         *pnBytesUsed = nDefaultSize;
     746                 : 
     747               0 :     if( pachData == NULL )
     748               0 :         return TRUE;
     749                 : 
     750               0 :     if( nBytesAvailable < nDefaultSize )
     751               0 :         return FALSE;
     752                 : 
     753               0 :     if( bIsVariable )
     754                 :     {
     755               0 :         pachData[0] = DDF_UNIT_TERMINATOR;
     756                 :     }
     757                 :     else
     758                 :     {
     759               0 :         if( GetBinaryFormat() == NotBinary )
     760                 :         {
     761               0 :             if( GetType() == DDFInt || GetType() == DDFFloat )
     762               0 :                 memset( pachData, '0', nDefaultSize );
     763                 :             else
     764               0 :                 memset( pachData, ' ', nDefaultSize );
     765                 :         }
     766                 :         else
     767               0 :             memset( pachData, 0, nDefaultSize );
     768                 :     }
     769                 : 
     770               0 :     return TRUE;
     771                 : }
     772                 : 
     773                 : /************************************************************************/
     774                 : /*                         FormatStringValue()                          */
     775                 : /************************************************************************/
     776                 : 
     777                 : /**
     778                 :  * Format string subfield value.
     779                 :  *
     780                 :  * Returns a buffer with the passed in string value reformatted in a way
     781                 :  * suitable for storage in a DDFField for this subfield.  
     782                 :  */
     783                 : 
     784               0 : int DDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable, 
     785                 :                                         int *pnBytesUsed, 
     786                 :                                         const char *pszValue,
     787                 :                                         int nValueLength )
     788                 : 
     789                 : {
     790                 :     int nSize;
     791                 : 
     792               0 :     if( nValueLength == -1 )
     793               0 :         nValueLength = strlen(pszValue);
     794                 : 
     795               0 :     if( bIsVariable )
     796                 :     {
     797               0 :         nSize = nValueLength + 1;
     798                 :     }
     799                 :     else
     800                 :     {                                                                  
     801               0 :         nSize = nFormatWidth;
     802                 :     }
     803                 : 
     804               0 :     if( pnBytesUsed != NULL )
     805               0 :         *pnBytesUsed = nSize;
     806                 : 
     807               0 :     if( pachData == NULL )
     808               0 :         return TRUE;
     809                 : 
     810               0 :     if( nBytesAvailable < nSize )
     811               0 :         return FALSE;
     812                 : 
     813               0 :     if( bIsVariable )
     814                 :     {
     815               0 :         strncpy( pachData, pszValue, nSize-1 );
     816               0 :         pachData[nSize-1] = DDF_UNIT_TERMINATOR;
     817                 :     }
     818                 :     else
     819                 :     {
     820               0 :         if( GetBinaryFormat() == NotBinary )
     821                 :         {
     822               0 :             memset( pachData, ' ', nSize );
     823               0 :             memcpy( pachData, pszValue, MIN(nValueLength,nSize) );
     824                 :         }
     825                 :         else
     826                 :         {
     827               0 :             memset( pachData, 0, nSize );
     828               0 :             memcpy( pachData, pszValue, MIN(nValueLength,nSize) );
     829                 :         }
     830                 :     }
     831                 : 
     832               0 :     return TRUE;
     833                 : }
     834                 : 
     835                 : /************************************************************************/
     836                 : /*                           FormatIntValue()                           */
     837                 : /************************************************************************/
     838                 : 
     839                 : /**
     840                 :  * Format int subfield value.
     841                 :  *
     842                 :  * Returns a buffer with the passed in int value reformatted in a way
     843                 :  * suitable for storage in a DDFField for this subfield.  
     844                 :  */
     845                 : 
     846               0 : int DDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable, 
     847                 :                                      int *pnBytesUsed, int nNewValue )
     848                 : 
     849                 : {
     850                 :     int nSize;
     851                 :     char szWork[30];
     852                 : 
     853               0 :     sprintf( szWork, "%d", nNewValue );
     854                 : 
     855               0 :     if( bIsVariable )
     856                 :     {
     857               0 :         nSize = strlen(szWork) + 1;
     858                 :     }
     859                 :     else
     860                 :     {                                                                  
     861               0 :         nSize = nFormatWidth;
     862                 : 
     863               0 :         if( GetBinaryFormat() == NotBinary && (int) strlen(szWork) > nSize )
     864               0 :             return FALSE;
     865                 :     }
     866                 : 
     867               0 :     if( pnBytesUsed != NULL )
     868               0 :         *pnBytesUsed = nSize;
     869                 : 
     870               0 :     if( pachData == NULL )
     871               0 :         return TRUE;
     872                 : 
     873               0 :     if( nBytesAvailable < nSize )
     874               0 :         return FALSE;
     875                 : 
     876               0 :     if( bIsVariable )
     877                 :     {
     878               0 :         strncpy( pachData, szWork, nSize-1 );
     879               0 :         pachData[nSize-1] = DDF_UNIT_TERMINATOR;
     880                 :     }
     881                 :     else
     882                 :     {
     883               0 :         GUInt32 nMask = 0xff;
     884                 :         int i;
     885                 : 
     886               0 :         switch( GetBinaryFormat() )
     887                 :         {
     888                 :           case NotBinary:
     889               0 :             memset( pachData, '0', nSize );
     890                 :             strncpy( pachData + nSize - strlen(szWork), szWork,
     891               0 :                      strlen(szWork) );
     892               0 :             break;
     893                 : 
     894                 :           case UInt:
     895                 :           case SInt:
     896               0 :             for( i = 0; i < nFormatWidth; i++ )
     897                 :             {
     898                 :                 int iOut;
     899                 : 
     900                 :                 // big endian required?
     901               0 :                 if( pszFormatString[0] == 'B' )
     902               0 :                     iOut = nFormatWidth - i - 1;
     903                 :                 else
     904               0 :                     iOut = i;
     905                 : 
     906               0 :                 pachData[iOut] = (char)((nNewValue & nMask) >> (i*8));
     907               0 :                 nMask *= 256;
     908                 :             }
     909               0 :             break;
     910                 : 
     911                 :           case FloatReal:
     912               0 :             CPLAssert( FALSE );
     913               0 :             break;
     914                 : 
     915                 :           default:
     916               0 :             CPLAssert( FALSE );
     917                 :             break;
     918                 :         }
     919                 :     }
     920                 : 
     921               0 :     return TRUE;
     922                 : }
     923                 : 
     924                 : /************************************************************************/
     925                 : /*                          FormatFloatValue()                          */
     926                 : /************************************************************************/
     927                 : 
     928                 : /**
     929                 :  * Format float subfield value.
     930                 :  *
     931                 :  * Returns a buffer with the passed in float value reformatted in a way
     932                 :  * suitable for storage in a DDFField for this subfield.  
     933                 :  */
     934                 : 
     935               0 : int DDFSubfieldDefn::FormatFloatValue( char *pachData, int nBytesAvailable, 
     936                 :                                        int *pnBytesUsed, double dfNewValue )
     937                 : 
     938                 : {
     939                 :     int nSize;
     940                 :     char szWork[120];
     941                 : 
     942               0 :     sprintf( szWork, "%.16g", dfNewValue );
     943                 : 
     944               0 :     if( bIsVariable )
     945                 :     {
     946               0 :         nSize = strlen(szWork) + 1;
     947                 :     }
     948                 :     else
     949                 :     {
     950               0 :         nSize = nFormatWidth;
     951                 : 
     952               0 :         if( GetBinaryFormat() == NotBinary && (int) strlen(szWork) > nSize )
     953               0 :             return FALSE;
     954                 :     }
     955                 : 
     956               0 :     if( pnBytesUsed != NULL )
     957               0 :         *pnBytesUsed = nSize;
     958                 : 
     959               0 :     if( pachData == NULL )
     960               0 :         return TRUE;
     961                 : 
     962               0 :     if( nBytesAvailable < nSize )
     963               0 :         return FALSE;
     964                 : 
     965               0 :     if( bIsVariable )
     966                 :     {
     967               0 :         strncpy( pachData, szWork, nSize-1 );
     968               0 :         pachData[nSize-1] = DDF_UNIT_TERMINATOR;
     969                 :     }
     970                 :     else
     971                 :     {
     972               0 :         if( GetBinaryFormat() == NotBinary )
     973                 :         {
     974               0 :             memset( pachData, '0', nSize );
     975                 :             strncpy( pachData + nSize - strlen(szWork), szWork,
     976               0 :                      strlen(szWork) );
     977                 :         }
     978                 :         else
     979                 :         {
     980               0 :             CPLAssert( FALSE );
     981                 :             /* implement me */
     982                 :         }
     983                 :     }
     984                 : 
     985               0 :     return TRUE;
     986                 : }

Generated by: LCOV version 1.7