📄 ddfrecord.cpp
字号:
#include "stdafx.h"#include "iso8211.h"#include "CplConv.h"static const size_t nLeaderSize = 24;/************************************************************************//* DDFRecord() *//************************************************************************/DDFRecord::DDFRecord( DDFModule * poModuleIn ){ poModule = poModuleIn; nReuseHeader = FALSE; nFieldOffset = 0; nDataSize = 0; pachData = NULL; nFieldCount = 0; paoFields = NULL; bIsClone = FALSE; _sizeFieldTag = 4; _sizeFieldPos = 0; _sizeFieldLength = 0;}/************************************************************************//* ~DDFRecord() *//************************************************************************/DDFRecord::~DDFRecord(){ Clear(); if( bIsClone ) poModule->RemoveCloneRecord( this );}/************************************************************************//* Dump() *//************************************************************************//** * Write out record contents to debugging file. * * A variety of information about this record, and all it's fields and * subfields is written to the given debugging file handle. Note that * field definition information (ala DDFFieldDefn) isn't written. * * @param fp The standard io file handle to write to. ie. stderr */void DDFRecord::Dump( FILE * fp ){ fprintf( fp, "DDFRecord:\n" ); fprintf( fp, " nReuseHeader = %d\n", nReuseHeader ); fprintf( fp, " nDataSize = %d\n", nDataSize ); fprintf( fp, " _sizeFieldLength=%d, _sizeFieldPos=%d, _sizeFieldTag=%d\n", _sizeFieldLength, _sizeFieldPos, _sizeFieldTag ); for( int i = 0; i < nFieldCount; i++ ) { paoFields[i].Dump( fp ); }}/************************************************************************//* Read() *//* *//* Read a record of data from the file, and parse the header to *//* build a field list for the record (or reuse the existing one *//* if reusing headers). It is expected that the file pointer *//* will be positioned at the beginning of a data record. It is *//* the DDFModule's responsibility to do so. *//* *//* This method should only be called by the DDFModule class. *//************************************************************************/int DDFRecord::Read(){/* -------------------------------------------------------------------- *//* Redefine the record on the basis of the header if needed. *//* As a side effect this will read the data for the record as well.*//* -------------------------------------------------------------------- */ if( !nReuseHeader ) { return( ReadHeader() ); }/* -------------------------------------------------------------------- *//* Otherwise we read just the data and carefully overlay it on *//* the previous records data without disturbing the rest of the *//* record. *//* -------------------------------------------------------------------- */ size_t nReadBytes; nReadBytes = VSIFRead( pachData + nFieldOffset, 1, nDataSize - nFieldOffset, poModule->GetFP() ); if( nReadBytes != (size_t) (nDataSize - nFieldOffset) && nReadBytes == 0 && VSIFEof( poModule->GetFP() ) ) { return FALSE; } else if( nReadBytes != (size_t) (nDataSize - nFieldOffset) ) { CPLError( CE_Failure, CPLE_FileIO, "Data record is short on DDF file.\n" ); return FALSE; } // notdef: eventually we may have to do something at this point to // notify the DDFField's that their data values have changed. return TRUE;}/************************************************************************//* Write() *//************************************************************************//** * Write record out to module. * * This method writes the current record to the module to which it is * attached. Normally this would be at the end of the file, and only used * for modules newly created with DDFModule::Create(). Rewriting existing * records is not supported at this time. Calling Write() multiple times * on a DDFRecord will result it multiple copies being written at the end of * the module. * * @return TRUE on success or FALSE on failure. */int DDFRecord::Write(){ if( !ResetDirectory() ) return FALSE; /* -------------------------------------------------------------------- *//* Prepare leader. *//* -------------------------------------------------------------------- */ char szLeader[nLeaderSize+1]; memset( szLeader, ' ', nLeaderSize ); sprintf( szLeader+0, "%05d", nDataSize + nLeaderSize ); szLeader[5] = ' '; szLeader[6] = 'D'; sprintf( szLeader + 12, "%05d", nFieldOffset + nLeaderSize ); szLeader[17] = ' '; szLeader[20] = (char) ('0' + _sizeFieldLength); szLeader[21] = (char) ('0' + _sizeFieldPos); szLeader[22] = '0'; szLeader[23] = (char) ('0' + _sizeFieldTag); /* notdef: lots of stuff missing *//* -------------------------------------------------------------------- *//* Write the leader. *//* -------------------------------------------------------------------- */ VSIFWrite( szLeader, nLeaderSize, 1, poModule->GetFP() );/* -------------------------------------------------------------------- *//* Write the remainder of the record. *//* -------------------------------------------------------------------- */ VSIFWrite( pachData, nDataSize, 1, poModule->GetFP() ); return TRUE;}/************************************************************************//* Clear() *//* *//* Clear any information associated with the last header in *//* preparation for reading a new header. *//************************************************************************/void DDFRecord::Clear(){ if( paoFields != NULL ) delete[] paoFields; paoFields = NULL; nFieldCount = 0; if( pachData != NULL ) CPLFree( pachData ); pachData = NULL; nDataSize = 0; nReuseHeader = FALSE;}/************************************************************************//* ReadHeader() *//* *//* This perform the header reading and parsing job for the *//* Read() method. It reads the header, and builds a field *//* list. *//************************************************************************/int DDFRecord::ReadHeader(){/* -------------------------------------------------------------------- *//* Clear any existing information. *//* -------------------------------------------------------------------- */ Clear(); /* -------------------------------------------------------------------- *//* Read the 24 byte leader. *//* -------------------------------------------------------------------- */ char achLeader[nLeaderSize]; int nReadBytes; nReadBytes = VSIFRead(achLeader,1,nLeaderSize,poModule->GetFP()); if( nReadBytes == 0 && VSIFEof( poModule->GetFP() ) ) { return FALSE; } else if( nReadBytes != (int) nLeaderSize ) { CPLError( CE_Failure, CPLE_FileIO, "Leader is short on DDF file." ); return FALSE; }/* -------------------------------------------------------------------- *//* Extract information from leader. *//* -------------------------------------------------------------------- */ int _recLength, _fieldAreaStart; char _leaderIden; _recLength = DDFScanInt( achLeader+0, 5 ); _leaderIden = achLeader[6]; _fieldAreaStart = DDFScanInt(achLeader+12,5); _sizeFieldLength = achLeader[20] - '0'; _sizeFieldPos = achLeader[21] - '0'; _sizeFieldTag = achLeader[23] - '0'; if( _sizeFieldLength < 0 || _sizeFieldLength > 9 || _sizeFieldPos < 0 || _sizeFieldPos > 9 || _sizeFieldTag < 0 || _sizeFieldTag > 9 ) { CPLError( CE_Failure, CPLE_AppDefined, "ISO8211 record leader appears to be corrupt." ); return FALSE; } if( _leaderIden == 'R' ) nReuseHeader = TRUE; nFieldOffset = _fieldAreaStart - nLeaderSize;/* -------------------------------------------------------------------- *//* Is there anything seemly screwy about this record? *//* -------------------------------------------------------------------- */ if(( _recLength < 24 || _recLength > 100000000 || _fieldAreaStart < 24 || _fieldAreaStart > 100000 ) && (_recLength != 0)) { CPLError( CE_Failure, CPLE_FileIO, "Data record appears to be corrupt on DDF file.\n" " -- ensure that the files were uncompressed without modifying\n" "carriage return/linefeeds (by default WINZIP does this)." ); return FALSE; }/* ==================================================================== *//* Handle the normal case with the record length available. *//* ==================================================================== */ if(_recLength != 0) {/* -------------------------------------------------------------------- *//* Read the remainder of the record. *//* -------------------------------------------------------------------- */ nDataSize = _recLength - nLeaderSize; pachData = (char *) CPLMalloc(nDataSize); if( VSIFRead( pachData, 1, nDataSize, poModule->GetFP()) != (size_t) nDataSize ) { CPLError( CE_Failure, CPLE_FileIO, "Data record is short on DDF file." ); return FALSE; }/* -------------------------------------------------------------------- *//* If we don't find a field terminator at the end of the record *//* we will read extra bytes till we get to it. *//* -------------------------------------------------------------------- */ while( pachData[nDataSize-1] != DDF_FIELD_TERMINATOR ) { nDataSize++; pachData = (char *) CPLRealloc(pachData,nDataSize); if( VSIFRead( pachData + nDataSize - 1, 1, 1, poModule->GetFP() ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Data record is short on DDF file." ); return FALSE; } CPLDebug( "ISO8211", "Didn't find field terminator, read one more byte." ); }/* -------------------------------------------------------------------- *//* Loop over the directory entries, making a pass counting them. *//* -------------------------------------------------------------------- */ int i; int nFieldEntryWidth;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -