📄 tabindfile.cpp
字号:
{ /*--------------------------------------------------------- * 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) { UGKError(ET_Failure, UGKErr_AssertionFailed, "TABINDFile: File has not been opened yet!"); return -1; } if (nIndexNumber < 1 || nIndexNumber > m_numIndexes || m_papoIndexRootNodes == NULL || m_papoIndexRootNodes[nIndexNumber-1] == NULL) { UGKError(ET_Failure, UGKErr_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, UGKBool 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 **********************************************************************/UGKByte *TABINDFile::BuildKey(int nIndexNumber, UGKInt32 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] = (UGKByte)(nValue & 0xff)+0x80; break; case 2: m_papbyKeyBuffers[nIndexNumber-1][0] = (UGKByte)(nValue/0x100 & 0xff)+0x80; m_papbyKeyBuffers[nIndexNumber-1][1] = (UGKByte)(nValue & 0xff); break; case 4: m_papbyKeyBuffers[nIndexNumber-1][0] = (UGKByte)(nValue/0x1000000 &0xff)+0x80; m_papbyKeyBuffers[nIndexNumber-1][1] = (UGKByte)(nValue/0x10000 & 0xff); m_papbyKeyBuffers[nIndexNumber-1][2] = (UGKByte)(nValue/0x100 &0xff); m_papbyKeyBuffers[nIndexNumber-1][3] = (UGKByte)(nValue & 0xff); break; default: UGKError(ET_Failure, UGKErr_AssertionFailed, "BuildKey(): %d bytes integer key length not supported", nKeyLength); break; } return m_papbyKeyBuffers[nIndexNumber-1];}/********************************************************************** * TABINDFile::BuildKey() * * BuildKey() for string fields **********************************************************************/UGKByte *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] = (UGKByte)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 **********************************************************************/UGKByte *TABINDFile::BuildKey(int nIndexNumber, double dValue){ if (ValidateIndexNo(nIndexNumber) != 0) return NULL; int nKeyLength = m_papoIndexRootNodes[nIndexNumber-1]->GetKeyLength(); assert(nKeyLength == 8 && sizeof(double) == 8); /*----------------------------------------------------------------- * Convert double and decimal values... * Reverse the sign of the value, and convert to MSB *----------------------------------------------------------------*/ dValue = -dValue; memcpy(m_papbyKeyBuffers[nIndexNumber-1], (UGKByte*)(&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 **********************************************************************/UGKInt32 TABINDFile::FindFirst(int nIndexNumber, UGKByte *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. * * 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 TABINDFile::FindNext(int nIndexNumber, UGKByte *pKeyValue){ if (ValidateIndexNo(nIndexNumber) != 0) return -1; return m_papoIndexRootNodes[nIndexNumber-1]->FindNext(pKeyValue);}/********************************************************************** * TABINDFile::CreateIndex() * * Create a new index with the specified field type and size. * Field size applies only to char field type... the other types have a * predefined key length. * * Key length is limited to 128 chars. char fields longer than 128 chars * will have their key truncated to 128 bytes. * * Note that a .IND file can contain only a maximum of 29 indexes. * * Returns the new field index on success (greater than 0), or -1 on error. **********************************************************************/int TABINDFile::CreateIndex(TABFieldType eType, int nFieldSize){ int i, nNewIndexNo = -1; if (m_fp == NULL || (m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite)) return -1; /*----------------------------------------------------------------- * Look for an empty slot in the current array, if there is none * then extend the array. *----------------------------------------------------------------*/ for(i=0; m_papoIndexRootNodes && i<m_numIndexes; i++) { if (m_papoIndexRootNodes[i] == NULL) { nNewIndexNo = i; break; } } if (nNewIndexNo == -1 && m_numIndexes >= 29) { UGKError(ET_Failure, UGKErr_AppDefined, "Cannot add new index to %s. A dataset can contain only a " "maximum of 29 indexes.", m_pszFname); return -1; } if (nNewIndexNo == -1) { /*------------------------------------------------------------- * Add a slot for new index at the end of the nodes array. *------------------------------------------------------------*/ m_numIndexes++; m_papoIndexRootNodes = (TABINDNode**)UGK_Realloc( m_papoIndexRootNodes, m_numIndexes* sizeof(TABINDNode*)); m_papbyKeyBuffers = (UGKByte **)UGK_Realloc(m_papbyKeyBuffers, m_numIndexes*sizeof(UGKByte*)); nNewIndexNo = m_numIndexes-1; } /*----------------------------------------------------------------- * Alloc and init new node * The call to InitNode() automatically allocates storage space for * the node in the file. * New nodes are created with a subtree_depth=1 since they start as * leaf nodes, i.e. their entries point directly to .DAT records *----------------------------------------------------------------*/ int nKeyLength = ((eType == TABFInteger) ? 4: (eType == TABFSmallInt) ? 2: (eType == TABFFloat) ? 8: (eType == TABFDecimal) ? 8: (eType == TABFDate) ? 4: (eType == TABFLogical) ? 4: MIN(128,nFieldSize)); m_papoIndexRootNodes[nNewIndexNo] = new TABINDNode(m_eAccessMode); if (m_papoIndexRootNodes[nNewIndexNo]->InitNode(m_fp, 0, nKeyLength, 1, // subtree depth=1 FALSE, // not unique &m_oBlockManager, NULL, 0, 0)!= 0) { // CPLError has already been called return -1; } // Alloc a temporary key buffer for this index. // This buffer will be used by the BuildKey() method m_papbyKeyBuffers[nNewIndexNo] = (UGKByte *)UGK_Calloc(nKeyLength+1, sizeof(UGKByte)); // Return 1-based index number return nNewIndexNo+1;}/********************************************************************** * TABINDFile::AddEntry() * * Add an .DAT record entry for pKeyValue in the specified index. * * Note that index numbers are positive values starting at 1. * nRecordNo is the .DAT record number, record numbers start at 1. * * Returns 0 on success, -1 on error **********************************************************************/int TABINDFile::AddEntry(int nIndexNumber, UGKByte *pKeyValue, UGKInt32 nRecordNo){ if ((m_eAccessMode != TABWrite && m_eAccessMode != TABReadWrite) || ValidateIndexNo(nIndexNumber) != 0) return -1; return m_papoIndexRootNodes[nIndexNumber-1]->AddEntry(pKeyValue,nRecordNo);}/********************************************************************** * TABINDFile::Dump() * * Dump block contents... available only in DEBUG mode. **********************************************************************/void TABINDFile::Dump(FILE *fpOut /*=NULL*/){ if (fpOut == NULL) fpOut = stdout; fprintf(fpOut, "----- TABINDFile::Dump() -----\n"); if (m_fp == NULL) { fprintf(fpOut, "File is not opened.\n"); } else { fprintf(fpOut, "File is opened: %s\n", m_pszFname); fprintf(fpOut, " m_numIndexes = %d\n", m_numIndexes); for(int i=0; i<m_numIndexes && m_papoIndexRootNodes; i++) { if (m_papoIndexRootNodes[i]) { fprintf(fpOut, " ----- Index # %d -----\n", i+1); m_papoIndexRootNodes[i]->Dump(fpOut); } } } fflush(fpOut);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -