📄 ddfrecord.cpp
字号:
/* -------------------------------------------------------------------- *//* 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; nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag; nFieldCount = 0; for( i = 0; i < nDataSize; i += nFieldEntryWidth ) { if( pachData[i] == DDF_FIELD_TERMINATOR ) break; nFieldCount++; } /* -------------------------------------------------------------------- *//* Allocate, and read field definitions. *//* -------------------------------------------------------------------- */ paoFields = new DDFField[nFieldCount]; for( i = 0; i < nFieldCount; i++ ) { char szTag[128]; int nEntryOffset = i*nFieldEntryWidth; int nFieldLength, nFieldPos; /* -------------------------------------------------------------------- *//* Read the position information and tag. *//* -------------------------------------------------------------------- */ strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag ); szTag[_sizeFieldTag] = '\0'; nEntryOffset += _sizeFieldTag; nFieldLength = DDFScanInt( pachData+nEntryOffset, _sizeFieldLength ); nEntryOffset += _sizeFieldLength; nFieldPos = DDFScanInt( pachData+nEntryOffset, _sizeFieldPos ); /* -------------------------------------------------------------------- *//* Find the corresponding field in the module directory. *//* -------------------------------------------------------------------- */ DDFFieldDefn *poFieldDefn = poModule->FindFieldDefn( szTag ); if( poFieldDefn == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Undefined field `%s' encountered in data record.", szTag ); return FALSE; }/* -------------------------------------------------------------------- *//* Assign info the DDFField. *//* -------------------------------------------------------------------- */ paoFields[i].Initialize( poFieldDefn, pachData + _fieldAreaStart + nFieldPos - nLeaderSize, nFieldLength ); } return TRUE; }/* ==================================================================== *//* Handle the exceptional case where the record length is *//* zero. In this case we have to read all the data based on *//* the size of data items as per ISO8211 spec Annex C, 1.5.1. *//* *//* See Bugzilla bug 181 and test with file US4CN21M.000. *//* ==================================================================== */ else { CPLDebug( "ISO8211", "Record with zero length, use variant (C.1.5.1) logic." ); /* ----------------------------------------------------------------- */ /* _recLength == 0, handle the large record. */ /* */ /* Read the remainder of the record. */ /* ----------------------------------------------------------------- */ nDataSize = 0; pachData = NULL; /* ----------------------------------------------------------------- */ /* Loop over the directory entries, making a pass counting them. */ /* ----------------------------------------------------------------- */ int nFieldEntryWidth = _sizeFieldLength + _sizeFieldPos + _sizeFieldTag; nFieldCount = 0; int i=0; char *tmpBuf = (char*)CPLMalloc(nFieldEntryWidth); // while we're not at the end, store this entry, // and keep on reading... do { // read an Entry: if(nFieldEntryWidth != (int) VSIFRead(tmpBuf, 1, nFieldEntryWidth, poModule->GetFP())) { CPLError(CE_Failure, CPLE_FileIO, "Data record is short on DDF file."); return FALSE; } // move this temp buffer into more permanent storage: char *newBuf = (char*)CPLMalloc(nDataSize+nFieldEntryWidth); if(pachData!=NULL) { memcpy(newBuf, pachData, nDataSize); CPLFree(pachData); } memcpy(&newBuf[nDataSize], tmpBuf, nFieldEntryWidth); pachData = newBuf; nDataSize += nFieldEntryWidth; if(DDF_FIELD_TERMINATOR != tmpBuf[0]) { nFieldCount++; } } while(DDF_FIELD_TERMINATOR != tmpBuf[0]); // Now, rewind a little. Only the TERMINATOR should have been read: int rewindSize = nFieldEntryWidth - 1; FILE *fp = poModule->GetFP(); long pos = ftell(fp) - rewindSize; fseek(fp, pos, SEEK_SET); nDataSize -= rewindSize; // -------------------------------------------------------------------- // Okay, now let's populate the heck out of pachData... // -------------------------------------------------------------------- for(i=0; i<nFieldCount; i++) { int nEntryOffset = (i*nFieldEntryWidth) + _sizeFieldTag; int nFieldLength = DDFScanInt(pachData + nEntryOffset, _sizeFieldLength); char *tmpBuf = (char*)CPLMalloc(nFieldLength); // read an Entry: if(nFieldLength != (int) VSIFRead(tmpBuf, 1, nFieldLength, poModule->GetFP())) { CPLError(CE_Failure, CPLE_FileIO, "Data record is short on DDF file."); return FALSE; } // move this temp buffer into more permanent storage: char *newBuf = (char*)CPLMalloc(nDataSize+nFieldLength); memcpy(newBuf, pachData, nDataSize); CPLFree(pachData); memcpy(&newBuf[nDataSize], tmpBuf, nFieldLength); CPLFree(tmpBuf); pachData = newBuf; nDataSize += nFieldLength; } /* ----------------------------------------------------------------- */ /* Allocate, and read field definitions. */ /* ----------------------------------------------------------------- */ paoFields = new DDFField[nFieldCount]; for( i = 0; i < nFieldCount; i++ ) { char szTag[128]; int nEntryOffset = i*nFieldEntryWidth; int nFieldLength, nFieldPos; /* ------------------------------------------------------------- */ /* Read the position information and tag. */ /* ------------------------------------------------------------- */ strncpy( szTag, pachData+nEntryOffset, _sizeFieldTag ); szTag[_sizeFieldTag] = '\0'; nEntryOffset += _sizeFieldTag; nFieldLength = DDFScanInt( pachData+nEntryOffset, _sizeFieldLength ); nEntryOffset += _sizeFieldLength; nFieldPos = DDFScanInt( pachData+nEntryOffset, _sizeFieldPos ); /* ------------------------------------------------------------- */ /* Find the corresponding field in the module directory. */ /* ------------------------------------------------------------- */ DDFFieldDefn *poFieldDefn = poModule->FindFieldDefn( szTag ); if( poFieldDefn == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "Undefined field `%s' encountered in data record.", szTag ); return FALSE; } /* ------------------------------------------------------------- */ /* Assign info the DDFField. */ /* ------------------------------------------------------------- */ paoFields[i].Initialize( poFieldDefn, pachData + _fieldAreaStart + nFieldPos - nLeaderSize, nFieldLength ); } return TRUE; }}/************************************************************************//* FindField() *//************************************************************************//** * Find the named field within this record. * * @param pszName The name of the field to fetch. The comparison is * case insensitive. * @param iFieldIndex The instance of this field to fetch. Use zero (the * default) for the first instance. * * @return Pointer to the requested DDFField. This pointer is to an * internal object, and should not be freed. It remains valid until * the next record read. */DDFField * DDFRecord::FindField( const char * pszName, int iFieldIndex ){ for( int i = 0; i < nFieldCount; i++ ) { if( EQUAL(paoFields[i].GetFieldDefn()->GetName(),pszName) ) { if( iFieldIndex == 0 ) return paoFields + i; else iFieldIndex--; } } return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -