LCOV - code coverage report
Current view: directory - frmts/iso8211 - ddfsubfielddefn.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 285 111 38.9 %
Date: 2012-04-28 Functions: 16 8 50.0 %

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

Generated by: LCOV version 1.7