?? mitab_indfile.cpp
字號:
/* First index def. starts at byte 48 */ poHeaderBlock->GotoByteInBlock(48); for(int iIndex=0; iIndex<m_numIndexes; iIndex++) { /*------------------------------------------------------------- * Read next index definition *------------------------------------------------------------*/ GInt32 nRootNodePtr = poHeaderBlock->ReadInt32(); poHeaderBlock->ReadInt16(); // skip... max. num of entries per node int nTreeDepth = poHeaderBlock->ReadByte(); int nKeyLength = poHeaderBlock->ReadByte(); poHeaderBlock->GotoByteRel(8); // skip next 8 bytes; /*------------------------------------------------------------- * And init root node for this index. * Note that if nRootNodePtr==0 then this means that the * corresponding index does not exist (i.e. has been deleted?) * so we simply do not allocate the root node in this case. * An error will be produced if the user tries to access this index * later during execution. *------------------------------------------------------------*/ if (nRootNodePtr > 0) { m_papoIndexRootNodes[iIndex] = new TABINDNode(m_eAccessMode); if (m_papoIndexRootNodes[iIndex]->InitNode(m_fp, nRootNodePtr, nKeyLength, nTreeDepth, FALSE, &m_oBlockManager)!= 0) { // CPLError has already been called delete poHeaderBlock; return -1; } // Alloc a temporary key buffer for this index. // This buffer will be used by the BuildKey() method m_papbyKeyBuffers[iIndex] = (GByte *)CPLCalloc(nKeyLength+1, sizeof(GByte)); } else { m_papoIndexRootNodes[iIndex] = NULL; m_papbyKeyBuffers[iIndex] = NULL; } } /*----------------------------------------------------------------- * OK, we won't need the header block any more... free it. *----------------------------------------------------------------*/ delete poHeaderBlock; return 0;}/********************************************************************** * TABINDFile::WriteHeader() * * (private method) * Write the header block based on current index information. * * Returns 0 on success, -1 on error. **********************************************************************/int TABINDFile::WriteHeader(){ CPLAssert(m_fp); CPLAssert(m_eAccessMode == TABWrite || m_eAccessMode == TABReadWrite); /*----------------------------------------------------------------- * Write the 48 bytes of file header *----------------------------------------------------------------*/ TABRawBinBlock *poHeaderBlock; poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE); poHeaderBlock->InitNewBlock(m_fp, 512, 0); poHeaderBlock->WriteInt32( IND_MAGIC_COOKIE ); poHeaderBlock->WriteInt16( 100 ); // ??? poHeaderBlock->WriteInt16( 512 ); // ??? poHeaderBlock->WriteInt32( 0 ); // ??? poHeaderBlock->WriteInt16( m_numIndexes ); poHeaderBlock->WriteInt16( 0x15e7); // ??? poHeaderBlock->WriteInt16( 10 ); // ??? poHeaderBlock->WriteInt16( 0x611d); // ??? poHeaderBlock->WriteZeros( 28 ); /*----------------------------------------------------------------- * The first index definition starts at byte 48 *----------------------------------------------------------------*/ for(int iIndex=0; iIndex<m_numIndexes; iIndex++) { TABINDNode *poRootNode = m_papoIndexRootNodes[iIndex]; if (poRootNode) { /*--------------------------------------------------------- * Write next index definition *--------------------------------------------------------*/ poHeaderBlock->WriteInt32(poRootNode->GetNodeBlockPtr()); poHeaderBlock->WriteInt16(poRootNode->GetMaxNumEntries()); poHeaderBlock->WriteByte( poRootNode->GetSubTreeDepth()); poHeaderBlock->WriteByte( poRootNode->GetKeyLength()); poHeaderBlock->WriteZeros( 8 ); /*--------------------------------------------------------- * Look for overflow of the SubTreeDepth field (byte) *--------------------------------------------------------*/ if (poRootNode->GetSubTreeDepth() > 255) { CPLError(CE_Failure, CPLE_AssertionFailed, "Index no %d is too large and will not be useable. " "(SubTreeDepth = %d, cannot exceed 255).", iIndex+1, poRootNode->GetSubTreeDepth()); return -1; } } else { /*--------------------------------------------------------- * NULL Root Node: This index has likely been deleted *--------------------------------------------------------*/ poHeaderBlock->WriteZeros( 16 ); } } /*----------------------------------------------------------------- * OK, we won't need the header block any more... write and free it. *----------------------------------------------------------------*/ if (poHeaderBlock->CommitToFile() != 0) return -1; delete poHeaderBlock; return 0;}/********************************************************************** * TABINDFile::ValidateIndexNo() * * Private method to validate the index no parameter of some methods... * returns 0 if index no. is OK, or produces an error ands returns -1 * if index no is not valid. **********************************************************************/int TABINDFile::ValidateIndexNo(int nIndexNumber){ if (m_fp == NULL) { CPLError(CE_Failure, CPLE_AssertionFailed, "TABINDFile: File has not been opened yet!"); return -1; } if (nIndexNumber < 1 || nIndexNumber > m_numIndexes || m_papoIndexRootNodes == NULL || m_papoIndexRootNodes[nIndexNumber-1] == NULL) { CPLError(CE_Failure, CPLE_AssertionFailed, "No field index number %d in %s: Valid range is [1..%d].", nIndexNumber, m_pszFname, m_numIndexes); return -1; } return 0; // Index seems valid}/********************************************************************** * TABINDFile::SetIndexFieldType() * * Sets the field type for the specified index. * This information will then be used in building the key values, etc. * * Returns 0 on success, -1 on error. **********************************************************************/int TABINDFile::SetIndexFieldType(int nIndexNumber, TABFieldType eType){ if (ValidateIndexNo(nIndexNumber) != 0) return -1; return m_papoIndexRootNodes[nIndexNumber-1]->SetFieldType(eType);}/********************************************************************** * TABINDFile::SetIndexUnique() * * Indicate that an index's keys are unique. This allows for some * optimization with read access. By default, an index is treated as if * its keys could have duplicates. * * Returns 0 on success, -1 on error. **********************************************************************/int TABINDFile::SetIndexUnique(int nIndexNumber, GBool bUnique/*=TRUE*/){ if (ValidateIndexNo(nIndexNumber) != 0) return -1; m_papoIndexRootNodes[nIndexNumber-1]->SetUnique(bUnique); return 0;}/********************************************************************** * TABINDFile::BuildKey() * * Encode a field value in the form required to be compared with index * keys in the specified index. * * Note that index numbers are positive values starting at 1. * * Returns a reference to an internal buffer that is valid only until the * next call to BuildKey(). (should not be freed by the caller). * Returns NULL if field index is invalid. * * The first flavour of the function handles integer type of values, this * corresponds to MapInfo types: integer, smallint, logical and date **********************************************************************/GByte *TABINDFile::BuildKey(int nIndexNumber, GInt32 nValue){ if (ValidateIndexNo(nIndexNumber) != 0) return NULL; int nKeyLength = m_papoIndexRootNodes[nIndexNumber-1]->GetKeyLength(); /*----------------------------------------------------------------- * Convert all int values to MSB using the right number of bytes * Note: * The most significant bit has to be unset for negative values, * and to be set for positive ones... that's the reverse of what it * should usually be. Adding 0x80 to the MSB byte will do the job. *----------------------------------------------------------------*/ switch(nKeyLength) { case 1: m_papbyKeyBuffers[nIndexNumber-1][0] = (GByte)(nValue & 0xff)+0x80; break; case 2: m_papbyKeyBuffers[nIndexNumber-1][0] = (GByte)(nValue/0x100 & 0xff)+0x80; m_papbyKeyBuffers[nIndexNumber-1][1] = (GByte)(nValue & 0xff); break; case 4: m_papbyKeyBuffers[nIndexNumber-1][0] = (GByte)(nValue/0x1000000 &0xff)+0x80; m_papbyKeyBuffers[nIndexNumber-1][1] = (GByte)(nValue/0x10000 & 0xff); m_papbyKeyBuffers[nIndexNumber-1][2] = (GByte)(nValue/0x100 &0xff); m_papbyKeyBuffers[nIndexNumber-1][3] = (GByte)(nValue & 0xff); break; default: CPLError(CE_Failure, CPLE_AssertionFailed, "BuildKey(): %d bytes integer key length not supported", nKeyLength); break; } return m_papbyKeyBuffers[nIndexNumber-1];}/********************************************************************** * TABINDFile::BuildKey() * * BuildKey() for string fields **********************************************************************/GByte *TABINDFile::BuildKey(int nIndexNumber, const char *pszStr){ if (ValidateIndexNo(nIndexNumber) != 0 || pszStr == NULL) return NULL; int nKeyLength = m_papoIndexRootNodes[nIndexNumber-1]->GetKeyLength(); /*----------------------------------------------------------------- * Strings keys are all in uppercase, and padded with '\0' *----------------------------------------------------------------*/ int i=0; for (i=0; i<nKeyLength && pszStr[i] != '\0'; i++) { m_papbyKeyBuffers[nIndexNumber-1][i] = (GByte)toupper(pszStr[i]); } /* Pad the end of the buffer with '\0' */ for( ; i<nKeyLength; i++) { m_papbyKeyBuffers[nIndexNumber-1][i] = '\0'; } return m_papbyKeyBuffers[nIndexNumber-1];}/********************************************************************** * TABINDFile::BuildKey() * * BuildKey() for float and decimal fields **********************************************************************/GByte *TABINDFile::BuildKey(int nIndexNumber, double dValue){ if (ValidateIndexNo(nIndexNumber) != 0) return NULL; int nKeyLength = m_papoIndexRootNodes[nIndexNumber-1]->GetKeyLength(); CPLAssert(nKeyLength == 8 && sizeof(double) == 8); /*----------------------------------------------------------------- * Convert double and decimal values... * Reverse the sign of the value, and convert to MSB *----------------------------------------------------------------*/ dValue = -dValue;#ifndef CPL_MSB CPL_SWAPDOUBLE(&dValue);#endif memcpy(m_papbyKeyBuffers[nIndexNumber-1], (GByte*)(&dValue), nKeyLength); return m_papbyKeyBuffers[nIndexNumber-1];}/********************************************************************** * TABINDFile::FindFirst() * * Search one of the indexes for a key value. * * Note that index numbers are positive values starting at 1. * * 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 **********************************************************************/GInt32 TABINDFile::FindFirst(int nIndexNumber, GByte *pKeyValue){ if (ValidateIndexNo(nIndexNumber) != 0) return -1; return m_papoIndexRootNodes[nIndexNumber-1]->FindFirst(pKeyValue);}/********************************************************************** * TABINDFile::FindNext() * * Continue the Search for pKeyValue previously initiated by FindFirst(). * NOTE: FindFirst() MUST have been previously called for this call to * work... * * Note that index numbers are positive values starting at 1.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -