⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mitab_rawbinblock.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 3 页
字号:

    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 + -