📄 mitab_rawbinblock.cpp
字号:
m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos);
m_bModified = TRUE;
return 0;
}
/**********************************************************************
* TABRawBinBlock::Write<datatype>()
*
* Arc/Info files are binary files with MSB first (Motorola) byte
* ordering. The following functions will reorder the byte for the
* value properly and write that to the output file.
*
* If a problem happens, then CPLError() will be called and
* CPLGetLastErrNo() can be used to test if a write operation was
* succesful.
**********************************************************************/
int TABRawBinBlock::WriteByte(GByte byValue)
{
return WriteBytes(1, (GByte*)&byValue);
}
int TABRawBinBlock::WriteInt16(GInt16 n16Value)
{
#ifdef CPL_MSB
n16Value = (GInt16)CPL_SWAP16(n16Value);
#endif
return WriteBytes(2, (GByte*)&n16Value);
}
int TABRawBinBlock::WriteInt32(GInt32 n32Value)
{
#ifdef CPL_MSB
n32Value = (GInt32)CPL_SWAP32(n32Value);
#endif
return WriteBytes(4, (GByte*)&n32Value);
}
int TABRawBinBlock::WriteFloat(float fValue)
{
#ifdef CPL_MSB
*(GUInt32*)(&fValue) = CPL_SWAP32(*(GUInt32*)(&fValue));
#endif
return WriteBytes(4, (GByte*)&fValue);
}
int TABRawBinBlock::WriteDouble(double dValue)
{
#ifdef CPL_MSB
CPL_SWAPDOUBLE(&dValue);
#endif
return WriteBytes(8, (GByte*)&dValue);
}
/**********************************************************************
* TABRawBinBlock::WriteZeros()
*
* Write a number of zeros (sepcified in bytes) at the current position
* in the file.
*
* If a problem happens, then CPLError() will be called and
* CPLGetLastErrNo() can be used to test if a write operation was
* succesful.
**********************************************************************/
int TABRawBinBlock::WriteZeros(int nBytesToWrite)
{
char acZeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int i;
int nStatus = 0;
/* Write by 8 bytes chunks. The last chunk may be less than 8 bytes
*/
for(i=0; nStatus == 0 && i< nBytesToWrite; i+=8)
{
nStatus = WriteBytes(MIN(8,(nBytesToWrite-i)), (GByte*)acZeros);
}
return nStatus;
}
/**********************************************************************
* TABRawBinBlock::WritePaddedString()
*
* Write a string and pad the end of the field (up to nFieldSize) with
* spaces number of spaces at the current position in the file.
*
* If a problem happens, then CPLError() will be called and
* CPLGetLastErrNo() can be used to test if a write operation was
* succesful.
**********************************************************************/
int TABRawBinBlock::WritePaddedString(int nFieldSize, const char *pszString)
{
char acSpaces[8] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
int i, nLen, numSpaces;
int nStatus = 0;
nLen = strlen(pszString);
nLen = MIN(nLen, nFieldSize);
numSpaces = nFieldSize - nLen;
if (nLen > 0)
nStatus = WriteBytes(nLen, (GByte*)pszString);
/* Write spaces by 8 bytes chunks. The last chunk may be less than 8 bytes
*/
for(i=0; nStatus == 0 && i< numSpaces; i+=8)
{
nStatus = WriteBytes(MIN(8,(numSpaces-i)), (GByte*)acSpaces);
}
return nStatus;
}
/**********************************************************************
* TABRawBinBlock::Dump()
*
* Dump block contents... available only in DEBUG mode.
**********************************************************************/
#ifdef DEBUG
void TABRawBinBlock::Dump(FILE *fpOut /*=NULL*/)
{
if (fpOut == NULL)
fpOut = stdout;
fprintf(fpOut, "----- TABRawBinBlock::Dump() -----\n");
if (m_pabyBuf == NULL)
{
fprintf(fpOut, "Block has not been initialized yet.");
}
else
{
fprintf(fpOut, "Block (type %d) size=%d bytes at offset %d in file.\n",
m_nBlockType, m_nBlockSize, m_nFileOffset);
fprintf(fpOut, "Current pointer at byte %d\n", m_nCurPos);
}
fflush(fpOut);
}
#endif // DEBUG
/**********************************************************************
* DumpBytes()
*
* Read and dump the contents of an Binary file.
**********************************************************************/
void TABRawBinBlock::DumpBytes(GInt32 nValue, int nOffset /*=0*/,
FILE *fpOut /*=NULL*/)
{
GInt32 anVal[2];
GInt16 *pn16Val1, *pn16Val2;
float *pfValue;
char *pcValue;
double *pdValue;
pfValue = (float*)(&nValue);
pcValue = (char*)(&nValue);
pdValue = (double*)anVal;
pn16Val1 = (GInt16*)(pcValue+2);
pn16Val2 = (GInt16*)(pcValue);
anVal[0] = anVal[1] = 0;
/* For double precision values, we only use the first half
* of the height bytes... and leave the other 4 bytes as zeros!
* It's a bit of a hack, but it seems to be enough for the
* precision of the values we print!
*/
#ifdef CPL_MSB
anVal[0] = nValue;
#else
anVal[1] = nValue;
#endif
if (fpOut == NULL)
fpOut = stdout;
fprintf(fpOut, "%d\t0x%8.8x %-5d\t%-6d %-6d %5.3e d=%5.3e",
nOffset, nValue, nValue,
*pn16Val1, *pn16Val2, *pfValue, *pdValue);
printf("\t[%c%c%c%c]\n", isprint(pcValue[0])?pcValue[0]:'.',
isprint(pcValue[1])?pcValue[1]:'.',
isprint(pcValue[2])?pcValue[2]:'.',
isprint(pcValue[3])?pcValue[3]:'.');
}
/**********************************************************************
* TABCreateMAPBlockFromFile()
*
* Load data from the specified file location and create and initialize
* a TABMAP*Block of the right type to handle it.
*
* Returns the new object if succesful or NULL if an error happened, in
* which case CPLError() will have been called.
**********************************************************************/
TABRawBinBlock *TABCreateMAPBlockFromFile(FILE *fpSrc, int nOffset,
int nSize /*= 512*/,
GBool bHardBlockSize /*= TRUE */,
TABAccess eAccessMode /*= TABRead*/)
{
TABRawBinBlock *poBlock = NULL;
GByte *pabyBuf;
if (fpSrc == NULL || nSize == 0)
{
CPLError(CE_Failure, CPLE_AssertionFailed,
"TABCreateMAPBlockFromFile(): Assertion Failed!");
return NULL;
}
/*----------------------------------------------------------------
* Alloc a buffer to contain the data
*---------------------------------------------------------------*/
pabyBuf = (GByte*)CPLMalloc(nSize*sizeof(GByte));
/*----------------------------------------------------------------
* Read from the file
*---------------------------------------------------------------*/
if (VSIFSeek(fpSrc, nOffset, SEEK_SET) != 0 ||
VSIFRead(pabyBuf, sizeof(GByte), nSize, fpSrc)!=(unsigned int)nSize )
{
CPLError(CE_Failure, CPLE_FileIO,
"TABCreateMAPBlockFromFile() failed reading %d bytes at offset %d.",
nSize, nOffset);
CPLFree(pabyBuf);
return NULL;
}
/*----------------------------------------------------------------
* Create an object of the right type
* Header block is different: it does not start with the object
* type byte but it is always the first block in a file
*---------------------------------------------------------------*/
if (nOffset == 0)
{
poBlock = new TABMAPHeaderBlock;
}
else
{
switch(pabyBuf[0])
{
case TABMAP_INDEX_BLOCK:
poBlock = new TABMAPIndexBlock(eAccessMode);
break;
case TABMAP_OBJECT_BLOCK:
poBlock = new TABMAPObjectBlock(eAccessMode);
break;
case TABMAP_COORD_BLOCK:
poBlock = new TABMAPCoordBlock(eAccessMode);
break;
case TABMAP_TOOL_BLOCK:
poBlock = new TABMAPToolBlock(eAccessMode);
break;
case TABMAP_GARB_BLOCK:
default:
poBlock = new TABRawBinBlock(eAccessMode, bHardBlockSize);
break;
}
}
/*----------------------------------------------------------------
* Init new object with the data we just read
*---------------------------------------------------------------*/
if (poBlock->InitBlockFromData(pabyBuf, nSize, nSize,
FALSE, fpSrc, nOffset) != 0)
{
// Some error happened... and CPLError() has been called
delete poBlock;
poBlock = NULL;
}
return poBlock;
}
/*=====================================================================
* class TABBinBlockManager
*====================================================================*/
/**********************************************************************
* TABBinBlockManager::TABBinBlockManager()
*
* Constructor.
**********************************************************************/
TABBinBlockManager::TABBinBlockManager(int nBlockSize /*=512*/)
{
m_nBlockSize=nBlockSize;
m_nLastAllocatedBlock = -1;
m_psGarbageBlocks = NULL;
}
/**********************************************************************
* TABBinBlockManager::~TABBinBlockManager()
*
* Destructor.
**********************************************************************/
TABBinBlockManager::~TABBinBlockManager()
{
Reset();
}
/**********************************************************************
* TABBinBlockManager::AllocNewBlock()
*
* Returns and reserves the address of the next available block, either a
* brand new block at end of file, or recycle a garbage block if one is
* available.
**********************************************************************/
GInt32 TABBinBlockManager::AllocNewBlock()
{
// Try to reuse garbage blocks first
if (GetFirstGarbageBlock() > 0)
return PopGarbageBlock();
// ... or alloc a new block at EOF
if (m_nLastAllocatedBlock==-1)
m_nLastAllocatedBlock = 0;
else
m_nLastAllocatedBlock+=m_nBlockSize;
return m_nLastAllocatedBlock;
}
/**********************************************************************
* TABBinBlockManager::Reset()
*
**********************************************************************/
void TABBinBlockManager::Reset()
{
m_nLastAllocatedBlock = -1;
// Flush list of garbage blocks
while (m_psGarbageBlocks != NULL)
{
TABBlockRef *psNext = m_psGarbageBlocks->psNext;
CPLFree(m_psGarbageBlocks);
m_psGarbageBlocks = psNext;
}
}
/**********************************************************************
* TABBinBlockManager::PushGarbageBlock()
*
* Insert a garbage block at the head of the list of garbage blocks.
**********************************************************************/
void TABBinBlockManager::PushGarbageBlock(GInt32 nBlockPtr)
{
TABBlockRef *psNewBlockRef = (TABBlockRef *)CPLMalloc(sizeof(TABBlockRef));
if (psNewBlockRef)
{
psNewBlockRef->nBlockPtr = nBlockPtr;
psNewBlockRef->psNext = m_psGarbageBlocks;
m_psGarbageBlocks = psNewBlockRef;
}
}
/**********************************************************************
* TABBinBlockManager::GetFirstGarbageBlock()
*
* Return address of the block at the head of the list of garbage blocks
* or 0 if the list is empty.
**********************************************************************/
GInt32 TABBinBlockManager::GetFirstGarbageBlock()
{
if (m_psGarbageBlocks)
return m_psGarbageBlocks->nBlockPtr;
return 0;
}
/**********************************************************************
* TABBinBlockManager::PopGarbageBlock()
*
* Return address of the block at the head of the list of garbage blocks
* and remove that block from the list.
* Retuns 0 if the list is empty.
**********************************************************************/
GInt32 TABBinBlockManager::PopGarbageBlock()
{
GInt32 nBlockPtr = 0;
if (m_psGarbageBlocks)
{
nBlockPtr = m_psGarbageBlocks->nBlockPtr;
TABBlockRef *psNext = m_psGarbageBlocks->psNext;
CPLFree(m_psGarbageBlocks);
m_psGarbageBlocks = psNext;
}
return nBlockPtr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -