From bfa452a375ea0a0a3f95304a69186936567e5263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 14 Aug 2023 19:45:36 +0200 Subject: New upstream version 4.1.4 --- src/core/xbixbase.cpp | 789 -------------------------------------------------- 1 file changed, 789 deletions(-) delete mode 100755 src/core/xbixbase.cpp (limited to 'src/core/xbixbase.cpp') diff --git a/src/core/xbixbase.cpp b/src/core/xbixbase.cpp deleted file mode 100755 index 8b64fd6..0000000 --- a/src/core/xbixbase.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/* xbixbase.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel - -The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. - -Email Contact: - - XDB-devel@lists.sourceforge.net - XDB-users@lists.sourceforge.net - - Base index class - -*/ - -#include "xbase.h" -#ifdef XB_INDEX_SUPPORT - -namespace xb{ - -/***********************************************************************/ -//! @brief Class constructor. -/*! - /param dbf Pointer to dbf instance. -*/ -xbIx::xbIx( xbDbf *dbf ) : xbFile( dbf->GetXbasePtr()) { - this->dbf = dbf; - vpCurTag = NULL; - cNodeBuf = NULL; - bLocked = xbFalse; -} -/***********************************************************************/ -//! @brief Class Destructor. -xbIx::~xbIx(){} - - -/***********************************************************************/ -//! @brief Add Keys for record number -/*! - For a given a record number, add keys to each tag in the index file - if it was updated - - \param ulRecNo Record number to add keys for - \returns Return Codes -*/ - -xbInt16 xbIx::AddKeys( xbUInt32 ulRecNo ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 i = 0; - xbInt16 iKeySts; - - try{ - void * vpTag; - xbInt16 iTagCount = GetTagCount(); - - for( i = 0; i < iTagCount; i++ ){ - vpTag = GetTag( i ); - iKeySts = GetKeySts( vpTag ); - - if( iKeySts == 1 || iKeySts == 2 ){ - if(( iRc = UpdateTagKey( 'A', vpTag, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIx::AddKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Allocate memory for index node. -/*! - Allocate an index node. - - \param ulBufSize Size of buffer to allocate - \returns null on error
Pointer to newly allocated xbIxNode on success -*/ -xbIxNode * xbIx::AllocateIxNode( xbUInt32 ulBufSize, xbInt16 ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - xbIxNode * pNode = (xbIxNode *) calloc( 1, sizeof( xbIxNode )); - if( pNode == NULL ){ - iErrorStop = 100; - iRc = XB_NO_MEMORY; - throw iRc; - } - if( ulBufSize == 0 ) - ulBufSize = GetBlockSize(); - - pNode->ulBufSize = ulBufSize; - pNode->cpBlockData = (char *) calloc( 1, ulBufSize ); - if( pNode->cpBlockData == NULL ){ - free( pNode ); - iErrorStop = 110; - iRc = XB_NO_MEMORY; - throw iRc; - } - return pNode; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIx::AllocateIxNode() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return NULL; -} - - -/***********************************************************************/ -//! @brief Binary search for given value on an index node. -/*! - - Binary search for key lookups - \param cKeyType Key type - \param npNode Pointer to index node for search - \param lKeyItemLen Lenth of key plus pointer values - \param vpKey Pointer to key value - \param lSearchKeyLen length of key to search - \param iCompRc output return code from the CompareKey routine. CompareKey returns an - integer value less than, equal to or greater than zero in when comparing values - - \param bDescending xbTrue for descending index key lookup.
- xbFalse for ascending index key lookup. - \return The position in the node the key was found, if multiples it returns the first occurrence. - If the key is not found, it returns the slot it should be in. -*/ - -xbInt16 xbIx::BSearchBlock( char cKeyType, xbIxNode *npNode, xbInt32 lKeyItemLen, const void *vpKey, - xbInt32 lSearchKeyLen, xbInt16 &iCompRc, xbBool bDescending ) const { - xbInt32 lLo = 0; - xbInt32 lHi = 0; - xbInt32 lMid = 0; - xbInt32 lKeyCnt = GetKeyCount( npNode ); - - - if( !bDescending ){ - lHi = lKeyCnt - 1; - - while( lLo <= lHi ){ - lMid = (lLo + lHi) / 2; - iCompRc = CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); - if( iCompRc > 0 ) - lHi = lMid - 1; - else if( iCompRc < 0 ) - lLo = lMid + 1; - else{ // found match, look for leftmost occurrence - - xbInt32 lFoundPos = lMid; - lMid--; - while( lMid >= 0 && CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ) == 0 ){ - lFoundPos = lMid; - lMid--; - } - iCompRc = 0; - lLo = lFoundPos; - lHi = -1; - } - } - // update the compare key results - if( lMid != lLo ){ - if( lLo >= lKeyCnt ) - iCompRc = 1; - else - iCompRc = CompareKey( cKeyType, GetKeyData( npNode, lLo, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); - } - return (xbInt16) lLo; - - } else { // descending key - - lLo = lKeyCnt - 1; - while( lLo >= lHi && lHi != -1 ){ - lMid = (lLo + lHi) / 2; - iCompRc = CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); - - if( iCompRc > 0 ) { - lHi = lMid + 1; - } - else if( iCompRc < 0) { - lLo = lMid - 1; - } - else{ // found match, look for leftmost occurrence - - xbInt32 lFoundPos = lMid; - lMid--; - while( lMid >= 0 && CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ) == 0 ){ - lFoundPos = lMid; - lMid--; - } - iCompRc = 0; - lHi = lFoundPos; - lLo = -1; - } - } - - // std::cout << "BSB1 lo = " << lLo << " mid = " << lMid << " hi = " << lHi << " keycnt = " << lKeyCnt << " iCompRc = " << iCompRc << "\n"; // key=" << (char *) vpKey << "\n"; - if( lLo < 0 && iCompRc < 0 ) - iCompRc = 1; - else if( iCompRc != 0 ) { - iCompRc = CompareKey( cKeyType, GetKeyData( npNode, (lLo < 0 ? 0 : lLo), lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); - } - // std::cout << "BSB2 lo = " << lLo << " mid = " << lMid << " hi = " << lHi << " keycnt = " << lKeyCnt << " iCompRc = " << iCompRc << "\n"; // key=" << (char *) vpKey << "\n"; - return (xbInt16) lHi; - } - - // should never get here - // return (xbInt16) 0; -} - -/***********************************************************************/ -//! @brief Check for duplicate keys. -/*! - \returns Return Codes -*/ -xbInt16 xbIx::CheckForDupKeys(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 i = 0; - - try{ - void * vpTag; - xbInt16 iTagCount = GetTagCount(); - for( i = 0; i < iTagCount; i++ ){ - vpTag = GetTag( i ); - if(( iRc = CheckForDupKey( vpTag )) < XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - if( iRc != XB_KEY_NOT_UNIQUE ){ - xbString sMsg; - sMsg.Sprintf( "xbIxBase::CheckForDupKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; -} -/***********************************************************************/ -//! @brief Close index file. -/*! - \returns Return Codes -*/ - -xbInt16 xbIx::Close(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - if(( iRc = xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIx::Close() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Compare keys. -/*! - \param cKeyType C - Character compare.
- N - Numeric BCD compare.
- D - Numeric compare.
- F - Numeric compare.
- \param v1 Left compare.
v2 - Right Compare. - \param iSearchKeyLen Length of key compare. - \returns 1 - Left operand is greater then right operand.
- 0 - Left operand is equal to right operand.
- -1 - Left operand is less than right operand. -*/ -inline xbInt16 xbIx::CompareKey( char cKeyType, const void *v1, const void *v2, size_t iSearchKeyLen ) const{ - if( cKeyType == 'C' ){ // character compare - return memcmp( v1, v2, iSearchKeyLen ); - } else if( cKeyType == 'N' ){ // numeric bcd compare, mdx bcd numeric indices - xbBcd bcdk1( v1 ); - return bcdk1.Compare( v2 ); - } else if( cKeyType == 'D' || cKeyType == 'F' ){ // julian date compare, ndx float numeric indices - xbDouble *d1 = (xbDouble *) v1; - xbDouble *d2 = (xbDouble *) v2; - if( *d1 < *d2 ) - return -1; - else if( *d1 > *d2 ) - return 1; - else - return 0; - } else { -// std::cout << "Unhandled key type [" << cKeyType << "]\n"; - } - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Create Keys for record number -/*! - \param iOpt 0 Build a key for FindKey usage, only rec buf 0.
- 1 Append Mode, Create key for an append, only use rec buf 0, set updated switch.
- 2 Update Mode, Create old version and new version keys, check if different, set update switch appropriately. - \returns Return Codes -*/ -xbInt16 xbIx::CreateKeys( xbInt16 iOpt ) { - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 i = 0; - - try{ - void * vpTag; - xbInt16 iTagCount = GetTagCount(); - - for( i = 0; i < iTagCount; i++ ){ - vpTag = GetTag( i ); - if(( iRc = CreateKey( vpTag, iOpt )) < XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIx::CreateKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Delete keys for record number -/*! - Delete keys to each tag in the index file if it was updated as determined - by CreateKeys function - - \returns Return Codes -*/ -//xbInt16 xbIx::DeleteKeys( xbUInt32 ulRecNo ){ - -xbInt16 xbIx::DeleteKeys(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 i = 0; - - try{ - void * vpTag; - xbInt16 iTagCount = GetTagCount(); - - for( i = 0; i < iTagCount; i++ ){ - vpTag = GetTag( i ); - if( GetKeySts( vpTag ) > 1 ){ // 0 = no update 1 = add 2 = update, 3 = delete - if(( iRc = UpdateTagKey( 'D', vpTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIx::DeleteKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -#ifdef XB_DEBUG_SUPPORT -//! @brief Dump anode for debug purposes. -/*! - \param pNode Pointer to node to dump. - \param iOption 0 = stdout
- 1 = Syslog
- 2 = Both
- \returns Return Codes -*/ - -xbInt16 xbIx::DumpNode( void *, xbIxNode *pNode, xbInt16 iOption ) const -{ - xbString s; - s.Sprintf( "Dump Node Block=[%d] CurKey=[%d]", pNode->ulBlockNo, pNode->iCurKeyNo ); - xbase->WriteLogMessage( s, iOption ); - - return XB_NO_ERROR; -} -#endif // XB_DEBUG_SUPPORT - -/***********************************************************************/ -//! @brief Find double key -/*! - \param vpTag Pointer to tag to search. - \param dKey Double value to search for. - \param iRetrieveSw xbTrue - Retrieve the record if key found.
- xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.
- XB_NOT_FOUND - Key not found.
- Return Codes -*/ -xbInt16 xbIx::FindKey( void *vpTag, xbDouble dKey, xbInt16 iRetrieveSw ){ - return FindKey( vpTag, &dKey, 8, iRetrieveSw ); -} -/***********************************************************************/ -//! @brief Find string key -/*! - \param vpTag Pointer to tag to search. - \param sKey String data to search for. - \param iRetrieveSw xbTrue - Retrieve the record if key found.
- xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.
- XB_NOT_FOUND - Key not found.
- Return Codes -*/ -xbInt16 xbIx::FindKey( void *vpTag, const xbString &sKey, xbInt16 iRetrieveSw ){ - return FindKey( vpTag, sKey.Str(), (xbInt32) sKey.Len(), iRetrieveSw ); -} -/***********************************************************************/ -//! @brief Find character key -/*! - \param vpTag Pointer to tag to search. - \param cKey String data to search for. - \param lKeyLen Length of key to search for. - \param iRetrieveSw xbTrue - Retrieve the record if key found.
- xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.
- XB_NOT_FOUND - Key not found.
- Return Codes -*/ -xbInt16 xbIx::FindKey( void *vpTag, const char *cKey, xbInt32 lKeyLen, xbInt16 iRetrieveSw ){ - return FindKey( vpTag, (void *) cKey, lKeyLen, iRetrieveSw ); -} -/***********************************************************************/ -//! @brief Find bcd key -/*! - \param vpTag Pointer to tag to search. - \param bcd BCD data to search for. - \param iRetrieveSw xbTrue - Retrieve the record if key found.
- xbFalse - Don't retrieve record, check for key existence only. - - \returns XB_NO_ERROR - Key found.
- XB_NOT_FOUND - Key not found.
- Return Codes -*/ -xbInt16 xbIx::FindKey( void *vpTag, const xbBcd &bcd, xbInt16 iRetrieveSw ){ - return FindKey( vpTag, bcd.GetBcd(), 12, iRetrieveSw ); -} -/***********************************************************************/ -//! @brief Find date key -/*! - \param vpTag Pointer to tag to search. - \param dtKey Date data to search for. - \param iRetrieveSw xbTrue - Retrieve the record if key found.
- xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.
- XB_NOT_FOUND - Key not found.
- Return Codes -*/ -xbInt16 xbIx::FindKey( void *vpTag, const xbDate &dtKey, xbInt16 iRetrieveSw ){ - xbDouble d = (xbDouble) dtKey.JulianDays(); - return FindKey( vpTag, &d, 8, iRetrieveSw ); -} -/***********************************************************************/ -//! @brief Free all nodes in a linked list. -/*! - \param np Pointer to first node in linked list to free. - \returns NULL. -*/ -xbIxNode *xbIx::FreeNodeChain( xbIxNode *np ){ - - // routine returns NULL - if( np ){ - // free memory for a given chain of nodes - xbIxNode * np2; - - // Clear the previous node's next pointer - if( np->npPrev ) - np->npPrev->npNext = NULL; - - // Clear out the tree - while( np ){ - np2 = np->npNext; - NodeFree( np ); - np = NULL; - np = np2; - } - } - return NULL; -} -/***********************************************************************/ -//! @brief Read block for block number. -/*! - Routine to read a node/block out of an index file and store in xbIxNode structure - \param vpTag Pointer to tag. - \param ulBlockNo Block number to read off disk. - \param iOpt - 0 = Node is read into block buffer, not added to the node chain
- 1 = Node is read into new xbIxNode, then added to the node chain, and sets CurNode with new node
- 2 = Node is read into new xbIxNode, not added to the node chain
- CurNode points to new node
- \param ulAddlBuf Additional buffer size added to memory - \returns Return Codes - -*/ - -xbInt16 xbIx::GetBlock( void *vpTag, xbUInt32 ulBlockNo, xbInt16 iOpt, xbUInt32 ulAddlBuf ){ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbIxNode *np = NULL; - try{ - - if( !vpTag && iOpt == 1 ){ - iErrorStop = 100; - throw iRc; - } - - // set target location of block read to read - char *cp; - if( iOpt == 0 ) - cp = cNodeBuf; - else{ - if(( np = AllocateIxNode(GetBlockSize() + ulAddlBuf )) == NULL ){ - iErrorStop = 110; - iRc = XB_NO_MEMORY; - throw( iRc ); - } - cp = np->cpBlockData; - } - if(( iRc = ReadBlock( ulBlockNo, GetBlockSize(), cp )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if( iOpt == 0 ) - return iRc; - np->ulBlockNo = ulBlockNo; - np->iCurKeyNo = 0; - if( iOpt == 1 ) - AppendNodeChain( vpTag, np ); - else if( iOpt == 2 ){ - std::cout << "Future use stub. xbIxbase::GetBlock() option 2 not coded.\n"; - iErrorStop = 130; - iRc = XB_INVALID_OPTION; - throw iRc; - // SetCurNode( vpTag, np ); - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIx::GetBlock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( np ) NodeFree( np ); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Get pointer to current tag. -/*! - \returns Pointer to current tag. -*/ - -void *xbIx::GetCurTag() const { - return vpCurTag; -} -/***********************************************************************/ -//! @brief Get pointer to dbf. -/*! - \returns Pointer to dbf. -*/ -xbDbf *xbIx::GetDbf() const { - return this->dbf; -} -/***********************************************************************/ -//! @brief Get the first key for the current tag. -/*! - \returns Return Codes -*/ -xbInt16 xbIx::GetFirstKey(){ - return GetFirstKey( vpCurTag, 0 ); -} - -/***********************************************************************/ -//! @brief Get the first key for a given tag. -/*! - \param vpTag Tag for get first key operation. - \returns Return Codes -*/ -xbInt16 xbIx::GetFirstKey( void *vpTag ){ - return GetFirstKey( vpTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the last key for the current tag. -/*! - \returns Return Codes -*/ -xbInt16 xbIx::GetLastKey(){ - return GetLastKey( 0, vpCurTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the last key for a given tag. -/*! - \param vpTag Tag for get last key operation. - \returns Return Codes -*/ -xbInt16 xbIx::GetLastKey( void *vpTag ){ - return GetLastKey( 0, vpTag, 0 ); -} - -/***********************************************************************/ -//! @brief Get the file lock status. -/*! - \returns xbTrue - Index file is locked.
xbFalse - Index file is not locked. -*/ -xbBool xbIx::GetLocked() const { - return bLocked; -} - -/***********************************************************************/ -//! @brief Get the key count for number of keys on a node. -/*! - \param np Given node for key count. - \returns Number of keys on the node. -*/ -xbInt32 xbIx::GetKeyCount( xbIxNode *np ) const { - // assumes the first four bytes of the block is a four byte number - // representing the number of keys contained on the block - return eGetInt32( np->cpBlockData ); -} -/***********************************************************************/ -//! @brief Get key data for a given key number. -/*! - \param np Given node for key retrieval. - \param iKeyNo Which key to pull. - \param iKeyItemLen Length of key plus pointers. - \returns Pointer to a given key. -*/ -char * xbIx::GetKeyData( xbIxNode *np, xbInt16 iKeyNo, xbInt16 iKeyItemLen ) const { - if( !np ) return NULL; - char *p = np->cpBlockData; - xbUInt32 ulKeyCnt = eGetUInt32( p ); - if( iKeyNo < 0 || iKeyNo > (xbInt16) ulKeyCnt ) return NULL; - xbInt16 iOffset = 12 + (iKeyNo * iKeyItemLen); - p+=iOffset; - return p; -} -/***********************************************************************/ -//! @brief Get the next key for the current tag. -/*! - \returns Return Codes -*/ -xbInt16 xbIx::GetNextKey(){ - return GetNextKey( vpCurTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the next key for the given tag. -/*! - \param vpTag Tag for next key operation. - \returns Return Codes -*/ -xbInt16 xbIx::GetNextKey( void *vpTag ){ - return GetNextKey( vpTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the prev key for the current tag. -/*! - \returns Return Codes -*/ -xbInt16 xbIx::GetPrevKey(){ - return GetPrevKey( vpCurTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the previous key for the given tag. -/*! - \param vpTag Tag for previous key operation. - \returns Return Codes -*/ -xbInt16 xbIx::GetPrevKey( void *vpTag ){ - return GetPrevKey( vpTag, 0 ); -} -/***********************************************************************/ -//! @brief Free an index node -/*! - \param ixNode Pointer to index node to free. - \returns void -*/ -void xbIx::NodeFree( xbIxNode *ixNode ){ - if( ixNode ){ - if( ixNode->cpBlockData ){ - free( ixNode->cpBlockData ); - ixNode->cpBlockData = NULL; - } - free( ixNode ); - ixNode = NULL; - } -} -/***********************************************************************/ -//! @brief Open an index file. -/*! - MDX files are opened automatically and don't need opened. - NDX files that are associated with the DBF file are opened automatically. - - Non production indexes that haven't been opened will need to be opened to be used. - \param sFileName Index file name to open. - \returns Return Codes -*/ -xbInt16 xbIx::Open( const xbString & sFileName ){ - - // There are no locking requirements when opening an NDX index - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - /* copy the file name to the class variable */ - this->SetFileName( sFileName ); - - if( !FileExists()){ - iErrorStop = 100; - iRc = XB_FILE_NOT_FOUND; - throw iRc; - } - /* open the file */ - if(( iRc = xbFopen( dbf->GetOpenMode(), dbf->GetShareMode())) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if(( iRc = ReadHeadBlock()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - SetCurTag( (xbInt16) 0 ); // default the first tag as the current tag - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIx::Open( %s ) Exception Caught. Error Stop = [%d] iRc = [%d]", sFileName.Str(), iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Set the current tag. -/*! - \param vpCurTag Pointer to tag to set as current. - \returns void -*/ -void xbIx::SetCurTag( void *vpCurTag ){ - this->vpCurTag = vpCurTag; -} -/***********************************************************************/ -//! @brief Set the dbf pointer. -/*! - \param dbf Dbf pointer to set. - \returns void -*/ -void xbIx::SetDbf( xbDbf *dbf ){ - this->dbf = dbf; -} -/***********************************************************************/ -//! @brief Set the file lock status. -/*! - \param bLocked xbTrue - Set to locked.
xbFalse - Set to unlocked. - \returns void -*/ -void xbIx::SetLocked( xbBool bLocked ){ - this->bLocked = bLocked; -} -/***********************************************************************/ -} /* namespace */ -#endif /* XB_INDEX_SUPPORT */ -- cgit v1.2.3 From c894a7cdd8686ea695602a23a511a3f1b0d047be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Mon, 14 Aug 2023 21:07:46 +0200 Subject: New upstream version 4.1.4 --- src/core/xbixbase.cpp | 789 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 789 insertions(+) create mode 100755 src/core/xbixbase.cpp (limited to 'src/core/xbixbase.cpp') diff --git a/src/core/xbixbase.cpp b/src/core/xbixbase.cpp new file mode 100755 index 0000000..e2f929c --- /dev/null +++ b/src/core/xbixbase.cpp @@ -0,0 +1,789 @@ +/* xbixbase.cpp + +XBase64 Software Library + +Copyright (c) 1997,2003,2014,2022,2023 Gary A Kunkel + +The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. + +Email Contact: + + XDB-devel@lists.sourceforge.net + XDB-users@lists.sourceforge.net + + Base index class + +*/ + +#include "xbase.h" +#ifdef XB_INDEX_SUPPORT + +namespace xb{ + +/***********************************************************************/ +//! @brief Class constructor. +/*! + /param dbf Pointer to dbf instance. +*/ +xbIx::xbIx( xbDbf *dbf ) : xbFile( dbf->GetXbasePtr()) { + this->dbf = dbf; + vpCurTag = NULL; + cNodeBuf = NULL; + bLocked = xbFalse; +} +/***********************************************************************/ +//! @brief Class Destructor. +xbIx::~xbIx(){} + + +/***********************************************************************/ +//! @brief Add Keys for record number +/*! + For a given a record number, add keys to each tag in the index file + if it was updated + + \param ulRecNo Record number to add keys for + \returns Return Codes +*/ + +xbInt16 xbIx::AddKeys( xbUInt32 ulRecNo ){ + + xbInt16 iRc = XB_NO_ERROR; + xbInt16 iErrorStop = 0; + xbInt16 i = 0; + xbInt16 iKeySts; + + try{ + void * vpTag; + xbInt16 iTagCount = GetTagCount(); + + for( i = 0; i < iTagCount; i++ ){ + vpTag = GetTag( i ); + iKeySts = GetKeySts( vpTag ); + + if( iKeySts == 1 || iKeySts == 2 ){ + if(( iRc = UpdateTagKey( 'A', vpTag, ulRecNo )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbIx::AddKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); + xbase->WriteLogMessage( sMsg ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +/***********************************************************************/ +//! @brief Allocate memory for index node. +/*! + Allocate an index node. + + \param ulBufSize Size of buffer to allocate + \returns null on error
Pointer to newly allocated xbIxNode on success +*/ +xbIxNode * xbIx::AllocateIxNode( xbUInt32 ulBufSize, xbInt16 ) +{ + xbInt16 iRc = XB_NO_ERROR; + xbInt16 iErrorStop = 0; + + try{ + xbIxNode * pNode = (xbIxNode *) calloc( 1, sizeof( xbIxNode )); + if( pNode == NULL ){ + iErrorStop = 100; + iRc = XB_NO_MEMORY; + throw iRc; + } + if( ulBufSize == 0 ) + ulBufSize = GetBlockSize(); + + pNode->ulBufSize = ulBufSize; + pNode->cpBlockData = (char *) calloc( 1, ulBufSize ); + if( pNode->cpBlockData == NULL ){ + free( pNode ); + iErrorStop = 110; + iRc = XB_NO_MEMORY; + throw iRc; + } + return pNode; + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbIx::AllocateIxNode() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return NULL; +} + + +/***********************************************************************/ +//! @brief Binary search for given value on an index node. +/*! + + Binary search for key lookups + \param cKeyType Key type + \param npNode Pointer to index node for search + \param lKeyItemLen Lenth of key plus pointer values + \param vpKey Pointer to key value + \param lSearchKeyLen length of key to search + \param iCompRc output return code from the CompareKey routine. CompareKey returns an + integer value less than, equal to or greater than zero in when comparing values + + \param bDescending xbTrue for descending index key lookup.
+ xbFalse for ascending index key lookup. + \return The position in the node the key was found, if multiples it returns the first occurrence. + If the key is not found, it returns the slot it should be in. +*/ + +xbInt16 xbIx::BSearchBlock( char cKeyType, xbIxNode *npNode, xbInt32 lKeyItemLen, const void *vpKey, + xbInt32 lSearchKeyLen, xbInt16 &iCompRc, xbBool bDescending ) const { + xbInt32 lLo = 0; + xbInt32 lHi = 0; + xbInt32 lMid = 0; + xbInt32 lKeyCnt = GetKeyCount( npNode ); + + + if( !bDescending ){ + lHi = lKeyCnt - 1; + + while( lLo <= lHi ){ + lMid = (lLo + lHi) / 2; + iCompRc = CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); + if( iCompRc > 0 ) + lHi = lMid - 1; + else if( iCompRc < 0 ) + lLo = lMid + 1; + else{ // found match, look for leftmost occurrence + + xbInt32 lFoundPos = lMid; + lMid--; + while( lMid >= 0 && CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ) == 0 ){ + lFoundPos = lMid; + lMid--; + } + iCompRc = 0; + lLo = lFoundPos; + lHi = -1; + } + } + // update the compare key results + if( lMid != lLo ){ + if( lLo >= lKeyCnt ) + iCompRc = 1; + else + iCompRc = CompareKey( cKeyType, GetKeyData( npNode, lLo, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); + } + return (xbInt16) lLo; + + } else { // descending key + + lLo = lKeyCnt - 1; + while( lLo >= lHi && lHi != -1 ){ + lMid = (lLo + lHi) / 2; + iCompRc = CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); + + if( iCompRc > 0 ) { + lHi = lMid + 1; + } + else if( iCompRc < 0) { + lLo = lMid - 1; + } + else{ // found match, look for leftmost occurrence + + xbInt32 lFoundPos = lMid; + lMid--; + while( lMid >= 0 && CompareKey( cKeyType, GetKeyData( npNode, lMid, lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ) == 0 ){ + lFoundPos = lMid; + lMid--; + } + iCompRc = 0; + lHi = lFoundPos; + lLo = -1; + } + } + + // std::cout << "BSB1 lo = " << lLo << " mid = " << lMid << " hi = " << lHi << " keycnt = " << lKeyCnt << " iCompRc = " << iCompRc << "\n"; // key=" << (char *) vpKey << "\n"; + if( lLo < 0 && iCompRc < 0 ) + iCompRc = 1; + else if( iCompRc != 0 ) { + iCompRc = CompareKey( cKeyType, GetKeyData( npNode, (lLo < 0 ? 0 : lLo), lKeyItemLen ), vpKey, (size_t) lSearchKeyLen ); + } + // std::cout << "BSB2 lo = " << lLo << " mid = " << lMid << " hi = " << lHi << " keycnt = " << lKeyCnt << " iCompRc = " << iCompRc << "\n"; // key=" << (char *) vpKey << "\n"; + return (xbInt16) lHi; + } + + // should never get here + // return (xbInt16) 0; +} + +/***********************************************************************/ +//! @brief Check for duplicate keys. +/*! + \returns Return Codes +*/ +xbInt16 xbIx::CheckForDupKeys(){ + + xbInt16 iRc = XB_NO_ERROR; + xbInt16 iErrorStop = 0; + xbInt16 i = 0; + + try{ + void * vpTag; + xbInt16 iTagCount = GetTagCount(); + for( i = 0; i < iTagCount; i++ ){ + vpTag = GetTag( i ); + if(( iRc = CheckForDupKey( vpTag )) < XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + } + catch (xbInt16 iRc ){ + if( iRc != XB_KEY_NOT_UNIQUE ){ + xbString sMsg; + sMsg.Sprintf( "xbIxBase::CheckForDupKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); + xbase->WriteLogMessage( sMsg ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + } + return iRc; +} +/***********************************************************************/ +//! @brief Close index file. +/*! + \returns Return Codes +*/ + +xbInt16 xbIx::Close(){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + if(( iRc = xbFclose()) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbIx::Close() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +/***********************************************************************/ +//! @brief Compare keys. +/*! + \param cKeyType C - Character compare.
+ N - Numeric BCD compare.
+ D - Numeric compare.
+ F - Numeric compare.
+ \param v1 Left compare.
v2 - Right Compare. + \param iSearchKeyLen Length of key compare. + \returns 1 - Left operand is greater then right operand.
+ 0 - Left operand is equal to right operand.
+ -1 - Left operand is less than right operand. +*/ +inline xbInt16 xbIx::CompareKey( char cKeyType, const void *v1, const void *v2, size_t iSearchKeyLen ) const{ + if( cKeyType == 'C' ){ // character compare + return memcmp( v1, v2, iSearchKeyLen ); + } else if( cKeyType == 'N' ){ // numeric bcd compare, mdx bcd numeric indices + xbBcd bcdk1( v1 ); + return bcdk1.Compare( v2 ); + } else if( cKeyType == 'D' || cKeyType == 'F' ){ // julian date compare, ndx float numeric indices + xbDouble *d1 = (xbDouble *) v1; + xbDouble *d2 = (xbDouble *) v2; + if( *d1 < *d2 ) + return -1; + else if( *d1 > *d2 ) + return 1; + else + return 0; + } else { +// std::cout << "Unhandled key type [" << cKeyType << "]\n"; + } + return XB_NO_ERROR; +} +/***********************************************************************/ +//! @brief Create Keys for record number +/*! + \param iOpt 0 Build a key for FindKey usage, only rec buf 0.
+ 1 Append Mode, Create key for an append, only use rec buf 0, set updated switch.
+ 2 Update Mode, Create old version and new version keys, check if different, set update switch appropriately. + \returns Return Codes +*/ +xbInt16 xbIx::CreateKeys( xbInt16 iOpt ) { + xbInt16 iRc = XB_NO_ERROR; + xbInt16 iErrorStop = 0; + xbInt16 i = 0; + + try{ + void * vpTag; + xbInt16 iTagCount = GetTagCount(); + + for( i = 0; i < iTagCount; i++ ){ + vpTag = GetTag( i ); + if(( iRc = CreateKey( vpTag, iOpt )) < XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbIx::CreateKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return XB_NO_ERROR; +} +/***********************************************************************/ +//! @brief Delete keys for record number +/*! + Delete keys to each tag in the index file if it was updated as determined + by CreateKeys function + + \returns Return Codes +*/ +//xbInt16 xbIx::DeleteKeys( xbUInt32 ulRecNo ){ + +xbInt16 xbIx::DeleteKeys(){ + + xbInt16 iRc = XB_NO_ERROR; + xbInt16 iErrorStop = 0; + xbInt16 i = 0; + + try{ + void * vpTag; + xbInt16 iTagCount = GetTagCount(); + + for( i = 0; i < iTagCount; i++ ){ + vpTag = GetTag( i ); + if( GetKeySts( vpTag ) > 1 ){ // 0 = no update 1 = add 2 = update, 3 = delete + if(( iRc = UpdateTagKey( 'D', vpTag )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbIx::DeleteKeys() Exception Caught. Error Stop = [%d] iRc = [%d] Tag=[%d]", iErrorStop, iRc, i ); + xbase->WriteLogMessage( sMsg ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +/***********************************************************************/ +#ifdef XB_DEBUG_SUPPORT +//! @brief Dump anode for debug purposes. +/*! + \param pNode Pointer to node to dump. + \param iOption 0 = stdout
+ 1 = Syslog
+ 2 = Both
+ \returns Return Codes +*/ + +xbInt16 xbIx::DumpNode( void *, xbIxNode *pNode, xbInt16 iOption ) const +{ + xbString s; + s.Sprintf( "Dump Node Block=[%d] CurKey=[%d]", pNode->ulBlockNo, pNode->iCurKeyNo ); + xbase->WriteLogMessage( s, iOption ); + + return XB_NO_ERROR; +} +#endif // XB_DEBUG_SUPPORT + +/***********************************************************************/ +//! @brief Find double key +/*! + \param vpTag Pointer to tag to search. + \param dKey Double value to search for. + \param iRetrieveSw xbTrue - Retrieve the record if key found.
+ xbFalse - Don't retrieve record, check for key existence only. + \returns XB_NO_ERROR - Key found.
+ XB_NOT_FOUND - Key not found.
+ Return Codes +*/ +xbInt16 xbIx::FindKey( void *vpTag, xbDouble dKey, xbInt16 iRetrieveSw ){ + return FindKey( vpTag, &dKey, 8, iRetrieveSw ); +} +/***********************************************************************/ +//! @brief Find string key +/*! + \param vpTag Pointer to tag to search. + \param sKey String data to search for. + \param iRetrieveSw xbTrue - Retrieve the record if key found.
+ xbFalse - Don't retrieve record, check for key existence only. + \returns XB_NO_ERROR - Key found.
+ XB_NOT_FOUND - Key not found.
+ Return Codes +*/ +xbInt16 xbIx::FindKey( void *vpTag, const xbString &sKey, xbInt16 iRetrieveSw ){ + return FindKey( vpTag, sKey.Str(), (xbInt32) sKey.Len(), iRetrieveSw ); +} +/***********************************************************************/ +//! @brief Find character key +/*! + \param vpTag Pointer to tag to search. + \param cKey String data to search for. + \param lKeyLen Length of key to search for. + \param iRetrieveSw xbTrue - Retrieve the record if key found.
+ xbFalse - Don't retrieve record, check for key existence only. + \returns XB_NO_ERROR - Key found.
+ XB_NOT_FOUND - Key not found.
+ Return Codes +*/ +xbInt16 xbIx::FindKey( void *vpTag, const char *cKey, xbInt32 lKeyLen, xbInt16 iRetrieveSw ){ + return FindKey( vpTag, (void *) cKey, lKeyLen, iRetrieveSw ); +} +/***********************************************************************/ +//! @brief Find bcd key +/*! + \param vpTag Pointer to tag to search. + \param bcd BCD data to search for. + \param iRetrieveSw xbTrue - Retrieve the record if key found.
+ xbFalse - Don't retrieve record, check for key existence only. + + \returns XB_NO_ERROR - Key found.
+ XB_NOT_FOUND - Key not found.
+ Return Codes +*/ +xbInt16 xbIx::FindKey( void *vpTag, const xbBcd &bcd, xbInt16 iRetrieveSw ){ + return FindKey( vpTag, bcd.GetBcd(), 12, iRetrieveSw ); +} +/***********************************************************************/ +//! @brief Find date key +/*! + \param vpTag Pointer to tag to search. + \param dtKey Date data to search for. + \param iRetrieveSw xbTrue - Retrieve the record if key found.
+ xbFalse - Don't retrieve record, check for key existence only. + \returns XB_NO_ERROR - Key found.
+ XB_NOT_FOUND - Key not found.
+ Return Codes +*/ +xbInt16 xbIx::FindKey( void *vpTag, const xbDate &dtKey, xbInt16 iRetrieveSw ){ + xbDouble d = (xbDouble) dtKey.JulianDays(); + return FindKey( vpTag, &d, 8, iRetrieveSw ); +} +/***********************************************************************/ +//! @brief Free all nodes in a linked list. +/*! + \param np Pointer to first node in linked list to free. + \returns NULL. +*/ +xbIxNode *xbIx::FreeNodeChain( xbIxNode *np ){ + + // routine returns NULL + if( np ){ + // free memory for a given chain of nodes + xbIxNode * np2; + + // Clear the previous node's next pointer + if( np->npPrev ) + np->npPrev->npNext = NULL; + + // Clear out the tree + while( np ){ + np2 = np->npNext; + NodeFree( np ); + np = NULL; + np = np2; + } + } + return NULL; +} +/***********************************************************************/ +//! @brief Read block for block number. +/*! + Routine to read a node/block out of an index file and store in xbIxNode structure + \param vpTag Pointer to tag. + \param ulBlockNo Block number to read off disk. + \param iOpt + 0 = Node is read into block buffer, not added to the node chain
+ 1 = Node is read into new xbIxNode, then added to the node chain, and sets CurNode with new node
+ 2 = Node is read into new xbIxNode, not added to the node chain
+ CurNode points to new node
+ \param ulAddlBuf Additional buffer size added to memory + \returns Return Codes + +*/ + +xbInt16 xbIx::GetBlock( void *vpTag, xbUInt32 ulBlockNo, xbInt16 iOpt, xbUInt32 ulAddlBuf ){ + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + xbIxNode *np = NULL; + try{ + + if( !vpTag && iOpt == 1 ){ + iErrorStop = 100; + throw iRc; + } + + // set target location of block read to read + char *cp; + if( iOpt == 0 ) + cp = cNodeBuf; + else{ + if(( np = AllocateIxNode(GetBlockSize() + ulAddlBuf )) == NULL ){ + iErrorStop = 110; + iRc = XB_NO_MEMORY; + throw( iRc ); + } + cp = np->cpBlockData; + } + if(( iRc = ReadBlock( ulBlockNo, GetBlockSize(), cp )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + if( iOpt == 0 ) + return iRc; + np->ulBlockNo = ulBlockNo; + np->iCurKeyNo = 0; + if( iOpt == 1 ) + AppendNodeChain( vpTag, np ); + else if( iOpt == 2 ){ + std::cout << "Future use stub. xbIxbase::GetBlock() option 2 not coded.\n"; + iErrorStop = 130; + iRc = XB_INVALID_OPTION; + throw iRc; + // SetCurNode( vpTag, np ); + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbIx::GetBlock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + if( np ) NodeFree( np ); + } + return iRc; +} + +/***********************************************************************/ +//! @brief Get pointer to current tag. +/*! + \returns Pointer to current tag. +*/ + +void *xbIx::GetCurTag() const { + return vpCurTag; +} +/***********************************************************************/ +//! @brief Get pointer to dbf. +/*! + \returns Pointer to dbf. +*/ +xbDbf *xbIx::GetDbf() const { + return this->dbf; +} +/***********************************************************************/ +//! @brief Get the first key for the current tag. +/*! + \returns Return Codes +*/ +xbInt16 xbIx::GetFirstKey(){ + return GetFirstKey( vpCurTag, 0 ); +} + +/***********************************************************************/ +//! @brief Get the first key for a given tag. +/*! + \param vpTag Tag for get first key operation. + \returns Return Codes +*/ +xbInt16 xbIx::GetFirstKey( void *vpTag ){ + return GetFirstKey( vpTag, 0 ); +} +/***********************************************************************/ +//! @brief Get the last key for the current tag. +/*! + \returns Return Codes +*/ +xbInt16 xbIx::GetLastKey(){ + return GetLastKey( 0, vpCurTag, 0 ); +} +/***********************************************************************/ +//! @brief Get the last key for a given tag. +/*! + \param vpTag Tag for get last key operation. + \returns Return Codes +*/ +xbInt16 xbIx::GetLastKey( void *vpTag ){ + return GetLastKey( 0, vpTag, 0 ); +} + +/***********************************************************************/ +//! @brief Get the file lock status. +/*! + \returns xbTrue - Index file is locked.
xbFalse - Index file is not locked. +*/ +xbBool xbIx::GetLocked() const { + return bLocked; +} + +/***********************************************************************/ +//! @brief Get the key count for number of keys on a node. +/*! + \param np Given node for key count. + \returns Number of keys on the node. +*/ +xbInt32 xbIx::GetKeyCount( xbIxNode *np ) const { + // assumes the first four bytes of the block is a four byte number + // representing the number of keys contained on the block + return eGetInt32( np->cpBlockData ); +} +/***********************************************************************/ +//! @brief Get key data for a given key number. +/*! + \param np Given node for key retrieval. + \param iKeyNo Which key to pull. + \param iKeyItemLen Length of key plus pointers. + \returns Pointer to a given key. +*/ +char * xbIx::GetKeyData( xbIxNode *np, xbInt16 iKeyNo, xbInt16 iKeyItemLen ) const { + if( !np ) return NULL; + char *p = np->cpBlockData; + xbUInt32 ulKeyCnt = eGetUInt32( p ); + if( iKeyNo < 0 || iKeyNo > (xbInt16) ulKeyCnt ) return NULL; + xbInt16 iOffset = 12 + (iKeyNo * iKeyItemLen); + p+=iOffset; + return p; +} +/***********************************************************************/ +//! @brief Get the next key for the current tag. +/*! + \returns Return Codes +*/ +xbInt16 xbIx::GetNextKey(){ + return GetNextKey( vpCurTag, 0 ); +} +/***********************************************************************/ +//! @brief Get the next key for the given tag. +/*! + \param vpTag Tag for next key operation. + \returns Return Codes +*/ +xbInt16 xbIx::GetNextKey( void *vpTag ){ + return GetNextKey( vpTag, 0 ); +} +/***********************************************************************/ +//! @brief Get the prev key for the current tag. +/*! + \returns Return Codes +*/ +xbInt16 xbIx::GetPrevKey(){ + return GetPrevKey( vpCurTag, 0 ); +} +/***********************************************************************/ +//! @brief Get the previous key for the given tag. +/*! + \param vpTag Tag for previous key operation. + \returns Return Codes +*/ +xbInt16 xbIx::GetPrevKey( void *vpTag ){ + return GetPrevKey( vpTag, 0 ); +} +/***********************************************************************/ +//! @brief Free an index node +/*! + \param ixNode Pointer to index node to free. + \returns void +*/ +void xbIx::NodeFree( xbIxNode *ixNode ){ + if( ixNode ){ + if( ixNode->cpBlockData ){ + free( ixNode->cpBlockData ); + ixNode->cpBlockData = NULL; + } + free( ixNode ); + ixNode = NULL; + } +} +/***********************************************************************/ +//! @brief Open an index file. +/*! + MDX files are opened automatically and don't need opened. + NDX files that are associated with the DBF file are opened automatically. + + Non production indexes that haven't been opened will need to be opened to be used. + \param sFileName Index file name to open. + \returns Return Codes +*/ +xbInt16 xbIx::Open( const xbString & sFileName ){ + + // There are no locking requirements when opening an NDX index + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + /* copy the file name to the class variable */ + this->SetFileName( sFileName ); + + if( !FileExists()){ + iErrorStop = 100; + iRc = XB_FILE_NOT_FOUND; + throw iRc; + } + /* open the file */ + if(( iRc = xbFopen( dbf->GetOpenMode(), dbf->GetShareMode())) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + if(( iRc = ReadHeadBlock()) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + SetCurTag( (xbInt16) 0 ); // default the first tag as the current tag + } + + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbIx::Open( %s ) Exception Caught. Error Stop = [%d] iRc = [%d]", sFileName.Str(), iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} +/***********************************************************************/ +//! @brief Set the current tag. +/*! + \param vpCurTag Pointer to tag to set as current. + \returns void +*/ +void xbIx::SetCurTag( void *vpCurTag ){ + this->vpCurTag = vpCurTag; +} +/***********************************************************************/ +//! @brief Set the dbf pointer. +/*! + \param dbf Dbf pointer to set. + \returns void +*/ +void xbIx::SetDbf( xbDbf *dbf ){ + this->dbf = dbf; +} +/***********************************************************************/ +//! @brief Set the file lock status. +/*! + \param bLocked xbTrue - Set to locked.
xbFalse - Set to unlocked. + \returns void +*/ +void xbIx::SetLocked( xbBool bLocked ){ + this->bLocked = bLocked; +} +/***********************************************************************/ +} /* namespace */ +#endif /* XB_INDEX_SUPPORT */ -- cgit v1.2.3