📄 mitab_rawbinblock.cpp
字号:
"GetBlockType(): Block has not been initialized.");
return -1;
}
if (m_nBlockType > TABMAP_LAST_VALID_BLOCK_TYPE)
{
CPLError(CE_Failure, CPLE_NotSupported,
"GetBlockType(): Unsupported block type %d.",
m_nBlockType);
return -1;
}
return m_nBlockType;
}
/**********************************************************************
* TABRawBinBlock::GotoByteInBlock()
*
* Move the block pointer to the specified position relative to the
* beginning of the block.
*
* Returns 0 if succesful or -1 if an error happened, in which case
* CPLError() will have been called.
**********************************************************************/
int TABRawBinBlock::GotoByteInBlock(int nOffset)
{
if ( (m_eAccess == TABRead && nOffset > m_nSizeUsed) ||
(m_eAccess != TABRead && nOffset > m_nBlockSize) )
{
CPLError(CE_Failure, CPLE_AppDefined,
"GotoByteInBlock(): Attempt to go past end of data block.");
return -1;
}
if (nOffset < 0)
{
CPLError(CE_Failure, CPLE_AppDefined,
"GotoByteInBlock(): Attempt to go before start of data block.");
return -1;
}
m_nCurPos = nOffset;
m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos);
return 0;
}
/**********************************************************************
* TABRawBinBlock::GotoByteRel()
*
* Move the block pointer by the specified number of bytes relative
* to its current position.
*
* Returns 0 if succesful or -1 if an error happened, in which case
* CPLError() will have been called.
**********************************************************************/
int TABRawBinBlock::GotoByteRel(int nOffset)
{
return GotoByteInBlock(m_nCurPos + nOffset);
}
/**********************************************************************
* TABRawBinBlock::GotoByteInFile()
*
* Move the block pointer to the specified position relative to the
* beginning of the file.
*
* In read access, the current block may be reloaded to contain a right
* block of binary data if necessary.
*
* In write mode, the current block may automagically be committed to
* disk and a new block initialized if necessary.
*
* bForceReadFromFile is used in write mode to read the new block data from
* file instead of creating an empty block. (Useful for TABCollection
* or other cases that need to do random access in the file in write mode.)
*
* bOffsetIsEndOfData is set to TRUE to indicate that the nOffset
* to which we are attempting to go is the end of the used data in this
* block (we are positioninig ourselves to append data), so if the nOffset
* corresponds to the beginning of a 512 bytes block then we should really
* be positioning ourselves at the end of the block that ends at this
* address instead of at the beginning of the blocks that starts at this
* address. This case can happen when going back and forth to write collection
* objects to a Coordblock and is documented in bug 1657.
*
* Returns 0 if succesful or -1 if an error happened, in which case
* CPLError() will have been called.
**********************************************************************/
int TABRawBinBlock::GotoByteInFile(int nOffset,
GBool bForceReadFromFile /*=FALSE*/,
GBool bOffsetIsEndOfData /*=FALSE*/)
{
int nNewBlockPtr;
if (nOffset < 0)
{
CPLError(CE_Failure, CPLE_AppDefined,
"GotoByteInFile(): Attempt to go before start of file.");
return -1;
}
nNewBlockPtr = ( (nOffset-m_nFirstBlockPtr)/m_nBlockSize)*m_nBlockSize +
m_nFirstBlockPtr;
if (m_eAccess == TABRead)
{
if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nSizeUsed) &&
ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0)
{
// Failed reading new block... error has already been reported.
return -1;
}
}
else if (m_eAccess == TABWrite)
{
if ( (nOffset<m_nFileOffset || nOffset>=m_nFileOffset+m_nBlockSize) &&
(CommitToFile() != 0 ||
InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0 ) )
{
// Failed reading new block... error has already been reported.
return -1;
}
}
else if (m_eAccess == TABReadWrite)
{
// TODO: THIS IS NOT REAL read/write access (it's more extended write)
// Currently we try to read from file only if explicitly requested.
// If we ever want true read/write mode we should implement
// more smarts to detect whether the caller wants an existing block to
// be read, or a new one to be created from scratch.
// CommitToFile() should only be called only if something changed.
//
if (bOffsetIsEndOfData && nOffset%m_nBlockSize == 0)
{
/* We're trying to go byte 512 of a block that's full of data.
* In this case it's okay to place the m_nCurPos at byte 512
* which is past the end of the block.
*/
/* Make sure we request the block that ends with requested
* address and not the following block that doesn't exist
* yet on disk */
nNewBlockPtr -= m_nBlockSize;
if ( (nOffset < m_nFileOffset ||
nOffset > m_nFileOffset+m_nBlockSize) &&
(CommitToFile() != 0 ||
(!bForceReadFromFile &&
InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0) ||
(bForceReadFromFile &&
ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) ) )
{
// Failed reading new block... error has already been reported.
return -1;
}
}
else
{
if ( (nOffset < m_nFileOffset ||
nOffset >= m_nFileOffset+m_nBlockSize) &&
(CommitToFile() != 0 ||
(!bForceReadFromFile &&
InitNewBlock(m_fp, m_nBlockSize, nNewBlockPtr) != 0) ||
(bForceReadFromFile &&
ReadFromFile(m_fp, nNewBlockPtr, m_nBlockSize) != 0) ) )
{
// Failed reading new block... error has already been reported.
return -1;
}
}
}
else
{
CPLError(CE_Failure, CPLE_NotSupported,
"Access mode not supported yet!");
return -1;
}
m_nCurPos = nOffset-m_nFileOffset;
m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos);
return 0;
}
/**********************************************************************
* TABRawBinBlock::SetFirstBlockPtr()
*
* Set the position in the file at which the first block starts.
* This value will usually be the header size and needs to be specified
* only if the header size is different from the other blocks size.
*
* This value will be used by GotoByteInFile() to properly align the data
* blocks that it loads automatically when a requested position is outside
* of the block currently in memory.
**********************************************************************/
void TABRawBinBlock::SetFirstBlockPtr(int nOffset)
{
m_nFirstBlockPtr = nOffset;
}
/**********************************************************************
* TABRawBinBlock::GetNumUnusedBytes()
*
* Return the number of unused bytes in this block.
**********************************************************************/
int TABRawBinBlock::GetNumUnusedBytes()
{
return (m_nBlockSize - m_nSizeUsed);
}
/**********************************************************************
* TABRawBinBlock::GetFirstUnusedByteOffset()
*
* Return the position of the first unused byte in this block relative
* to the beginning of the file, or -1 if the block is full.
**********************************************************************/
int TABRawBinBlock::GetFirstUnusedByteOffset()
{
if (m_nSizeUsed < m_nBlockSize)
return m_nFileOffset + m_nSizeUsed;
else
return -1;
}
/**********************************************************************
* TABRawBinBlock::GetCurAddress()
*
* Return the current pointer position, relative to beginning of file.
**********************************************************************/
int TABRawBinBlock::GetCurAddress()
{
return (m_nFileOffset + m_nCurPos);
}
/**********************************************************************
* TABRawBinBlock::ReadBytes()
*
* Copy the number of bytes from the data block's internal buffer to
* the user's buffer pointed by pabyDstBuf.
*
* Passing pabyDstBuf = NULL will only move the read pointer by the
* specified number of bytes as if the copy had happened... but it
* won't crash.
*
* Returns 0 if succesful or -1 if an error happened, in which case
* CPLError() will have been called.
**********************************************************************/
int TABRawBinBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
{
/*----------------------------------------------------------------
* Make sure block is initialized with Read access and that the
* operation won't go beyond the buffer's size.
*---------------------------------------------------------------*/
if (m_pabyBuf == NULL)
{
CPLError(CE_Failure, CPLE_AppDefined,
"ReadBytes(): Block has not been initialized.");
return -1;
}
if (m_eAccess != TABRead && m_eAccess != TABReadWrite )
{
CPLError(CE_Failure, CPLE_AppDefined,
"ReadBytes(): Block does not support read operations.");
return -1;
}
if (m_nCurPos + numBytes > m_nSizeUsed)
{
CPLError(CE_Failure, CPLE_AppDefined,
"ReadBytes(): Attempt to read past end of data block.");
return -1;
}
if (pabyDstBuf)
{
memcpy(pabyDstBuf, m_pabyBuf + m_nCurPos, numBytes);
}
m_nCurPos += numBytes;
return 0;
}
/**********************************************************************
* TABRawBinBlock::Read<datatype>()
*
* MapInfo files are binary files with LSB first (Intel) byte
* ordering. The following functions will read from the input file
* and return a value with the bytes ordered properly for the current
* platform.
**********************************************************************/
GByte TABRawBinBlock::ReadByte()
{
GByte byValue;
ReadBytes(1, (GByte*)(&byValue));
return byValue;
}
GInt16 TABRawBinBlock::ReadInt16()
{
GInt16 n16Value;
ReadBytes(2, (GByte*)(&n16Value));
#ifdef CPL_MSB
return (GInt16)CPL_SWAP16(n16Value);
#else
return n16Value;
#endif
}
GInt32 TABRawBinBlock::ReadInt32()
{
GInt32 n32Value;
ReadBytes(4, (GByte*)(&n32Value));
#ifdef CPL_MSB
return (GInt32)CPL_SWAP32(n32Value);
#else
return n32Value;
#endif
}
float TABRawBinBlock::ReadFloat()
{
float fValue;
ReadBytes(4, (GByte*)(&fValue));
#ifdef CPL_MSB
*(GUInt32*)(&fValue) = CPL_SWAP32(*(GUInt32*)(&fValue));
#endif
return fValue;
}
double TABRawBinBlock::ReadDouble()
{
double dValue;
ReadBytes(8, (GByte*)(&dValue));
#ifdef CPL_MSB
CPL_SWAPDOUBLE(&dValue);
#endif
return dValue;
}
/**********************************************************************
* TABRawBinBlock::WriteBytes()
*
* Copy the number of bytes from the user's buffer pointed by pabySrcBuf
* to the data block's internal buffer.
* Note that this call only writes to the memory buffer... nothing is
* written to the file until WriteToFile() is called.
*
* Passing pabySrcBuf = NULL will only move the write pointer by the
* specified number of bytes as if the copy had happened... but it
* won't crash.
*
* Returns 0 if succesful or -1 if an error happened, in which case
* CPLError() will have been called.
**********************************************************************/
int TABRawBinBlock::WriteBytes(int nBytesToWrite, GByte *pabySrcBuf)
{
/*----------------------------------------------------------------
* Make sure block is initialized with Write access and that the
* operation won't go beyond the buffer's size.
*---------------------------------------------------------------*/
if (m_pabyBuf == NULL)
{
CPLError(CE_Failure, CPLE_AppDefined,
"WriteBytes(): Block has not been initialized.");
return -1;
}
if (m_eAccess != TABWrite && m_eAccess != TABReadWrite )
{
CPLError(CE_Failure, CPLE_AppDefined,
"WriteBytes(): Block does not support write operations.");
return -1;
}
if (m_nCurPos + nBytesToWrite > m_nBlockSize)
{
CPLError(CE_Failure, CPLE_AppDefined,
"WriteBytes(): Attempt to write past end of data block.");
return -1;
}
/*----------------------------------------------------------------
* Everything is OK... copy the data
*---------------------------------------------------------------*/
if (pabySrcBuf)
{
memcpy(m_pabyBuf + m_nCurPos, pabySrcBuf, nBytesToWrite);
}
m_nCurPos += nBytesToWrite;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -