LCOV - code coverage report
Current view: directory - frmts/iso8211 - ddfsubfielddefn.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 287 112 39.0 %
Date: 2013-03-30 Functions: 16 8 50.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ddfsubfielddefn.cpp 25697 2013-03-02 18:44:32Z 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 25697 2013-03-02 18:44:32Z rouault $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                          DDFSubfieldDefn()                           */
      37                 : /************************************************************************/
      38                 : 
      39            3154 : DDFSubfieldDefn::DDFSubfieldDefn()
      40                 : 
      41                 : {
      42            3154 :     pszName = NULL;
      43                 :     
      44            3154 :     bIsVariable = TRUE;
      45            3154 :     nFormatWidth = 0;
      46            3154 :     chFormatDelimeter = DDF_UNIT_TERMINATOR;
      47            3154 :     eBinaryFormat = NotBinary;
      48            3154 :     eType = DDFString;
      49                 :     
      50            3154 :     pszFormatString = CPLStrdup("");
      51                 : 
      52            3154 :     nMaxBufChars = 0;
      53            3154 :     pachBuffer = NULL;
      54            3154 : }
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                          ~DDFSubfieldDefn()                          */
      58                 : /************************************************************************/
      59                 : 
      60            3154 : DDFSubfieldDefn::~DDFSubfieldDefn()
      61                 : 
      62                 : {
      63            3154 :     CPLFree( pszName );
      64            3154 :     CPLFree( pszFormatString );
      65            3154 :     CPLFree( pachBuffer );
      66            3154 : }
      67                 : 
      68                 : /************************************************************************/
      69                 : /*                              SetName()                               */
      70                 : /************************************************************************/
      71                 : 
      72            3154 : void DDFSubfieldDefn::SetName( const char * pszNewName )
      73                 : 
      74                 : {
      75                 :     int         i;
      76                 :     
      77            3154 :     CPLFree( pszName );
      78                 : 
      79            3154 :     pszName = CPLStrdup( pszNewName );
      80                 : 
      81            3448 :     for( i = strlen(pszName)-1; i > 0 && pszName[i] == ' '; i-- )
      82             294 :         pszName[i] = '\0';
      83            3154 : }
      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            3154 : int DDFSubfieldDefn::SetFormat( const char * pszFormat )
      97                 : 
      98                 : {
      99            3154 :     CPLFree( pszFormatString );
     100            3154 :     pszFormatString = CPLStrdup( pszFormat );
     101                 : 
     102                 : /* -------------------------------------------------------------------- */
     103                 : /*      These values will likely be used.                               */
     104                 : /* -------------------------------------------------------------------- */
     105            3154 :     if( pszFormatString[1] == '(' )
     106                 :     {
     107            2308 :         nFormatWidth = atoi(pszFormatString+2);
     108            2308 :         bIsVariable = nFormatWidth == 0;
     109                 :     }
     110                 :     else
     111             846 :         bIsVariable = TRUE;
     112                 :     
     113                 : /* -------------------------------------------------------------------- */
     114                 : /*      Interpret the format string.                                    */
     115                 : /* -------------------------------------------------------------------- */
     116            3154 :     switch( pszFormatString[0] )
     117                 :     {
     118                 :       case 'A':
     119                 :       case 'C':         // It isn't clear to me how this is different than 'A'
     120            1173 :         eType = DDFString;
     121            1173 :         break;
     122                 : 
     123                 :       case 'R':
     124             206 :         eType = DDFFloat;
     125             206 :         break;
     126                 :         
     127                 :       case 'I':
     128                 :       case 'S':
     129            1246 :         eType = DDFInt;
     130            1246 :         break;
     131                 : 
     132                 :       case 'B':
     133                 :       case 'b':
     134                 :         // Is the width expressed in bits? (is it a bitstring)
     135             529 :         bIsVariable = FALSE;
     136             529 :         if( pszFormatString[1] == '(' )
     137                 :         {
     138              37 :             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              37 :             nFormatWidth = atoi(pszFormatString+2) / 8;
     147              37 :             eBinaryFormat = SInt; // good default, works for SDTS.
     148                 : 
     149              37 :             if( nFormatWidth < 5 )
     150              16 :                 eType = DDFInt;
     151                 :             else
     152              21 :                 eType = DDFBinaryString;
     153                 :         }
     154                 :         
     155                 :         // or do we have a binary type indicator? (is it binary)
     156                 :         else
     157                 :         {
     158             492 :             eBinaryFormat = (DDFBinaryFormat) (pszFormatString[1] - '0');
     159             492 :             nFormatWidth = atoi(pszFormatString+2);
     160                 : 
     161             984 :             if( eBinaryFormat == SInt || eBinaryFormat == UInt )
     162             492 :                 eType = DDFInt;
     163                 :             else
     164               0 :                 eType = DDFFloat;
     165                 :         }
     166             529 :         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            3154 :     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           90279 : int DDFSubfieldDefn::GetDataLength( const char * pachSourceData,
     240                 :                                     int nMaxBytes, int * pnConsumedBytes )
     241                 : 
     242                 : {
     243           90279 :     if( !bIsVariable )
     244                 :     {
     245           87907 :         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           87907 :             if( pnConsumedBytes != NULL )
     260           84542 :                 *pnConsumedBytes = nFormatWidth;
     261                 : 
     262           87907 :             return nFormatWidth;
     263                 :         }
     264                 :     }
     265                 :     else
     266                 :     {
     267            2372 :         int     nLength = 0;
     268            2372 :         int     bAsciiField = TRUE;
     269            2372 :         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            7118 :         if( nMaxBytes > 1 
     293            2372 :             && (pachSourceData[nMaxBytes-2] == chFormatDelimeter
     294            2250 :                 || pachSourceData[nMaxBytes-2] == DDF_FIELD_TERMINATOR) 
     295             124 :             && pachSourceData[nMaxBytes-1] == 0x00 )
     296               2 :             bAsciiField = FALSE;
     297                 : 
     298                 : //        if( !bAsciiField )
     299                 : //            CPLDebug( "ISO8211", "Non-ASCII field detected." );
     300                 : 
     301           21461 :         while( nLength < nMaxBytes)
     302                 :         {
     303           19089 :             if (bAsciiField)
     304                 :             {
     305           35304 :                 if (pachSourceData[nLength] == chFormatDelimeter ||
     306           16475 :                     pachSourceData[nLength] == DDF_FIELD_TERMINATOR)
     307            2370 :                     break;
     308                 :             }
     309                 :             else
     310                 :             {
     311             776 :                 if (nLength > 0 
     312             258 :                     && (pachSourceData[nLength-1] == chFormatDelimeter 
     313             254 :                         || pachSourceData[nLength-1] == DDF_FIELD_TERMINATOR) 
     314               4 :                     && 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               4 :                     if (nLength+1 < nMaxBytes &&
     320               2 :                         pachSourceData[nLength+1] == DDF_FIELD_TERMINATOR)
     321               2 :                         extraConsumedBytes++;
     322               2 :                     break;
     323                 :                 } 
     324                 :             }
     325                 :             
     326           16717 :             nLength++;
     327                 :         }
     328                 : 
     329            2372 :         if( pnConsumedBytes != NULL )
     330                 :         {
     331            1977 :             if( nMaxBytes == 0 )
     332               0 :                 *pnConsumedBytes = nLength + extraConsumedBytes;
     333                 :             else
     334            1977 :                 *pnConsumedBytes = nLength + extraConsumedBytes + 1;
     335                 :         }
     336                 :         
     337            2372 :         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            4003 : DDFSubfieldDefn::ExtractStringData( const char * pachSourceData,
     378                 :                                     int nMaxBytes, int * pnConsumedBytes )
     379                 : 
     380                 : {
     381                 :     int         nLength = GetDataLength( pachSourceData, nMaxBytes,
     382            4003 :                                          pnConsumedBytes );
     383                 : 
     384                 : /* -------------------------------------------------------------------- */
     385                 : /*      Do we need to grow the buffer.                                  */
     386                 : /* -------------------------------------------------------------------- */
     387            4003 :     if( nMaxBufChars < nLength+1 )
     388                 :     {
     389             523 :         CPLFree( pachBuffer );
     390                 :         
     391             523 :         nMaxBufChars = nLength+1;
     392             523 :         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            4003 :     memcpy( pachBuffer, pachSourceData, nLength );
     400            4003 :     pachBuffer[nLength] = '\0';
     401                 : 
     402            4003 :     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              88 : DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
     434                 :                                    int nMaxBytes, int * pnConsumedBytes )
     435                 : 
     436                 : {
     437              88 :     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              88 :                                       pnConsumedBytes));
     446                 : 
     447                 :       case 'B':
     448                 :       case 'b':
     449                 :       {
     450                 :           unsigned char   abyData[8];
     451               0 :           void* pabyData = abyData;
     452                 : 
     453               0 :           if( nFormatWidth > nMaxBytes )
     454                 :           {
     455                 :               CPLError( CE_Warning, CPLE_AppDefined,
     456                 :                         "Attempt to extract float subfield %s with format %s\n"
     457                 :                         "failed as only %d bytes available.  Using zero.",
     458               0 :                         pszName, pszFormatString, nMaxBytes );
     459               0 :               return 0;
     460                 :           }
     461                 : 
     462               0 :           if( pnConsumedBytes != NULL )
     463               0 :               *pnConsumedBytes = nFormatWidth;
     464                 : 
     465                 :           // Byte swap the data if it isn't in machine native format.
     466                 :           // In any event we copy it into our buffer to ensure it is
     467                 :           // word aligned.
     468                 : #ifdef CPL_LSB
     469               0 :           if( pszFormatString[0] == 'B' )
     470                 : #else            
     471                 :               if( pszFormatString[0] == 'b' )
     472                 : #endif            
     473                 :               {
     474               0 :                   for( int i = 0; i < nFormatWidth; i++ )
     475               0 :                       abyData[nFormatWidth-i-1] = pachSourceData[i];
     476                 :               }
     477                 :               else
     478                 :               {
     479               0 :                   memcpy( abyData, pachSourceData, nFormatWidth );
     480                 :               }
     481                 : 
     482                 :           // Interpret the bytes of data.
     483               0 :           switch( eBinaryFormat )
     484                 :           {
     485                 :             case UInt:
     486               0 :               if( nFormatWidth == 1 )
     487               0 :                   return( abyData[0] );
     488               0 :               else if( nFormatWidth == 2 )
     489               0 :                   return( *((GUInt16 *) pabyData) );
     490               0 :               else if( nFormatWidth == 4 )
     491               0 :                   return( *((GUInt32 *) pabyData) );
     492                 :               else
     493                 :               {
     494                 :                   //CPLAssert( FALSE );
     495               0 :                   return 0.0;
     496                 :               }
     497                 :             
     498                 :             case SInt:
     499               0 :               if( nFormatWidth == 1 )
     500               0 :                   return( *((signed char *) abyData) );
     501               0 :               else if( nFormatWidth == 2 )
     502               0 :                   return( *((GInt16 *) pabyData) );
     503               0 :               else if( nFormatWidth == 4 )
     504               0 :                   return( *((GInt32 *) pabyData) );
     505                 :               else
     506                 :               {
     507                 :                   //CPLAssert( FALSE );
     508               0 :                   return 0.0;
     509                 :               }
     510                 :             
     511                 :             case FloatReal:
     512               0 :               if( nFormatWidth == 4 )
     513               0 :                   return( *((float *) pabyData) );
     514               0 :               else if( nFormatWidth == 8 )
     515               0 :                   return( *((double *) pabyData) );
     516                 :               else
     517                 :               {
     518                 :                   //CPLAssert( FALSE );
     519               0 :                   return 0.0;
     520                 :               }
     521                 : 
     522                 :             case NotBinary:            
     523                 :             case FPReal:
     524                 :             case FloatComplex:
     525                 :               //CPLAssert( FALSE );
     526               0 :               return 0.0;
     527                 :           }
     528                 :           break;
     529                 :           // end of 'b'/'B' case.
     530                 :       }
     531                 : 
     532                 :       default:
     533                 :         //CPLAssert( FALSE );
     534               0 :         return 0.0;
     535                 :     }
     536                 : 
     537                 :     //CPLAssert( FALSE );
     538               0 :     return 0.0;
     539                 : }
     540                 : 
     541                 : /************************************************************************/
     542                 : /*                           ExtractIntData()                           */
     543                 : /************************************************************************/
     544                 : 
     545                 : /**
     546                 :  * Extract a subfield value as an integer.  Given a pointer to the data
     547                 :  * for this subfield (from within a DDFRecord) this method will return the
     548                 :  * int data for this subfield.  The number of bytes
     549                 :  * consumed as part of this field can also be fetched.  This method may be
     550                 :  * called for any type of subfield, and will return zero if the subfield is
     551                 :  * not numeric.
     552                 :  *
     553                 :  * @param pachSourceData The pointer to the raw data for this field.  This
     554                 :  * may have come from DDFRecord::GetData(), taking into account skip factors
     555                 :  * over previous subfields data.
     556                 :  * @param nMaxBytes The maximum number of bytes that are accessable after
     557                 :  * pachSourceData.
     558                 :  * @param pnConsumedBytes Pointer to an integer into which the number of
     559                 :  * bytes consumed by this field should be written.  May be NULL to ignore.
     560                 :  * This is used as a skip factor to increment pachSourceData to point to the
     561                 :  * next subfields data.
     562                 :  *
     563                 :  * @return The subfield's numeric value (or zero if it isn't numeric).
     564                 :  *
     565                 :  * @see ExtractFloatData(), ExtractStringData()
     566                 :  */
     567                 : 
     568                 : int
     569           49544 : DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
     570                 :                                  int nMaxBytes, int * pnConsumedBytes )
     571                 : 
     572                 : {
     573           49544 :     switch( pszFormatString[0] )
     574                 :     {
     575                 :       case 'A':
     576                 :       case 'I':
     577                 :       case 'R':
     578                 :       case 'S':
     579                 :       case 'C':
     580                 :         return atoi(ExtractStringData(pachSourceData, nMaxBytes,
     581             633 :                                       pnConsumedBytes));
     582                 : 
     583                 :       case 'B':
     584                 :       case 'b':
     585                 :       {
     586                 :           unsigned char   abyData[8];
     587           48911 :           void* pabyData = abyData;
     588                 : 
     589           48911 :           if( nFormatWidth > nMaxBytes || nFormatWidth >= (int)sizeof(abyData) )
     590                 :           {
     591                 :               CPLError( CE_Warning, CPLE_AppDefined, 
     592                 :                         "Attempt to extract int subfield %s with format %s\n"
     593                 :                         "failed as only %d bytes available.  Using zero.",
     594               0 :                         pszName, pszFormatString, MIN(nMaxBytes, (int)sizeof(abyData)) );
     595               0 :               return 0;
     596                 :           }
     597                 : 
     598           48911 :           if( pnConsumedBytes != NULL )
     599           48781 :               *pnConsumedBytes = nFormatWidth;
     600                 : 
     601                 :           // Byte swap the data if it isn't in machine native format.
     602                 :           // In any event we copy it into our buffer to ensure it is
     603                 :           // word aligned.
     604                 : #ifdef CPL_LSB
     605           48911 :           if( pszFormatString[0] == 'B' )
     606                 : #else            
     607                 :               if( pszFormatString[0] == 'b' )
     608                 : #endif            
     609                 :               {
     610               0 :                   for( int i = 0; i < nFormatWidth; i++ )
     611               0 :                       abyData[nFormatWidth-i-1] = pachSourceData[i];
     612                 :               }
     613                 :               else
     614                 :               {
     615           48911 :                   memcpy( abyData, pachSourceData, nFormatWidth );
     616                 :               }
     617                 : 
     618                 :           // Interpret the bytes of data.
     619           48911 :           switch( eBinaryFormat )
     620                 :           {
     621                 :             case UInt:
     622           48667 :               if( nFormatWidth == 4 )
     623           23650 :                   return( (int) *((GUInt32 *) pabyData) );
     624           25017 :               else if( nFormatWidth == 1 )
     625           16499 :                   return( abyData[0] );
     626            8518 :               else if( nFormatWidth == 2 )
     627            8518 :                   return( *((GUInt16 *) pabyData) );
     628                 :               else
     629                 :               {
     630                 :                   //CPLAssert( FALSE );
     631               0 :                   return 0;
     632                 :               }
     633                 :             
     634                 :             case SInt:
     635             244 :               if( nFormatWidth == 4 )
     636             244 :                   return( *((GInt32 *) pabyData) );
     637               0 :               else if( nFormatWidth == 1 )
     638               0 :                   return( *((signed char *) abyData) );
     639               0 :               else if( nFormatWidth == 2 )
     640               0 :                   return( *((GInt16 *) pabyData) );
     641                 :               else
     642                 :               {
     643                 :                   //CPLAssert( FALSE );
     644               0 :                   return 0;
     645                 :               }
     646                 :             
     647                 :             case FloatReal:
     648               0 :               if( nFormatWidth == 4 )
     649               0 :                   return( (int) *((float *) pabyData) );
     650               0 :               else if( nFormatWidth == 8 )
     651               0 :                   return( (int) *((double *) pabyData) );
     652                 :               else
     653                 :               {
     654                 :                   //CPLAssert( FALSE );
     655               0 :                   return 0;
     656                 :               }
     657                 : 
     658                 :             case NotBinary:            
     659                 :             case FPReal:
     660                 :             case FloatComplex:
     661                 :               //CPLAssert( FALSE );
     662               0 :               return 0;
     663                 :           }
     664                 :           break;
     665                 :           // end of 'b'/'B' case.
     666                 :       }
     667                 : 
     668                 :       default:
     669                 :         //CPLAssert( FALSE );
     670               0 :         return 0;
     671                 :     }
     672                 : 
     673                 :     //CPLAssert( FALSE );
     674               0 :     return 0;
     675                 : }
     676                 : 
     677                 : /************************************************************************/
     678                 : /*                              DumpData()                              */
     679                 : /*                                                                      */
     680                 : /*      Dump the instance data for this subfield from a data            */
     681                 : /*      record.  This fits into the output dump stream of a DDFField.   */
     682                 : /************************************************************************/
     683                 : 
     684                 : /**
     685                 :  * Dump subfield value to debugging file.
     686                 :  *
     687                 :  * @param pachData Pointer to data for this subfield.
     688                 :  * @param nMaxBytes Maximum number of bytes available in pachData.
     689                 :  * @param fp File to write report to.
     690                 :  */
     691                 : 
     692               0 : void DDFSubfieldDefn::DumpData( const char * pachData, int nMaxBytes,
     693                 :                                 FILE * fp )
     694                 : 
     695                 : {
     696               0 :     if( eType == DDFFloat )
     697                 :         fprintf( fp, "      Subfield `%s' = %f\n",
     698                 :                  pszName,
     699               0 :                  ExtractFloatData( pachData, nMaxBytes, NULL ) );
     700               0 :     else if( eType == DDFInt )
     701                 :         fprintf( fp, "      Subfield `%s' = %d\n",
     702                 :                  pszName,
     703               0 :                  ExtractIntData( pachData, nMaxBytes, NULL ) );
     704               0 :     else if( eType == DDFBinaryString )
     705                 :     {
     706                 :         int     nBytes, i;
     707               0 :         GByte   *pabyBString = (GByte *) ExtractStringData( pachData, nMaxBytes, &nBytes );
     708                 : 
     709               0 :         fprintf( fp, "      Subfield `%s' = 0x", pszName );
     710               0 :         for( i = 0; i < MIN(nBytes,24); i++ )
     711               0 :             fprintf( fp, "%02X", pabyBString[i] );
     712                 : 
     713               0 :         if( nBytes > 24 )
     714               0 :             fprintf( fp, "%s", "..." );
     715                 : 
     716               0 :         fprintf( fp, "\n" );
     717                 :     }
     718                 :     else
     719                 :         fprintf( fp, "      Subfield `%s' = `%s'\n",
     720                 :                  pszName,
     721               0 :                  ExtractStringData( pachData, nMaxBytes, NULL ) );
     722               0 : }
     723                 : 
     724                 : /************************************************************************/
     725                 : /*                          GetDefaultValue()                           */
     726                 : /************************************************************************/
     727                 : 
     728                 : /**
     729                 :  * Get default data. 
     730                 :  *
     731                 :  * Returns the default subfield data contents for this subfield definition.
     732                 :  * For variable length numbers this will normally be "0<unit-terminator>". 
     733                 :  * For variable length strings it will be "<unit-terminator>".  For fixed
     734                 :  * length numbers it is zero filled.  For fixed length strings it is space
     735                 :  * filled.  For binary numbers it is binary zero filled. 
     736                 :  *
     737                 :  * @param pachData the buffer into which the returned default will be placed.
     738                 :  * May be NULL if just querying default size.
     739                 :  * @param nBytesAvailable the size of pachData in bytes. 
     740                 :  * @param pnBytesUsed will receive the size of the subfield default data in
     741                 :  * bytes.
     742                 :  *
     743                 :  * @return TRUE on success or FALSE on failure or if the passed buffer is too
     744                 :  * small to hold the default.
     745                 :  */
     746                 : 
     747               0 : int DDFSubfieldDefn::GetDefaultValue( char *pachData, int nBytesAvailable, 
     748                 :                                       int *pnBytesUsed )
     749                 : 
     750                 : {
     751                 :     int nDefaultSize;
     752                 : 
     753               0 :     if( !bIsVariable )
     754               0 :         nDefaultSize = nFormatWidth;
     755                 :     else
     756               0 :         nDefaultSize = 1;
     757                 : 
     758               0 :     if( pnBytesUsed != NULL )
     759               0 :         *pnBytesUsed = nDefaultSize;
     760                 : 
     761               0 :     if( pachData == NULL )
     762               0 :         return TRUE;
     763                 : 
     764               0 :     if( nBytesAvailable < nDefaultSize )
     765               0 :         return FALSE;
     766                 : 
     767               0 :     if( bIsVariable )
     768                 :     {
     769               0 :         pachData[0] = DDF_UNIT_TERMINATOR;
     770                 :     }
     771                 :     else
     772                 :     {
     773               0 :         if( GetBinaryFormat() == NotBinary )
     774                 :         {
     775               0 :             if( GetType() == DDFInt || GetType() == DDFFloat )
     776               0 :                 memset( pachData, '0', nDefaultSize );
     777                 :             else
     778               0 :                 memset( pachData, ' ', nDefaultSize );
     779                 :         }
     780                 :         else
     781               0 :             memset( pachData, 0, nDefaultSize );
     782                 :     }
     783                 : 
     784               0 :     return TRUE;
     785                 : }
     786                 : 
     787                 : /************************************************************************/
     788                 : /*                         FormatStringValue()                          */
     789                 : /************************************************************************/
     790                 : 
     791                 : /**
     792                 :  * Format string subfield value.
     793                 :  *
     794                 :  * Returns a buffer with the passed in string value reformatted in a way
     795                 :  * suitable for storage in a DDFField for this subfield.  
     796                 :  */
     797                 : 
     798               0 : int DDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable, 
     799                 :                                         int *pnBytesUsed, 
     800                 :                                         const char *pszValue,
     801                 :                                         int nValueLength )
     802                 : 
     803                 : {
     804                 :     int nSize;
     805                 : 
     806               0 :     if( nValueLength == -1 )
     807               0 :         nValueLength = strlen(pszValue);
     808                 : 
     809               0 :     if( bIsVariable )
     810                 :     {
     811               0 :         nSize = nValueLength + 1;
     812                 :     }
     813                 :     else
     814                 :     {                                                                  
     815               0 :         nSize = nFormatWidth;
     816                 :     }
     817                 : 
     818               0 :     if( pnBytesUsed != NULL )
     819               0 :         *pnBytesUsed = nSize;
     820                 : 
     821               0 :     if( pachData == NULL )
     822               0 :         return TRUE;
     823                 : 
     824               0 :     if( nBytesAvailable < nSize )
     825               0 :         return FALSE;
     826                 : 
     827               0 :     if( bIsVariable )
     828                 :     {
     829               0 :         strncpy( pachData, pszValue, nSize-1 );
     830               0 :         pachData[nSize-1] = DDF_UNIT_TERMINATOR;
     831                 :     }
     832                 :     else
     833                 :     {
     834               0 :         if( GetBinaryFormat() == NotBinary )
     835                 :         {
     836               0 :             memset( pachData, ' ', nSize );
     837               0 :             memcpy( pachData, pszValue, MIN(nValueLength,nSize) );
     838                 :         }
     839                 :         else
     840                 :         {
     841               0 :             memset( pachData, 0, nSize );
     842               0 :             memcpy( pachData, pszValue, MIN(nValueLength,nSize) );
     843                 :         }
     844                 :     }
     845                 : 
     846               0 :     return TRUE;
     847                 : }
     848                 : 
     849                 : /************************************************************************/
     850                 : /*                           FormatIntValue()                           */
     851                 : /************************************************************************/
     852                 : 
     853                 : /**
     854                 :  * Format int subfield value.
     855                 :  *
     856                 :  * Returns a buffer with the passed in int value reformatted in a way
     857                 :  * suitable for storage in a DDFField for this subfield.  
     858                 :  */
     859                 : 
     860               0 : int DDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable, 
     861                 :                                      int *pnBytesUsed, int nNewValue )
     862                 : 
     863                 : {
     864                 :     int nSize;
     865                 :     char szWork[30];
     866                 : 
     867               0 :     sprintf( szWork, "%d", nNewValue );
     868                 : 
     869               0 :     if( bIsVariable )
     870                 :     {
     871               0 :         nSize = strlen(szWork) + 1;
     872                 :     }
     873                 :     else
     874                 :     {                                                                  
     875               0 :         nSize = nFormatWidth;
     876                 : 
     877               0 :         if( GetBinaryFormat() == NotBinary && (int) strlen(szWork) > nSize )
     878               0 :             return FALSE;
     879                 :     }
     880                 : 
     881               0 :     if( pnBytesUsed != NULL )
     882               0 :         *pnBytesUsed = nSize;
     883                 : 
     884               0 :     if( pachData == NULL )
     885               0 :         return TRUE;
     886                 : 
     887               0 :     if( nBytesAvailable < nSize )
     888               0 :         return FALSE;
     889                 : 
     890               0 :     if( bIsVariable )
     891                 :     {
     892               0 :         strncpy( pachData, szWork, nSize-1 );
     893               0 :         pachData[nSize-1] = DDF_UNIT_TERMINATOR;
     894                 :     }
     895                 :     else
     896                 :     {
     897               0 :         GUInt32 nMask = 0xff;
     898                 :         int i;
     899                 : 
     900               0 :         switch( GetBinaryFormat() )
     901                 :         {
     902                 :           case NotBinary:
     903               0 :             memset( pachData, '0', nSize );
     904                 :             strncpy( pachData + nSize - strlen(szWork), szWork,
     905               0 :                      strlen(szWork) );
     906               0 :             break;
     907                 : 
     908                 :           case UInt:
     909                 :           case SInt:
     910               0 :             for( i = 0; i < nFormatWidth; i++ )
     911                 :             {
     912                 :                 int iOut;
     913                 : 
     914                 :                 // big endian required?
     915               0 :                 if( pszFormatString[0] == 'B' )
     916               0 :                     iOut = nFormatWidth - i - 1;
     917                 :                 else
     918               0 :                     iOut = i;
     919                 : 
     920               0 :                 pachData[iOut] = (char)((nNewValue & nMask) >> (i*8));
     921               0 :                 nMask *= 256;
     922                 :             }
     923               0 :             break;
     924                 : 
     925                 :           case FloatReal:
     926               0 :             CPLAssert( FALSE );
     927               0 :             break;
     928                 : 
     929                 :           default:
     930               0 :             CPLAssert( FALSE );
     931                 :             break;
     932                 :         }
     933                 :     }
     934                 : 
     935               0 :     return TRUE;
     936                 : }
     937                 : 
     938                 : /************************************************************************/
     939                 : /*                          FormatFloatValue()                          */
     940                 : /************************************************************************/
     941                 : 
     942                 : /**
     943                 :  * Format float subfield value.
     944                 :  *
     945                 :  * Returns a buffer with the passed in float value reformatted in a way
     946                 :  * suitable for storage in a DDFField for this subfield.  
     947                 :  */
     948                 : 
     949               0 : int DDFSubfieldDefn::FormatFloatValue( char *pachData, int nBytesAvailable, 
     950                 :                                        int *pnBytesUsed, double dfNewValue )
     951                 : 
     952                 : {
     953                 :     int nSize;
     954                 :     char szWork[120];
     955                 : 
     956               0 :     sprintf( szWork, "%.16g", dfNewValue );
     957                 : 
     958               0 :     if( bIsVariable )
     959                 :     {
     960               0 :         nSize = strlen(szWork) + 1;
     961                 :     }
     962                 :     else
     963                 :     {
     964               0 :         nSize = nFormatWidth;
     965                 : 
     966               0 :         if( GetBinaryFormat() == NotBinary && (int) strlen(szWork) > nSize )
     967               0 :             return FALSE;
     968                 :     }
     969                 : 
     970               0 :     if( pnBytesUsed != NULL )
     971               0 :         *pnBytesUsed = nSize;
     972                 : 
     973               0 :     if( pachData == NULL )
     974               0 :         return TRUE;
     975                 : 
     976               0 :     if( nBytesAvailable < nSize )
     977               0 :         return FALSE;
     978                 : 
     979               0 :     if( bIsVariable )
     980                 :     {
     981               0 :         strncpy( pachData, szWork, nSize-1 );
     982               0 :         pachData[nSize-1] = DDF_UNIT_TERMINATOR;
     983                 :     }
     984                 :     else
     985                 :     {
     986               0 :         if( GetBinaryFormat() == NotBinary )
     987                 :         {
     988               0 :             memset( pachData, '0', nSize );
     989                 :             strncpy( pachData + nSize - strlen(szWork), szWork,
     990               0 :                      strlen(szWork) );
     991                 :         }
     992                 :         else
     993                 :         {
     994               0 :             CPLAssert( FALSE );
     995                 :             /* implement me */
     996                 :         }
     997                 :     }
     998                 : 
     999               0 :     return TRUE;
    1000                 : }

Generated by: LCOV version 1.7