📄 ddfrecord.cpp
字号:
poField->Initialize( poDefn, poField->GetData(), poField->GetDataSize() ); } poModule->RemoveCloneRecord( poClone ); poClone->poModule = poTargetModule; poTargetModule->AddCloneRecord( poClone ); return poClone;}/************************************************************************//* DeleteField() *//************************************************************************//** * Delete a field instance from a record. * * Remove a field from this record, cleaning up the data * portion and repacking the fields list. We don't try to * reallocate the data area of the record to be smaller. * * NOTE: This method doesn't actually remove the header * information for this field from the record tag list yet. * This should be added if the resulting record is even to be * written back to disk! * * @param poTarget the field instance on this record to delete. * * @return TRUE on success, or FALSE on failure. Failure can occur if * poTarget isn't really a field on this record. */int DDFRecord::DeleteField( DDFField *poTarget ){ int iTarget, i;/* -------------------------------------------------------------------- *//* Find which field we are to delete. *//* -------------------------------------------------------------------- */ for( iTarget = 0; iTarget < nFieldCount; iTarget++ ) { if( paoFields + iTarget == poTarget ) break; } if( iTarget == nFieldCount ) return FALSE;/* -------------------------------------------------------------------- *//* Change the target fields data size to zero. This takes care *//* of repacking the data array, and updating all the following *//* field data pointers. *//* -------------------------------------------------------------------- */ ResizeField( poTarget, 0 );/* -------------------------------------------------------------------- *//* remove the target field, moving down all the other fields *//* one step in the field list. *//* -------------------------------------------------------------------- */ for( i = iTarget; i < nFieldCount-1; i++ ) { paoFields[i] = paoFields[i+1]; } nFieldCount--; return TRUE;}/************************************************************************//* ResizeField() *//************************************************************************//** * Alter field data size within record. * * This method will rearrange a DDFRecord altering the amount of space * reserved for one of the existing fields. All following fields will * be shifted accordingly. This includes updating the DDFField infos, * and actually moving stuff within the data array after reallocating * to the desired size. * * @param poField the field to alter. * @param nNewDataSize the number of data bytes to be reserved for the field. * * @return TRUE on success or FALSE on failure. */int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize ){ int iTarget, i; int nBytesToMove;/* -------------------------------------------------------------------- *//* Find which field we are to resize. *//* -------------------------------------------------------------------- */ for( iTarget = 0; iTarget < nFieldCount; iTarget++ ) { if( paoFields + iTarget == poField ) break; } if( iTarget == nFieldCount ) return FALSE;/* -------------------------------------------------------------------- *//* Reallocate the data buffer accordingly. *//* -------------------------------------------------------------------- */ int nBytesToAdd = nNewDataSize - poField->GetDataSize(); const char *pachOldData = pachData; pachData = (char *) CPLRealloc(pachData, nDataSize + nBytesToAdd ); nDataSize += nBytesToAdd;/* -------------------------------------------------------------------- *//* Shift data after the target field on by the bytes added. *//* -------------------------------------------------------------------- */ nBytesToMove = nDataSize - (poField->GetData()+poField->GetDataSize()-pachOldData+nBytesToAdd); memmove( (char *)poField->GetData() + poField->GetDataSize() + nBytesToAdd, (char *)poField->GetData() + poField->GetDataSize(), nBytesToMove ); /* -------------------------------------------------------------------- *//* Update fields to point into newly allocated buffer. *//* -------------------------------------------------------------------- */ for( i = 0; i < nFieldCount; i++ ) { int nOffset; nOffset = paoFields[i].GetData() - pachOldData; paoFields[i].Initialize( paoFields[i].GetFieldDefn(), pachData + nOffset, paoFields[i].GetDataSize() ); }/* -------------------------------------------------------------------- *//* Update the target fields info. *//* -------------------------------------------------------------------- */ poField->Initialize( poField->GetFieldDefn(), poField->GetData(), poField->GetDataSize() + nBytesToAdd );/* -------------------------------------------------------------------- *//* Shift all following fields down, and update their data *//* locations. *//* -------------------------------------------------------------------- */ if( nBytesToAdd < 0 ) { for( i = iTarget+1; i < nFieldCount; i++ ) { char *pszOldDataLocation; pszOldDataLocation = (char *) paoFields[i].GetData(); paoFields[i].Initialize( paoFields[i].GetFieldDefn(), pszOldDataLocation + nBytesToAdd, paoFields[i].GetDataSize() ); } } else { for( i = nFieldCount-1; i > iTarget; i-- ) { char *pszOldDataLocation; pszOldDataLocation = (char *) paoFields[i].GetData(); paoFields[i].Initialize( paoFields[i].GetFieldDefn(), pszOldDataLocation + nBytesToAdd, paoFields[i].GetDataSize() ); } } return TRUE;}/************************************************************************//* AddField() *//************************************************************************//** * Add a new field to record. * * Add a new zero sized field to the record. The new field is always * added at the end of the record. * * NOTE: This method doesn't currently update the header information for * the record to include the field information for this field, so the * resulting record image isn't suitable for writing to disk. However, * everything else about the record state should be updated properly to * reflect the new field. * * @param poDefn the definition of the field to be added. * * @return the field object on success, or NULL on failure. */DDFField *DDFRecord::AddField( DDFFieldDefn *poDefn ){/* -------------------------------------------------------------------- *//* Reallocate the fields array larger by one, and initialize *//* the new field. *//* -------------------------------------------------------------------- */ DDFField *paoNewFields; paoNewFields = new DDFField[nFieldCount+1]; if( nFieldCount > 0 ) { memcpy( paoNewFields, paoFields, sizeof(DDFField) * nFieldCount ); delete[] paoFields; } paoFields = paoNewFields; nFieldCount++;/* -------------------------------------------------------------------- *//* Initialize the new field properly. *//* -------------------------------------------------------------------- */ if( nFieldCount == 1 ) { paoFields[0].Initialize( poDefn, GetData(), 0 ); } else { paoFields[nFieldCount-1].Initialize( poDefn, paoFields[nFieldCount-2].GetData() + paoFields[nFieldCount-2].GetDataSize(), 0 ); }/* -------------------------------------------------------------------- *//* Initialize field. *//* -------------------------------------------------------------------- */ CreateDefaultFieldInstance( paoFields + nFieldCount-1, 0 ); return paoFields + (nFieldCount - 1);}/************************************************************************//* SetFieldRaw() *//************************************************************************//** * Set the raw contents of a field instance. * * @param poField the field to set data within. * @param iIndexWithinField The instance of this field to replace. Must * be a value between 0 and GetRepeatCount(). If GetRepeatCount() is used, a * new instance of the field is appeneded. * @param pachRawData the raw data to replace this field instance with. * @param nRawDataSize the number of bytes pointed to by pachRawData. * * @return TRUE on success or FALSE on failure. */intDDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField, const char *pachRawData, int nRawDataSize ){ int iTarget, nRepeatCount;/* -------------------------------------------------------------------- *//* Find which field we are to update. *//* -------------------------------------------------------------------- */ for( iTarget = 0; iTarget < nFieldCount; iTarget++ ) { if( paoFields + iTarget == poField ) break; } if( iTarget == nFieldCount ) return FALSE; nRepeatCount = poField->GetRepeatCount(); if( iIndexWithinField < 0 || iIndexWithinField > nRepeatCount ) return FALSE;/* -------------------------------------------------------------------- *//* Are we adding an instance? This is easier and different *//* than replacing an existing instance. *//* -------------------------------------------------------------------- */ if( iIndexWithinField == nRepeatCount || !poField->GetFieldDefn()->IsRepeating() ) { char *pachFieldData; int nOldSize; if( !poField->GetFieldDefn()->IsRepeating() && iIndexWithinField != 0 ) return FALSE; nOldSize = poField->GetDataSize(); if( nOldSize == 0 ) nOldSize++; // for added DDF_FIELD_TERMINATOR. if( !ResizeField( poField, nOldSize + nRawDataSize ) ) return FALSE; pachFieldData = (char *) poField->GetData(); memcpy( pachFieldData + nOldSize - 1, pachRawData, nRawDataSize ); pachFieldData[nOldSize+nRawDataSize-1] = DDF_FIELD_TERMINATOR; return TRUE; }/* -------------------------------------------------------------------- *//* Get a pointer to the start of the existing data for this *//* iteration of the field. *//* -------------------------------------------------------------------- */ const char *pachWrkData; int nInstanceSize; // We special case this to avoid alot of warnings when initializing // the field the first time. if( poField->GetDataSize() == 0 ) { pachWrkData = poField->GetData(); nInstanceSize = 0; } else { pachWrkData = poField->GetInstanceData( iIndexWithinField, &nInstanceSize ); }/* -------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -