📄 ddfrecord.cpp
字号:
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;}/************************************************************************//* GetField() *//************************************************************************//** * Fetch field object based on index. * * @param i The index of the field to fetch. Between 0 and GetFieldCount()-1. * * @return A DDFField pointer, or NULL if the index is out of range. */DDFField *DDFRecord::GetField( int i ){ if( i < 0 || i >= nFieldCount ) return NULL; else return paoFields + i;}/************************************************************************//* GetIntSubfield() *//************************************************************************//** * Fetch value of a subfield as an integer. This is a convenience * function for fetching a subfield of a field within this record. * * @param pszField The name of the field containing the subfield. * @param iFieldIndex The instance of this field within the record. Use * zero for the first instance of this field. * @param pszSubfield The name of the subfield within the selected field. * @param iSubfieldIndex The instance of this subfield within the record. * Use zero for the first instance. * @param pnSuccess Pointer to an int which will be set to TRUE if the fetch * succeeds, or FALSE if it fails. Use NULL if you don't want to check * success. * @return The value of the subfield, or zero if it failed for some reason. */int DDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex, const char * pszSubfield, int iSubfieldIndex, int * pnSuccess ){ DDFField *poField; int nDummyErr; if( pnSuccess == NULL ) pnSuccess = &nDummyErr; *pnSuccess = FALSE; /* -------------------------------------------------------------------- *//* Fetch the field. If this fails, return zero. *//* -------------------------------------------------------------------- */ poField = FindField( pszField, iFieldIndex ); if( poField == NULL ) return 0;/* -------------------------------------------------------------------- *//* Get the subfield definition *//* -------------------------------------------------------------------- */ DDFSubfieldDefn *poSFDefn; poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield ); if( poSFDefn == NULL ) return 0;/* -------------------------------------------------------------------- *//* Get a pointer to the data. *//* -------------------------------------------------------------------- */ int nBytesRemaining; const char *pachData = poField->GetSubfieldData(poSFDefn, &nBytesRemaining, iSubfieldIndex);/* -------------------------------------------------------------------- *//* Return the extracted value. *//* -------------------------------------------------------------------- */ *pnSuccess = TRUE; return( poSFDefn->ExtractIntData( pachData, nBytesRemaining, NULL ) );}/************************************************************************//* GetFloatSubfield() *//************************************************************************//** * Fetch value of a subfield as a float (double). This is a convenience * function for fetching a subfield of a field within this record. * * @param pszField The name of the field containing the subfield. * @param iFieldIndex The instance of this field within the record. Use * zero for the first instance of this field. * @param pszSubfield The name of the subfield within the selected field. * @param iSubfieldIndex The instance of this subfield within the record. * Use zero for the first instance. * @param pnSuccess Pointer to an int which will be set to TRUE if the fetch * succeeds, or FALSE if it fails. Use NULL if you don't want to check * success.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -