📄 ddfsubfielddefn.cpp
字号:
#include "stdafx.h"#include "iso8211.h"#include "CplConv.h"/************************************************************************//* DDFSubfieldDefn() *//************************************************************************/DDFSubfieldDefn::DDFSubfieldDefn(){ pszName = NULL; bIsVariable = TRUE; nFormatWidth = 0; chFormatDelimeter = DDF_UNIT_TERMINATOR; eBinaryFormat = NotBinary; eType = DDFString; pszFormatString = CPLStrdup(""); nMaxBufChars = 0; pachBuffer = NULL;}/************************************************************************//* ~DDFSubfieldDefn() *//************************************************************************/DDFSubfieldDefn::~DDFSubfieldDefn(){ CPLFree( pszName ); CPLFree( pszFormatString ); CPLFree( pachBuffer );}/************************************************************************//* SetName() *//************************************************************************/void DDFSubfieldDefn::SetName( const char * pszNewName ){ int i; CPLFree( pszName ); pszName = CPLStrdup( pszNewName ); for( i = strlen(pszName)-1; i > 0 && pszName[i] == ' '; i-- ) pszName[i] = '\0';}/************************************************************************//* SetFormat() *//* *//* While interpreting the format string we don't support: *//* *//* o Passing an explicit terminator for variable length field. *//* o 'X' for unused data ... this should really be filtered *//* out by DDFFieldDefn::ApplyFormats(), but isn't. *//* o 'B' bitstrings that aren't a multiple of eight. *//************************************************************************/int DDFSubfieldDefn::SetFormat( const char * pszFormat ){ CPLFree( pszFormatString ); pszFormatString = CPLStrdup( pszFormat );/* -------------------------------------------------------------------- *//* These values will likely be used. *//* -------------------------------------------------------------------- */ if( pszFormatString[1] == '(' ) { nFormatWidth = atoi(pszFormatString+2); bIsVariable = nFormatWidth == 0; } else bIsVariable = TRUE; /* -------------------------------------------------------------------- *//* Interpret the format string. *//* -------------------------------------------------------------------- */ switch( pszFormatString[0] ) { case 'A': case 'C': // It isn't clear to me how this is different than 'A' eType = DDFString; break; case 'R': eType = DDFFloat; break; case 'I': case 'S': eType = DDFInt; break; case 'B': case 'b': // Is the width expressed in bits? (is it a bitstring) bIsVariable = FALSE; if( pszFormatString[1] == '(' ) { CPLAssert( atoi(pszFormatString+2) % 8 == 0 ); nFormatWidth = atoi(pszFormatString+2) / 8; eBinaryFormat = SInt; // good default, works for SDTS. if( nFormatWidth < 5 ) eType = DDFInt; else eType = DDFBinaryString; } // or do we have a binary type indicator? (is it binary) else { eBinaryFormat = (DDFBinaryFormat) (pszFormatString[1] - '0'); nFormatWidth = atoi(pszFormatString+2); if( eBinaryFormat == SInt || eBinaryFormat == UInt ) eType = DDFInt; else eType = DDFFloat; } break; case 'X': // 'X' is extra space, and shouldn't be directly assigned to a // subfield ... I haven't encountered it in use yet though. CPLError( CE_Failure, CPLE_AppDefined, "Format type of `%c' not supported.\n", pszFormatString[0] ); CPLAssert( FALSE ); return FALSE; default: CPLError( CE_Failure, CPLE_AppDefined, "Format type of `%c' not recognised.\n", pszFormatString[0] ); CPLAssert( FALSE ); return FALSE; } return TRUE;}/************************************************************************//* Dump() *//************************************************************************//** * Write out subfield definition info to debugging file. * * A variety of information about this field definition is written to the * give debugging file handle. * * @param fp The standard io file handle to write to. ie. stderr */void DDFSubfieldDefn::Dump( FILE * fp ){ fprintf( fp, " DDFSubfieldDefn:\n" ); fprintf( fp, " Label = `%s'\n", pszName ); fprintf( fp, " FormatString = `%s'\n", pszFormatString );}/************************************************************************//* GetDataLength() *//* *//* This method will scan for the end of a variable field. *//************************************************************************//** * Scan for the end of variable length data. Given a pointer to the data * for this subfield (from within a DDFRecord) this method will return the * number of bytes which are data for this subfield. The number of bytes * consumed as part of this field can also be fetched. This number may * be one longer than the length if there is a terminator character * used.<p> * * This method is mainly for internal use, or for applications which * want the raw binary data to interpret themselves. Otherwise use one * of ExtractStringData(), ExtractIntData() or ExtractFloatData(). * * @param pachSourceData The pointer to the raw data for this field. This * may have come from DDFRecord::GetData(), taking into account skip factors * over previous subfields data. * @param nMaxBytes The maximum number of bytes that are accessable after * pachSourceData. * @param pnConsumedBytes Pointer to an integer into which the number of * bytes consumed by this field should be written. May be NULL to ignore. * * @return The number of bytes at pachSourceData which are actual data for * this record (not including unit, or field terminator). */int DDFSubfieldDefn::GetDataLength( const char * pachSourceData, int nMaxBytes, int * pnConsumedBytes ){ if( !bIsVariable ) { if( nFormatWidth > nMaxBytes ) { CPLError( CE_Warning, CPLE_AppDefined, "Only %d bytes available for subfield %s with\n" "format string %s ... returning shortened data.", nMaxBytes, pszName, pszFormatString ); if( pnConsumedBytes != NULL ) *pnConsumedBytes = nMaxBytes; return nMaxBytes; } else { if( pnConsumedBytes != NULL ) *pnConsumedBytes = nFormatWidth; return nFormatWidth; } } else { int nLength = 0; int bCheckFieldTerminator = TRUE; /* We only check for the field terminator because of some buggy * datasets with missing format terminators. However, we have found * the field terminator is a legal character within the fields of * some extended datasets (such as JP34NC94.000). So we don't check * for the field terminator if the field appears to be multi-byte * which we established by the first character being out of the * ASCII printable range (32-127). */ if( pachSourceData[0] < 32 || pachSourceData[0] >= 127 ) bCheckFieldTerminator = FALSE; while( nLength < nMaxBytes && pachSourceData[nLength] != chFormatDelimeter ) { if( bCheckFieldTerminator && pachSourceData[nLength] == DDF_FIELD_TERMINATOR ) break; nLength++; } if( pnConsumedBytes != NULL ) { if( nMaxBytes == 0 ) *pnConsumedBytes = nLength; else *pnConsumedBytes = nLength+1; } return nLength; }}/************************************************************************//* ExtractStringData() *//************************************************************************//** * Extract a zero terminated string containing the data for this subfield. * Given a pointer to the data * for this subfield (from within a DDFRecord) this method will return the * data for this subfield. The number of bytes * consumed as part of this field can also be fetched. This number may * be one longer than the string length if there is a terminator character * used.<p> * * This function will return the raw binary data of a subfield for * types other than DDFString, including data past zero chars. This is * the standard way of extracting DDFBinaryString subfields for instance.<p> * * @param pachSourceData The pointer to the raw data for this field. This * may have come from DDFRecord::GetData(), taking into account skip factors * over previous subfields data. * @param nMaxBytes The maximum number of bytes that are accessable after * pachSourceData. * @param pnConsumedBytes Pointer to an integer into which the number of * bytes consumed by this field should be written. May be NULL to ignore. * This is used as a skip factor to increment pachSourceData to point to the * next subfields data. * * @return A pointer to a buffer containing the data for this field. The * returned pointer is to an internal buffer which is invalidated on the * next ExtractStringData() call on this DDFSubfieldDefn(). It should not * be freed by the application. * * @see ExtractIntData(), ExtractFloatData() */const char *DDFSubfieldDefn::ExtractStringData( const char * pachSourceData, int nMaxBytes, int * pnConsumedBytes ){ int nLength = GetDataLength( pachSourceData, nMaxBytes, pnConsumedBytes );/* -------------------------------------------------------------------- *//* Do we need to grow the buffer. *//* -------------------------------------------------------------------- */ if( nMaxBufChars < nLength+1 ) { CPLFree( pachBuffer ); nMaxBufChars = nLength+1; pachBuffer = (char *) CPLMalloc(nMaxBufChars); }/* -------------------------------------------------------------------- *//* Copy the data to the buffer. We use memcpy() so that it *//* will work for binary data. *//* -------------------------------------------------------------------- */ memcpy( pachBuffer, pachSourceData, nLength ); pachBuffer[nLength] = '\0'; return pachBuffer;}/************************************************************************//* ExtractFloatData() *//************************************************************************//** * Extract a subfield value as a float. Given a pointer to the data * for this subfield (from within a DDFRecord) this method will return the * floating point data for this subfield. The number of bytes * consumed as part of this field can also be fetched. This method may be * called for any type of subfield, and will return zero if the subfield is * not numeric. * * @param pachSourceData The pointer to the raw data for this field. This * may have come from DDFRecord::GetData(), taking into account skip factors * over previous subfields data. * @param nMaxBytes The maximum number of bytes that are accessable after * pachSourceData. * @param pnConsumedBytes Pointer to an integer into which the number of * bytes consumed by this field should be written. May be NULL to ignore. * This is used as a skip factor to increment pachSourceData to point to the * next subfields data. * * @return The subfield's numeric value (or zero if it isn't numeric). * * @see ExtractIntData(), ExtractStringData() */doubleDDFSubfieldDefn::ExtractFloatData( const char * pachSourceData, int nMaxBytes, int * pnConsumedBytes ){ switch( pszFormatString[0] ) { case 'A': case 'I': case 'R': case 'S': case 'C': return atof(ExtractStringData(pachSourceData, nMaxBytes, pnConsumedBytes)); case 'B': case 'b': { unsigned char abyData[8]; CPLAssert( nFormatWidth <= nMaxBytes ); if( pnConsumedBytes != NULL ) *pnConsumedBytes = nFormatWidth; // Byte swap the data if it isn't in machine native format. // In any event we copy it into our buffer to ensure it is // word aligned.#ifdef CPL_LSB if( pszFormatString[0] == 'B' )#else if( pszFormatString[0] == 'b' )#endif { for( int i = 0; i < nFormatWidth; i++ ) abyData[nFormatWidth-i-1] = pachSourceData[i]; } else { memcpy( abyData, pachSourceData, nFormatWidth ); } // Interpret the bytes of data. switch( eBinaryFormat ) { case UInt: if( nFormatWidth == 1 ) return( abyData[0] ); else if( nFormatWidth == 2 ) return( *((GUInt16 *) abyData) ); else if( nFormatWidth == 4 ) return( *((GUInt32 *) abyData) ); else { CPLAssert( FALSE ); return 0.0; } case SInt: if( nFormatWidth == 1 ) return( *((signed char *) abyData) ); else if( nFormatWidth == 2 ) return( *((GInt16 *) abyData) ); else if( nFormatWidth == 4 ) return( *((GInt32 *) abyData) ); else { CPLAssert( FALSE ); return 0.0; } case FloatReal: if( nFormatWidth == 4 ) return( *((float *) abyData) ); else if( nFormatWidth == 8 ) return( *((double *) abyData) ); else { CPLAssert( FALSE ); return 0.0; } case NotBinary: case FPReal: case FloatComplex: CPLAssert( FALSE ); return 0.0; } break; // end of 'b'/'B' case. } default: CPLAssert( FALSE ); return 0.0; } CPLAssert( FALSE ); return 0.0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -