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

📄 tabindnode.cpp

📁 linux下一款GIS程序源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// tabindnode.cpp: implementation of the TABINDNode class.////////////////////////////////////////////////////////////////////////#include "tabindnode.h"#include "ugk_errhandle.h"/********************************************************************** *                   TABINDNode::TABINDNode() * * Constructor. **********************************************************************/TABINDNode::TABINDNode(TABAccess eAccessMode /*=TABRead*/){    m_fp = NULL;    m_poCurChildNode = NULL;    m_nSubTreeDepth = 0;    m_nKeyLength = 0;    m_eFieldType = TABFUnknown;    m_poDataBlock = NULL;    m_numEntriesInNode = 0;    m_nCurIndexEntry = 0;    m_nPrevNodePtr = 0;    m_nNextNodePtr = 0;    m_poBlockManagerRef = NULL;    m_poParentNodeRef = NULL;    m_bUnique = FALSE;    m_eAccessMode = eAccessMode;}/********************************************************************** *                   TABINDNode::~TABINDNode() * * Destructor. **********************************************************************/TABINDNode::~TABINDNode(){    if (m_poCurChildNode)        delete m_poCurChildNode;    if (m_poDataBlock)        delete m_poDataBlock;}/********************************************************************** *                   TABINDNode::InitNode() * * Init a node... this function can be used either to initialize a new * node, or to make it point to a new data block in the file. * * By default, this call will read the data from the file at the * specified location if necessary, and leave the object ready to be searched. * * In write access, if the block does not exist (i.e. nBlockPtr=0) then a * new one is created and initialized. * * poParentNode is used in write access in order to update the parent node * when this node becomes full and has to be split. * * Returns 0 on success, -1 on error. **********************************************************************/int TABINDNode::InitNode(FILE *fp, int nBlockPtr,                          int nKeyLength, int nSubTreeDepth,                          UGKBool bUnique,                         TABBinBlockManager *poBlockMgr /*=NULL*/,                         TABINDNode *poParentNode /*=NULL*/,                         int nPrevNodePtr /*=0*/, int nNextNodePtr /*=0*/){    /*-----------------------------------------------------------------     * If the block already points to the right block, then don't do      * anything here.     *----------------------------------------------------------------*/    if (m_fp == fp && nBlockPtr> 0 && m_nCurDataBlockPtr == nBlockPtr)        return 0;    // Keep track of some info    m_fp = fp;    m_nKeyLength = nKeyLength;    m_nSubTreeDepth = nSubTreeDepth;    m_nCurDataBlockPtr = nBlockPtr;    m_bUnique = bUnique;    // Do not overwrite the following values if we receive NULL (the defaults)    if (poBlockMgr)        m_poBlockManagerRef = poBlockMgr;    if (poParentNode)        m_poParentNodeRef = poParentNode;    // Set some defaults    m_numEntriesInNode = 0;    m_nPrevNodePtr = nPrevNodePtr;    m_nNextNodePtr = nNextNodePtr;    m_nCurIndexEntry = 0;    /*-----------------------------------------------------------------     * Init RawBinBlock     * The node's buffer has to be created with read/write access since     * the index is a very dynamic structure!     *----------------------------------------------------------------*/    if (m_poDataBlock == NULL)        m_poDataBlock = new TABRawBinBlock(TABReadWrite, TRUE);    if ((m_eAccessMode == TABWrite || m_eAccessMode == TABReadWrite) &&         nBlockPtr == 0 && m_poBlockManagerRef)    {        /*-------------------------------------------------------------         * Write access: Create and init a new block         *------------------------------------------------------------*/        m_nCurDataBlockPtr = m_poBlockManagerRef->AllocNewBlock();        m_poDataBlock->InitNewBlock(m_fp, 512, m_nCurDataBlockPtr);        m_poDataBlock->WriteInt32( m_numEntriesInNode );        m_poDataBlock->WriteInt32( m_nPrevNodePtr );        m_poDataBlock->WriteInt32( m_nNextNodePtr );    }    else    {        assert(m_nCurDataBlockPtr > 0);        /*-------------------------------------------------------------         * Read the data block from the file, applies to read access, or         * to write access (to modify an existing block)         *------------------------------------------------------------*/        if (m_poDataBlock->ReadFromFile(m_fp, m_nCurDataBlockPtr, 512) != 0)        {            // CPLError() has already been called.            return -1;        }        m_poDataBlock->GotoByteInBlock(0);        m_numEntriesInNode = m_poDataBlock->ReadInt32();        m_nPrevNodePtr = m_poDataBlock->ReadInt32();        m_nNextNodePtr = m_poDataBlock->ReadInt32();    }    // m_poDataBlock is now positioned at the beginning of the key entries    return 0;}/********************************************************************** *                   TABINDNode::GotoNodePtr() * * Move to the specified node ptr, and read the new node data from the file. * * This is just a cover funtion on top of InitNode() **********************************************************************/int TABINDNode::GotoNodePtr(UGKInt32 nNewNodePtr){    // First flush current changes if any.    if ((m_eAccessMode == TABWrite || m_eAccessMode == TABReadWrite) &&         m_poDataBlock && m_poDataBlock->CommitToFile() != 0)        return -1;    assert(nNewNodePtr % 512 == 0);    // Then move to the requested location.    return InitNode(m_fp, nNewNodePtr, m_nKeyLength, m_nSubTreeDepth,                     m_bUnique);}/********************************************************************** *                   TABINDNode::ReadIndexEntry() * * Read the key value and record/node ptr for the specified index entry * inside the current node data. * * nEntryNo is the 0-based index of the index entry that we are interested * in inside the current node. * * Returns the record/node ptr, and copies the key value inside the * buffer pointed to by *pKeyValue... this assumes that *pKeyValue points * to a buffer big enough to hold the key value (m_nKeyLength bytes). * If pKeyValue == NULL, then this parameter is ignored and the key value * is not copied. **********************************************************************/UGKInt32 TABINDNode::ReadIndexEntry(int nEntryNo, UGKByte *pKeyValue){    UGKInt32 nRecordPtr = 0;    if (nEntryNo >= 0 && nEntryNo < m_numEntriesInNode)    {        if (pKeyValue)        {            m_poDataBlock->GotoByteInBlock(12 + nEntryNo*(m_nKeyLength+4));            m_poDataBlock->ReadBytes(m_nKeyLength, pKeyValue);        }        else        {            m_poDataBlock->GotoByteInBlock(12 + nEntryNo*(m_nKeyLength+4)+                                                                 m_nKeyLength);        }        nRecordPtr = m_poDataBlock->ReadInt32();    }    return nRecordPtr;}/********************************************************************** *                   TABINDNode::IndexKeyCmp() * * Compare the specified index entry with the key value, and  * return 0 if equal, an integer less than 0 if key is smaller than  * index entry, and an integer greater than 0 if key is bigger than  * index entry. * * nEntryNo is the 0-based index of the index entry that we are interested * in inside the current node. **********************************************************************/int   TABINDNode::IndexKeyCmp(UGKByte *pKeyValue, int nEntryNo){    assert(pKeyValue);    assert(nEntryNo >= 0 && nEntryNo < m_numEntriesInNode);    m_poDataBlock->GotoByteInBlock(12 + nEntryNo*(m_nKeyLength+4));    return memcmp(pKeyValue, m_poDataBlock->GetCurDataPtr(), m_nKeyLength);}/********************************************************************** *                   TABINDNode::SetFieldType() * * Sets the field type for the current index and recursively set all  * children as well. * This information will then be used in building the key values, etc. * * Returns 0 on success, -1 on error. **********************************************************************/int TABINDNode::SetFieldType(TABFieldType eType){    if (m_fp == NULL)    {        UGKError(ET_Failure, UGKErr_AssertionFailed,                 "TABINDNode::SetFieldType(): File has not been opened yet!");        return -1;    }    /*-----------------------------------------------------------------     * Validate field type with key length     *----------------------------------------------------------------*/    if ((eType == TABFInteger && m_nKeyLength != 4) ||        (eType == TABFSmallInt && m_nKeyLength != 2) ||        (eType == TABFFloat && m_nKeyLength != 8) ||        (eType == TABFDecimal && m_nKeyLength != 8) ||        (eType == TABFDate && m_nKeyLength != 4) ||        (eType == TABFLogical && m_nKeyLength != 4) )    {        UGKError(ET_Failure, UGKErr_IllegalArg,                  "Index key length (%d) does not match field type (%s).",                  m_nKeyLength, TABFIELDTYPE_2_STRING(eType) );        return -1;    }                   m_eFieldType = eType;    /*-----------------------------------------------------------------     * Pass the field type info to child nodes     *----------------------------------------------------------------*/    if (m_poCurChildNode)        return m_poCurChildNode->SetFieldType(eType);    return 0;}/********************************************************************** *                   TABINDNode::FindFirst() * * Start a new search in this node and its children for a key value. * If the index is not unique, then FindNext() can be used to return * the other values that correspond to the key. * * Return value: *  - the key's corresponding record number in the .DAT file (greater than 0) *  - 0 if the key was not found *  - or -1 if an error happened **********************************************************************/UGKInt32 TABINDNode::FindFirst(UGKByte *pKeyValue){    if (m_poDataBlock == NULL)    {        UGKError(ET_Failure, UGKErr_AssertionFailed,                  "TABINDNode::Search(): Node has not been initialized yet!");        return -1;    }    /*-----------------------------------------------------------------     * Unless something has been broken, this method will be called by our     * parent node after it has established that we are the best candidate     * to contain the first instance of the key value.  So there is no     * need to look in the previous or next nodes in the chain... if the     * value is not found in the current node block then it is not present     * in the index at all.     *     * m_nCurIndexEntry will be used to keep track of the search pointer     * when FindNext() will be used.     *----------------------------------------------------------------*/    m_nCurIndexEntry = 0;    if (m_nSubTreeDepth == 1)    {        /*-------------------------------------------------------------         * Leaf node level... we look for an exact match         *------------------------------------------------------------*/        while(m_nCurIndexEntry < m_numEntriesInNode)        {            int nCmpStatus = IndexKeyCmp(pKeyValue, m_nCurIndexEntry);            if (nCmpStatus > 0)            {                /* Not there yet... (pKey > IndexEntry) */                m_nCurIndexEntry++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -