diff options
Diffstat (limited to 'src/core')
-rwxr-xr-x | src/core/xbbcd.cpp | 5 | ||||
-rwxr-xr-x | src/core/xbblockread.cpp | 271 | ||||
-rwxr-xr-x | src/core/xbdbf.cpp | 154 | ||||
-rwxr-xr-x | src/core/xbdbf3.cpp | 8 | ||||
-rwxr-xr-x | src/core/xbdbf4.cpp | 19 | ||||
-rwxr-xr-x | src/core/xbexp.cpp | 31 | ||||
-rwxr-xr-x | src/core/xbfile.cpp | 286 | ||||
-rwxr-xr-x | src/core/xbfilter.cpp | 50 | ||||
-rwxr-xr-x | src/core/xbixmdx.cpp | 50 | ||||
-rwxr-xr-x | src/core/xbixndx.cpp | 3 | ||||
-rwxr-xr-x | src/core/xblog.cpp | 4 | ||||
-rwxr-xr-x | src/core/xbssv.cpp | 111 | ||||
-rwxr-xr-x | src/core/xbstring.cpp | 71 | ||||
-rwxr-xr-x | src/core/xbtblmgr.cpp | 85 | ||||
-rwxr-xr-x | src/core/xbxbase.cpp | 54 |
15 files changed, 998 insertions, 204 deletions
diff --git a/src/core/xbbcd.cpp b/src/core/xbbcd.cpp index ff64110..f86e74f 100755 --- a/src/core/xbbcd.cpp +++ b/src/core/xbbcd.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +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. @@ -268,7 +268,6 @@ xbInt16 xbBcd::Compare( const xbBcd &bcdIn ){ return -1; } - /***********************************************************************/ unsigned char xbBcd::GetEncDigitsNoSign() const { unsigned char c = bcd.cEncDigits << 1; @@ -277,7 +276,7 @@ unsigned char xbBcd::GetEncDigitsNoSign() const { /***********************************************************************/ unsigned xbBcd::GetSign() const { //return bcd.Sign; - return bcd.cEncDigits >> 7; + return (unsigned) bcd.cEncDigits >> 7; } /***********************************************************************/ unsigned xbBcd::GetSigDigits() const { diff --git a/src/core/xbblockread.cpp b/src/core/xbblockread.cpp new file mode 100755 index 0000000..09076b1 --- /dev/null +++ b/src/core/xbblockread.cpp @@ -0,0 +1,271 @@ +/* xbblockread.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 + +This module handles block read methods. Block reading is used for performance improvement +during sequential access processing. + +*/ + +#include "xbase.h" + +#ifdef XB_BLOCKREAD_SUPPORT + +namespace xb{ + +/************************************************************************/ +xbBlockRead::xbBlockRead( xbDbf * d ) { + pBlock = NULL; + ulBlkSize = 0; + ulFirstBlkRec = 0; + ulRecCnt = 0; + ulMaxRecs = 0; + bEof = xbFalse; + this->dbf = d; + tFmTime = 0; +} +/************************************************************************/ +xbBlockRead::~xbBlockRead(){ + if( pBlock ){ + free( pBlock ); + pBlock = NULL; + } +} + +/************************************************************************/ +//! @brief Dump read block internals to stdout. +/*! + Dump the current read block internals to stdout. +*/ + + +#ifdef XB_DEBUG_SUPPORT +void xbBlockRead::DumpReadBlockInternals(){ + std::cout << "------- DumpBlockInternals ---------" << std::endl; + std::cout << "Dflt Blk Size = [" << dbf->GetXbasePtr()->GetDefaultBlockReadSize() + << "]" << std::endl; + std::cout << "Dbf Record Count = [" << dbf->GetRecordCount() << "]" << std::endl; + std::cout << "Dbf Record Len = [" << dbf->GetRecordLen() << "]" << std::endl; + std::cout << "ulBlkSize = [" << ulBlkSize << "]" << std::endl; + std::cout << "ulMaxRecs = [" << ulMaxRecs << "]" << std::endl; + std::cout << "ulFirstBlkRec = [" << ulFirstBlkRec << "]" << std::endl; + std::cout << "ulRecCnt = [" << ulRecCnt << "]" << std::endl; + std::cout << "bEof = [" << bEof << "]" << std::endl; +} +#endif // XB_DEBUG_SUPPORT +/************************************************************************/ +//! @brief Get the first record number in the current block. +/*! + Retrieve the first record numer in the current block.<br> + + \returns First record number in the current block. +*/ + +xbUInt32 xbBlockRead::GetBlockFirstRecNo() const{ + return ulFirstBlkRec; +} +/************************************************************************/ +//! @brief Get record for specified record number. +/*! + Retrieve a record from read block buffer and copy it into the record buffer. + If the current record is not in the current block, the routine calls + GetBlockForRecNo to load the currect block from disk.<br><br> + For performance reasons, this method assumes a valid record number has been + passed.<br><br> + + \param ulRecNo - Record number to retrieve. + \returns <a href="xbretcod_8h.html">Return Codes</a> +*/ + +xbInt16 xbBlockRead::GetRecord( xbUInt32 ulRecNo ){ + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + // std::cout << "xbBlockRead::GetRecord( " << ulRecNo << ")\n"; + + try{ + if( !( ulRecNo >= ulFirstBlkRec && ulRecNo < (ulFirstBlkRec + ulRecCnt))){ + if(( iRc = GetBlockForRecNo( ulRecNo )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } + char *s = pBlock; + s += (ulRecNo - ulFirstBlkRec) * dbf->GetRecordLen(); + char *t = dbf->RecBuf; + xbUInt32 ulRecLen = dbf->GetRecordLen(); + for( xbUInt32 l = 0; l < ulRecLen; l++ ){ + *t = *s; + t++; + s++; + } + dbf->ulCurRec = ulRecNo; + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbBlockRead::GetBlockForRecNo() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); + } + return iRc; +} + +/************************************************************************/ +//! @brief Get record for specified record number. +/*! + Retrieve a block containing specified record. This routine calculates the + correct block in the DBF file, updates the internal block fields and retrieves + the block of records from disk and loads into the block buffer.<br><br> + + \param ulRecNo - Record number to retrieve. + \returns <a href="xbretcod_8h.html">Return Codes</a> +*/ + +xbInt16 xbBlockRead::GetBlockForRecNo( xbUInt32 ulRecNo ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + xbUInt32 ulDbfRecCnt = dbf->GetRecordCount(); + + // calc to determine block number for the requested record, 0 based offset + xbUInt32 ulBlockNo = (xbUInt32)(ulRecNo / ulMaxRecs); + if( ulRecNo % ulMaxRecs == 0 ) ulBlockNo--; + + // calc the first record + ulFirstBlkRec = (ulBlockNo * ulMaxRecs); + + // calc the record count + if(( ulFirstBlkRec + ulMaxRecs) > ulDbfRecCnt ){ + ulRecCnt = ulDbfRecCnt - ulFirstBlkRec; + bEof = xbTrue; + } else { + ulRecCnt = ulMaxRecs; + bEof = xbFalse; + } + + // position accordingly + xbInt64 ulStartPos = dbf->GetHeaderLen() + ((xbInt64) ulFirstBlkRec * dbf->GetRecordLen()); + if(( dbf->xbFseek( ulStartPos, SEEK_SET )) != XB_NO_ERROR ){ + iErrorStop = 110; + iRc = XB_SEEK_ERROR; + throw iRc; + } + + if(( dbf->GetFileMtime( tFmTime )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + // read it + if(( dbf->xbFread( (void *) pBlock, ulRecCnt * dbf->GetRecordLen(), 1 )) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + + ulFirstBlkRec++; // zero offset in the routine, regular record number from ths point forward + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbBlockRead::GetBlockForRecNo() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); + } + return iRc; +} + + +/************************************************************************/ +//! @brief Get the current block size. +/*! + Retrieve the current block size.<br><br> + + \returns Current Block Size. +*/ + +xbUInt32 xbBlockRead::GetBlockSize() const{ + return ulBlkSize; +} + +/************************************************************************/ +//! @brief Get the current block record count. +/*! + Retrieve the current number of records loaded in the block.<br><br> + + \returns Current Block Size. +*/ + +xbUInt32 xbBlockRead::GetBlockRecCnt() const { + return ulRecCnt; +} + +/************************************************************************/ +//! @brief Init the block processing for a iven DBF file. +/*! + Initialize the settings for a given DBF file.<br> + This routine may adjust the block size as needed to eliminate unused + memory or adjust it bigger if too small. + + \param ulRecNo - ulBlockSize - Block size to allocate. If 0 or missing, it uses default block size of 32K. + \returns <a href="xbretcod_8h.html">Return Codes</a> +*/ + +xbInt16 xbBlockRead::Init(xbUInt32 ulBlockSize ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + + // calculate the block size + if( ulBlockSize == 0 ) + ulBlkSize = dbf->GetXbasePtr()->GetDefaultBlockReadSize(); + + // if not big enough to handle more than one record, bump it up to something meaningful + if( ulBlkSize < (xbUInt32)(dbf->GetRecordLen() * 2 )) + ulBlkSize = (xbUInt32) dbf->GetRecordLen() * 10; + + ulMaxRecs = (xbUInt32) ulBlkSize / dbf->GetRecordLen(); + ulBlkSize = ulMaxRecs * dbf->GetRecordLen(); + + // allocate memory for the block + if(( pBlock = (char *) calloc( 1, ulBlkSize )) == NULL ){ + iErrorStop = 100; + throw iRc; + } + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbBlockRead::Init() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); + } + return iRc; +} + +/************************************************************************/ +//! @brief Set the block size. +/*! + St block size for this DBF file.<br>. + + \param ulBlkSize - Block Size. + \returns XB_NO_ERROR +*/ + +xbInt16 xbBlockRead::SetBlockSize( xbUInt32 ulBlkSize ){ + this->ulBlkSize = ulBlkSize; + return XB_NO_ERROR; +} + +/************************************************************************/ +} /* namespace */ +#endif /* XB_BLOCKREAD_SUPPORT */
\ No newline at end of file diff --git a/src/core/xbdbf.cpp b/src/core/xbdbf.cpp index 3d13369..4033ef9 100755 --- a/src/core/xbdbf.cpp +++ b/src/core/xbdbf.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +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. @@ -24,10 +24,16 @@ namespace xb{ \param x Pointer to xbXbase */ xbDbf::xbDbf( xbXBase * x ) : xbFile( x ){ - xbase = x; - SchemaPtr = NULL; - RecBuf = NULL; - RecBuf2 = NULL; + xbase = x; + SchemaPtr = NULL; + RecBuf = NULL; + RecBuf2 = NULL; + + #ifdef XB_BLOCKREAD_SUPPORT + pRb = NULL; + bBlockReadEnabled = xbFalse; // batch read switch, if xbTrue, then ON + #endif // XB_BLOCKREAD_SUPPORT + InitVars(); } /************************************************************************/ @@ -77,7 +83,7 @@ void xbDbf::InitVars() #ifdef XB_INF_SUPPORT llInfData.Clear(); - #endif // XB_INF_SUPPORT + #endif // XB_INF_SUPPORT } /************************************************************************/ @@ -104,6 +110,16 @@ xbDbf::~xbDbf(){ free( RecBuf2 ); RecBuf2 = NULL; } + if( RecBuf ){ + free( RecBuf ); + RecBuf = NULL; + } + + #ifdef XB_BLOCKREAD_SUPPORT + if( bBlockReadEnabled ) + DisableBlockReadProcessing(); + #endif // XB_BLOCKREAD_SUPPORT + Close(); } /************************************************************************/ @@ -1952,6 +1968,18 @@ xbInt16 xbDbf::GetFirstKey(){ } /************************************************************************/ +//! @brief GetHeaderLen for dbf +/*! + + Returns the length of the header portion of the dbf file + \returns Length of header protion of dbf file + +*/ +xbUInt16 xbDbf::GetHeaderLen() const { + return uiHeaderLen; +} + +/************************************************************************/ //! @brief GetLastKey for tag. /*! @@ -2054,6 +2082,32 @@ xbInt16 xbDbf::Find( xbDouble &dKey ){ #endif // XB_INDEX_SUPPORT /************************************************************************/ +//! @brief Return true if dbf file empty or positioned to the first record +/*! + \returns Returns true if dbf file is empty or positioned on the first record. +*/ +xbBool xbDbf::GetBof() { +/* + if( GetRecordCount() == 0 || GetCurRecNo() == 1 ) + return xbTrue; + else + */ + return xbFalse; +} +/************************************************************************/ +//! @brief Return true if dbf file empty or positioned to the last record +/*! + \returns Returns true if dbf file is empty or positioned on the last record. +*/ +xbBool xbDbf::GetEof() { + xbUInt32 ulRecCnt = GetRecordCount(); + + if( ulRecCnt == 0 || GetCurRecNo() == ulRecCnt ) + return xbTrue; + else + return xbFalse; +} +/************************************************************************/ //! @brief Return the current record number. /*! \returns Returns the current record number. @@ -2428,15 +2482,23 @@ xbInt16 xbDbf::GetRecord( xbUInt32 ulRecNo ){ iErrorStop = 120; throw iRc; } - } - } + } + } + + // std::cout << "xbdbf::GetRecord: " << ulRecNo << " " << ulNoOfRecs << "\n"; if( ulRecNo > ulNoOfRecs || ulRecNo == 0L ){ iErrorStop = 130; iRc = XB_INVALID_RECORD; throw iRc; } + #ifdef XB_BLOCKREAD_SUPPORT + if( bBlockReadEnabled ) + return pRb->GetRecord( ulRecNo ); + #endif // XB_BLOCK_READ_SUPPORT + + if(( xbFseek( (uiHeaderLen+(( (xbInt64) ulRecNo-1L ) * uiRecordLen )), SEEK_SET )) != XB_NO_ERROR ){ iErrorStop = 140; iRc = XB_SEEK_ERROR; @@ -2475,9 +2537,6 @@ char * xbDbf::GetRecordBuf( xbInt16 iOpt ) const { return RecBuf; } - - - /************************************************************************/ //! @brief Get the current number of records in the dbf data file. /*! @@ -3211,12 +3270,12 @@ xbInt16 xbDbf::Open( const xbString & sTableName, const xbString & sAlias ){ xbLinkListNode<xbString> * llN = llInfData.GetHeadNode(); for( xbUInt32 i = 0; i < llNodeCnt; i++ ){ s2 = llN->GetKey(); - #ifdef XB_NDX_SUPPORT + #ifdef XB_NDX_SUPPORT if(( iRc = OpenIndex( "NDX", s2 )) != XB_NO_ERROR ){ iErrorStop = 120; throw iRc ; } - #endif // XB_NDX_SUPPORT + #endif // XB_NDX_SUPPORT llN = llN->GetNextNode(); } } @@ -3270,7 +3329,6 @@ xbInt16 xbDbf::OpenIndex( const xbString &sIxType, const xbString &sFileName ){ #ifdef XB_MDX_SUPPORT } else if( sType == "MDX" ){ - pIx = new xbIxMdx( this ); if(( iRc = pIx->Open( sFileName )) != XB_NO_ERROR ){ iErrorStop = 120; @@ -4209,4 +4267,72 @@ xbInt16 xbDbf::Zap(){ return iRc; } /************************************************************************/ +#ifdef XB_BLOCKREAD_SUPPORT +// block read processing is designed to provide a way to rapidly retrieve +// all the records from a .DBF file in sequential order. + +// It is not designed for doing any read/write processing or data retrieval based on a tag sort. +// It is designed for doing a fast sequentil block read out of a table + + +xbInt16 xbDbf::DisableBlockReadProcessing(){ + + if( bBlockReadEnabled ){ + bBlockReadEnabled = xbFalse; + delete pRb; + pRb = NULL; + } + return XB_NO_ERROR; +} + +xbBool xbDbf::GetBlockReadStatus() const { + return bBlockReadEnabled; +} + +xbInt16 xbDbf::EnableBlockReadProcessing(){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + try{ + + if( !bBlockReadEnabled ){ + if( iDbfStatus == XB_UPDATED ){ + if( GetAutoCommit() == 1 ){ + if(( iRc = Commit()) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + } else { + if(( iRc = Abort()) != XB_NO_ERROR ){ + iErrorStop = 110; + throw iRc; + } + } + } + pRb = new xbBlockRead( this ); + if( !pRb ){ + iErrorStop = 120; + iRc = XB_NO_MEMORY; + throw iRc; + } + if(( iRc = pRb->Init()) != XB_NO_ERROR ){ + iErrorStop = 130; + throw iRc; + } + + bBlockReadEnabled = xbTrue; + } + + } catch( xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbdbf::EnableBlockReadProcessing() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +#endif // XB_BLOCKREAD_SUPPORT +/************************************************************************/ } /* namespace */
\ No newline at end of file diff --git a/src/core/xbdbf3.cpp b/src/core/xbdbf3.cpp index 504542f..d57be3c 100755 --- a/src/core/xbdbf3.cpp +++ b/src/core/xbdbf3.cpp @@ -261,7 +261,7 @@ xbInt16 xbDbf3::CreateTable( const xbString & sTableName, const xbString & sAlia catch( xbInt16 rc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf3::CreateTable() Exception Caught Error Stop = %d rc = %d", iErrorStop, rc ); + sMsg.Sprintf( "xbdbf3::CreateTable() Exception Caught Error Stop = [%d] rc = [%d]", iErrorStop, rc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( rc )); @@ -453,7 +453,7 @@ xbInt16 xbDbf3::Open( const xbString & sTableName, const xbString & sAlias, catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf3::Open() Exception Caught Error Stop = %d iRc = %d ShareMode = %d OpenMode = %d", iErrorStop, iRc, iShareMode, iOpenMode ); + sMsg.Sprintf( "xbdbf3::Open() Exception Caught Error Stop = [%d] iRc = [%d] ShareMode = [%d] OpenMode = [%d]", iErrorStop, iRc, iShareMode, iOpenMode ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); xbFclose(); @@ -623,14 +623,14 @@ xbInt16 xbDbf3::Rename( const xbString sNewName ){ xbTblList *tle = xbase->GetTblListEntry( this ); if( tle ){ // std::cout << "setting [" << GetFqFileName().Str() << "][" << sNewNameWoExt.Str() << "]\n"; - tle->psTblName->Set( GetFqFileName().Str()); + tle->psFqTblName->Set( GetFqFileName().Str()); tle->psTblAlias->Set( sNewNameWoExt.Str()); } } catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf3::Rename() Exception Caught Error Stop = %d iRc = %d", iErrorStop, iRc ); + sMsg.Sprintf( "xbdbf3::Rename() Exception Caught Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); diff --git a/src/core/xbdbf4.cpp b/src/core/xbdbf4.cpp index 2b49be9..59ba39a 100755 --- a/src/core/xbdbf4.cpp +++ b/src/core/xbdbf4.cpp @@ -180,10 +180,10 @@ xbInt16 xbDbf4::CreateTable( const xbString &sTableName, const xbString &sAlias, ulCurRec = 0L; uiHeaderLen = 33 + iNoOfFields * 32; xbDate d; - cUpdateYY = (char) (d.YearOf() - 1900); - cUpdateMM = (char) d.MonthOf(); - cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); - + cUpdateYY = (char) (d.YearOf() - 1900); + cUpdateMM = (char) d.MonthOf(); + cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); + cIndexFlag = 0; // Default language driver to 0x1b cLangDriver = 0x1b; @@ -264,7 +264,7 @@ xbInt16 xbDbf4::CreateTable( const xbString &sTableName, const xbString &sAlias, catch( xbInt16 rc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf4::CreateTable() Exception Caught Error Stop = %d rc = %d", iErrorStop, rc ); + sMsg.Sprintf( "xbdbf4::CreateTable() Exception Caught Error Stop = [%d] rc = [%d]", iErrorStop, rc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( rc )); @@ -452,6 +452,9 @@ xbInt16 xbDbf4::Open( const xbString & sTableName, const xbString & sAlias, #endif #ifdef XB_MDX_SUPPORT + +// printf( "cIndexFlag [%x]\n", cIndexFlag ); + if( cIndexFlag ){ // create the file name xbString sIxFileName = GetFqFileName(); @@ -471,7 +474,7 @@ xbInt16 xbDbf4::Open( const xbString & sTableName, const xbString & sAlias, catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf4::Open() Exception Caught Error Stop = %d iRc = %d ShareMode = %d OpenMode = %d", iErrorStop, iRc, iShareMode, iOpenMode ); + sMsg.Sprintf( "xbdbf4::Open() Exception Caught Error Stop = [%d] iRc = [%d] ShareMode = [%d] OpenMode = [%d]", iErrorStop, iRc, iShareMode, iOpenMode ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); xbFclose(); @@ -726,7 +729,7 @@ xbInt16 xbDbf4::Rename( const xbString sNewName ){ // rename the table in the table list xbTblList *tle = xbase->GetTblListEntry( this ); if( tle ){ - tle->psTblName->Set( GetFqFileName().Str()); + tle->psFqTblName->Set( GetFqFileName().Str()); tle->psTblAlias->Set( sNewNameWoExt.Str()); } @@ -735,7 +738,7 @@ xbInt16 xbDbf4::Rename( const xbString sNewName ){ catch ( xbInt16 iRc ) { xbString sMsg; - sMsg.Sprintf( "xbdbf4::Rename() Exception Caught Error Stop = %d iRc = %d", iErrorStop, iRc ); + sMsg.Sprintf( "xbdbf4::Rename() Exception Caught Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); diff --git a/src/core/xbexp.cpp b/src/core/xbexp.cpp index 23bc7c6..deea53d 100755 --- a/src/core/xbexp.cpp +++ b/src/core/xbexp.cpp @@ -669,10 +669,22 @@ xbInt16 xbExp::GetTokenDatabaseField( xbExpToken &t ){ } // look for -> - // remove the field name from before the -> + // remove the table name from before the -> if( strncmp( s, "->", 2 ) == 0 ){ ulTokenLen2+=2; s+=2; + +/* + if( strncmp( s, "->", 2 ) == 0 || strncmp( s, ".", 1 ) == 0){ + if( *s == '.' ){ + ulTokenLen2+=1; + s+=1; + } else { + ulTokenLen2+=2; + s+=2; + } +*/ + // go past white space while( *s && !IsTokenSeparator( *s ) && IsWhiteSpace( *s )) { ulTokenLen2++; @@ -1489,6 +1501,7 @@ xbInt16 xbExp::ParseExpressionField( xbExpToken &t, xbExpNode *n ){ try{ xbUInt32 lPos; + if(( lPos = t.sToken.Pos( "->" )) > 0 ){ // table name is part of the token xbString sTableName = t.sToken; @@ -1496,6 +1509,22 @@ xbInt16 xbExp::ParseExpressionField( xbExpToken &t, xbExpNode *n ){ sFieldName = t.sToken; sFieldName.Mid( lPos + 2, t.sToken.Len() - lPos - 1 ); pDbf = (xbDbf *) xbase->GetDbfPtr( sTableName ); + + +/* + // updated 1/2/23 to support either table.field or table->field + if((( lPos = t.sToken.Pos( "->" )) > 0) || (( lPos = t.sToken.Pos( "." )) > 0) ){ + // table name is part of the token + xbString sTableName = t.sToken; + sTableName.Left( lPos-1 ); + sFieldName = t.sToken; + if( t.sToken[lPos] == '.' ) + sFieldName.Mid( lPos + 1, t.sToken.Len() - lPos ); + else // -> + sFieldName.Mid( lPos + 2, t.sToken.Len() - lPos - 1 ); + pDbf = (xbDbf *) xbase->GetDbfPtr( sTableName ); +*/ + } else { // table name is not part of the token pDbf = dbf; diff --git a/src/core/xbfile.cpp b/src/core/xbfile.cpp index 937c16f..3b798a2 100755 --- a/src/core/xbfile.cpp +++ b/src/core/xbfile.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +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. @@ -49,6 +49,119 @@ xbFile::~xbFile(){ } /************************************************************************/ +//! @brief Create Home Folders. +/*! + Create xbase64 log and data folders in the home directory for current usre. + + \returns <a href="xbretcod_8h.html">Return Codes</a> +*/ + +xbInt16 xbFile::SetHomeFolders(){ + + xbInt16 iErrorStop = 0; + xbInt16 iRc = XB_NO_ERROR; + xbString sHomeDir; + char cPathSeperator; + xbString sDflt; + + try{ + + GetHomeDir( sHomeDir ); + //std::cout << "CreateHomeFolders() home dir = [" << sHomeDir.Str() << "]\n"; + + if( FileExists( sHomeDir ) == xbFalse ){ + iErrorStop = 100; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + + #ifdef WIN32 + cPathSeperator = '\\'; + #else + cPathSeperator = '/'; + #endif + sDflt.Sprintf( ".%c", cPathSeperator ); + // set the default folders just in case later steps fail + xbase->SetDataDirectory( sDflt ); + #ifdef XB_LOGGING_SUPPORT + xbase->SetLogDirectory( sDflt ); + #endif + + if( sHomeDir[sHomeDir.Len()] != cPathSeperator ) + sHomeDir += cPathSeperator; + + xbString sWork( sHomeDir ); + sWork += "xbase64"; + + if( FileExists( sWork ) == xbFalse ){ + #ifdef WIN32 + if( CreateDirectory( sWork.Str(), NULL ) == 0 ){ + iErrorStop = 130; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #else + // 0777 mode is correct, the mode will be modified by the user's umask + if( mkdir( sWork.Str(), 0777 ) == -1 ){ + iErrorStop = 140; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #endif + } + + #ifdef XB_LOGGING_SUPPORT + sWork.Sprintf( "%sxbase64%clogs", sHomeDir.Str(), cPathSeperator ); + // std::cout << "logdir = " << sWork.Str() << "\n"; + + if( FileExists( sWork ) == xbFalse ){ + #ifdef WIN32 + if( CreateDirectory( sWork.Str(), NULL ) == 0 ){ + iErrorStop = 110; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #else + if( mkdir( sWork.Str(), 0777 ) == -1 ){ + iErrorStop = 120; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #endif + } + xbase->SetLogDirectory( sWork ); + #endif // XB_LOGGING_SUPPORT + + sWork.Sprintf( "%sxbase64%cdata", sHomeDir.Str(), cPathSeperator ); + // std::cout << "datadir = " << sWork.Str() << "\n"; + if( FileExists( sWork ) == xbFalse ){ + #ifdef WIN32 + if( CreateDirectory( sWork.Str(), NULL ) == 0 ){ + iErrorStop = 130; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #else + if( mkdir( sWork.Str(), 0777 ) == -1 ){ + iErrorStop = 140; + iRc = XB_DIRECTORY_ERROR; + throw iRc; + } + #endif + } + xbase->SetDataDirectory( sWork ); + + } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbFile::CreateHomeFolders() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + } + return iRc; +} + +/************************************************************************/ //! @brief Create a unique file name. /*! Given a directory and file extension as inputs, create a unique file name. @@ -1445,7 +1558,7 @@ xbInt16 xbFile::xbFputs( const xbString & s ){ /*! \param p Pointer to data to write \param size size of write - \param nmemb Number of times to write it + \param nmemb Number of times to read it \returns <a href="xbretcod_8h.html">Return Codes</a> */ @@ -1899,69 +2012,39 @@ void xbFile::SetLockRetryCount( xbInt16 iLockRetries ) { } #endif + + /***********************************************************************/ #ifdef XB_DEBUG_SUPPORT -//! @brief Debugging routine - dump a block to the log file. +//! @brief Debugging routine - dump mem to the log file. /*! - This routine dumps a block to a file in the log file. This is + This routine dumps data from meemory to the log file. This is primarily used for debugging and analysis purposes. - \param ulBlockNo Block number to write + \param p Pointer to data to write \param lBlxkSize Size of block \returns <a href="xbretcod_8h.html">Return Codes</a> */ -xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ +xbInt16 xbFile::DumpMemToDisk( char *p, size_t lSize ){ xbInt16 iRc = 0; xbInt16 iErrorStop = 0; - - xbUInt32 ulStartBlock; - xbUInt32 ulEndBlock; - - char *p = 0x00; - xbString sDir; xbString sFn; - char *buf = NULL; - FILE *fpd = NULL; - try{ - iErrorStop = 100; - if( ulBlockNo == 0 ){ - ulStartBlock = 0; - xbUInt64 ullFileSizeulBlockNo; - if(( iRc = GetFileSize( ullFileSizeulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - ulEndBlock = (xbUInt32) (ullFileSizeulBlockNo / lBlkSize); - } else { - ulStartBlock = ulBlockNo; - ulEndBlock = ulBlockNo; - } - - if(( buf = (char *) malloc( lBlkSize )) == NULL ){ - iErrorStop = 120; - iRc = XB_NO_MEMORY; - throw iRc; - } - - sDir = GetDefaultLogDirectory(); - char cLastChar = sDir[sDir.Len()]; + FILE *fpd = NULL; - for( xbUInt32 l = ulStartBlock; l < ulEndBlock; l++ ){ + try{ - if(( iRc = ReadBlock( l, lBlkSize, buf )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } + sDir = GetLogDirectory(); + char cLastChar = sDir[sDir.Len()]; // build logfile name if( cLastChar != '/' && cLastChar != '\\' ) - sFn.Sprintf( "%s/Blockdump.B%ld", sDir.Str(), l); + sFn.Sprintf( "%s/MemDump.txt", sDir.Str()); else - sFn.Sprintf( "%sBlockDump.%ld", sDir.Str(), l); + sFn.Sprintf( "%sMemDump.txt", sDir.Str()); // open the dump file for append #ifdef HAVE__FSOPEN_F @@ -1969,17 +2052,17 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ #else if(( fpd = fopen( sFn.Str(), "w+b")) == NULL ){ #endif - iErrorStop = 140; + iErrorStop = 100; iRc = XB_OPEN_ERROR; throw iRc; } + int i; // dump the block to the file - p = buf; - for( size_t l = 0; l < lBlkSize; l++ ){ - //if( fputc( *p, fpd ) != *p ){ - if( fputc( *p, fpd ) == EOF ){ - iErrorStop = 150; + for( size_t l = 0; l < lSize; l++ ){ + i = *p; + if( fputc( i, fpd ) == EOF ){ + iErrorStop = 110; iRc = XB_WRITE_ERROR; throw iRc; } @@ -1988,6 +2071,103 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ // close the dump file fclose( fpd ); } + catch (xbInt16 iRc ){ + xbString sMsg; + sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + xbase->WriteLogMessage( sMsg.Str() ); + xbase->WriteLogMessage( GetErrorMessage( iRc )); + if( fpd ) + fclose( fpd ); + } + return iRc; +} + +/***********************************************************************/ +//! @brief Debugging routine - dump a block to the log file. +/*! + This routine dumps a block to the log file. This is + primarily used for debugging and analysis purposes. + + \param ulBlockNo Block number to write + \param lBlxkSize Size of block + \returns <a href="xbretcod_8h.html">Return Codes</a> +*/ +xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ + + xbInt16 iRc = 0; + xbInt16 iErrorStop = 0; + + xbUInt32 ulStartBlock; + xbUInt32 ulEndBlock; + + char *p = 0x00; + + xbString sDir; + xbString sFn; + char *buf = NULL; + FILE *fpd = NULL; + try{ + + if( ulBlockNo == 0 ){ + ulStartBlock = 0; + xbUInt64 ullFileSizeulBlockNo; + if(( iRc = GetFileSize( ullFileSizeulBlockNo )) != XB_NO_ERROR ){ + iErrorStop = 100; + throw iRc; + } + ulEndBlock = (xbUInt32) (ullFileSizeulBlockNo / lBlkSize); + } else { + ulStartBlock = ulBlockNo; + ulEndBlock = ulBlockNo; + } + + if(( buf = (char *) malloc( lBlkSize )) == NULL ){ + iErrorStop = 110; + iRc = XB_NO_MEMORY; + throw iRc; + } + + sDir = GetLogDirectory(); + char cLastChar = sDir[sDir.Len()]; + + for( xbUInt32 l = ulStartBlock; l < ulEndBlock; l++ ){ + + if(( iRc = ReadBlock( l, lBlkSize, buf )) != XB_NO_ERROR ){ + iErrorStop = 120; + throw iRc; + } + + // build logfile name + if( cLastChar != '/' && cLastChar != '\\' ) + sFn.Sprintf( "%s/BlockDump.B%ld", sDir.Str(), l); + else + sFn.Sprintf( "%sBlockDump.%ld", sDir.Str(), l); + + // open the dump file for append + #ifdef HAVE__FSOPEN_F + if(( fpd = _fsopen( sFn.Str(), "w+b", 0x40 )) == NULL ){ + #else + if(( fpd = fopen( sFn.Str(), "w+b")) == NULL ){ + #endif + iErrorStop = 130; + iRc = XB_OPEN_ERROR; + throw iRc; + } + + // dump the block to the file + p = buf; + for( size_t l = 0; l < lBlkSize; l++ ){ + //if( fputc( *p, fpd ) != *p ){ + if( fputc( *p, fpd ) == EOF ){ + iErrorStop = 140; + iRc = XB_WRITE_ERROR; + throw iRc; + } + p++; + } + // close the dump file + fclose( fpd ); + } // free the buffer if( buf ) @@ -1995,10 +2175,7 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ } catch (xbInt16 iRc ){ xbString sMsg; - if( iErrorStop == 160 ) - sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d] c=[%c][%x]", iErrorStop, iRc, *p, *p ); - else - sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + sMsg.Sprintf( "xbFile::DumpBlockToDisk() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg.Str() ); xbase->WriteLogMessage( GetErrorMessage( iRc )); if( buf ) @@ -2007,7 +2184,6 @@ xbInt16 xbFile::DumpBlockToDisk( xbUInt32 ulBlockNo, size_t lBlkSize ){ fclose( fpd ); } return iRc; - } #endif /***********************************************************************/ diff --git a/src/core/xbfilter.cpp b/src/core/xbfilter.cpp index 507a9e7..0fb643d 100755 --- a/src/core/xbfilter.cpp +++ b/src/core/xbfilter.cpp @@ -26,8 +26,7 @@ This module handles uda (user data area) methods namespace xb{ /************************************************************************/ -xbFilter::xbFilter( xbXBase *xbase, xbDbf *dbf ) { - this->xbase = xbase; +xbFilter::xbFilter( xbDbf *dbf ) { this->dbf = dbf; this->exp = NULL; lLimit = 0; // max number of responses @@ -63,6 +62,12 @@ void xbFilter::ResetQryCnt(){ } /************************************************************************/ +xbInt16 xbFilter::Set( const char *sFilter ) { + xbString sFilt( sFilter ); + return Set( sFilt ); +} + +/************************************************************************/ xbInt16 xbFilter::Set( xbString &sFilter ) { xbInt16 iRc = XB_NO_ERROR; @@ -72,7 +77,7 @@ xbInt16 xbFilter::Set( xbString &sFilter ) { if( exp ) delete exp; - exp = new xbExp( xbase, dbf ); + exp = new xbExp( dbf->GetXbasePtr(), dbf ); if(( iRc = exp->ParseExpression( sFilter.Str() )) != XB_NO_ERROR ){ iErrorStop = 100; throw iRc; @@ -88,8 +93,8 @@ xbInt16 xbFilter::Set( xbString &sFilter ) { catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::SetExpression() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -141,8 +146,8 @@ xbInt16 xbFilter::GetFirstRecord( xbInt16 iOption ) { catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetFirstRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -196,8 +201,8 @@ xbInt16 xbFilter::GetNextRecord( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetNextRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -251,8 +256,8 @@ xbInt16 xbFilter::GetPrevRecord( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetPrevRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -304,8 +309,8 @@ xbInt16 xbFilter::GetLastRecord( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetLastRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -363,8 +368,8 @@ xbInt16 xbFilter::GetFirstRecordIx( xbInt16 iOption ) { catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetFirstRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -419,8 +424,8 @@ xbInt16 xbFilter::GetNextRecordIx( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetNextRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -475,8 +480,8 @@ xbInt16 xbFilter::GetPrevRecordIx( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetPrevRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } @@ -491,7 +496,6 @@ xbInt16 xbFilter::GetLastRecordIx( xbInt16 iOption ){ iErrorStop = 100; throw iRc; } - lCurQryCnt = 0; if(( iRc = dbf->GetCurIx()->GetLastKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ if( iRc == XB_EOF ) @@ -501,7 +505,6 @@ xbInt16 xbFilter::GetLastRecordIx( xbInt16 iOption ){ throw iRc; } } - xbBool bFound = xbFalse; while( !bFound && iRc == XB_NO_ERROR ){ if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ @@ -528,12 +531,11 @@ xbInt16 xbFilter::GetLastRecordIx( xbInt16 iOption ){ catch (xbInt16 iRc ){ xbString sMsg; sMsg.Sprintf( "xbFilter::GetLastRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( xbase->GetErrorMessage( iRc )); + dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); + dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); } return iRc; } - #endif // XB_INDEX_SUPPORT diff --git a/src/core/xbixmdx.cpp b/src/core/xbixmdx.cpp index 95f342c..135cde8 100755 --- a/src/core/xbixmdx.cpp +++ b/src/core/xbixmdx.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +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. @@ -108,7 +108,7 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ } else { // land here with a full leaf node - //std::cout << "Section B begin split leaf node\n"; + // std::cout << "Section B begin split leaf node\n"; iHeadNodeUpdateOpt = 1; npRightNode = AllocateIxNode( npTag, GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, npTag->npCurNode->ulBlockNo * (xbUInt32) iBlockFactor ); @@ -122,7 +122,7 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ ulNewRightChild = npRightNode->ulBlockNo * (xbUInt32) iBlockFactor; } - //std::cout << "ulNewRightChild = " << ulNewRightChild << "\n"; + // std::cout << "ulNewRightChild = " << ulNewRightChild << "\n"; if(( iRc = xbIxMdx::SplitNodeL( npTag, npTag->npCurNode, npRightNode, npTag->npCurNode->iCurKeyNo, npTag->cpKeyBuf, ulRecNo )) != XB_NO_ERROR ){ iErrorStop = 130; @@ -169,7 +169,8 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ // section D - if cur node is split root, create new root if(( npTag->npCurNode->ulBlockNo * (xbUInt32) iBlockFactor ) == npTag->ulRootPage ){ - // std::cout << "Section D begin\n"; + + // std::cout << "Section D begin right node = " << npRightNode << "\n"; if(( iRc = AddKeyNewRoot( npTag, npTag->npCurNode, npRightNode )) != XB_NO_ERROR ){ iErrorStop = 160; @@ -179,9 +180,10 @@ xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ if( npRightNode ) npRightNode = FreeNodeChain( npRightNode ); - //std::cout << "Section D end\n"; + // std::cout << "Section D end\n"; } else { + // std::cout << "Section E, put key in parent\n"; if(( iRc = InsertNodeI( (void *) vpTag, (xbIxNode *) npParent, (xbInt16) npParent->iCurKeyNo, BlockToPage( npRightNode->ulBlockNo ))) != XB_NO_ERROR ){ iErrorStop = 170; @@ -284,8 +286,8 @@ xbInt16 xbIxMdx::AddKeyNewRoot( xbMdxTag *npTag, xbIxNode *npLeft, xbIxNode *np // std::cout << "AddKeyNewRoot - LeftBlock = " << npLeft->ulBlockNo << "\n"; // std::cout << "AddKeyNewRoot - RightBlock = " << npRight->ulBlockNo << "\n"; - pLastKey = (char *) malloc( (size_t) npTag->iKeyLen ); + pLastKey = (char *) malloc( (size_t) npTag->iKeyLen ); if(( iRc = GetLastKeyForBlockNo( npTag, npLeft->ulBlockNo, pLastKey )) != XB_NO_ERROR ){ iErrorStop = 110; throw iRc; @@ -301,10 +303,17 @@ xbInt16 xbIxMdx::AddKeyNewRoot( xbMdxTag *npTag, xbIxNode *npLeft, xbIxNode *np // set the key pTrg+= 4; + // std::cout << "AddKeyNewRoot - key [" << pLastKey << "] len = [" << strlen( pLastKey) << "]\n"; memcpy( pTrg, pLastKey, (size_t) npTag->iKeyLen ); // set the right node number - pTrg+= (npTag->iKeyLen); + //pTrg+= (npTag->iKeyLen); + // pTrg+= (npTag->iKeyItemLen)-4; + + pTrg+= npTag->iKeyItemLen - 4; + + //pTrg-=4; + ePutUInt32( pTrg, npRight->ulBlockNo * (xbUInt32) iBlockFactor ); // write out the new block @@ -598,15 +607,17 @@ xbInt16 xbIxMdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ iErrorStop = 100; throw iRc; } - bLocked = xbTrue; + bLocked = xbTrue; } #endif memset( npTag->cpKeyBuf2, 0x00, (size_t) npTag->iKeyLen ); + // memset( npTag->cpKeyBuf2, 0x00, (size_t) npTag->iKeyItemLen ); cKeyType = GetKeyType( vpTag ); pPrevKeyBuf = (char *) calloc( 1, (size_t) npTag->iKeyLen ); iRc = GetFirstKey( vpTag, 0 ); + memcpy( pPrevKeyBuf, GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), (size_t) npTag->iKeyLen ); // for each key in the index, make sure it is trending in the right direction @@ -719,7 +730,7 @@ xbInt16 xbIxMdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ free( pPrevKeyBuf ); if( iErrorStop == 160 ){ - sMsg.Sprintf( "xbIxNdx::CheckTagIntegrity() Missing index entry for record [%d]", ulThisRecNo ); + sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Missing index entry for record [%d]", ulThisRecNo ); xbase->WriteLogMessage( sMsg, iOpt ); } } @@ -1171,8 +1182,13 @@ xbInt16 xbIxMdx::CreateTag( const xbString &sName, const xbString &sKey, const tte->cKeyType2 = tte->cKeyType; tte->iKeyItemLen = tte->iKeyLen + 4; + while(( tte->iKeyItemLen % 4 ) != 0 ) tte->iKeyItemLen++; tte->iKeysPerBlock = (xbInt16) (GetBlockSize() - 12) / tte->iKeyItemLen; + + //std::cout << "-------------- create tag info\n"; + //std::cout << "keylen=" << tte->iKeyLen << " iKeyItemLen = " << tte->iKeyItemLen << " keys per block calc = " << tte->iKeysPerBlock << "\n"; + tte->cKeyFmt3 = CalcTagKeyFmt( *tte->exp ); // printf( "ulRootPage=[%d] cKeyFmt2=[%d] cKeyType2=[%d] iKeyLen=[%d]iKeysPerBlock=[%d]\n", tte->ulRootPage, tte->cKeyFmt2, tte->cKeyType2, tte->iKeyLen, tte->iKeysPerBlock ); @@ -2657,6 +2673,7 @@ xbInt16 xbIxMdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw = 0 ){ // convert the tag pointer to mdx tag pointer xbMdxTag * mpTag = (xbMdxTag *) vpTag; + try{ // clear out any history if( mpTag->npNodeChain ){ @@ -2668,6 +2685,7 @@ xbInt16 xbIxMdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw = 0 ){ iErrorStop = 100; throw iRc; } + // lRootPage is available if(( iRc = GetBlock( vpTag, (mpTag->ulRootPage / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ iErrorStop = 110; @@ -2683,8 +2701,7 @@ xbInt16 xbIxMdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw = 0 ){ return iRc; } - while( !IsLeaf( vpTag, mpTag->npCurNode )) // go down the chain looking for a leaf node - { + while( !IsLeaf( vpTag, mpTag->npCurNode )){ // go down the chain looking for a leaf node if(( iRc = GetKeyPtr( vpTag, 0, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ iErrorStop = 120; throw iRc; @@ -2878,7 +2895,7 @@ xbInt16 xbIxMdx::GetLastKey( xbUInt32 ulBlockNo, void *vpTag, xbInt16 iRetrieveS } mpTag->npCurNode->iCurKeyNo = ulNoOfKeys; - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); + ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); xbUInt32 ulKeyPtr = 0; while( !IsLeaf( vpTag, mpTag->npCurNode )){ // go down the chain looking for a leaf node @@ -3559,6 +3576,11 @@ xbInt16 xbIxMdx::InsertNodeI( void *vpTag, xbIxNode *npNode, xbInt16 iSlotNo, xb pSrc = pLastKey; for( xbInt16 i = 0; i < npTag->iKeyLen; i++ ) *pTrg++ = *pSrc++; + + pTrg = pNewKeyPos; + //pTrg+= npTag->iKeyItemLen - 4; + pTrg+= npTag->iKeyItemLen; + ePutUInt32( pTrg, ulPtr); ePutInt32( npNode->cpBlockData, ++lKeyCnt ); @@ -4683,7 +4705,7 @@ xbInt16 xbIxMdx::SplitNodeI( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, } catch (xbInt16 iRc ){ xbString sMsg; - sMsg.Sprintf( "xbIxNdx::SplitNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); + sMsg.Sprintf( "xbIxMdx::SplitNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); xbase->WriteLogMessage( sMsg ); xbase->WriteLogMessage( GetErrorMessage( iRc )); } @@ -4712,7 +4734,7 @@ xbInt16 xbIxMdx::SplitNodeI( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, \returns <a href="xbretcod_8h.html">Return Codes</a> */ -xbInt16 xbIxMdx::SplitNodeL( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, +xbInt16 xbIxMdx::SplitNodeL( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, xbInt16 iSlotNo, char * cpKeyBuf, xbUInt32 ulPtr ){ xbInt16 iRc = XB_NO_ERROR; diff --git a/src/core/xbixndx.cpp b/src/core/xbixndx.cpp index dcec5f9..9d946dd 100755 --- a/src/core/xbixndx.cpp +++ b/src/core/xbixndx.cpp @@ -342,7 +342,7 @@ xbInt16 xbIxNdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ iErrorStop = 100; throw iRc; } - bLocked = xbTrue; + bLocked = xbTrue; } #endif @@ -425,7 +425,6 @@ xbInt16 xbIxNdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ sMsg.Sprintf( "CheckTagIntegrity() Index entry count [%ld] matches dbf record count [%ld]", ulIxCnt, ulDbfCnt ); xbase->WriteLogMessage( sMsg, iOpt ); } - if( pPrevKeyBuf ) free( pPrevKeyBuf ); diff --git a/src/core/xblog.cpp b/src/core/xblog.cpp index ea7c9d6..6031c9e 100755 --- a/src/core/xblog.cpp +++ b/src/core/xblog.cpp @@ -25,8 +25,8 @@ namespace xb{ //! @brief Constructor. xbLog::xbLog() : xbFile( NULL ){ - SetDirectory( GetDefaultLogDirectory()); - SetFileName ( GetDefaultLogFileName()); + SetDirectory( GetLogDirectory()); + SetFileName ( GetLogFileName()); bLoggingStatus = xbFalse; lLogSize = 50000; diff --git a/src/core/xbssv.cpp b/src/core/xbssv.cpp index 252daab..d3e1070 100755 --- a/src/core/xbssv.cpp +++ b/src/core/xbssv.cpp @@ -2,7 +2,7 @@ XBase64 Software Library -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel +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. @@ -15,8 +15,6 @@ Email Contact: #include "xbase.h" - - namespace xb{ const xbErrorMessage xbErrorMessages[] = { @@ -26,6 +24,7 @@ const xbErrorMessage xbErrorMessages[] = { { XB_DUP_TABLE_OR_ALIAS, "Duplicate Alias/Table Name" }, { XB_INVALID_NODELINK, "Invalid Node Link" }, { XB_KEY_NOT_UNIQUE, "Key Not Unique" }, + { XB_MEMCPY_ERROR, "Memory copy failure" }, { XB_FILE_EXISTS, "File Already Exists" }, { XB_ALREADY_OPEN, "Database already open" }, { XB_DBF_FILE_NOT_OPEN, "DBF File Not Open" }, @@ -49,6 +48,8 @@ const xbErrorMessage xbErrorMessages[] = { { XB_INVALID_TABLE_NAME, "Invalid Table Name" }, { XB_EMPTY, "Empty Table or Index" }, { XB_LIMIT_REACHED, "Limit Reached" }, + { XB_BLOCKREAD_NOT_ENABLED, "Block Read Mode is not enabled" }, + { XB_DIRECTORY_ERROR, "Directory Read/Write error" }, { XB_INVALID_FIELD_TYPE, "Unknown Field Type" }, { XB_INVALID_FIELD_NO, "Invalid Field Number" }, { XB_INVALID_DATA, "Invalid Data" }, @@ -89,12 +90,13 @@ xbBool xbSsv::bDefaultAutoCommit = xbTrue; xbString xbSsv::sDataDirectory = PROJECT_DATA_DIR; #else xbString xbSsv::sDataDirectory = PROJECT_DATA_DIR; -#endif +#endif // #ifdef XB_LOGGING_SUPPORT -xbString xbSsv::sDefaultLogDirectory = PROJECT_LOG_DIR; -xbString xbSsv::sDefaultLogFileName = PROJECT_DFLT_LOGFILE; -#endif +xbString xbSsv::sLogDirectory = PROJECT_LOG_DIR; +//xbString xbSsv::sLogDirectory = ""; +xbString xbSsv::sLogFileName = PROJECT_DFLT_LOGFILE; +#endif // XB_LOGGING_SUPPORT #ifdef XB_LOCKING_SUPPORT xbInt32 xbSsv::lDefaultLockWait = 100; @@ -104,18 +106,21 @@ xbInt16 xbSsv::iDefaultLockFlavor = 1; xbBool xbSsv::bMultiUser = xbTrue; #else xbBool xbSsv::bMultiUser = xbFalse; -#endif +#endif // XB_LOCKING_SUPPORT #if defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) xbInt16 xbSsv::iUniqueKeyOpt = XB_HALT_ON_DUPKEY; // is one of XB_HALT_ON_DUPKEY || XB_EMULATE_DBASE -#endif +#endif // defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) #ifdef XB_MDX_SUPPORT xbInt16 xbSsv::iCreateMdxBlockSize = 1024; // 1024 is DBase 7 default size for MDX index blocks -#endif +#endif // XB_MDX_SUPPORT +#ifdef XB_BLOCKREAD_SUPPORT +xbUInt32 xbSsv::ulDefaultBlockReadSize = 32768; // 32K buffer for block DBF datafile reads +#endif // XB_BLOCKREAD_SUPPORT /*************************************************************************/ //! @brief Class Constructor. @@ -139,7 +144,6 @@ void xbSsv::BitDump( char c ) const { xbBool xbSsv::BitSet( unsigned char c, xbInt16 iBitNo ) const { return c & 1 << iBitNo; } - /*************************************************************************/ //! @brief Display error message on console for a given error number. /*! @@ -164,7 +168,6 @@ void xbSsv::DisplayError( xbInt16 iErrorCode ) const { xbBool xbSsv::GetDefaultAutoCommit() const { return bDefaultAutoCommit; } - /*************************************************************************/ //! @brief Get the current data directory. /*! @@ -184,19 +187,6 @@ xbString &xbSsv::GetDataDirectory() const { xbString & xbSsv::GetDefaultDateFormat() const { return sDefaultDateFormat; } - -/*************************************************************************/ -// @brief Get the default file format version. -/* - \returns 3 - Dbase III file format<br> - 4 - Dbase IV file format<br> -*/ - -/* -xbInt16 xbSsv::GetDefaultFileVersion() const { - return iDefaultFileVersion; -} -*/ /*************************************************************************/ //! @brief Get the Endian type. /*! @@ -206,7 +196,6 @@ xbInt16 xbSsv::GetDefaultFileVersion() const { xbInt16 xbSsv::GetEndianType() const { return iEndianType; } - /*************************************************************************/ //! @brief Get an error message. /*! @@ -230,7 +219,25 @@ const char * xbSsv::GetErrorMessage( xbInt16 iErrorCode ) const{ } return ""; } +/*************************************************************************/ +//! @brief Get home directory. +/*! + \param sHomeDirOut - Output home directory for current user. + \returns void +*/ + +void xbSsv::GetHomeDir( xbString &sHomeDirOut ){ + #ifdef WIN32 + sHomeDirOut.Sprintf( "%s%s", getenv( "HOMEDRIVE" ), getenv( "HOMEPATH" )); + #else + sHomeDirOut.Sprintf( "%s", getenv( "HOME" )); + sHomeDirOut.Trim(); + if( sHomeDirOut == "" ) + sHomeDirOut.Sprintf( "%s", getpwuid( getuid())->pw_dir ); + #endif + sHomeDirOut.Trim(); +} /*************************************************************************/ //! @brief Set the data directory. /*! @@ -240,7 +247,6 @@ const char * xbSsv::GetErrorMessage( xbInt16 iErrorCode ) const{ void xbSsv::SetDataDirectory( const xbString &sDataDirectory ){ this->sDataDirectory = sDataDirectory; - #ifdef WIN32 this->sDataDirectory.SwapChars( '/', '\\' ); #else @@ -302,57 +308,53 @@ void xbSsv::SetEndianType() { /*! \returns Returns the log file name. */ -xbString & xbSsv::GetDefaultLogFileName() const { - return sDefaultLogFileName; +xbString & xbSsv::GetLogFileName() const { + return sLogFileName; } - /*************************************************************************/ //! @brief Get the default log directory. /*! \returns Returns the log directory. */ -xbString & xbSsv::GetDefaultLogDirectory() const { - return sDefaultLogDirectory; +xbString & xbSsv::GetLogDirectory() const { + return sLogDirectory; } /*************************************************************************/ //! @brief Set the default log directory name. /*! - \param sDefaultLogDirectory Name of desired log directory. + \param sLogDirectory Name of desired log directory. */ -void xbSsv::SetDefaultLogDirectory( const xbString &sDefaultLogDirectory ){ - - this->sDefaultLogDirectory = sDefaultLogDirectory; +void xbSsv::SetLogDirectory( const xbString &sLogDirectoryIn ){ + this->sLogDirectory = sLogDirectoryIn; #ifdef WIN32 - this->sDefaultLogDirectory.SwapChars( '/', '\\' ); + this->sLogDirectory.SwapChars( '/', '\\' ); #else - this->sDefaultLogDirectory.SwapChars( '\\', '/' ); + this->sLogDirectory.SwapChars( '\\', '/' ); #endif - } #else -xbString & xbSsv::GetDefaultLogFileName() const { +xbString & xbSsv::GetLogFileName() const { return sNullString; } -xbString & xbSsv::GetDefaultLogDirectory() const { +xbString & xbSsv::GetLogDirectory() const { return sNullString; } -void xbSsv::SetDefaultLogDirectory( const xbString &sDefaultLogDirectory ){ +void xbSsv::SetLogDirectory( const xbString &sLogDirectory ){ return; } #endif - /*************************************************************************/ #ifdef XB_LOCKING_SUPPORT @@ -541,6 +543,29 @@ xbInt16 xbSsv::SetUniqueKeyOpt( xbInt16 iOpt ){ } #endif /************************************************************************/ +#ifdef XB_BLOCKREAD_SUPPORT + +//! @brief Get Default Read Block Size +/*! + This routine returns the default read block size used when allocating + buffer space for block reads of table data. Initial setting is 32768 bytes. +*/ +xbUInt32 xbSsv::GetDefaultBlockReadSize() const { + return ulDefaultBlockReadSize; +} + + +//! @brief Set Default Read Block Size +/*! + This routine sets the default read block size used when allocating + buffer space for block reads of table data. Initial setting is 32768 bytes. +*/ +void xbSsv::SetDefaultBlockReadSize( xbUInt32 ulDfltBlockReadSize ){ + ulDefaultBlockReadSize = ulDfltBlockReadSize; +} + +#endif // XB_BLOCKREAD_SUPPORT +/************************************************************************/ diff --git a/src/core/xbstring.cpp b/src/core/xbstring.cpp index 81e67b8..701e50e 100755 --- a/src/core/xbstring.cpp +++ b/src/core/xbstring.cpp @@ -1267,6 +1267,45 @@ xbString &xbString::PadRight( char c, xbUInt32 ulNewLen ){ //! @brief Determine position of a given character /*! \param c Seek character + \param ulStartPos starting position for search, first position is 1 + \returns Position within string. Returns 0 if not found. +*/ +xbUInt32 xbString::Pos(char c, xbUInt32 ulStartPos ) const { + + if (data == NULL) + return 0; + char *p = data; + + if( ulStartPos >= size ) + return 0; + + xbUInt32 iPos = 0; + while( (iPos+1) < ulStartPos ){ + p++; + iPos++; + } + xbBool bFound = 0; + while( *p && !bFound && iPos < ( size - 1 )){ + if( *p == c ) + bFound = 1; + else { + iPos++; + p++; + } + } + + if( bFound ) + return iPos + 1; + else + return 0; +} + + + +/************************************************************************/ +//! @brief Determine position of a given character +/*! + \param c Seek character \returns Position within string. Returns 0 if not found. */ xbUInt32 xbString::Pos(char c) const { @@ -1375,41 +1414,51 @@ xbString &xbString::Replace( const char *sReplace, const char *sReplaceWith, xbI xbBool bDone = xbFalse; xbUInt32 ulPos; - xbUInt32 ulNewSize; + xbUInt32 ulNewLen; + xbUInt32 ulReplaceWithLen; + xbUInt32 ulRsLen; // size of right side of string after replaced data xbUInt32 ulSp2; char *sBuf2; + const char *s; // source ptr + char *t; // target ptr + while( !bDone ){ ulPos = Pos( sReplace ); if( ulPos == 0 ){ bDone = xbTrue; } else { - ulNewSize = this->size + sizeof( sReplaceWith ) - sizeof( sReplace ); - sBuf2 = (char *) calloc( 1, ulNewSize ); + ulReplaceWithLen = (xbUInt32) strlen( sReplaceWith ); + ulNewLen = this->size + ulReplaceWithLen - (xbUInt32) strlen( sReplace ); + sBuf2 = (char *) calloc( 1, ulNewLen ); // copy part1 + t = sBuf2; + s = data; for( xbUInt32 ul = 0; ul < ulPos-1; ul++ ) - sBuf2[ul] = data[ul]; + *t++ = *s++; // copy part2 - strcat( sBuf2, sReplaceWith ); + s = sReplaceWith; + for( xbUInt32 ul = 0; ul < ulReplaceWithLen; ul++ ) + *t++ = *s++; // copy part3 - ulSp2 = ulPos + strlen( sReplace ); - char *p = data; - p+= (ulSp2 - 1); - strcat( sBuf2, p ); + ulSp2 = ulPos + (xbUInt32) strlen( sReplace ); + s = data; + s+= (ulSp2 - 1); + ulRsLen = (xbUInt32) strlen( s ); + for( xbUInt32 ul = 0; ul < ulRsLen; ul++ ) + *t++ = *s++; if( iOption ) bDone = xbTrue; free(data); data = sBuf2; - } } - return *this; } diff --git a/src/core/xbtblmgr.cpp b/src/core/xbtblmgr.cpp index f154dc6..2fe6a8c 100755 --- a/src/core/xbtblmgr.cpp +++ b/src/core/xbtblmgr.cpp @@ -22,20 +22,19 @@ Email Contact: namespace xb{ /*************************************************************************/ - xbTblMgr::xbTblMgr(){ TblList = NULL; iOpenTableCount = 0; } /*************************************************************************/ - xbTblMgr::~xbTblMgr(){ xbTblList *l; if( TblList ){ while( TblList ){ l = TblList; TblList = TblList->pNext; + delete l->psFqTblName; delete l->psTblName; delete l->psTblAlias; free( l ); @@ -44,47 +43,74 @@ xbTblMgr::~xbTblMgr(){ } /*************************************************************************/ - -xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sTblName ){ - return AddTblToTblList( d, sTblName, "" ); +xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sFqTblName ){ + return AddTblToTblList( d, sFqTblName, "" ); } /*************************************************************************/ +xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sFqTblName, const xbString & sTblAlias ) { + + // Set the Fq (fully qualified name) + // Pull the table name from the FQ name + // Set the Alias to the table name if the alias name is not provided -xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sTblName, const xbString & sTblAlias ) { xbTblList *i, *s, *t; xbInt16 iRc = 0; xbInt16 iErrorStop = 0; + xbString sTblName; xbString sAlias; + xbString sTemp; + xbString sFqTemp; + xbUInt32 iSlashPos; + + // std::cout << "AddTblToTblList fq in = [" << sFqTblName.Str() << "] alias in =[" << sTblAlias.Str() << "]\n"; try{ - if( sTblName.Len() == 0 ){ + if( sFqTblName.Len() == 0 ){ iErrorStop = 100; iRc = XB_INVALID_TABLE_NAME; throw iRc; } - if( sTblAlias.Len() == 0 ){ + sTblName = sFqTblName; + sTblName.SwapChars( '\\', '/' ); + iSlashPos = sTblName.GetLastPos( '/' ); + + // std::cout << "slashpos = " << iSlashPos << "\n"; + + + if( iSlashPos > 0 ){ + sTblName.Ltrunc( iSlashPos ); // remove the directory part from the table name + sFqTemp = sFqTblName; + } else{ + sFqTemp.Sprintf( "%s%s", GetDataDirectory().Str(), sFqTblName.Str()); // add the dir part to the FQ name + } + + xbUInt32 iDbfPos = sFqTemp.Pos( ".DBF" ); + if( iDbfPos == 0 ) + sFqTemp += ".DBF"; + else + sTblName.Resize( sTblName.Len() - 3 ); + + if( sTblAlias.Len() == 0 ) sAlias = sTblName; - sAlias.SwapChars( '\\', '/' ); - xbUInt32 iPos = sAlias.GetLastPos( '/' ); - if( iPos > 0 ) /* get rid of the directory part of the name */ - sAlias.Ltrunc( iPos ); - } else { + else sAlias = sTblAlias; - } + + //std::cout << "fq=[" << sFqTemp.Str() << "] tblname = [" << sTblName.Str() << "] alias = [" << sAlias.Str() << "]\n"; if((i = (xbTblList *) calloc(1, sizeof(xbTblList))) == NULL){ iErrorStop = 110; iRc = XB_NO_MEMORY; throw iRc; } - i->psTblName = new xbString( sTblName ); - i->psTblAlias = new xbString( sAlias ); - i->pDbf = d; - i->pNext = NULL; + i->psFqTblName = new xbString( sFqTemp ); + i->psTblName = new xbString( sTblName ); + i->psTblAlias = new xbString( sAlias ); + i->pDbf = d; + i->pNext = NULL; // insert new table into the list of open tables, sorted by table name s = NULL; @@ -97,7 +123,7 @@ xbInt16 xbTblMgr::AddTblToTblList( xbDbf *d, const xbString & sTblName, const xb if( t && (strcmp( t->psTblAlias->Str(), sAlias.Str()) == 0 )){ iErrorStop = 120; - delete i->psTblName; + delete i->psFqTblName; delete i->psTblAlias; free( i ); iRc = XB_DUP_TABLE_OR_ALIAS; @@ -131,7 +157,7 @@ xbInt16 xbTblMgr::DisplayTableList() const { else{ while( l ){ iTblCnt++; - std::cout << iTblCnt << " Table=[" << l->psTblName->Str() << "] Alias=[" << l->psTblAlias->Str() << "]" << std::endl; + std::cout << iTblCnt << " FqFileName=[" << l->psFqTblName->Str() << "] TableName=[" << l->psTblName->Str() << "] Alias=[" << l->psTblAlias->Str() << "]" << std::endl; l = l->pNext; } } @@ -149,6 +175,7 @@ xbInt16 xbTblMgr::DisplayTableList() const { xbDbf *xbTblMgr::GetDbfPtr(const xbString& sTblAlias) const { + xbTblList *t; t = TblList; xbString s; @@ -159,14 +186,26 @@ xbDbf *xbTblMgr::GetDbfPtr(const xbString& sTblAlias) const { s.Set( sTblAlias ); while( t ){ - if( s == t->psTblAlias->Str()) + if( s == t->psTblAlias->Str()){ + return t->pDbf; + } + t = t->pNext; + } + + t = TblList; + while( t ){ + std::cout << "s = [" << s.Str() << "] tbl name = [" << t->psTblName->Str() << "]\n"; + if( s == t->psTblName->Str()){ + std::cout << "found\n"; return t->pDbf; + } t = t->pNext; } + t = TblList; while( t ){ - if( sTblAlias == t->psTblName->Str()) + if( sTblAlias == t->psFqTblName->Str()) return t->pDbf; t = t->pNext; } @@ -227,6 +266,7 @@ xbInt16 xbTblMgr::RemoveTblFromTblList( const xbString & sTblAlias ) { else TblList = i->pNext; + delete i->psFqTblName; delete i->psTblName; delete i->psTblAlias; free( i ); @@ -254,6 +294,7 @@ xbInt16 xbTblMgr::RemoveTblFromTblList( xbDbf *pTbl ) { else TblList = i->pNext; + delete i->psFqTblName; delete i->psTblName; delete i->psTblAlias; free( i ); diff --git a/src/core/xbxbase.cpp b/src/core/xbxbase.cpp index 7443b26..20b7fcc 100755 --- a/src/core/xbxbase.cpp +++ b/src/core/xbxbase.cpp @@ -24,6 +24,10 @@ xbXBase::xbXBase() { #ifdef XB_LOGGING_SUPPORT xLog = new xbLog(); #endif + + xbFile f( this ); + f.SetHomeFolders(); + } /*************************************************************************/ //! @brief Class Deconstructor. @@ -69,6 +73,53 @@ xbInt16 xbXBase::CloseAllTables(){ } return iRc; } + + + +/*************************************************************************/ +//! @brief Parse commmand line options for a given parm request +/*! + \param lArgc Value passed from main( argc, argv[] ) + \param sArgv Valued passed from main + \param sOptRqst Option to search for in the arguments list + \param sParmOut String token immediately to the right of the the option request, if found + \returns 0 - paramater request not found<br> 1 - Parameter found +*/ + +xbInt16 xbXBase::GetCmdLineOpt( xbInt32 lArgc, char **sArgv, const char *sOptRqst, xbString &sParmOut ){ + xbString sOpt( sOptRqst ); + return GetCmdLineOpt( lArgc, sArgv, sOpt, sParmOut ); +} + +/*************************************************************************/ +//! @brief Parse commmand line options for a given parm request +/*! + \param lArgc Value passed from main( argc, argv[] ) + \param sArgv Valued passed from main + \param sOptRqst Option to search for in the arguments list + \param sParmOut String token immediately to the right of the the option request, if found + \returns 0 - paramater request not found<br> 1 - Parameter found +*/ + +xbInt16 xbXBase::GetCmdLineOpt( xbInt32 lArgc, char **sArgv, xbString &sOptRqst, xbString &sParmOut ){ + + xbInt16 iFound = 0; + sParmOut = ""; + if( lArgc < 2 ) // first string is the program name + return iFound; + + xbInt32 i = 1; + while( iFound == 0 && i < lArgc ){ + if( sOptRqst == sArgv[i] ){ + iFound = 1; + if( i < (lArgc-1)) + sParmOut = sArgv[i+1]; + } + i++; + } + return iFound; +} + /*************************************************************************/ #ifdef XB_LOGGING_SUPPORT //! @brief Get fully qualified log file name. @@ -109,6 +160,7 @@ xbBool xbXBase::GetLogStatus() const { \return void */ void xbXBase::SetLogFileName( const xbString & sLogFileName ){ + xLog->SetFileName( sLogFileName ); } @@ -550,7 +602,7 @@ xbDbf* xbXBase::Open( const xbString &sTableName, xbInt16 &iRc ){ \param iOpenMode - XB_READ_WRITE or XB_READ \param iShareMode - XB_SINGLE_USER or XB_MULTI_USER \param iRequestVersion 0 - Highest available - 4 - Version four dbf + 4 - Version four dbf 3 - Version three dbf \param iRc - Return code from open request \returns param dbf - Output pointer to dbf file opened or null if error |