diff options
Diffstat (limited to '1Tdata/xbase/xbase64-4.1.4/src/core')
26 files changed, 0 insertions, 31184 deletions
diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbbcd.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbbcd.cpp deleted file mode 100755 index f86e74f..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbbcd.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* xbbcd.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 - - BCD class - -*/ - -#include "xbase.h" - -#ifdef XB_INDEX_SUPPORT -///@cond DOXYOFF -namespace xb{ - - - -xbBool bcdBitSet( unsigned char c, xbInt16 iBitNo ){ - return c & 1 << iBitNo; -} -void bcdBitDump( unsigned char c ){ - for( int i = 7; i >= 0; i-- ) - std::cout << (bcdBitSet( c, i ) ? 1 : 0); -} -void bcdBitDump( char c ){ - bcdBitDump( (unsigned char) c ); -} - - -/***********************************************************************/ -void xbBcd::ctor(){ - memset( &bcd, 0x00, sizeof( xbBcdStruct )); -} -/***********************************************************************/ -xbBcd::xbBcd( xbDouble d ) { - Set( d ); -} -/***********************************************************************/ -xbBcd::xbBcd( const xbString &sNumIn ) { - Set( sNumIn ); -} -/***********************************************************************/ -xbBcd::xbBcd( const void *vBcdIn ) { - memcpy( &bcd, vBcdIn, sizeof( xbBcdStruct )); -} -/***********************************************************************/ -void xbBcd::Set( xbDouble d ) { - ctor(); - xbString s( d ); - StringToBcd( s ); -} -/***********************************************************************/ -void xbBcd::Set( const xbString &sNumIn ) { - ctor(); - StringToBcd( sNumIn ); -} -/***********************************************************************/ -void xbBcd::Set( const void *vBcdIn ) { - memcpy( &bcd, vBcdIn, sizeof( xbBcdStruct )); -} -/***********************************************************************/ -void xbBcd::StringToBcd( const xbString &sIn ) -{ - - unsigned char cEdc = 0; // encoded digit count - xbUInt32 iPos; // current position in source string - xbBool bDecHit = xbFalse; // decimal position hit? - unsigned char *p = bcd.cData; // pointer to cData - xbInt16 iBytePos = 0; // next load position in xbs structure - xbInt16 iBcdDataPos = 0; // current position in output structure - xbByteSplit xbs; // combiner - - - ctor(); - xbString sNum( sIn ); - xbBool bSign = xbFalse; - - sNum.Trim(); - if( sNum[1] == '-' ){ - bSign = 1; - sNum.ZapLeadingChar( '-' ); - } - sNum.ZapLeadingChar( '0' ); - - xbInt16 iDecPos = sNum.Pos( '.' ); - if( iDecPos > 0 ){ - sNum.ZapTrailingChar( '0' ); - cEdc = (unsigned char) (sNum.Len() - 1); - } else { - cEdc = (unsigned char) (sNum.Len()); - } - if( cEdc > 31 ) cEdc = 31; // max 5 bit number - - - if( sNum[1] == '.' ){ - iPos = 2; - bDecHit = xbTrue; - while( sNum[iPos] == '0' && iPos <= sNum.Len()){ - bcd.cSigDigits--; - iPos++; - } - } else { - iPos = 1; - } - - while( iPos <= sNum.Len() ){ - if( sNum[iPos] == '.' ) - bDecHit = true; - else{ - if( !bDecHit ){ - bcd.cSigDigits++; - } - if( iBytePos++ == 0 ){ - xbs.c2 = (unsigned) sNum[iPos] - 0x30; - } else { - xbs.c1 = (unsigned) sNum[iPos] - 0x30; - iBytePos = 0; - if( iBcdDataPos++ < 10 ){ - memcpy( p++, &xbs, 1 ); - xbs.c1 = 0x00; - } - } - } - iPos++; - } - - if( iBytePos == 1 && iBcdDataPos < 10 ){ - memcpy( p, &xbs, 1 ); - } - - bcd.cSigDigits += 52; - bcd.cEncDigits = cEdc << 2; - bcd.cEncDigits = bcd.cEncDigits | 0x01; - if( bSign ) - bcd.cEncDigits = bcd.cEncDigits | 0x80; - -} -/***********************************************************************/ -void xbBcd::ToChar( char * cOut ){ - - memcpy( cOut, &bcd, sizeof( xbBcdStruct )); -} -/***********************************************************************/ -void xbBcd::ToDouble( xbDouble &d ){ - xbString s; - ToString( s ); - d = atof( s.Str()); -} -/***********************************************************************/ -void xbBcd::ToString( xbString &sStringOut ){ - -// printf( "\n\n\nToString " ); -// printf( "Sig digits [%d] EncodedDigits [%d] sign [%d] sizeof struct [%d]\n", -// bcd.cSigDigits - 52 , bcd.EncDigits, bcd.Sign, sizeof( xbBcdStruct )); - -// this routine converts a bcd numeric key value to a base 10 number in a string - - - xbBool bHasDot = false; - xbInt16 iSig = bcd.cSigDigits - 52; - xbByteSplit xbs; - unsigned char *p = bcd.cData; - unsigned char c; - -// xbInt16 iEnc = bcd.cEncDigits; - xbInt16 iEnc = GetEncDigitsNoSign(); - - // set the sign - // if( bcd.Sign ) - if( bcd.cEncDigits >> 7 ) - sStringOut = "-"; - else - sStringOut = ""; - - // do add any needed zeroes after the decimal - if( iSig <= 0 ){ - if( iEnc > 0 ){ - sStringOut.Append( "." ); - bHasDot = true; - } - for( xbInt16 i = iSig; i < 0; i++ ) - sStringOut.Append( "0" ); - } - - // do the encoded digits - while( iEnc > 0 ){ - if( iSig == 0 && !bHasDot ) - sStringOut.Append( "." ); - c = *p++; - memcpy( &xbs, &c, 1 ); - c = xbs.c2 + 0x30; - sStringOut.Append((char) c ); - iSig--; - iEnc--; - if( iEnc > 0 ){ - if( iSig == 0 && !bHasDot ) - sStringOut.Append( "." ); - c = xbs.c1 + 0x30; - sStringOut.Append((char) c ); - iSig--; - iEnc--; - } - } - // do the trailing zeroes - while( iSig-- > 0 ) - sStringOut.Append( "0" ); - if( sStringOut == "" ) - sStringOut = "0"; - -} - -/***********************************************************************/ -xbInt16 xbBcd::Compare( xbDouble d ){ - xbBcd bcdIn( d ); - - xbString s; - bcdIn.ToString( s ); - return Compare( bcdIn ); -} - -/***********************************************************************/ -xbInt16 xbBcd::Compare( const xbBcd &bcdIn ){ - // if this == bcdIn return 0 - // if this < bcdIn return -1 - // if this > bcdIn return 1 - - - xbInt16 iRc = 0; -// if( bcd.Sign != bcdIn.GetSign() ){ -// bcd.Sign > 0 ? iRc = -1 : iRc = 1; - - if( (unsigned)(bcd.cEncDigits >> 7 ) != bcdIn.GetSign() ){ - (bcd.cEncDigits >> 7 ) > 0 ? iRc = -1 : iRc = 1; - return iRc; - } - - if( (unsigned) bcd.cSigDigits != bcdIn.GetSigDigits()){ - // if( !bcd.Sign ){ // positive numbers - if( !(bcd.cEncDigits >> 7 )){ // positive numbers - if( (unsigned) bcd.cSigDigits > bcdIn.GetSigDigits()) - return 1; - else - return -1; - } else { // negative numbers - if( (unsigned) bcd.cSigDigits > bcdIn.GetSigDigits()) - return -1; - else - return 1; - } - } - -// iRc = xbXBase::xbMemcmp( bcd.cData, bcdIn.GetData(), (size_t)((bcd.cEncDigits + 1) / 2) ); - iRc = xbXBase::xbMemcmp( bcd.cData, bcdIn.GetData(), (size_t)((GetEncDigitsNoSign() + 1) / 2) ); - if( iRc == 0 ) - return 0; - // else if((!bcd.Sign && iRc > 0) || (bcd.Sign && iRc < 0 )) - else if((!(bcd.cEncDigits >> 7) && iRc > 0) || ((bcd.cEncDigits >> 7) && iRc < 0 )) - return 1; - else - return -1; -} - -/***********************************************************************/ -unsigned char xbBcd::GetEncDigitsNoSign() const { - unsigned char c = bcd.cEncDigits << 1; - return c >> 3; -} -/***********************************************************************/ -unsigned xbBcd::GetSign() const { - //return bcd.Sign; - return (unsigned) bcd.cEncDigits >> 7; -} -/***********************************************************************/ -unsigned xbBcd::GetSigDigits() const { - return bcd.cSigDigits; -} -/***********************************************************************/ -unsigned xbBcd::GetActualSigDigits() const { - return bcd.cSigDigits - (xbUInt32) 52; -} -/***********************************************************************/ -const unsigned char * xbBcd::GetData() const { - const unsigned char *p = bcd.cData; - return p; -} -/***********************************************************************/ -const void * xbBcd::GetBcd() const { - return &bcd; -} -} /* namespace */ -///@endcond DOXYOFF -#endif /* XB_INDEX_SUPPORT */ - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbblockread.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbblockread.cpp deleted file mode 100755 index 7e2c5fc..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbblockread.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* 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(){ - - xbUInt32 ulRecCnt; - dbf->GetRecordCnt( ulRecCnt ); - - std::cout << "------- DumpBlockInternals ---------" << std::endl; - std::cout << "Dflt Blk Size = [" << dbf->GetXbasePtr()->GetDefaultBlockReadSize() - << "]" << std::endl; - std::cout << "Dbf Record Count = [" << ulRecCnt << "]" << 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; - - if(( iRc = dbf->GetRecordCnt( ulDbfRecCnt )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // 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/1Tdata/xbase/xbase64-4.1.4/src/core/xbdate.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbdate.cpp deleted file mode 100755 index 54834ac..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbdate.cpp +++ /dev/null @@ -1,867 +0,0 @@ -/* xbdate.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 - -*/ - -#include "xbase.h" -#include <time.h> - -namespace xb{ - -int xbDate::iDaysInMonths[2][13]; -int xbDate::iAggregatedDaysInMonths[2][13]; - -/*************************************************************************/ -//! @brief Constructor. - -xbDate::xbDate() { - sDate8.Set( "" ); - SetDateTables(); -} - -/*************************************************************************/ -//! @brief Constructor. -/*! - \param iInitOpt - Constructor to use to initialize date static variables - Called by the main xbXbase::xbXBase constructor -*/ - -xbDate::xbDate( xbUInt16 ) { - - SetDateTables(); - Sysdate(); -} -/*************************************************************************/ -//! @brief Constructor. -/*! - \param sDate8In - Input date. -*/ - -xbDate::xbDate( const xbString & sDate8In ) { - - if( DateIsValid( sDate8In )) - sDate8.Set( sDate8In ); - else - sDate8.Set( "" ); - - // SetDateTables(); -} - -/*************************************************************************/ -//! @brief Constructor. -/*! - \param sDate8In - Input date. -*/ -xbDate::xbDate( const char * sDate8In ) { - - if( DateIsValid( sDate8In )) - sDate8.Set( sDate8In ); - else - sDate8.Set( "" ); - - // SetDateTables(); -} - -/*************************************************************************/ -//! @brief Constructor. -/*! - \param lJulDate - Input julian date. -*/ -xbDate::xbDate( xbInt32 lJulDate ) { - // SetDateTables(); - JulToDate8( lJulDate ); -} - -/*************************************************************************/ -//! @brief Destructor. -xbDate::~xbDate(){} -/*************************************************************************/ -//! @brief Set operator= -/*! - \param dt - Date value for set operation. -*/ -void xbDate::operator=( const xbDate & dt ){ - sDate8.Set( dt.Str()); -} -/*************************************************************************/ -//! @brief operator += -/*! - This routine adds lDays to the date if the date is not null. - \param lDays - Number of days to add to the date. -*/ -void xbDate::operator+=( xbInt32 lDays ){ - if( !IsNull() ) - JulToDate8( JulianDays() + lDays ); -} -/*************************************************************************/ -//! @brief operator -= -/*! - This routine subtracts lDays from the date if the date is not null. - \param lDays - Number of days to subtract from the date. -*/ -void xbDate::operator-=( xbInt32 lDays ){ - if( !IsNull() ) - JulToDate8( JulianDays() - lDays ); -} -/*************************************************************************/ -//! @brief operator ++ -/*! - This routine adds one day to the date field if the date is not null. -*/ -void xbDate::operator++(xbInt32){ - if( !IsNull() ) - *this+=1; -} -/*************************************************************************/ -//! @brief operator -- -/*! - This routine subtracts one day from the date field if the date is not null. -*/ -void xbDate::operator--(xbInt32){ - if( !IsNull()) - *this-=1; -} -/*************************************************************************/ -//! @brief operator - -/*! - This routine subtracts one date from another date returning the difference. - \param dt - Date to subtract - \returns Number of days difference or zero if one of the dates is null. -*/ -xbInt32 xbDate::operator-( const xbDate &dt ) const{ - if( !IsNull() && !dt.IsNull() ) - return JulianDays() - dt.JulianDays(); - else - return 0; -} -/*************************************************************************/ -//! @brief operator + -/*! - This routine adds additional days to a valid date field. - \param lCount - Number of days to add. - \returns New date in CCYYMMDD format. -*/ -const char *xbDate::operator+( xbInt32 lCount ){ - if( !IsNull() ) - JulToDate8( JulianDays() + lCount ); - return sDate8.Str(); -} -/*************************************************************************/ -//! @brief operator - -/*! - This routine subtracts days from a valid date field. - \param lCount - Number of days to subtract. - \returns New date in CCYYMMDD format. -*/ -const char *xbDate::operator-( xbInt32 lCount ){ - if( !IsNull() ) - JulToDate8( JulianDays() - lCount ); - return sDate8; -} -/*************************************************************************/ -//! @brief operator == -/*! - This routine compares two dates for equality. - \param dt - Date to compare. - \returns xbTrue - Dates match.<br>xbFalse - Dates don't match. -*/ -xbBool xbDate::operator==( const xbDate &dt ) const{ - if( JulianDays() == dt.JulianDays() ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief operator != -/*! - This routine compares two dates for inequality. - \param dt - Date to compare. - \returns xbTrue - Dates don't match.<br>xbFalse - Dates match. -*/ -xbBool xbDate::operator!=( const xbDate &dt ) const{ - if( JulianDays() != dt.JulianDays() ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief operator < -/*! - This routine compares two dates - \param dt - Date to compare. - \returns xbTrue - Left date is less than right date.<br> - xbFalse - Left date is not less than right date. -*/ -xbBool xbDate::operator<( const xbDate &dt ) const { - if( JulianDays() < dt.JulianDays() ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief > -/*! - This routine compares two dates - \param dt - Date to compare. - \returns xbTrue - Left date is greater than right date.<br> - xbFalse - Left date is not greater than right date. -*/ -xbBool xbDate::operator>( const xbDate &dt ) const { - if( JulianDays() > dt.JulianDays() ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief operator <= -/*! - This routine compares two dates - \param dt - Date to compare. - \returns xbTrue - Left date is less than or equal to right date.<br> - xbFalse - Left date is not less than or equal to right date. -*/ -xbBool xbDate::operator<=( const xbDate &dt ) const { - if( JulianDays() <= dt.JulianDays() ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief operator >= -/*! - This routine compares two dates - \param dt - Date to compare. - \returns xbTrue - Left date is greater than or equal to right date.<br> - xbFalse - Left date is not greater than or equal to right date. -*/ -xbBool xbDate::operator>=( const xbDate &dt ) const { - if( JulianDays() >= dt.JulianDays() ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief Calculate century for a given year. -/*! - This routine calculates a century for a given year. It uses an 80/20 - rolling date window to calculate the century. - - \param iCalcYear - Two digit year to calculate a century for. - \returns Century calculated for the two digit year. -*/ -xbInt16 xbDate::CalcRollingCenturyForYear( xbInt16 iCalcYear ) const { - - xbDate d; - d.Sysdate(); - xbInt16 iThisYear = d.YearOf(); - xbInt16 iThisCentury = d.CenturyOf(); - iThisYear -= (iThisCentury * 100); - if( iThisYear < 80 && iCalcYear < (iThisYear+20) ) - return iThisCentury; - else if( iThisYear >= 80 && - iCalcYear < iThisYear && - iCalcYear >= (iThisYear-80)) - return iThisCentury; - else - return iThisCentury - 1; -} -/*************************************************************************/ -//! @brief Get century for date. -/*! - \returns the century from the valid date.\ or 0 for a null date. -*/ -xbInt16 xbDate::CenturyOf() const { - if( !IsNull() ){ - char Century[3]; - Century[0] = sDate8[1]; - Century[1] = sDate8[2]; - Century[2] = 0x00; - return( atoi( Century )); - } else { - return 0; - } -} -/*************************************************************************/ -//! @brief Get the day of the week. -/*! - \param sOutCharDay - Output character day of week (Sun-Sat). - \returns XB_INVALID_DATE<br>XB_NO_ERROR -*/ -xbInt16 xbDate::CharDayOf( xbString &sOutCharDay ) { - - if( !IsNull()){ - struct tm tblock; - char buf[25]; - - tblock.tm_year = YearOf() - 1900; - tblock.tm_mon = MonthOf() - 1; - tblock.tm_mday = DayOf( XB_FMT_MONTH ); - tblock.tm_hour = 0; - tblock.tm_min = 0; - tblock.tm_sec = 1; - tblock.tm_isdst = -1; - if( mktime( &tblock ) == -1 ){ - sOutCharDay = "" ; - return XB_INVALID_DATE; - } else { - strftime( buf, 25, "%A", &tblock ); - sOutCharDay = buf; - } - } - return XB_NO_ERROR;; -} -/*************************************************************************/ -//! @brief Get the month from the date. -/*! - \param sOutCharMonth - Output character month. - \returns XB_INVALID_DATE<br>XB_NO_ERROR -*/ -xbInt16 xbDate::CharMonthOf( xbString &sOutCharMonth ) { - - if( !IsNull()){ - struct tm tblock; - char buf[25]; - tblock.tm_year = YearOf() - 1900; - tblock.tm_mon = MonthOf() - 1; - tblock.tm_mday = DayOf( XB_FMT_MONTH ); - tblock.tm_hour = 0; - tblock.tm_min = 0; - tblock.tm_sec = 1; - tblock.tm_isdst = -1; - if( mktime( &tblock ) == -1 ){ - sOutCharMonth = ""; - return XB_INVALID_DATE; - } else { - strftime( buf, 25, "%B", &tblock ); - sOutCharMonth = buf; - } - } - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Check a date for valid data. -/*! - \param sDateIn - Date to check for valid formaat of CCYYMMDD. - \returns xbTrue - Valid date.<br>xbFalse - Not a valid date. -*/ -xbBool xbDate::DateIsValid( const xbString &sDateIn ) const { - - xbInt16 iYear, iMonth, iDay; - char sYear[5]; - char sMonth[3]; - char sDay[3]; - - if( sDateIn.Len() != 8 ) - return xbFalse; - - if(!isdigit( sDateIn[1] ) || !isdigit( sDateIn[2] ) || !isdigit( sDateIn[3] ) || - !isdigit( sDateIn[4] ) || !isdigit( sDateIn[5] ) || !isdigit( sDateIn[6] ) || - !isdigit( sDateIn[7] ) || !isdigit( sDateIn[8] ) ) - return xbFalse; - - sDay[0] = sDateIn[7]; - sDay[1] = sDateIn[8]; - sDay[2] = 0x00; - iDay = atoi( sDay ); - - sMonth[0] = sDateIn[5]; - sMonth[1] = sDateIn[6]; - sMonth[2] = 0x00; - iMonth = atoi( sMonth ); - - sYear[0] = sDateIn[1]; - sYear[1] = sDateIn[2]; - sYear[2] = sDateIn[3]; - sYear[3] = sDateIn[4]; - sYear[4] = 0x00; - iYear = atoi( sYear ); - - // valid years are 0001 thru 9999 - if( iYear < 1 || iYear > 9999 || iMonth < 1 || iMonth > 12 || iDay < 1 || iDay > 31 ) - return xbFalse; - - // April, June, September and November have 30 days - if(( iMonth==4 || iMonth==6 || iMonth==9 || iMonth==11 )&& iDay > 30 ) - return xbFalse; - - // check for February with leap year - if( iMonth == 2 ){ - if(( iYear % 4 == 0 && iYear % 100 != 0 ) || iYear % 400 == 0 ){ - if( iDay > 29 ){ - return xbFalse; - } - } else if( iDay > 28 ){ - return xbFalse; - } - } - return xbTrue; -} - -/*************************************************************************/ -//! @brief -/*! - This routine returns the numeric day. - \param iFormat - XB_FMT_WEEK Number of day in WEEK 0-6 ( Sat - Fri )<br> - XB_FMT_MONTH Number of day in MONTH 1-31<br> - XB_FMT_YEAR Number of day in YEAR 1-366 - \returns XB_INVALID_OPTION<br>XB_NO_ERROR -*/ - -xbInt16 xbDate::DayOf( xbInt16 iFormat ) const { - - if( !IsNull()){ - xbInt16 iOutDay = 0; - char sDay[3]; - xbInt16 iDay, iMonth, iYear, iDay2; - - // check for valid format switch - if( iFormat!=XB_FMT_WEEK && iFormat!=XB_FMT_MONTH && iFormat!=XB_FMT_YEAR ) - return XB_INVALID_OPTION; - - if( iFormat == XB_FMT_WEEK ){ - //DayOf( XB_FMT_MONTH, iDay ); - iDay = DayOf( XB_FMT_MONTH ); - iMonth = MonthOf(); - iYear = YearOf(); - - // The following formula uses Zeller's Congruence to determine the day of the week - if( iMonth > 2 ) // init to February - iMonth -= 2; - else { - iMonth += 10; - iYear--; - } - iDay2 = ((13 * iMonth - 1) / 5) + iDay + ( iYear % 100 ) + - (( iYear % 100 ) / 4) + ((iYear /100 ) / 4 ) - 2 * - ( iYear / 100 ) + 77 ; - - iOutDay = iDay2 - 7 * ( iDay2 / 7 ); - iOutDay == 6 ? iOutDay = 0 : iOutDay++; - } - else if( iFormat == XB_FMT_MONTH ){ - sDay[0] = sDate8[7]; - sDay[1] = sDate8[8]; - sDay[2] = 0x00; - iOutDay = atoi( sDay ); - } else { - iOutDay = iAggregatedDaysInMonths[IsLeapYear()][MonthOf()-1] + DayOf( XB_FMT_MONTH ); - } - return iOutDay; - } else { - return 0; - } -} -/*************************************************************************/ -#ifdef XB_DEBUG_SUPPORT -//! @brief Dump date information to stdout. -/*! - \param sTitle - Title for output. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -void xbDate::Dump( const char *sTitle ){ - fprintf( stdout, "%s\n sDate = [%s]\n", sTitle, sDate8.Str() ); -} - -/*************************************************************************/ -//! @brief Dump the date tables. -/*! - This dumps the internal date structures to stdout. - \returns void -*/ - -void xbDate::DumpDateTables(){ - fprintf( stdout, "Date Tables\n" ); - fprintf( stdout, "Month *-Aggragated Days-* *--Days In Month--*\n" ); - fprintf( stdout, " *-NonLeap Leap-* *--NonLeap Leap--*\n" ); - for( int i = 1; i < 13; i++ ) - fprintf( stdout, " %2d %3d %3d %3d %3d\n", i, - iAggregatedDaysInMonths[0][i],iAggregatedDaysInMonths[1][i], - iDaysInMonths[0][i], iDaysInMonths[1][i]); -} -#endif - -/*************************************************************************/ -//! @brief Format MM/DD/YY date -/*! - This routine takes an MM/DD/YY format date as input and populates a - date class with the appropriate YYYYMMDD data. - - \param sCtodInDate - MM/DD/YY formatted date as input. - \returns XB_INVALID_OPTION<br>XB_NO_ERROR -*/ -xbInt16 xbDate::CTOD( const xbString &sCtodInDate ){ - - if( sCtodInDate[1] != ' ' && ( sCtodInDate[3] == '\\' || sCtodInDate[3] == '/') ){ - char yy[3]; - yy[0] = sCtodInDate[7]; - yy[1] = sCtodInDate[8]; - yy[2] = 0x00; - sDate8.Sprintf( "%02d%c%c%c%c%c%c", CalcRollingCenturyForYear( atoi( yy )), - sCtodInDate[7], sCtodInDate[8], sCtodInDate[1], sCtodInDate[2], sCtodInDate[4], sCtodInDate[5] ); - return XB_NO_ERROR; - } - else{ - return XB_INVALID_DATE; - } -} -/*************************************************************************/ -//! @brief -/*! - This routine will reformat a date based on the format specifiers entered - in sFmtIn. If no input format is specified, the routine will use the - system default date format. - - \param sFmtIn - A format specifier with the following paramaters:<br> - - 1) YYDDD - A julian date format - 2) YY or YYYY will print a 2 or 4 digit year - 3) M,MM,MMM or MMMM - M - one digit month if no leading zero - MM - two digit month, contains leading zero - MMM - Jan through Dec - MMMM - January through December - 4) D,DD,DDD or DDDD - D - one digit dayif no leading zero - DD - two digit day, contains leading zero - DDD - Sun through Sat (or julian if YYDDD) - DDDD - Sunday through Saturday - - \param sOutFmtDate - Reformatted output date. - \returns XB_NO_ERROR - <br><br> - Format Examples:<br> - MM/DD/YY<br> - YYYY-MM-DD<br> - DDDDDDDDDDD MMMMMMMMMMM DD,YYYY -*/ -xbInt16 xbDate::FormatDate( const xbString &sFmtIn, xbString &sOutFmtDate ){ - xbUInt32 FmtCtr; - char type; - xbUInt32 iTypeCtr; - xbString ws; - xbString sWrkFmt; - sOutFmtDate = ""; - - if( IsNull()) - return XB_NO_ERROR; - - /* use format for this specific string if available, else use default format */ - if( strlen( sFmtIn ) > 0 ) - sWrkFmt = sFmtIn; - else - sWrkFmt = GetDefaultDateFormat(); - - if( strstr( sWrkFmt.Str(), "YYDDD" )){ - sOutFmtDate.Sprintf( "%c%c%03d", sDate8[3], sDate8[4], DayOf( XB_FMT_YEAR )); - } else { - FmtCtr = 1; - while( FmtCtr <= sWrkFmt.Len() ){ - if( sWrkFmt[FmtCtr] != 'D' && sWrkFmt[FmtCtr] != 'M' && sWrkFmt[FmtCtr] != 'Y' ){ - sOutFmtDate += sWrkFmt[FmtCtr]; - FmtCtr++; - iTypeCtr = 0; - } else { - type = sWrkFmt[FmtCtr]; - iTypeCtr = 0; - while( sWrkFmt[FmtCtr] == type ) { - iTypeCtr++; - FmtCtr++; - } - switch( type ){ - case 'D': - - if( iTypeCtr == 1 ){ - sOutFmtDate += ws.Sprintf( "%d", DayOf( XB_FMT_MONTH )); - } - else if( iTypeCtr == 2 ){ - sOutFmtDate += ws.Sprintf( "%c%c", sDate8[7], sDate8[8] ); - } else { - xbString sCDO; - CharDayOf( sCDO ); - ws.Assign( sCDO, 1, iTypeCtr ); - sOutFmtDate += ws.Str(); - } - break; - - case 'M': - if( iTypeCtr == 1 ){ - sOutFmtDate += ws.Sprintf( "%d", MonthOf()); - } - else if( iTypeCtr == 2 ){ - sOutFmtDate += ws.Sprintf( "%c%c", sDate8[5], sDate8[6] ); - } else { - xbString sCMO; - CharMonthOf( sCMO ); - ws.Assign( sCMO, 1, iTypeCtr ); - sOutFmtDate += ws.Str(); - } - break; - - case 'Y': - if( iTypeCtr == 2 ){ - sOutFmtDate += ws.Sprintf( "%c%c", sDate8[3], sDate8[4] ); - } - else if( iTypeCtr == 4 ){ - sOutFmtDate += ws.Sprintf( "%c%c%c%c", sDate8[1], sDate8[2], sDate8[3], sDate8[4] ); - } - break; - default: - break; - } - } - } - } - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Return the date value. -/*! - \returns char ptr to date value. -*/ -const char * xbDate::Str() const{ - return sDate8.Str(); -}; -/*************************************************************************/ -//! @brief Determine if date is a leap year. -/*! - \returns xbTrue - Is leapyear.<br> xbFalse - Not a leap year. -*/ -xbBool xbDate::IsLeapYear() const { - if( IsNull() ) - return xbFalse; - xbInt16 iYear = YearOf(); - if(( iYear % 4 == 0 && iYear % 100 != 0 ) || iYear % 400 == 0 ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief Determine if date is a leap year. -/*! - \param iYear - Year to check for leap year status. - \returns xbTrue - Is leapyear.<br> xbFalse - Not a leap year. -*/ -xbBool xbDate::IsLeapYear( xbInt16 iYear ) const { - if(( iYear % 4 == 0 && iYear % 100 != 0 ) || iYear % 400 == 0 ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief Determine if date is null date -/*! - \returns xbTrue - If null date.<br> xbFalse - Not a null date. -*/ -xbBool xbDate::IsNull() const { - if( sDate8.Len() < 8 ) - return xbTrue; - else - return xbFalse; -} -/*************************************************************************/ -//! @brief Calculate julian days for a given date. -/*! - \returns The number of days since 01/01/0001 + JUL_OFFSET. -*/ -xbInt32 xbDate::JulianDays() const{ - if( !IsNull()){ - xbInt32 ly = YearOf() - 1; - xbInt32 lDays = ly * 365L + ly / 4L - ly / 100L + ly / 400L; - lDays += DayOf( XB_FMT_YEAR ); - return lDays + JUL_OFFSET; - } else { - return 0; - } -} -/*************************************************************************/ -//! @brief Convert the number of julian days to gregorian date. -/*! - \param lJulDays - Julian days. - \returns XB_NO_ERROR -*/ -xbInt16 xbDate::JulToDate8( xbInt32 lJulDays ) -{ - lJulDays -= JUL_OFFSET; - // calculate the year - xbInt16 iYear = (xbInt16)(lJulDays / 365.24 ); - lJulDays -= (iYear * 365L) + (iYear / 4L) - (iYear / 100L) + (iYear / 400L); - iYear++; - while( lJulDays <= 0 ){ - iYear--; - lJulDays += (365L + IsLeapYear( iYear )); - } - // this for loop calculates the month by comparing the number of days remaining to one of the tables - xbInt16 iIsLeap = IsLeapYear(iYear); - xbInt16 iMonth = 1; - while( ((xbInt16) lJulDays > iAggregatedDaysInMonths[iIsLeap][iMonth]) && (iMonth < 12) ) - iMonth++; - lJulDays -= iAggregatedDaysInMonths[iIsLeap][iMonth-1]; - sDate8.Sprintf( "%04d%02d%02ld", iYear, iMonth, lJulDays ); - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Set the date to the last day of month for a given date. -/*! - This routine sets the last date of the month. - \returns XB_NO_ERROR -*/ -xbInt16 xbDate::LastDayOfMonth(){ - if( !IsNull()) - sDate8.Sprintf( "%4.4d%2.2d%2.2d", YearOf(), MonthOf(), iDaysInMonths[IsLeapYear()][MonthOf()]); - return XB_NO_ERROR; -}; -/*************************************************************************/ -//! @brief Return the month for the date. -/*! - \returns The month of the date. -*/ -xbInt16 xbDate::MonthOf() const { - if( !IsNull()){ - xbInt16 iOutMonth; - char month[3]; - month[0] = sDate8[5]; - month[1] = sDate8[6]; - month[2] = 0x00; - iOutMonth = atoi( month ); - return iOutMonth; - } else { - return 0; - } -} - -/*************************************************************************/ -//! @brief Set the date. -/*! - \param sDateIn - Input date. - \returns XB_NO_ERROR -*/ -xbInt16 xbDate::Set( const xbString & sDateIn ){ - - if( DateIsValid( sDateIn )){ - sDate8 = sDateIn; - } else { - sDate8 = ""; // set to null date if invalid date - } - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief This routine sets up static data tables on startup. -/*! - \returns void -*/ -void xbDate::SetDateTables() { - if( iAggregatedDaysInMonths[1][12] != 366 ){ /* first time called ? */ - - iAggregatedDaysInMonths[0][0] = 0; - iAggregatedDaysInMonths[0][1] = 31; - iAggregatedDaysInMonths[0][2] = 59; - iAggregatedDaysInMonths[0][3] = 90; - iAggregatedDaysInMonths[0][4] = 120; - iAggregatedDaysInMonths[0][5] = 151; - iAggregatedDaysInMonths[0][6] = 181; - iAggregatedDaysInMonths[0][7] = 212; - iAggregatedDaysInMonths[0][8] = 243; - iAggregatedDaysInMonths[0][9] = 273; - iAggregatedDaysInMonths[0][10] = 304; - iAggregatedDaysInMonths[0][11] = 334; - iAggregatedDaysInMonths[0][12] = 365; - iAggregatedDaysInMonths[1][0] = 0; - iAggregatedDaysInMonths[1][1] = 31; - iAggregatedDaysInMonths[1][2] = 60; - iAggregatedDaysInMonths[1][3] = 91; - iAggregatedDaysInMonths[1][4] = 121; - iAggregatedDaysInMonths[1][5] = 152; - iAggregatedDaysInMonths[1][6] = 182; - iAggregatedDaysInMonths[1][7] = 213; - iAggregatedDaysInMonths[1][8] = 244; - iAggregatedDaysInMonths[1][9] = 274; - iAggregatedDaysInMonths[1][10] = 305; - iAggregatedDaysInMonths[1][11] = 335; - iAggregatedDaysInMonths[1][12] = 366; - - iDaysInMonths[0][0] = 0; - iDaysInMonths[0][1] = 31; - iDaysInMonths[0][2] = 28; - iDaysInMonths[0][3] = 31; - iDaysInMonths[0][4] = 30; - iDaysInMonths[0][5] = 31; - iDaysInMonths[0][6] = 30; - iDaysInMonths[0][7] = 31; - iDaysInMonths[0][8] = 31; - iDaysInMonths[0][9] = 30; - iDaysInMonths[0][10] = 31; - iDaysInMonths[0][11] = 30; - iDaysInMonths[0][12] = 31; - iDaysInMonths[1][0] = 0; - iDaysInMonths[1][1] = 31; - iDaysInMonths[1][2] = 29; - iDaysInMonths[1][3] = 31; - iDaysInMonths[1][4] = 30; - iDaysInMonths[1][5] = 31; - iDaysInMonths[1][6] = 30; - iDaysInMonths[1][7] = 31; - iDaysInMonths[1][8] = 31; - iDaysInMonths[1][9] = 30; - iDaysInMonths[1][10] = 31; - iDaysInMonths[1][11] = 30; - iDaysInMonths[1][12] = 31; - } -} -/*************************************************************************/ -//! @brief Set the date equal to the system date. -/*! - \returns XB_NO_ERROR -*/ -xbInt16 xbDate::Sysdate(){ - - #ifdef HAVE__LOCALTIME64_S_F - __time64_t timer; - _time64( &timer ); - struct tm tblock; - _localtime64_s( &tblock, &timer ); - tblock.tm_year += 1900; - tblock.tm_mon++; - sDate8.Sprintf( "%4d%02d%02d", tblock.tm_year, tblock.tm_mon, tblock.tm_mday ); - #else - time_t timer; - timer = time( &timer ); - struct tm *tblock; - tblock = localtime( &timer ); - tblock->tm_year += 1900; - tblock->tm_mon++; - sDate8.Sprintf( "%4d%02d%02d",tblock->tm_year,tblock->tm_mon,tblock->tm_mday ); - #endif - - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Returns the year of the date. -/*! - \returns The year of the date. -*/ -xbInt16 xbDate::YearOf() const { - if( !IsNull()){ - char year[5]; - year[0] = sDate8[1]; - year[1] = sDate8[2]; - year[2] = sDate8[3]; - year[3] = sDate8[4]; - year[4] = 0x00; - xbInt16 iOutYear = atoi( year ); - return iOutYear; - } else { - return 0; - } -}; -} /* namespace */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf.cpp deleted file mode 100755 index 8904a6d..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf.cpp +++ /dev/null @@ -1,4533 +0,0 @@ -/* xbdbf.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 - -*/ - -#include "xbase.h" - - -namespace xb{ - -/************************************************************************/ -//! @brief Constructor -/*! - \param x Pointer to xbXbase -*/ -xbDbf::xbDbf( xbXBase * x ) : xbFile( x ){ - 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(); -} -/************************************************************************/ -void xbDbf::InitVars() -{ - iNoOfFields = 0; - iDbfStatus = XB_CLOSED; - ulCurRec = 0L; - cVersion = 0x00; - cUpdateYY = 0x00; - cUpdateMM = 0x00; - cUpdateDD = 0x00; - ulNoOfRecs = 0L; - uiHeaderLen = 0x00; - uiRecordLen = 0x00; - cTransactionFlag = 0x00; - cEncryptionFlag = 0x00; - cIndexFlag = 0x00; - cLangDriver = 0x00; - iFileVersion = 0; /* Xbase64 file version */ - iAutoCommit = -1; - - SetFileName ( "" ); - sAlias.Set ( "" ); - SetDirectory ( GetDataDirectory()); - - #ifdef XB_LOCKING_SUPPORT - iLockFlavor = -1; - bTableLocked = xbFalse; - bHeaderLocked = xbFalse; - ulAppendLocked = 0; - SetAutoLock( -1 ); - lloRecLocks.SetDupKeys( xbFalse ); - #endif // XB_LOCKING_SUPPORT - - #ifdef XB_INDEX_SUPPORT - ixList = NULL; - pCurIx = NULL; - vpCurIxTag = NULL; - sCurIxType = ""; - ClearTagList(); - #endif // XB_INDEX_SUPPORT - - #ifdef XB_MEMO_SUPPORT - Memo = NULL; - #endif // XB_MEMO_SUPPORT - - #ifdef XB_INF_SUPPORT - llInfData.Clear(); - #endif // XB_INF_SUPPORT -} - -/************************************************************************/ -//! @brief Destructor -xbDbf::~xbDbf(){ - - // is there is an uncommited update, discard it. - // as we don't know if it is an append or an update - if( iDbfStatus == XB_UPDATED ) - Abort(); - - if( iDbfStatus != XB_CLOSED ) - Close(); - - if( SchemaPtr ){ - free( SchemaPtr ); - SchemaPtr = NULL; - } - if( RecBuf ){ - free( RecBuf ); - RecBuf = NULL; - } - if( RecBuf2){ - free( RecBuf2 ); - RecBuf2 = NULL; - } - if( RecBuf ){ - free( RecBuf ); - RecBuf = NULL; - } - - #ifdef XB_BLOCKREAD_SUPPORT - if( bBlockReadEnabled ) - DisableBlockReadProcessing(); - #endif // XB_BLOCKREAD_SUPPORT - - Close(); -} -/************************************************************************/ -//! @brief Abort any uncommited changes for the current record buffer. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::Abort(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - if( iDbfStatus == XB_UPDATED ){ - #ifdef XB_MEMO_SUPPORT - if( MemoFieldsExist()){ - if(( iRc = Memo->Abort()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - #endif - memcpy( RecBuf, RecBuf2, uiRecordLen ); - iDbfStatus = XB_OPEN; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Abort() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Add an index to the internal list of indices for this table. -/*! - The index list is used during any table update process to update any open - index file. Index files can contain one or more tags. Temporary tags - are not included here because they are created after a table is open - and will be deleted when the table is closed. - - \param ixIn Pointer to index object for a given index file. - \param sFmt NDX, MDX or TDX. - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbDbf::AddIndex( xbIx * ixIn, const xbString &sFmt ){ - - xbIxList *ixt; // this - if(( ixt = (xbIxList *) malloc( sizeof( xbIxList ))) == NULL ) - return XB_NO_ERROR; - - ixt->ix = ixIn; - ixt->next = NULL; - ixt->sFmt = new xbString( sFmt ); - ixt->sFmt->ToUpperCase(); - - if( ixList ){ - xbIxList *ixn = ixList; // next - while( ixn->next ){ - ixn = ixn->next; - } - ixn->next = ixt; - } else { - ixList = ixt; - } - return XB_NO_ERROR; -} -#endif // XB_INDEX_SUPPORT - - -/************************************************************************/ -//! @brief Append the current record to the data file. -/*! - This method attempts to append the contents of the current record buffer - to the end of the DBF file, updates the file date, number of records in the file - and updates any open indices associated with this data file.<br> - - To add a record, an application would typically blank the record buffer, - update various fields in the record buffer, then append the record.<br> - - The append method performs the following tasks:<br> - 1) Create new index key values<br> - 2) Lock the table<br> - 3) Lock append bytes<br> - 4) Lock indices<br> - 5) Read the dbf header<br> - 6) Check for dup keys<br> - 7) Calc last update date, no of recs<br> - 8) Add keys<br> - 9) Unlock indices<br> - 10) Update file header<br> - 11) Unlock file header<br> - 12) Append record<br> - 13) Unlock append bytes<br> - -Note: Locking memo files is not needed as the memo file updates are handled outside of the append method.<br> - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::AppendRecord(){ - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - xbUInt32 ulSaveCurRec = 0; - - try{ - #ifdef XB_INDEX_SUPPORT - xbIxList *ixList = GetIxList(); - // do this step first before anything is locked, reduce lock time as much as possible - while( ixList ){ - - // std::cout << "xbDbf::CreateKeys(x)\n"; - if(( iRc = ixList->ix->CreateKeys( 1 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - ixList = ixList->next; - } - #endif // XB_INDEX_SUPPORT - - // lock everything up for an update - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockHeader( XB_LOCK )) != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ) { - return iRc; - } else { - iErrorStop = 110; - throw iRc; - } - } - if(( iRc = LockAppend( XB_LOCK )) != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ){ - LockHeader( XB_UNLOCK ); - return iRc; - } else { - iErrorStop = 120; - throw iRc; - } - } - - #ifdef XB_INDEX_SUPPORT - if(( iRc = LockIndices( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - #endif // XB_INDEX_SUPPORT - - } - #endif // XB_LOCKING_SUPPORT - if(( iRc = ReadHeader( 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - #ifdef XB_INDEX_SUPPORT - ixList = GetIxList(); - - while( ixList ){ - if(( iRc = ixList->ix->CheckForDupKeys()) != 0 ){ - if( iRc < 0 ){ - iErrorStop = 150; - throw iRc; - } - return XB_KEY_NOT_UNIQUE; - } - ixList = ixList->next; - } - - #endif // XB_INDEX_SUPPORT - - // calculate the latest header information - xbDate d; - d.Sysdate(); - cUpdateYY = (char) d.YearOf() - 1900; - cUpdateMM = (char) d.MonthOf(); - cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); - ulSaveCurRec = ulCurRec; - ulNoOfRecs++; - ulCurRec = ulNoOfRecs; - - #ifdef XB_INDEX_SUPPORT - - - ixList = GetIxList(); - while( ixList ){ - if(( iRc = ixList->ix->AddKeys( ulCurRec )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - ixList = ixList->next; - } - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock ){ - if(( iRc = LockIndices( XB_UNLOCK )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - #endif // XB_LOCKING_SUPPORT - #endif // XB_INDEX_SUPPORT - - // rewrite the header record - if(( iRc = WriteHeader( 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock ){ - if(( iRc = LockHeader( XB_UNLOCK )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - } - #endif - - // write the last record - if(( iRc = xbFseek( (uiHeaderLen+((xbInt64)(ulNoOfRecs-1)*uiRecordLen)), 0 )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - - if(( iRc = xbFwrite( RecBuf, uiRecordLen, 1 )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - - // write the end of file marker - if(( iRc = xbFputc( XB_CHAREOF )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock ){ - if(( iRc = LockAppend( XB_UNLOCK )) != XB_NO_ERROR ){ - iErrorStop = 230; - throw( iRc ); - } - } - #endif // XB_LOCKING_SUPPORT - - } - catch (xbInt16 iRc ){ - if( ulSaveCurRec != 0 ){ - ulCurRec = ulSaveCurRec; - ulNoOfRecs--; - } - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock ){ - #ifdef XB_INDEX_SUPPORT - LockIndices( XB_UNLOCK ); - #endif // XB_INDEX_SUPPORT - LockAppend( XB_UNLOCK ); - LockHeader( XB_UNLOCK ); - } - #endif // XB_LOCKING_SUPPORT - - if( iRc != XB_LOCK_FAILED && iRc != XB_KEY_NOT_UNIQUE ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Append() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - - if( iRc == XB_NO_ERROR ) - iDbfStatus = XB_OPEN; - return iRc; -} - -/************************************************************************/ -#ifdef XB_INF_SUPPORT -//! @brief Asscoiate a non production index to a DBF file. -/*! - - The original Dbase (TM) software supported non production indices (NDX) and production indices (MDX). - The production indices are opened automatically when the DBF file is opened but the non-production - indices are not. This method is specific to the Xbas64 library and providex a means to link non production - NDX index files to the DBF file so they will be opened automatically when the DBF file is opened.<br> - - This routine requires INF support be enabled when building the library.<br> - This routine creates a file with the same name as the DBF file, but with an extension of INF.<br> - - - \param sIxType Currently only NDX. Future versions will support additional non prod index types. - \param sIxName The index name. - \param iOpt 0 - Add index to .INF if not already there<br> - 1 - Remove index from .INF if exists - - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbDbf::AssociateIndex( const xbString &sIxType, const xbString &sIxName, xbInt16 iOpt ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - xbString sIxTypeIn = sIxType; - sIxTypeIn.Trim(); - xbString sIxNameIn = sIxName; - sIxNameIn.Trim(); - - if( sIxTypeIn != "NDX" || sIxName == "" ) - return XB_INVALID_INDEX; - - if(( iRc = LoadInfData()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // check if entry exists - xbLinkListNode<xbString> * llN = llInfData.GetHeadNode(); - xbBool bFound = xbFalse; - xbString s; - - while( llN && !bFound ){ - s = llN->GetKey(); - if( s.Len() > 0 ){ - if( sIxNameIn == s ) - bFound = xbTrue; - } - llN = llN->GetNextNode(); - } - - xbBool bUpdated = xbFalse; - if( iOpt == 0 && !bFound ){ - s.Sprintf( "%s%c%c", sIxName.Str(), 0x0d, 0x0a ); - llInfData.InsertAtEnd( s ); - bUpdated = xbTrue; - - } else if( iOpt == 1 && bFound ){ - llInfData.RemoveByVal( s ); - bUpdated = xbTrue; - } - - if( bUpdated ){ - if(( iRc = SaveInfData()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - - } catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::AssociateIndex() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INF_SUPPORT - -/************************************************************************/ -//! @brief Blank the record buffer. -/*! - - This method would typically be called to initialize the record buffer before - updates are applied to append a new record. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::BlankRecord() -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - - if( iDbfStatus == XB_CLOSED ){ - iErrorStop = 100; - iRc = XB_NOT_OPEN; - throw iRc; - } - - if( iDbfStatus == XB_UPDATED ){ - if( GetAutoCommit() == 1 ){ - if(( iRc = Commit()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } else { - if(( iRc = Abort()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - } - ulCurRec = 0; - memset( RecBuf, 0x20, uiRecordLen ); - memset( RecBuf2, 0x20, uiRecordLen ); - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::BlankRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - return iRc; -} -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -/*! - This method is used to check an index tag's intgerity. - - \param iTagOpt 0 - Check current tag<br> - 1 - Check all tags<br> - - \param iOutputOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::CheckTagIntegrity( xbInt16 iTagOpt, xbInt16 iOutputOpt ){ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - if( iTagOpt == 0 ){ - if( pCurIx ) - return pCurIx->CheckTagIntegrity( vpCurIxTag, iOutputOpt ); - else - return XB_INVALID_TAG; - - } else { - - xbLinkListNode<xbTag *> *llN = GetTagList(); - xbTag *pTag; - - while( llN ){ - pTag = llN->GetKey(); - if(( iRc = pTag->GetIx()->CheckTagIntegrity( pTag->GetVpTag(), iOutputOpt )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - llN = llN->GetNextNode(); - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::CheckTagIntegrity() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -/*! - This method is used to reindex / rebuild index tag. - - \param iTagOpt 0 - Reindex current tag<br> - 1 - Reindex all tags<br> - 2 - Reindex for tag identified by vpTag - \param iErrorOpt 0 - Don't delete tag on reindex failure<br> - 1 - Delete tag on reindex failure - \param vpTag if option 2 used, pointer to tag to reindex - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::Reindex( xbInt16 iTagOpt, xbInt16 iErrorOpt, xbIx **ppIx, void **vppTag ){ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - void *vp; - - xbString sType; - xbString sTagName; - - if( iTagOpt < 0 || iTagOpt > 2 || (iTagOpt == 2 && (!ppIx || !vppTag ))) - return XB_INVALID_OPTION; - - - #ifdef XB_BLOCKREAD_SUPPORT - xbBool bOriginalBlockReadSts = GetBlockReadStatus(); - #endif - - try{ - - #ifdef XB_BLOCKREAD_SUPPORT - if( !bOriginalBlockReadSts ) - EnableBlockReadProcessing(); - #endif - - if( iTagOpt == 0 ){ - if( pCurIx ){ - - if(( iRc = pCurIx->Reindex( &vpCurIxTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - return iRc; - } else { - return XB_INVALID_TAG; - } - - } else if( iTagOpt == 1 ) { - - xbLinkListNode<xbTag *> *llN = GetTagList(); - xbTag *pTag; - - while( llN ){ - pTag = llN->GetKey(); - vp = pTag->GetVpTag(); - if(( iRc = pTag->GetIx()->Reindex( &vp )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - llN = llN->GetNextNode(); - } - } else if( iTagOpt == 2 ){ - - // xbIx *pIx; - // pIx = *ppIx; - xbIx *pIx = *ppIx; - // void *vpTag; - // vpTag = *vppTag; - void *vpTag = *vppTag; - - if(( iRc = pIx->Reindex( &vpTag )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Reindex() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - #ifdef XB_BLOCKREAD_SUPPORT - if( !bOriginalBlockReadSts ) - DisableBlockReadProcessing(); - #endif - - return iRc; -} - -/************************************************************************/ -// @brief Clear the index tag list. -/* - Protected method. Clears the list inf index tags. - \returns void. -*/ -void xbDbf::ClearTagList(){ - - xbTag *pTag; - xbBool bDone = xbFalse; - while( llTags.GetNodeCnt() > 0 && !bDone ){ - if( llTags.RemoveFromFront( pTag ) != XB_NO_ERROR ){ - bDone = xbTrue; - } else { - if( pTag ) - delete pTag; - } - } -} -#endif // XB_INDEX_SUPPORT - -/************************************************************************/ -//! @brief Close DBF file/table. -/*! - This routine flushes any remaining updates to disk, closes the DBF file and - any associated memo and index files. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::Close(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - - if(iDbfStatus == XB_CLOSED) - return XB_NO_ERROR; - - else 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; - } - } - } - - if(SchemaPtr){ - free( SchemaPtr ); - SchemaPtr = NULL; - } - if(RecBuf){ - free( RecBuf ); - RecBuf = NULL; - } - if(RecBuf2){ - free( RecBuf2 ); - RecBuf2 = NULL; - } - - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ){ - Memo->CloseMemoFile(); - delete Memo; - Memo = NULL; - } - #endif - - // close any open index files, remove from the ix list - #ifdef XB_INDEX_SUPPORT - while( ixList ){ - ixList->ix->Close(); - RemoveIndex( ixList->ix ); - } - #endif - - if(( iRc = xbase->RemoveTblFromTblList( this )) != XB_NO_ERROR ){ - xbString sMsg; - sMsg.Sprintf( "Alias = [%s]", sAlias.Str()); - xbase->WriteLogMessage( sMsg.Str() ); - iErrorStop = 120; - throw iRc; - } - xbFclose(); - InitVars(); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Close() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Close an open index file -/*! - All index files are automatically closed when the DBF file is closed. - Under normal conditions, it is not necessary to explicitly close an index file - with this routine. Any updates posted to a DBF file while an index is closed - will not be reflected in the closed index file. - - \param pIx Pointer to index object to close. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::CloseIndexFile( xbIx *pIx ){ - - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - - try{ - - // verify index is open and in the list - xbBool bFound = xbFalse; - xbIxList *p = GetIxList(); - while( p && !bFound ){ - if( pIx == p->ix ) - bFound = xbTrue; - p = p->next; - } - if( !bFound ){ - iErrorStop = 100; - iRc = XB_NOT_OPEN; - throw iRc; - } - // close it - if(( iRc = pIx->Close()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // remove it from the list - if(( iRc = RemoveIndex( pIx )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - // refresh the tag list - if(( iRc = UpdateTagList()) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( pIx == pCurIx ){ - pCurIx = NULL; - vpCurIxTag = NULL; - sCurIxType = ""; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::CloseIndexFile() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INDEX_SUPPORT - -/************************************************************************/ -//! @brief Commit updates to disk -/*! - - This routine commits any pending updates to disk. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::Commit(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( iDbfStatus == XB_UPDATED ){ - if( ulCurRec == 0 ){ - if(( iRc = AppendRecord()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } else { - if(( iRc = PutRecord( ulCurRec )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - } - } - catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Commit() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; -} - -/************************************************************************/ -//! @brief Copy table (dbf) file structure. -/*! - - This routine will copy the structure of a dbf file and if successful - return a pointer to the new table in an open state. - - \param dNewTable Reference to new table object. - \param sNewTableName New table (dbf) name. - \param sNewTableAlias Alias name of new table. - \param iOverlay xbTrue - Overlay existing file.<br> - xbFalse - Don't overlay existing file. - \param iShareMode XB_SINGLE_USER<br> - XB_MULTI_USER - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -//! Copy DBF structure -/*! -*/ -xbInt16 xbDbf::CopyDbfStructure( xbDbf * dNewTable, const xbString &sNewTableName, - const xbString & sNewTableAlias, xbInt16 iOverlay, xbInt16 iShareMode ) { - -// If successful, the table is returned in an open state after executing this method - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbSchema *newTableSchema = NULL; - - try{ - - if( iDbfStatus == XB_CLOSED ){ - iErrorStop = 100; - iRc = XB_DBF_FILE_NOT_OPEN; - throw iRc; - } - - if( !dNewTable ){ - iErrorStop = 110; - iRc = XB_INVALID_OBJECT; - throw iRc; - } - - // Get the number of schema entries for this table - xbInt32 lSchemaRecCnt = GetFieldCnt() + 1; - - // Allocate a Schema = No Of Fields + 1 - if((newTableSchema=(xbSchema *)malloc( (size_t) lSchemaRecCnt * sizeof(xbSchema)))==NULL){ - iErrorStop = 120; - iRc = XB_NO_MEMORY; - throw iRc; - } - - // Populate the Schema - xbInt32 l; - for( l = 0; l < lSchemaRecCnt-1; l++ ){ - memset( newTableSchema[l].cFieldName, 0x00, 11 ); - for( int x = 0; x < 10 && SchemaPtr[l].cFieldName[x]; x++ ) - newTableSchema[l].cFieldName[x] = SchemaPtr[l].cFieldName[x]; - newTableSchema[l].cType = SchemaPtr[l].cType; - newTableSchema[l].iFieldLen = SchemaPtr[l].cFieldLen; - newTableSchema[l].iNoOfDecs = SchemaPtr[l].cNoOfDecs; - } - - // set the last one to zeroes - memset( newTableSchema[l].cFieldName, 0x00, 11 ); - newTableSchema[l].cType = 0; - newTableSchema[l].iFieldLen = 0; - newTableSchema[l].iNoOfDecs = 0; - - dNewTable->SetVersion(); - #ifdef XB_MEMO_SUPPORT - if( MemoFieldsExist()) - dNewTable->SetCreateMemoBlockSize( Memo->GetBlockSize() ); - #endif - - // Call the create a table function - if(( iRc = dNewTable->CreateTable( sNewTableName, sNewTableAlias, newTableSchema, iOverlay, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbDbf::CopyDbfStructure() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - if( newTableSchema ) - free( newTableSchema ); - - return iRc; -} - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Create a new tag (index) for this dbf file (table). -/*! - This routine creates a new tag (index) on a dbf file. The library currently supports NDX, MDX ans TDX. - indices. If you don't have a specific need for an NDX file, use MDX. - - \param sIxType "MDX", "NDX" or "NTX". - \param sName Index or tag name. - \param sKey Index key expression, - \param sFilter Filter expression. Not applicable for NDX indices. - \param iDescending xbTrue for descending. Not available for NDX indices.<br> - xbFalse - ascending - \param iUnique xbTrue - Unique index<br>xbFalse - Not unique index. - \param iOverLay xbTrue - Overlay if exists<br> - xbFalse - Don't overlay if it exists. - \param pIxOut Pointer to pointer of output index object. - \param vpTagOut Pointer to pointer of newly created tag, - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::CreateTag( const xbString &sIxType, const xbString &sName, const xbString &sKey, const xbString &sFilter, - xbInt16 iDescending, xbInt16 iUnique, xbInt16 iOverLay, xbIx **pIxOut, void **vpTagOut ){ - - // this routine is used to open indices and link to files - - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif - - try{ - xbString sType = sIxType; - sType.ToUpperCase(); - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw( iRc ); - } - bLocked = xbTrue; - } - #endif // XB_LOCKING_SUPPORT - - if( sIxType == "" ){ - iErrorStop = 110; - iRc = XB_INVALID_OPTION; - throw iRc; - - #ifdef XB_NDX_SUPPORT - } else if( sIxType == "NDX" ){ - xbIxNdx *ixNdx = new xbIxNdx( this ); - - if(( iRc = ixNdx->CreateTag( sName, sKey, sFilter, iDescending, iUnique, iOverLay, vpTagOut )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - if(( iRc = AddIndex( ixNdx, sIxType )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - *pIxOut = ixNdx; - - - - // Set the current tag if one not already set - if( sCurIxType == "" ){ - sCurIxType = "NDX"; - pCurIx = ixNdx; - vpCurIxTag = ixNdx->GetTag(0); - } - - #endif - - #ifdef XB_MDX_SUPPORT - } else if( sIxType == "MDX" ){ - - if( GetVersion() == 3 ){ // MDX indexes were version 4 and higher - iErrorStop = 140; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - xbIxMdx *ixMdx; - xbString s; - // look through the index list and see if there is an mdx pointer we can grab - xbBool bMdxFound = xbFalse; - xbIxList *ixList = GetIxList(); - while( ixList && !bMdxFound ){ - s = ixList->sFmt->Str(); - if( s == "MDX" ){ - ixMdx = (xbIxMdx *) ixList->ix; - bMdxFound = xbTrue; - } - ixList = ixList->next; - } - - if( !bMdxFound ) - ixMdx = new xbIxMdx( this ); - - if(( iRc = ixMdx->CreateTag( sName, sKey, sFilter, iDescending, iUnique, iOverLay, vpTagOut )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - if( !bMdxFound ){ - if(( iRc = AddIndex( ixMdx, "MDX" )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - - cIndexFlag = 0x01; - if(( iRc = WriteHeader( 1, 0 )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - *pIxOut = ixMdx; - - // set the current tag if one not already set - if( sCurIxType == "" ){ - sCurIxType = "MDX"; - pCurIx = ixMdx; - vpCurIxTag = ixMdx->GetTag(0); - } - #endif - - #ifdef XB_TDX_SUPPORT - } else if( sIxType == "TDX" ){ - - if( GetVersion() == 3 ){ // TDX indexes were version 4 and higher - iErrorStop = 140; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - xbIxTdx *ixTdx; - xbString s; - // look through the index list and see if there is an mdx pointer we can grab - xbBool bTdxFound = xbFalse; - xbIxList *ixList = GetIxList(); - while( ixList && !bTdxFound ){ - s = ixList->sFmt->Str(); - if( s == "TDX" ){ - ixTdx = (xbIxTdx *) ixList->ix; - bTdxFound = xbTrue; - } - ixList = ixList->next; - } - if( !bTdxFound ) - ixTdx = new xbIxTdx( this ); - - if(( iRc = ixTdx->CreateTag( sName, sKey, sFilter, iDescending, iUnique, iOverLay, vpTagOut )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if( !bTdxFound ){ - if(( iRc = AddIndex( ixTdx, "TDX" )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - } - *pIxOut = ixTdx; - - // set the current tag if one not already set - if( sCurIxType == "" ){ - - sCurIxType = "TDX"; - pCurIx = ixTdx; - vpCurIxTag = ixTdx->GetTag(0); - } - - #endif - - } else { - iErrorStop = 200; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - if(( iRc = UpdateTagList()) != XB_NO_ERROR ){ - iErrorStop = 300; - throw iRc; - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::CreateTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - #ifdef XB_LOCKING_SUPPORT - if( bLocked ) - LockTable( XB_UNLOCK ); - #endif // XB_LOCKING_SUPPORT - - return iRc; -} -#endif // XB_INDEX_SUPPORT - -/************************************************************************/ -//! @brief Delete or undelete all records in a dbf file (table). -/*! - This routine deletes or un-deletes all records. The xbase file format contains - a leading one byte character used for flagging a record as deleted. When a record - is deleted, it's not physically removed from the file, the first byte is flagged as deleted. - - \param iOption 0 - Delete all records.<br> - 1 - Un-delete all deleted records. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::DeleteAll( xbInt16 iOption ) -{ - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - xbUInt32 ulRecCnt; - - try{ - if(( iRc = GetRecordCnt( ulRecCnt )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if( ulRecCnt == 0 ) - return XB_NO_ERROR; - for( xbUInt32 ul = 0; ul < ulRecCnt; ul++ ){ - if(( iRc = GetRecord( ul+1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if( iOption == 0 ){ /* delete all option */ - if( !RecordDeleted()){ - if(( iRc = DeleteRecord()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = Commit()) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - } else { /* undelete all option */ - if( RecordDeleted()){ - if(( iRc = UndeleteRecord()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if(( iRc = Commit()) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - } - } - } - catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbDbf::DeleteAll() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; -} - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief -/*! - This routine deletes all indices associated with the dbf file. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::DeleteAllIndexFiles(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif // XB_LOCKING_SUPPORT - - #ifdef XB_INF_SUPPORT - xbString sIxName; - #endif // XB_INF_SUPPORT - - try{ - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw( iRc ); - } - bLocked = xbTrue; - } - #endif // XB_LOCKING_SUPPORT - - // close any open index files, delete it, remove from the ix list - while( ixList ){ - - // next two lines for debugging - ixList->ix->GetFileNamePart( sIxName ); - ixList->ix->Close(); - if(( iRc = ixList->ix->xbRemove()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - #ifdef XB_INF_SUPPORT - // if XB_INF_SUPPORT is enabled, all open non prod indices should be in here - if( *ixList->sFmt != "MDX" && *ixList->sFmt != "TDX" ){ // production and temp indices not stored in .INF dataset - if(( iRc = ixList->ix->GetFileNamePart( sIxName )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = AssociateIndex( *ixList->sFmt, sIxName, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - #endif - RemoveIndex( ixList->ix ); - } - } catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::DeleteAllIndexFiles() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - #ifdef XB_LOCKING_SUPPORT - if( bLocked ) - LockTable( XB_UNLOCK ); - #endif // XB_LOCKING_SUPPORT - return iRc; -} -#endif // XB_INDEX_SUPPORT - -/************************************************************************/ -//! @brief Delete all records. -/*! - This routine deletes all the records in a table / dbf file. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::DeleteAllRecords(){ - return DeleteAll( 0 ); -} - -/************************************************************************/ -#ifdef XB_INF_SUPPORT -//! @brief Delete .INF File -/*! - The original Dbase (TM) software supported non production indices (NDX) and production indices (MDX). - The production indices are opened automatically when the DBF file is opened but the non-production - indices are not. This method is specific to the Xbas64 library and providex a means to link non production - NDX index files to the DBF file so they will be opened automatically when the DBF file is opened.<br> - - This routine requires INF support be enabled when building the library.<br> - This routine deletes the .INF file.<br> - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::DeleteInfData(){ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - xbString sInfFileName; - if(( iRc = GetInfFileName( sInfFileName )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - xbFile f( xbase ); - f.SetFileName( sInfFileName ); - if( f.FileExists()){ - if(( iRc = f.xbRemove()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - } catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::DeleteInfData() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INF_SUPPORT - -/************************************************************************/ -//! @brief Delete the current record. -/*! - This routine flags the current record for deletion if it's not already flagged. - - \returns XB_NO_ERROR<br> - XB_INVALID_RECORD -*/ - -xbInt16 xbDbf::DeleteRecord(){ - if( RecBuf && ulCurRec > 0 ){ - if( RecBuf[0] != 0x2a){ - if( iDbfStatus != XB_UPDATED ){ - iDbfStatus = XB_UPDATED; - memcpy( RecBuf2, RecBuf, uiRecordLen ); // save off original before making any updates - } - RecBuf[0] = 0x2a; - } - return XB_NO_ERROR; - } - else - return XB_INVALID_RECORD; -} -/************************************************************************/ -//! @brief Delete a table. -/*! - This routine deletes a given table, associated index files if any, the - memo file if any and the .INF file if any. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::DeleteTable(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - #ifdef XB_LOCKING_SUPPORT - xbBool bTableLocked = xbFalse; - #endif - - try{ - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } else { - bTableLocked = xbTrue; - } - } - #endif // XB_LOCKING_SUPPORT - - #ifdef XB_INDEX_SUPPORT - if(( iRc = DeleteAllIndexFiles()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - #ifdef XB_INF_SUPPORT - if(( iRc = DeleteInfData()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - #endif // XB_INF_SUPPORT - #endif // XB_INDEX_SUPPORT - - #ifdef XB_MEMO_SUPPORT - xbInt16 iMemoFldCnt = GetMemoFieldCnt(); - xbString sMemoFileName; - if(iMemoFldCnt > 0 ){ - sMemoFileName = Memo->GetFqFileName(); - } - #endif // XB_MEMO_SUPPORT - - if(( iRc = Close()) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - if(( iRc = xbRemove()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ){ - xbFile f( xbase ); - if(( iRc = f.xbRemove( sMemoFileName )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - #endif // XB_MEMO_SUPPORT - - } catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::DeleteTable() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - #ifdef XB_LOCKING_SUPPORT - if( bTableLocked ) - LockTable( XB_UNLOCK ); - #endif // XB_LOCKING_SUPPORT - return iRc; -} - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Delete an index tag. - -/*! - This routine deletes an index tag - \param sIxType Either "NDX", "MDX" or "TDX".<br> - \param sName Tag name to delete.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::DeleteTag( const xbString &sIxType, const xbString &sName ){ - - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - xbIx *pIx = NULL; - - #ifdef XB_LOCKING_SUPPORT - xbBool bTableLocked = xbFalse; - #endif - - try{ - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !GetTableLocked() ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } else { - bTableLocked = xbTrue; - } - } - #endif // XB_LOCKING_SUPPORT - - if( sIxType == "" ){ - iErrorStop = 110; - iRc = XB_INVALID_OPTION; - throw iRc; - - #ifdef XB_NDX_SUPPORT - } else if( sIxType == "NDX" ){ - - xbIxList *ixl = ixList; - xbBool bDone = xbFalse; - while( ixl && !bDone ){ - - if( ixl->ix->GetTagName( NULL ) == sName ){ - bDone = xbTrue; - - // remove from .INF if it's there - #ifdef XB_INF_SUPPORT - if(( iRc = AssociateIndex( "NDX", sName, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - #endif // XB_INF_SUPPORT - - if(( iRc = ixl->ix->DeleteTag( ixl->ix->GetTag( 0 ))) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - if(( iRc = RemoveIndex( ixl->ix )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - if( !ixList || ixl->ix == pCurIx ) - SetCurTag( "", NULL, NULL ); - - } - ixl = ixl->next; - } - #endif - - #ifdef XB_MDX_SUPPORT - } else if( sIxType == "MDX" ){ - xbIxList *ixl = ixList; - xbIxList *ixlNext; - xbIxList *ixlPrev = NULL; - xbBool bDone = xbFalse; - xbIxMdx *pMdx; - xbMdxTag *pMdxTag; - xbInt16 iTagCnt = 0; - - while( ixl && !bDone ){ - ixlNext = ixl->next; - pMdx = (xbIxMdx *) ixl->ix; - iTagCnt = pMdx->GetTagCount(); - for( xbInt16 i = 0; i < iTagCnt && !bDone; i++ ){ - pMdxTag = (xbMdxTag *) pMdx->GetTag( i ); - if( pMdx->GetTagName( pMdxTag ) == sName ){ - bDone = xbTrue; - iRc = pMdx->DeleteTag( pMdxTag ); - if( iRc > 0 ){ - // Successful delete of only tag in production mdx file - need to remove it from the list, update the dbf header - cIndexFlag = 0x00; - if(( iRc = WriteHeader( 1, 0 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if(( iRc = RemoveIndex( ixl->ix )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if( ixlPrev == NULL ){ - // std::cout << "setting ixList to null or should be\n"; - ixList = ixlNext; - } else { - ixlPrev = ixlNext; - } - } else if( iRc < 0 ){ - iErrorStop = 170; - throw iRc; - } - if( !ixList || ixl->ix == pCurIx ) - SetCurTag( "", NULL, NULL ); - } - } - ixlPrev = ixl; - ixl = ixlNext; - } - - if( !bDone ) - return XB_INVALID_TAG; - #endif - - #ifdef XB_TDX_SUPPORT - } else if( sIxType == "TDX" ){ - xbIxList *ixl = ixList; - xbIxList *ixlNext; - xbIxList *ixlPrev = NULL; - xbBool bDone = xbFalse; - xbIxTdx *pTdx; - xbMdxTag *pMdxTag; - xbInt16 iTagCnt = 0; - - while( ixl && !bDone ){ - ixlNext = ixl->next; - pTdx = (xbIxTdx *) ixl->ix; - iTagCnt = pTdx->GetTagCount(); - for( xbInt16 i = 0; i < iTagCnt && !bDone; i++ ){ - pMdxTag = (xbMdxTag *) pTdx->GetTag( i ); - if( pTdx->GetTagName( pMdxTag ) == sName ){ - bDone = xbTrue; - iRc = pTdx->DeleteTag( pMdxTag ); - if( iRc > 0 ){ - // Successful delete of only tag in production mdx file - need to remove it from the list, update the dbf header - cIndexFlag = 0x00; - if(( iRc = WriteHeader( 1, 0 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if(( iRc = RemoveIndex( ixl->ix )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if( ixlPrev == NULL ){ - // std::cout << "setting ixList to null or should be\n"; - ixList = ixlNext; - } else { - ixlPrev = ixlNext; - } - } else if( iRc < 0 ){ - iErrorStop = 170; - throw iRc; - } - if( ixList ) - std::cout << "ixlist not null\n"; - else - std::cout << "ixlist null\n"; - - if( !ixList || ixl->ix == pCurIx ) - SetCurTag( "", NULL, NULL ); - } - } - ixlPrev = ixl; - ixl = ixlNext; - } - - if( !bDone ) - return XB_INVALID_TAG; - - #endif - - - - } else { - iErrorStop = 180; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - if(( iRc = UpdateTagList()) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - - - } - catch (xbInt16 iRc ){ - if( pIx ) delete pIx; - xbString sMsg; - sMsg.Sprintf( "xbdbf::DeleteTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && GetTableLocked() ){ - LockTable( XB_UNLOCK ); - } - #endif // XB_LOCKING_SUPPORT - } - - #ifdef XB_LOCKING_SUPPORT - if( bTableLocked ){ - LockTable( XB_UNLOCK ); - } - #endif // XB_LOCKING_SUPPORT - - - return iRc; -} -#endif // XB_INDEX_SUPPORT -/************************************************************************/ -//! @brief Dump dbf file header. -/*! - This routine dumps dbf header information to the console. - - \param iOption 1 = Print header only<br> - 2 = Field data only<br> - 3 = Header and Field data<br> - 4 = Header, Field and Memo header data if applicable - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::DumpHeader( xbInt16 iOption ){ - int i; - int iMemoCtr = 0; - - if( iOption < 1 || iOption > 4 ) - return XB_INVALID_OPTION; - - xbInt16 iRc = ReadHeader( xbTrue, 0 ); - if( iRc != XB_NO_ERROR ) - return iRc; - -// if( iDbfStatus == XB_CLOSED ) -// return XB_NOT_OPEN; - - std::cout << "\nDatabase file " << GetFqFileName() << std::endl << std::endl; - - if( iOption != 2 ){ - std::cout << "File header data:" << std::endl; - - xbInt16 sVer = DetermineXbaseTableVersion( cVersion ); - - if( sVer == 3 ) - std::cout << "Dbase III file" << std::endl; - else if ( sVer == 4 ) - std::cout << "Dbase IV file" << std::endl << std::endl; - else if ( sVer == 5 ) - std::cout << "Dbase V file" << std::endl << std::endl; - else if ( sVer == 7 ) - std::cout << "Dbase VII file" << std::endl << std::endl; - else - std::cout << "Unknown Version" << std::endl; - - /* display the bit stream */ - unsigned char c, tfv, displayMask = 1 << 7; - tfv = cVersion; - std::cout << "File descriptor bits = "; - for( c = 1; c<= 8; c++ ){ - std::cout << (tfv & displayMask ? '1' : '0'); - tfv <<= 1; - } - std::cout << std::endl; - - std::cout << "Descriptor bits legend:" << std::endl; - std::cout << " 0-2 = version number" << std::endl; - std::cout << " 3 = presence of dBASE IV memo" << std::endl; - std::cout << " 4-6 = SQL table presence" << std::endl; - std::cout << " 7 = Presence of any memo file (dBASE III PLUS or dBASE IV)" << std::endl << std::endl; - - std::cout << "Last update date = " - << (int) cUpdateMM << "/" << (int) cUpdateDD << "/" << (int) cUpdateYY % 100 << std::endl; - - std::cout << "Header length = " << uiHeaderLen << std::endl; - std::cout << "Record length = " << uiRecordLen << std::endl; - std::cout << "Records in file = " << ulNoOfRecs << std::endl << std::endl << std::endl; - - std::cout << "Transaction Flag = "; - xbase->BitDump( cTransactionFlag ); - std::cout << std::endl; - - std::cout << "Encryption Flag = "; - xbase->BitDump( cEncryptionFlag ); - std::cout << std::endl; - - std::cout << "Index Flag = "; - xbase->BitDump( cIndexFlag ); - std::cout << std::endl; - - std::cout << "Lang Driver = " << (int) cIndexFlag << " - "; - xbase->BitDump( cIndexFlag ); - std::cout << std::endl; - #ifdef XB_INDEX_SUPPORT - std::cout << "Open Index Files = " << GetPhysicalIxCnt() << std::endl; - #endif // XB_INDEX_SUPPORT - } - - if( iOption != 1 ){ - char c; - std::cout << "Field Name Type Length Decimals IxFlag" << std::endl; - std::cout << "---------- ---- ------ -------- ------" << std::endl; - for( i = 0; i < iNoOfFields; i++ ){ - - SchemaPtr[i].cIxFlag ? c = 'Y' : c = ' '; - - if( SchemaPtr[i].cType == 'C' && SchemaPtr[i].cNoOfDecs > 0 ) - printf( "%10s %1c %4d %4d %c\n", SchemaPtr[i].cFieldName, - SchemaPtr[i].cType, SchemaPtr[i].cFieldLen, 0, c ); - else - printf( "%10s %1c %4d %4d %c\n", SchemaPtr[i].cFieldName, - SchemaPtr[i].cType, SchemaPtr[i].cFieldLen, SchemaPtr[i].cNoOfDecs, c ); - - if( SchemaPtr[i].cType == 'M' ) - iMemoCtr++; - } - } - std::cout << std::endl; - -#ifdef XB_MEMO_SUPPORT - if( iOption > 3 && iMemoCtr > 0 ) - Memo->DumpMemoHeader(); -#endif - - return XB_NO_ERROR; -} -/************************************************************************/ -//! Dump record -/*! - Dump the contents of the specified record - - - \param ulRecNo Record number of record to be dumped. - \param iOutputDest 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - - \param iOutputFmt 0 = with field names<br> - 1 = 1 line per rec, no field names<br> - 2 = 1 line per rec, first line is a list of field names. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::DumpRecord( xbUInt32 ulRecNo, xbInt16 iOutputDest, xbInt16 iOutputFmt ) { - int i, iRc = XB_NO_ERROR; - - xbString sTemp; - xbString s2; - if( ulRecNo == 0 || ulRecNo > ulNoOfRecs ) - return XB_INVALID_RECORD; - - if( ulCurRec != ulRecNo ){ - iRc = GetRecord( ulRecNo ); - if( iRc != XB_NO_ERROR ) - return iRc; - } - - if( iOutputFmt >= 1 ){ - if( iOutputFmt == 2 ){ - sTemp = "RecNo,DEL"; - for( i = 0; i < iNoOfFields; i++ ){ - s2 = SchemaPtr[i].cFieldName; - s2.Trim(); - sTemp += ","; - sTemp += s2; - } - xbase->WriteLogMessage( sTemp.Str(), iOutputDest ); - } - - if( RecordDeleted() ) - s2.Sprintf( "%ld,DEL", ulRecNo ); - else - s2.Sprintf( "%ld,", ulRecNo ); - - for( i = 0; i < iNoOfFields; i++ ){ - GetField( i, sTemp ); - sTemp.Trim(); - s2.Sprintf( "%s,'%s'", s2.Str(), sTemp.Str()); - } - xbase->WriteLogMessage( s2.Str(),iOutputDest ); - return XB_NO_ERROR; - } - - sTemp.Sprintf( "\nRec Number: %ld", ulRecNo ); - xbase->WriteLogMessage( sTemp.Str(),iOutputDest); - - if( RecordDeleted()) - xbase->WriteLogMessage( "Record flagged as deleted", iOutputDest ); - - - #ifdef XB_MEMO_SUPPORT - xbString sMemo; - #endif - - for( i = 0; i < iNoOfFields; i++ ){ - - #ifdef XB_MEMO_SUPPORT - GetField( i, sTemp ); - sTemp.Trim(); - - if(SchemaPtr[i].cType == 'M'){ - GetMemoField( i, sMemo ); - if( sMemo.Len() > 70 ) - sMemo.Resize( 70 ); - s2.Sprintf ( "%c %s = '%s'", SchemaPtr[i].cType, SchemaPtr[i].cFieldName, sMemo.Str()); - xbase->WriteLogMessage( s2.Str(), iOutputDest); - - /* - xbUInt32 ulMlen; - if( MemoFieldExists( i )){ - Memo->GetMemoFieldLen( i, ulMlen ); - s2.Sprintf( " Len = %d", ulMlen ); - } - xbase->WriteLogMessage( s2.Str(), iOutputDest); - */ - - } - else{ - s2.Sprintf ( "%c %s = '%s'", SchemaPtr[i].cType, SchemaPtr[i].cFieldName, sTemp.Str()); - xbase->WriteLogMessage( s2.Str(), iOutputDest); - } - #else - GetField( i, sTemp ); - sTemp.Trim(); - s2.Sprintf( "%s = '%s'", SchemaPtr[i].cFieldName, sTemp.Str()); - xbase->WriteLogMessage( s2.Str(), iOutputDest); - #endif - - } - return XB_NO_ERROR; -} - - -/************************************************************************/ -#ifdef XB_DEBUG_SUPPORT - - -#ifdef XB_LOCKING_SUPPORT -//! @brief Dump the table lock status -/*! - Debugging routine. Dumps the table lock status to the console. - \returns void -*/ - -void xbDbf::DumpTableLockStatus() const { - - std::cout << "File Lock Retry Count = [" << GetLockRetryCount() << "]" << std::endl; - std::cout << "File Lock Flavor = ["; - switch (GetLockFlavor()){ - case 1: - std::cout << "Dbase]" << std::endl; - break; - case 2: - std::cout << "Clipper]" << std::endl; - break; - case 3: - std::cout << "Fox]" << std::endl; - break; - case 9: - std::cout << "Xbase64]" << std::endl; - break; - default: - std::cout << "Unknown]" << std::endl; - break; - } - std::cout << "File Auto Lock = ["; - - if( GetAutoLock()) - std::cout << "ON]" << std::endl; - else - std::cout << "OFF]" << std::endl; - if( GetHeaderLocked()) - std::cout << "Header Locked = [TRUE]\n"; - else - std::cout << "Header Locked = [FALSE]\n"; - - if( GetTableLocked()) - std::cout << "Table Locked = [TRUE]\n"; - else - std::cout << "Table Locked = [FALSE]\n"; - - if( GetAppendLocked() > 0 ) - std::cout << "Append Locked = [" << GetAppendLocked() << "]\n"; - else - std::cout << "Append Locked = [FALSE]\n"; - - #ifdef XB_MEMO_SUPPORT - if( GetMemoLocked()) - std::cout << "Memo Locked = [TRUE]\n"; - else - std::cout << "Memo Locked = [FALSE]\n"; - #endif // XB_MEMO_SUPPORT - - xbLinkListNode<xbUInt32> * llN = GetFirstRecLock(); - if( llN ){ - while( llN ){ - std::cout << "Record Locked = [" << llN->GetKey() << "]\n"; - llN = llN->GetNextNode(); - } - } else { - std::cout << "Record Locked = [None]\n"; - } -} -#endif // XB_LOCKING_SUPPORT -#endif // XB_DEBUG_SUPPORT - -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Get the append locked bytes status -/*! - \returns The record number of the new record for the append lock operation. -*/ - -xbUInt32 xbDbf::GetAppendLocked() const { - return this->ulAppendLocked; -} - -#endif // XB_LOCKING_SUPPORT - -/************************************************************************/ -//! @brief Get auto commit setting. -/*! - - This routine returns the table setting if set, otherwise returns the system - level setting. - - \returns Not 0 - Auto commit on for this table.<br> - 0 - Auto commit off for this table. -*/ - -xbInt16 xbDbf::GetAutoCommit() const { - return GetAutoCommit( 1 ); -} - -/************************************************************************/ -//! @brief Get auto commit setting. -/*! - - \param iOption 0 - Specific setting for this table<br> - 1 - If this table should be auto updated (takes DBMS setting into account) - \returns Not 0 - Auto commit on for this table.<br> - 0 - Auto commit off for this table. -*/ - -xbInt16 xbDbf::GetAutoCommit( xbInt16 iOption ) const { - if( iOption == 1 && iAutoCommit == -1 ) - return xbase->GetDefaultAutoCommit(); - else - return iAutoCommit; -} - - -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Get Auto Lock setting. -/*! - \returns Auto lock setting. -*/ -xbInt16 xbDbf::GetAutoLock() const{ - return iAutoLock; -} -#endif // XB_LOCKING_SUPPORT - -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT -//! @brief Get the memo file block size used when creating a memo file. -/*! - \returns Memo block size. -*/ -xbUInt32 xbDbf::GetCreateMemoBlockSize() const { - return ulCreateMemoBlockSize; -} -#endif // XB_MEMO_SUPPORT - -/************************************************************************/ -//! @brief Get a pointer to the current index object. -/*! - \returns Pointer to current index. -*/ -#ifdef XB_INDEX_SUPPORT -xbIx *xbDbf::GetCurIx() const { - return pCurIx; -} -/************************************************************************/ -//! @brief Get pointer to current tag for the current index. -/*! - An index file can have one or more tags - NDX index files have one tag per file. - MDX index files can can have up to 47 tags per file. - TDX index files can can have up to 47 tags per file. - - \returns Pointer to current tag. -*/ -void *xbDbf::GetCurTag() const { - return vpCurIxTag; -} -/************************************************************************/ -//! @brief Get the current index type. -/*! - \returns NDX for single tag index.<br> - MDX for production multi tag index.<br> - TDX for temporary tag index. -*/ -const xbString &xbDbf::GetCurIxType() const { - return sCurIxType; -} - -/************************************************************************/ -//! @brief Get the current tag name. -/*! - \returns Current Tag Name.<br> -*/ - -const xbString &xbDbf::GetCurTagName() const { - - if( pCurIx ) - return pCurIx->GetTagName( vpCurIxTag ); - else - return sNullString; -} - -/************************************************************************/ -//! @brief GetFirstKey for tag. -/*! - - Position to the first key for the current tag - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf::GetFirstKey(){ - if( pCurIx ) - return pCurIx->GetFirstKey( vpCurIxTag, 1 ); - else - return XB_INVALID_TAG; -} - -/************************************************************************/ -//! @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. -/*! - - Position to the last key for the current tag - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf::GetLastKey(){ - if( pCurIx ) - return pCurIx->GetLastKey( vpCurIxTag, 1 ); - else - return XB_INVALID_TAG; -} - -/************************************************************************/ -//! @brief GetNextKey for tag. -/*! - - Position to the next key for the current tag - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf::GetNextKey(){ - if( pCurIx ) - return pCurIx->GetNextKey( vpCurIxTag, 1 ); - else - return XB_INVALID_TAG; -} - -/************************************************************************/ -//! @brief GetPrevKey for tag. -/*! - - Position to the previous key for the current tag - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf::GetPrevKey(){ - if( pCurIx ) - return pCurIx->GetPrevKey( vpCurIxTag, 1 ); - else - return XB_INVALID_TAG; -} - -/************************************************************************/ -//! @brief Find record for key. -/*! - - Find a key and position to record if key found - - \param sKey String key to find - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf::Find( xbString &sKey ){ - if( pCurIx ) - return pCurIx->FindKey( vpCurIxTag, sKey.Str(), (xbInt32) sKey.Len(), 1 ); - else - return XB_INVALID_TAG; -} - -/************************************************************************/ -//! @brief Find record for key. -/*! - - Find a key and position to record if key found - - \param dtKey Date key to find - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf::Find( xbDate &dtKey ){ - - if( pCurIx ) - return pCurIx->FindKey( vpCurIxTag, dtKey, 1 ); - else - return XB_INVALID_TAG; - -} -/************************************************************************/ -//! @brief Find record for key. -/*! - - Find a key and position to record if key found - - \param dtKey Date key to find - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf::Find( xbDouble &dKey ){ - - if( pCurIx ) - return pCurIx->FindKey( vpCurIxTag, dKey, 1 ); - else - return XB_INVALID_TAG; - -} - - -#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 error, dbf file is empty or positioned on the last record. -*/ -xbBool xbDbf::GetEof() { - - // xbUInt32 ulRecCnt = GetRecordCount(); - - xbUInt32 ulRecCnt; - xbInt16 iRc = GetRecordCnt( ulRecCnt ); - - if( iRc != XB_NO_ERROR || ulRecCnt == 0 || GetCurRecNo() == ulRecCnt ) - return xbTrue; - else - return xbFalse; -} -/************************************************************************/ -//! @brief Return the current record number. -/*! - \returns Returns the current record number. -*/ -xbUInt32 xbDbf::GetCurRecNo() const { - return ulCurRec; -} - -/************************************************************************/ -//! @brief Return the current dbf status. -/*! - \returns 0 = closed<br> - 1 = open<br> - 2 = updates pending<br> -*/ -xbInt16 xbDbf::GetDbfStatus() const { - return iDbfStatus; -} -/************************************************************************/ -//! @brief Return the number of fields in the table. -/*! - \returns The number of fields in the table. -*/ -xbInt32 xbDbf::GetFieldCnt() const { - return iNoOfFields; -} - -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Get the first first record lock. -/*! - Get the first record lock from a linked list of record locks. - \returns First record lock. -*/ -xbLinkListNode<xbUInt32> * xbDbf::GetFirstRecLock() const { - return lloRecLocks.GetHeadNode(); -} -#endif // XB_LOCKING_SUPPORT -/************************************************************************/ -//! @brief Get the first record. -/*! - Get the first not deleted record. This routines skips over any deleted records. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetFirstRecord() -{ - return GetFirstRecord( XB_ACTIVE_RECS ); -} - -/************************************************************************/ -//! @brief Get the first record. -/*! - - \param iOption XB_ALL_RECS - Get the first record, deleted or not.<br> - XB_ACTIVE_RECS - Get the first active record.<br> - XB_DELETED_RECS - Get the first deleted record.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetFirstRecord( xbInt16 iOption ) -{ - if( ulNoOfRecs == 0 ) - return XB_EMPTY; - - xbInt16 iRc = GetRecord( 1L ); - while( iRc == XB_NO_ERROR && - ((RecordDeleted() && iOption == XB_ACTIVE_RECS) || - (!RecordDeleted() && iOption == XB_DELETED_RECS))) - if( ulCurRec < ulNoOfRecs ) - iRc = GetRecord( ulCurRec + 1 ); - else - return XB_EOF; - - return iRc; -} - -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Return lock status of the table header -/*! \returns DBF header lock status -*/ - -xbBool xbDbf::GetHeaderLocked() const { - return this->bHeaderLocked; -} -#endif // XB_LOCKING_SUPPORT - -#ifdef XB_INDEX_SUPPORT -//! @brief Return pointer to list of index files for the table. -/*! - \returns Returns an xbIxList * pointer to list of open index files. -*/ - -xbIxList *xbDbf::GetIxList() const{ - return ixList; -} -#endif // XB_INDEX_SUPPORT - - -/************************************************************************/ -//! @brief Get the last record. -/*! - Get the last not deleted record. This routines skips over any deleted records. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetLastRecord() -{ - return GetLastRecord( XB_ACTIVE_RECS ); -} -/************************************************************************/ -//! @brief Get the last record. -/*! - - \param iOption XB_ALL_RECS - Get the last record, deleted or not.<br> - XB_ACTIVE_RECS - Get the last active record.<br> - XB_DELETED_RECS - Get the last deleted record.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetLastRecord( xbInt16 iOption ) -{ - if( ulNoOfRecs == 0 ) - return XB_EMPTY; - - xbInt16 iRc = GetRecord( ulNoOfRecs ); - while( iRc == XB_NO_ERROR && - ((RecordDeleted() && iOption == XB_ACTIVE_RECS) || - (!RecordDeleted() && iOption == XB_DELETED_RECS))) - if( ulCurRec > 1 ) - iRc = GetRecord( ulCurRec - 1 ); - else - return XB_EOF; - - return iRc; -} - - -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Get lock flavor. -/*! - This routine is currently in place to provide structure for future locking - schemes that may differ from the legacy DBase (TM) locking scheme. - \returns Always 1. -*/ - -xbInt16 xbDbf::GetLockFlavor() const{ - if( iLockFlavor == -1 ) - return xbase->GetDefaultLockFlavor(); - else - return iLockFlavor; -} -#endif // XB_LOCKING_SUPPORT - -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Get the lock status of the memo file. -/*! - \returns Lock status of memo file. -*/ -xbBool xbDbf::GetMemoLocked() const { - if( MemoFieldsExist()) - return Memo->GetMemoLocked(); - else - return xbFalse; -} -#endif // XB_LOCKING_SUPPORT - -/************************************************************************/ -//! @brief Get pointer to Memo object. -/*! - \returns This routine returns the pointer to the memo object. -*/ - -xbMemo * xbDbf::GetMemoPtr(){ - return Memo; -} - -#endif // XB_MEMO_SUPPORT - - -/************************************************************************/ -#ifdef XB_INF_SUPPORT -//! @brief Return the .INF file name -/*! - If NDXIDX support is enabled in the library, and a non production (ndx) - has been associated with the dbf file, the .INF file name can be retrieved - with this routine. - - \param sInfFileName Output string containing .INF file name. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::GetInfFileName( xbString &sInfFileName ){ - - sInfFileName = GetFqFileName(); - xbUInt32 lLen = sInfFileName.Len(); - if( lLen < 5 ) - return XB_FILE_NOT_FOUND; - sInfFileName.PutAt(lLen-2, 'I'); - sInfFileName.PutAt(lLen-1, 'N'); - sInfFileName.PutAt(lLen, 'F'); - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Return first node of linked list of .INF items. -/*! - \returns List of .INF entries. -*/ - -xbLinkListNode<xbString> * xbDbf::GetInfList() const{ - return llInfData.GetHeadNode(); -} -#endif // XB_INF_SUPPORT - - -/************************************************************************/ -//! @brief Get the next record. -/*! - Get the next not deleted record. This routines skips over any deleted records. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetNextRecord(){ - return GetNextRecord( XB_ACTIVE_RECS ); -} - -/************************************************************************/ -//! @brief Get the next record. -/*! - \param iOption XB_ALL_RECS - Get the next record, deleted or not.<br> - XB_ACTIVE_RECS - Get the next active record.<br> - XB_DELETED_RECS - Get the next deleted record.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetNextRecord( xbInt16 iOption ){ - if( ulNoOfRecs == 0 ) - return XB_EMPTY; - else if( ulCurRec >= ulNoOfRecs ) - return XB_EOF; - xbInt16 iRc = GetRecord( ulCurRec + 1 ); - while( iRc == XB_NO_ERROR && - ((RecordDeleted() && iOption == XB_ACTIVE_RECS) || - (!RecordDeleted() && iOption == XB_DELETED_RECS))) - if( ulCurRec < ulNoOfRecs ) - iRc = GetRecord( ulCurRec + 1 ); - else - return XB_EOF; - return iRc; -} -/************************************************************************/ -//! @brief Get the next record. -/*! - - \param iOption XB_ALL_RECS - Get the next record, deleted or not.<br> - XB_ACTIVE_RECS - Get the next active record.<br> - XB_DELETED_RECS - Get the next deleted record.<br> - \param ulStartRec Get next record, starting from ulStartRec. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::GetNextRecord( xbInt16 iOption , xbUInt32 ulStartRec ){ - - if( iOption == 0 ) - return GetNextRecord(); - else if( iOption == 1 ){ - if( ulStartRec > 0 ) - ulCurRec = ulStartRec; - xbInt16 iRc = GetNextRecord(); - while( iRc == XB_NO_ERROR && RecordDeleted()) - iRc = GetNextRecord(); - return iRc; - } - else - return XB_INVALID_OPTION; -} - - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Physical count of open index files. -/*! - - Returns a physical count of open index files for the dbf file. An index file - can contain one or more tags. - \returns Count of open index files. -*/ - -xbInt32 xbDbf::GetPhysicalIxCnt() const { - - xbInt32 lCnt = 0; - #ifdef XB_INDEX_SUPPORT - xbIxList *p = ixList; - while( p ){ - lCnt++; - p = p->next; - } - #endif - return lCnt; -} -#endif // XB_INDEX_SUPPORT - - -/************************************************************************/ -//! @brief Get the previous record. -/*! - Get the previous not deleted record. This routine skips over any deleted records. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::GetPrevRecord() -{ - return GetPrevRecord( XB_ACTIVE_RECS ); -} - -/************************************************************************/ -//! @brief Get the previous record. -/*! - - \param iOption XB_ALL_RECS - Get the previous record, deleted or not.<br> - XB_ACTIVE_RECS - Get the previous active record.<br> - XB_DELETED_RECS - Get the previous deleted record.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetPrevRecord( xbInt16 iOption ){ - if( ulNoOfRecs == 0 ) - return XB_EMPTY; - else if( ulCurRec <= 1L ) - return XB_BOF; - xbInt16 iRc = GetRecord( ulCurRec - 1 ); - while( iRc == XB_NO_ERROR && - ((RecordDeleted() && iOption == XB_ACTIVE_RECS) || - (!RecordDeleted() && iOption == XB_DELETED_RECS))) - if( ulCurRec > 1 ) - iRc = GetRecord( ulCurRec - 1 ); - else - return XB_BOF; - - return iRc; -} - - -/************************************************************************/ -//! @brief Get record for specified record number. -/*! - Retrieve a record from disk and load it into the record buffer. If auto commit - is enabled and there are pending updates, this routine will flush the updates - to disk before proceeding to ulRecNo. - - \param ulRecNo - Record number to retrieve. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetRecord( xbUInt32 ulRecNo ){ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - /* verify the file is open */ - if( iDbfStatus == XB_CLOSED ){ - iErrorStop = 100; - iRc = XB_NOT_OPEN; - throw iRc; - } - if( iDbfStatus == XB_UPDATED ){ - if( GetAutoCommit() == 1 ){ - if(( iRc = Commit()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } else { - if(( iRc = Abort()) != XB_NO_ERROR ){ - 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; - throw iRc; - } - - if( xbFread( RecBuf, uiRecordLen, 1 ) != XB_NO_ERROR ){ - iErrorStop = 150; - iRc = XB_READ_ERROR; - throw iRc; - } - ulCurRec = ulRecNo; - } - - catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbDbf::GetRecord() Exception Caught. Error Stop = [%d] iRc = [%d] record = [%d]", iErrorStop, iRc, ulRecNo ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; -} -/************************************************************************/ -//! @brief Get pointer to record buffer -/*! - \param iOpt 0 for RecBuf (current) or 1 for RecBuf2 (original contents) - - \returns Pointer to record buffer. -*/ -char * xbDbf::GetRecordBuf( xbInt16 iOpt ) const { - if( iOpt ) - return RecBuf2; - else - return RecBuf; -} - -/************************************************************************/ -//! @brief Get the current number of records in the dbf data file. -/*! - \returns Record count or <a href="xbretcod_8h.html">Return Codes</a> -*/ -/* -xbUInt32 xbDbf::GetRecordCount(){ - - xbUInt32 ulCnt; - xbInt16 iRc = GetRecordCnt( ulCnt ); - if( iRc < 0 ) - return (xbUInt32) iRc; - else - return ulCnt; -} -*/ -/************************************************************************/ -//! @brief Get the current number of records in the dbf data file. -/*! - \param ulRecCnt Output number of records in file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::GetRecordCnt( xbUInt32 & ulRecCnt ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif // XB_LOCKING_SUPPORT - - try{ - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockHeader( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } else - bLocked = xbTrue; - } - #endif // XB_LOCKING_SUPPORT - - if((iRc = ReadHeader(1,1)) != XB_NO_ERROR){ - iErrorStop = 110; - throw iRc; - } - } - catch( xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbDbf::GetRecordCnt() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - LockHeader( XB_UNLOCK ); - } - #endif - - ulRecCnt = ulNoOfRecs; - return iRc; -} -/************************************************************************/ -//! @brief Get the dbf record length. -/*! - \returns Record length. -*/ -xbUInt16 xbDbf::GetRecordLen() const { - return uiRecordLen; -} -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Get table locked status -/*! - \returns Table lock status. -*/ -xbBool xbDbf::GetTableLocked() const { - return this->bTableLocked; -} -#endif // XB_LOCKING_SUPPORT -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Get tag list for dbf file. -/*! - This routine returns a list of tags for the file.<br> - - The library is structured to support one or more files of the same or differing - index types (NDX/MDX/TDX), with each file supporting one or more index tags.<br> - - \returns Tag list for the file/table. -*/ -xbLinkListNode<xbTag *> *xbDbf::GetTagList() const { - return llTags.GetHeadNode(); -} -#endif // XB_INDEX_SUPPORT -/************************************************************************/ -//! @brief Get the table alias. -/*! - This routine returns the table alias. - \returns Table alias -*/ -const xbString & xbDbf::GetTblAlias() const { - return this->sAlias; -} - -/************************************************************************/ -//! @brief Get the pointer to the xbXbase structure, -/*! - \returns Pointer to xbXbase structure. -*/ -xbXBase * xbDbf::GetXbasePtr() const { - return xbase; -} -/************************************************************************/ -#ifdef XB_INF_SUPPORT -//! @brief Load .INF data file, -/*! - Protected method. This routine loads the ndx inf file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::LoadInfData(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - // create file name - xbString sInfFileName; - if(( iRc = GetInfFileName( sInfFileName )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // if file does not exist, return no error - xbFile fMd( xbase ); - if( !fMd.FileExists( sInfFileName )) - return XB_NO_ERROR; - - // open file file in read only mode - if(( iRc = fMd.xbFopen( "r", sInfFileName, GetShareMode())) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // clear the linked list - llInfData.Clear(); - - // for each entry in the file, add a linked list item - xbString sRec; - xbString sLeft3; - xbString sFn; - - while( iRc == XB_NO_ERROR ){ - sRec = ""; - if(( iRc = fMd.xbFgets( 132, sRec )) == XB_NO_ERROR ){ - sLeft3 = sRec; - sLeft3.Left( 3 ); - sLeft3.ToUpperCase(); - if( sLeft3 == "NDX"){ - sFn.ExtractElement(sRec.Str(), '=', 2 ); - sFn.ZapChar( 0x0d ); - sFn.ZapChar( 0x0a ); - llInfData.InsertAtEnd( sFn ); - } - } - } - // close the file - if(( iRc = fMd.xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - } catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::LoadInfData() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INF_SUPPORT - -/************************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Lock append bytes. -/*! - This routine locks the append bytes and is used by the AppendRecord function. - - \param iLockFunction XB_LOCK<br>XB_UNLOCK - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::LockAppend( xbInt16 iLockFunction ) -{ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbUInt32 ulAppendRec; - - try{ - if( iLockFunction == XB_LOCK ){ - iErrorStop = 100; - if( ulAppendLocked > 0 ) /* already have an append lock */ - return XB_NO_ERROR; - - ulAppendRec = ulNoOfRecs + 1; /* record number needing to be locked */ - if( GetLockFlavor() == LK_DBASE ){ - iRc = xbLock( XB_LOCK, LK4026531839, 1 ); - if( iRc != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbInt64 llAppendRecLockByte = (xbInt64) LK4026531838 - ulAppendRec; - iRc = xbLock( XB_LOCK, llAppendRecLockByte, 1 ); - if( iRc != XB_NO_ERROR ){ - xbLock( XB_UNLOCK, LK4026531839, 1 ); - if( iRc == XB_LOCK_FAILED ){ - return iRc; - } else { - iErrorStop = 120; - throw iRc; - } - } - ulAppendLocked = ulAppendRec; /* set the append lock switch */ - - - // } else { - other lock-table flavor options go here Clipper, Fox, etc - } - - } else { - iErrorStop = 130; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - } else if( iLockFunction == XB_UNLOCK ){ - iErrorStop = 200; - - if( ulAppendLocked == 0 ) /* verify we have an active append lock */ - return XB_NO_ERROR; - - if( GetLockFlavor() == LK_DBASE ){ - xbInt64 llAppendRecLockByte =(xbInt64) LK4026531838 - ulAppendLocked; - iRc = xbLock( XB_UNLOCK, llAppendRecLockByte, 1 ); - if( iRc != XB_NO_ERROR ){ - xbLock( XB_UNLOCK, LK4026531839, 1 ); - iErrorStop = 220; - throw iRc; - } - iRc = xbLock( XB_UNLOCK, LK4026531839, 1 ); - if( iRc != XB_NO_ERROR ){ - iErrorStop = 230; - throw iRc; - } - - ulAppendLocked = 0; /* release the append lock switch */ - - // } else { - other unlock-table flavor options go here Clipper, Fox, etc - } - - } else { - iErrorStop = 290; - iRc = XB_INVALID_OPTION; - throw iRc; - } - } else { - iErrorStop = 300; - iRc = XB_INVALID_OPTION; - throw iRc; - } - } catch( xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::LockAppendBytes() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - - return iRc; -} - -/************************************************************************/ -//! @brief Lock Header -/*! - This routine locks the file header. - \param iLockFunction XB_LOCK<br>XB_UNLOCK - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::LockHeader( xbInt16 iLockFunction ) -{ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - try{ - - if( iLockFunction == XB_LOCK ){ - iErrorStop = 100; - if( GetHeaderLocked()) - return XB_NO_ERROR; - - iErrorStop = 110; - if( GetLockFlavor() == LK_DBASE ){ - - iRc = xbLock( XB_LOCK, LK4026531838, 1 ); - - if( iRc != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ) - return iRc; - else{ - iErrorStop = 120; - throw iRc; - } - } - - } else { - iErrorStop = 130; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - SetHeaderLocked( xbTrue ); - - } else if( iLockFunction == XB_UNLOCK ){ - - iErrorStop = 200; - if( !GetHeaderLocked()) - return XB_NO_ERROR; - - iErrorStop = 210; - if( GetLockFlavor() == LK_DBASE ){ - iRc = xbLock( XB_UNLOCK, LK4026531838, 1 ); - if( iRc != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - } else { - iErrorStop = 230; - iRc = XB_INVALID_OPTION; - throw iRc; - } - SetHeaderLocked( xbFalse ); - } else { - iErrorStop = 300; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - } catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::LockHeader() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; -} -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Lock Index files. -/*! - This routine locks all the index files. - \param iLockFunction XB_LOCK<br>XB_UNLOCK - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::LockIndices( xbInt16 iLockFunction ) -{ - // this function doesn't take into account any Lack Flavors other than DBASE, - // would need updated to supprot other lock flavors - Clipper, FoxPro etc - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - xbIxList *ixLI = GetIxList(); // index list item - - while( ixLI ){ - if( iLockFunction == XB_LOCK ){ - - #ifdef XB_NDX_SUPPORT - if( *ixLI->sFmt == "NDX" ){ - if( !ixLI->ix->GetLocked()){ - if(( iRc = ixLI->ix->xbLock( XB_LOCK, LK4026531838, 1 )) != XB_NO_ERROR ){ - ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 ); - iErrorStop = 100; - throw iRc; - } - ixLI->ix->SetLocked( xbTrue ); - } - } - #endif - - #ifdef XB_MDX_SUPPORT - if( *ixLI->sFmt == "MDX" ){ - if( !ixLI->ix->GetLocked()){ - if(( iRc = ixLI->ix->xbLock( XB_LOCK, LK4026531838, 1 )) != XB_NO_ERROR ){ - ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 ); - iErrorStop = 100; - throw iRc; - } - ixLI->ix->SetLocked( xbTrue ); - } - } - #endif - - #ifdef XB_TDX_SUPPORT - if( *ixLI->sFmt == "TDX" ){ - if( !ixLI->ix->GetLocked()){ - if(( iRc = ixLI->ix->xbLock( XB_LOCK, LK4026531838, 1 )) != XB_NO_ERROR ){ - ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 ); - iErrorStop = 100; - throw iRc; - } - ixLI->ix->SetLocked( xbTrue ); - } - } - #endif - - } else if( iLockFunction == XB_UNLOCK ){ - - #ifdef XB_NDX_SUPPORT - if( *ixLI->sFmt == "NDX" ){ - if( ixLI->ix->GetLocked()){ - if(( iRc = ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - ixLI->ix->SetLocked( xbFalse ); - } - } - #endif - - #ifdef XB_MDX_SUPPORT - if( *ixLI->sFmt == "MDX" ){ - if( ixLI->ix->GetLocked()){ - if(( iRc = ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - ixLI->ix->SetLocked( xbFalse ); - } - } - #endif - - #ifdef XB_TDX_SUPPORT - if( *ixLI->sFmt == "MDX" ){ - if( ixLI->ix->GetLocked()){ - if(( iRc = ixLI->ix->xbLock( XB_UNLOCK, LK4026531838, 1 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - ixLI->ix->SetLocked( xbFalse ); - } - } - #endif - - } - ixLI = ixLI->next; - } - - } catch( xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::LockIndices() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; -} -#endif // XB_INDEX_SUPPORT -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT -//! @brief Lock Memo file. -/*! - This routine locks the memo file for updates. - \param iLockFunction XB_LOCK<br>XB_UNLOCK - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::LockMemo( xbInt16 iLockFunction ){ - if( MemoFieldsExist()) - return Memo->LockMemo( iLockFunction ); - else - return XB_NO_ERROR; -} -#endif // XB_MEMO_SUPPORT - - - -/************************************************************************/ -//! @brief Loc Record -/*! - This routine locks a record for update. - \param iLockFunction XB_LOCK<br>XB_UNLOCK - \param ulRecNo Record number to lock - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::LockRecord( xbInt16 iLockFunction, xbUInt32 ulRecNo ) -{ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - - if( ulRecNo > ulNoOfRecs ) - return XB_INVALID_RECORD; - - if( iLockFunction == XB_LOCK ){ - iErrorStop = 100; - - if( lloRecLocks.KeyExists( ulRecNo )) - return XB_NO_ERROR; - - if( GetLockFlavor() == LK_DBASE ){ - - iRc = xbLock( XB_LOCK, LK4026531838 - ulRecNo, 1 ); - if( iRc != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ){ - return iRc; - } else { - iErrorStop = 110; - throw iRc; - } - } - // other lock-table flavor options go here Clipper, Fox, etc - - } else { - iErrorStop = 120; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - // add the record lock info to the linked list chain of record locks - iRc = lloRecLocks.InsertKey( ulRecNo ); - if( iRc != XB_NO_ERROR ){ - xbLock( XB_UNLOCK, LK4026531838 - ulRecNo, 1 ); - iErrorStop = 130; - throw iRc; - } - - } else if( iLockFunction == XB_UNLOCK ){ - - iErrorStop = 200; - - if( !lloRecLocks.KeyExists( ulRecNo ) ) - return XB_NO_ERROR; - - if( GetLockFlavor() == LK_DBASE ){ - iRc = xbLock( XB_UNLOCK, LK4026531838 - ulRecNo, 1 ); - if( iRc != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - } else { - iErrorStop = 220; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - // remove the record lock info to the linked list chain of record locks - // next line is crashing - iRc = lloRecLocks.RemoveKey( ulRecNo ); - if( iRc != XB_NO_ERROR ){ - iErrorStop = 230; - throw iRc; - } - - } else { - iErrorStop = 300; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - } catch( xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::LockRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; -} - -/************************************************************************/ -//! @brief Lock table. -/*! - This routine locks the table for updates. - - \param iLockFunction XB_LOCK<br>XB_UNLOCK - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::LockTable( xbInt16 iLockFunction ) -{ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - if( iLockFunction == XB_LOCK ){ - iErrorStop = 100; - if( GetTableLocked()) - return XB_NO_ERROR; // table already locked - - iErrorStop = 110; - if( GetLockFlavor() == LK_DBASE ){ - - // lOffset = LK4026531838; - // iLen = 2; - iRc = xbLock( XB_LOCK, LK4026531838, 2 ); - if( iRc != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ) - return iRc; - else{ - iErrorStop = 120; - throw iRc; - } - } - - // lOffset = LK3026531838; - // iLen = LK1000000000; - iRc = xbLock( XB_LOCK, LK3026531838, LK1000000000); - if( iRc != XB_NO_ERROR ){ - - // lOffset = LK4026531838; - // iLen = 2; - xbLock( XB_UNLOCK, LK4026531838, 2 ); - if( iRc == XB_LOCK_FAILED ){ - return iRc; - } else { - iErrorStop = 130; - throw iRc; - } - } - - // iRc = xbLock( XB_UNLOCK, lOffset, iLen ); - iRc = xbLock( XB_UNLOCK, LK3026531838, LK1000000000); - if( iRc != XB_NO_ERROR ){ - // lOffset = LK4026531838; - // iLen = 2; - xbLock( XB_UNLOCK, LK4026531838, 2 ); - iErrorStop = 140; - throw iRc; - } - - // other lock-table flavor options go here Clipper, Fox, etc - - } else { - iErrorStop = 190; - iRc = XB_INVALID_OPTION; - throw iRc; - } - SetTableLocked( xbTrue ); - - } else if( iLockFunction == XB_UNLOCK ){ - - iErrorStop = 200; - if( !GetTableLocked()) - return XB_NO_ERROR; // table already unlocked - - iErrorStop = 210; - if( GetLockFlavor() == LK_DBASE ){ - - // lOffset = LK4026531838; - // iLen = 2; - iRc = xbLock( XB_UNLOCK, LK4026531838, 2 ); - if( iRc != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - } else { - iErrorStop = 290; - iRc = XB_INVALID_OPTION; - throw iRc; - } - SetTableLocked( xbFalse ); - - } else { - iErrorStop = 300; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - } catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::LockFile() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - return iRc; - -} -#endif // XB_LOCKING_SUPPORT - - -/************************************************************************/ -//! @brief Check for existence of any memo fields. -/*! - \returns xbTrue - Memo fields exist.<br>xbFalse - Memo fields don't exist. -*/ -xbBool xbDbf::MemoFieldsExist() const { - - -#ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ) - return xbTrue; -#endif - return xbFalse; -} - -/************************************************************************/ -//! @brief Open a table/dbf file. -/*! - This routine sets the alias name to the same as the table name. - - \param sTableName Table name to open, Include the .dbf or .DBF extension. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::Open( const xbString & sTableName ) { - return Open( sTableName, sTableName ); -} - -/************************************************************************/ -//! @brief Open a table/dbf file. -/*! - \param sTableName Table name to open, Include the .dbf or .DBF extension. - \param sAlias Alias name to assign to this entry. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::Open( const xbString & sTableName, const xbString & sAlias ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - if(( iRc = Open( sTableName, sAlias, XB_READ_WRITE, XB_MULTI_USER )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // do any .INF data things on the file, like open indices - #ifdef XB_INF_SUPPORT - if(( iRc = LoadInfData()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - xbUInt32 llNodeCnt = llInfData.GetNodeCnt(); - if( llNodeCnt > 0 ){ - xbString s2; - xbLinkListNode<xbString> * llN = llInfData.GetHeadNode(); - for( xbUInt32 i = 0; i < llNodeCnt; i++ ){ - s2 = llN->GetKey(); - #ifdef XB_NDX_SUPPORT - if(( iRc = OpenIndex( "NDX", s2 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc ; - } - #endif // XB_NDX_SUPPORT - llN = llN->GetNextNode(); - } - } - #endif // XB_INF_SUPPORT - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Open() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Open an index. -/*! - Open an index file for the dbf file. - - \param sIxType - "NDX" or "MDX" - \param sFileName - File name of index, - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::OpenIndex( const xbString &sIxType, const xbString &sFileName ){ - - // this routine is used to open indices and set up linkages - - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - xbIx *pIx = NULL; - - try{ - xbString sType = sIxType; - sType.ToUpperCase(); - - if( sType == "" ){ - iErrorStop = 100; - iRc = XB_INVALID_OPTION; - throw iRc; - - #ifdef XB_NDX_SUPPORT - } else if( sType == "NDX" ){ - pIx = new xbIxNdx( this ); - if(( iRc = pIx->Open( sFileName )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - #endif - - #ifdef XB_MDX_SUPPORT - } else if( sType == "MDX" ){ - pIx = new xbIxMdx( this ); - if(( iRc = pIx->Open( sFileName )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - #endif - - } else { - iErrorStop = 130; - iRc = XB_INVALID_OPTION; - throw iRc; - } - - if(( iRc = AddIndex( pIx, sIxType )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if(( iRc = UpdateTagList()) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - pCurIx = pIx; - sCurIxType = sIxType; - vpCurIxTag = pIx->GetTag( 0 ); - } - catch (xbInt16 iRc ){ - if( pIx ) delete pIx; - xbString sMsg; - sMsg.Sprintf( "xbdbf::OpenIndex() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INDEX_SUPPORT - - - -/************************************************************************/ -//! @brief Pack dbf file. -/*! - This routine eliminates all deleted records from the file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::Pack() -{ - xbUInt32 ulDeletedRecCnt; - return Pack( ulDeletedRecCnt ); -} - - -/************************************************************************/ -//! @brief Pack dbf file. -/*! - This routine eliminates all deleted records from the file and clears - out any unused blocks in the memo file if one exists. - \param ulDeletedRecCnt - Output - number of recrods removed from the file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::Pack( xbUInt32 &ulDeletedRecCnt ) -{ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbUInt32 ulLastMovedRec = 0; - xbUInt32 ulStartPos = 0; - xbUInt32 ulLastPackedRec = 0; - xbUInt32 ulMoveRec = 0; - xbUInt32 ulRecCnt = 0; - ulDeletedRecCnt = 0; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif // XB_LOCKING_SUPPORT - - try{ - if( !FileIsOpen() ){ - iErrorStop = 100; - iRc = XB_DBF_FILE_NOT_OPEN; - throw iRc; - } - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } else { - bLocked = xbTrue; - } - } - #endif - - if(( iRc = GetRecordCnt( ulRecCnt )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - xbBool bDone = xbFalse; - for( xbUInt32 ulI = 1; ulI <= ulRecCnt && !bDone; ulI++ ){ - - if(( iRc = GetRecord( ulI )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( RecordDeleted()){ - ulDeletedRecCnt++; - if( ulI > ulLastMovedRec ) - ulStartPos = ulI; - else - ulStartPos = ulLastMovedRec; - - iRc = GetNextRecord( 1, ulStartPos ); - - if( iRc == XB_NO_ERROR ){ - ulMoveRec = ulCurRec; - } - else if( iRc == XB_EOF ){ - ulMoveRec = 0; - bDone = xbTrue; - } - else{ - iErrorStop = 140; - throw iRc; - } - if( ulMoveRec > 0 ){ - if(( iRc = DeleteRecord()) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if(( iRc = PutRecord( ulMoveRec )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if(( iRc = UndeleteRecord()) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - if(( iRc = PutRecord( ulI )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - ulLastPackedRec = ulI; - } - - } else { - ulLastPackedRec = ulI; - } - } - - if( ulLastPackedRec < ulRecCnt ){ - // update header record count - - xbDate d; - d.Sysdate(); - cUpdateYY = (char) d.YearOf() - 1900; - cUpdateMM = (char) d.MonthOf(); - cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); - ulNoOfRecs = ulLastPackedRec; - - // rewrite the header record - if(( iRc = WriteHeader( 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - - // truncate the file to the new size - if(( iRc = xbTruncate( uiHeaderLen + uiRecordLen * ulLastPackedRec )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - } - - if( ulNoOfRecs > 0 ){ - if(( iRc = GetRecord( 1 )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - } else { - BlankRecord(); - ulCurRec = 0; - } - - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ){ - if(( iRc = Memo->PackMemo( 0 )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - } - #endif // XB_MEMO_SUPPORT - } - catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Pack() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - LockTable( XB_UNLOCK ); - } - #endif - return iRc; -} - -/************************************************************************/ -//! @brief Write the current record to disk. -/*! - This routine is used to write any updates to the current record buffer to disk. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::PutRecord() { - return PutRecord(ulCurRec); -} - -/************************************************************************/ -//! @brief Write record to disk. -/*! - This routine is used to write a copy of the current record buffer to disk - for a given record number. - - \param ulRecNo Record number to update. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::PutRecord(xbUInt32 ulRecNo) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( ulRecNo < 1 ){ - iErrorStop = 100; - throw XB_INVALID_RECORD; - } - - xbUInt32 ulRecCnt; - if(( iRc = GetRecordCnt( ulRecCnt )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - if( ulRecNo > ulRecCnt ){ - iErrorStop = 120; - throw XB_INVALID_RECORD; - } - - if( iDbfStatus == XB_CLOSED ){ - iErrorStop = 130; - iRc = XB_NOT_OPEN; - throw iRc; - } - /* lock the database */ - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockHeader( XB_LOCK )) != XB_NO_ERROR ){ - throw iRc; - } - } - #endif // XB_LOCKING_SUPPORT - - if(( iRc = ReadHeader( 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - // verify valid record number request - if( ulRecNo > ulNoOfRecs || ulRecNo == 0L ){ - iErrorStop = 160; - iRc = XB_INVALID_RECORD; - throw iRc; - } - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock && !bTableLocked ){ - if(( iRc = LockRecord( XB_LOCK, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - - #ifdef XB_INDEX_SUPPORT - if(( iRc = LockIndices( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - #endif // XB_INDEX_SUPPORT - } - #endif // XB_LOCKING_SUPPORT - - // build keys, check for duplicate keys, add keys - #ifdef XB_INDEX_SUPPORT - xbIxList *ixList = GetIxList(); - - while( ixList ){ - if(( iRc = ixList->ix->CreateKeys( 2 )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - iRc = ixList->ix->CheckForDupKeys(); - if( iRc != 0 ){ - if( iRc < 0 ){ - iErrorStop = 200; - throw iRc; - } - throw XB_KEY_NOT_UNIQUE; - } - ixList = ixList->next; - } - - ixList = GetIxList(); - while( ixList ){ - - if(( iRc = ixList->ix->AddKeys( ulCurRec )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - ixList = ixList->next; - } - - ixList = GetIxList(); - while( ixList ){ - if(( iRc = ixList->ix->DeleteKeys()) != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - ixList = ixList->next; - } - #endif // XB_INDEX_SUPPORT - - // update latest header date if changed - xbDate d; - d.Sysdate(); - if( (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 ); - // rewrite the header record - first 8 bytes - if(( iRc = WriteHeader( 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 70; - throw iRc; - } - } - - // update record - iRc = xbFseek( (uiHeaderLen+(( (xbInt64) ulRecNo-1L ) * uiRecordLen )),0 ); - if( iRc != XB_NO_ERROR ){ - iErrorStop = 240; - throw iRc; - } - - if( xbFwrite( RecBuf, uiRecordLen, 1 ) != XB_NO_ERROR ){ - iErrorStop = 250; - iRc = XB_WRITE_ERROR; - throw iRc; - } - - #ifdef XB_MEMO_SUPPORT - if( MemoFieldsExist() ){ - if(( iRc = Memo->Commit()) != XB_NO_ERROR ){ - iErrorStop = 260; - throw iRc; - } - } - #endif - - ulCurRec = ulRecNo; - iDbfStatus = XB_OPEN; - } - - catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED && iRc != XB_KEY_NOT_UNIQUE ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::PutRecord() Exception Caught. Error Stop = [%d] iRc = [%d] record = [%d]", iErrorStop, iRc, ulRecNo ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock ){ - LockHeader( XB_UNLOCK ); - LockAppend( XB_UNLOCK ); - LockRecord( XB_UNLOCK, ulRecNo ); - #ifdef XB_INDEX_SUPPORT - LockIndices( XB_UNLOCK ); - #endif // XB_INDEX_SUPPORT - } - #endif // XB_LOCKING_SUPPORT - - return iRc; -} - -/************************************************************************/ -//! @brief Read dbf file header information. -/*! - This method assumes the header has been locked appropriately - in a multi user environment - - - \param iPositionOption 0 - Don't fseek to beginning of file before read.<br> - 1 - Start from beginning of file. - - \param iReadOption 0 - Read entire 32 byte header<br> - 1 - Read first eight bytes which includes the last update date and number of records. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::ReadHeader( xbInt16 iPositionOption, xbInt16 iReadOption ){ - - char buf[32]; - size_t iReadSize; - - if(iPositionOption) - xbRewind(); - if( iReadOption == 1 ) - iReadSize = 8; - else - iReadSize = 32; - - if(xbFread(buf, iReadSize, 1) != XB_NO_ERROR) - return XB_READ_ERROR; - memcpy(&cVersion, buf, 4); - ulNoOfRecs = eGetUInt32(&buf[4]); - if( iReadOption == 1 ) - return XB_NO_ERROR; - - uiHeaderLen = eGetUInt16(&buf[8]); - uiRecordLen = eGetUInt16(&buf[10]); - cTransactionFlag = buf[14]; - cEncryptionFlag = buf[15]; - cIndexFlag = buf[28]; - cLangDriver = buf[29]; - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Return record deletion status. -/*! - This routine returns the record deletion status. - \param iOpt 0 = Current record buffer, 1 = Original record buffer - \returns xbTrue - Record deleted.<br>xbFalse - Record not deleted. -*/ -xbInt16 xbDbf::RecordDeleted( xbInt16 iOpt ) const { - if( !iOpt && RecBuf && RecBuf[0] == 0x2a ) - return xbTrue; - else if( iOpt && RecBuf2 && RecBuf2[0] == 0x2a ) - return xbTrue; - else - return xbFalse; -} - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Remove an index from the internal list of indices for this table -/* - The index list is used during any table update process to update any open - index file. Index files can contain one or more tags. - - \param ixIn Pointer to index object for a given index file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::RemoveIndex( xbIx * ixIn ){ - - xbIxList *p = ixList; - // if index is the first entry in the list - if( ixList->ix == ixIn ){ - ixList = ixList->next; - delete p->sFmt; - delete p->ix; - free( p ); - return XB_NO_ERROR; - } - - // spin down to the correct ix - xbIxList *p2 = NULL; - while( p && p->ix != ixIn ){ - p2 = p; - p = p->next; - } - if( p ){ - p2->next = p->next; - delete p->sFmt; - delete p->ix; - free( p ); - } - return XB_NO_ERROR; -} -#endif // XB_INDEX_SUPPORT - -/************************************************************************/ -// @brief Reset number of records. -/* - Protected method. Resets number of records to 0. - \returns void -*/ -void xbDbf::ResetNoOfRecords() { - ulNoOfRecs = 0UL; -} - -/************************************************************************/ -#ifdef XB_INF_SUPPORT -// @brief Update .INF data file. -/* - Protected method. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf::SaveInfData(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbFile fMd( xbase ); - - try{ - - xbUInt32 llNodeCnt = llInfData.GetNodeCnt(); - - xbString sInfFileName; - if(( iRc = GetInfFileName( sInfFileName )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // open the file - if(( iRc = fMd.xbFopen( "w", sInfFileName, GetShareMode())) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - xbString s1; - xbString s2; - s2.Sprintf( "[dbase]%c%c", 0x0d, 0x0a ); - if(( iRc = fMd.xbFputs( s2 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - // for each entry in the linked list, write a line - xbLinkListNode<xbString> * llN = llInfData.GetHeadNode(); - for( xbUInt32 i = 0; i < llNodeCnt; i++ ){ - s2 = llN->GetKey(); - if( i > 0 ) - s1.Sprintf( "NDX%d=%s%c%c", i, s2.Str(), 0x0d, 0x0a ); - else - s1.Sprintf( "NDX=%s%c%c", s2.Str(), 0x0d, 0x0a ); - - if(( iRc = fMd.xbFputs( s1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - llN = llN->GetNextNode(); - } - - // close the file - if(( iRc = fMd.xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - } catch( xbInt16 iRc ){ - if( fMd.FileIsOpen()) - fMd.xbFclose(); - xbString sMsg; - sMsg.Sprintf( "xbdbf::SaveInfData() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INF_SUPPORT -/************************************************************************/ -//! @brief Set auto commit. -/*! - This routine sets the auto commit setting for this table. - \returns XB_NO_ERROR; -*/ -xbInt16 xbDbf::SetAutoCommit( xbBool iAutoCommit ) { - this->iAutoCommit = iAutoCommit; - return XB_NO_ERROR; -} - - -/************************************************************************/ -//! @brief Set auto lock. -/*! - This routine sets the auto lock setting for this table. - There is an overall system level auto lock default setting and each table - can have it's own autolock setting. This method controls the table level - auto lock setting. - - \param iAutoLock 1 - Use auto lock for this table.<br> - 0 - Don't use auto lock for this table.<br> - -1 - (minus one) Use system default.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -#ifdef XB_LOCKING_SUPPORT -void xbDbf::SetAutoLock( xbInt16 iAutoLock ){ - if( iAutoLock == -1 ) - this->iAutoLock = xbase->GetDefaultAutoLock(); - else - this->iAutoLock = iAutoLock; -} -#endif - - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Set the current tag for the dbf file. -/*! - \param sTagName - Tag Name - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::SetCurTag( const xbString &sTagName ){ - - if( sTagName == "" ){ - SetCurTag( "", 0, 0 ); - return XB_NO_ERROR; - - } else { - xbLinkListNode<xbTag *> *llN = GetTagList(); - xbTag *pTag; - while( llN ){ - pTag = llN->GetKey(); - if( pTag->GetTagName() == sTagName ){ - SetCurTag( pTag->GetType(), pTag->GetIx(), pTag->GetVpTag()); - return XB_NO_ERROR; - } - llN = llN->GetNextNode(); - } - } - - return XB_INVALID_TAG; -} - -/************************************************************************/ -//! @brief Set the current tag for the dbf file. -/*! - - \param sIxType - One of "NDX", MDX or TDX", - \param pIx - Pointer to index object. - \param vpTag - Pointer to tag object. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -void xbDbf::SetCurTag( const xbString &sIxType, xbIx *pIx, void *vpTag ){ - pCurIx = pIx; - vpCurIxTag = vpTag; - sCurIxType.Set( sIxType ); -} -#endif // XB_INDEX_SUPPORT - -/************************************************************************/ -//! @brief Set the header locked status. -/*! - \param bHeaderLocked xbTrue - Locked<br>xbFalse - Not locked. - \returns void -*/ -#ifdef XB_LOCKING_SUPPORT -void xbDbf::SetHeaderLocked( xbBool bHeaderLocked ){ - this->bHeaderLocked = bHeaderLocked; -} -#endif - -/************************************************************************/ -//! @brief Set lock flavor. -/*! - This routine is for future expansion. - \param iLockFlavor 1 - Use Dbase (tm) style locking. - \returns void -*/ -#ifdef XB_LOCKING_SUPPORT -void xbDbf::SetLockFlavor( xbInt16 iLockFlavor ){ - this->iLockFlavor = iLockFlavor; -} -#endif - -/************************************************************************/ -//! @brief Set table locked status. -/*! - \param bTableLocked - xbTrue Table locked.<br>xbFalse Table unlocked. - \returns void -*/ -#ifdef XB_LOCKING_SUPPORT -void xbDbf::SetTableLocked( xbBool bTableLocked ){ - this->bTableLocked = bTableLocked; -} -#endif -/************************************************************************/ -//! @brief Undelete all records. -/*! - This routine will remove the deletion flag on any deleted records in the table. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::UndeleteAllRecords(){ - return DeleteAll( 1 ); -} - -/************************************************************************/ -//! @brief Undelete one record. -/*! - This routine will undelete the current record, if it is deleted. - \returns XB_NO_ERROR<br>XB_INVALID_RECORD -*/ -xbInt16 xbDbf::UndeleteRecord() -{ - if( RecBuf && ulCurRec > 0 ){ - if( RecBuf[0] != 0x20 ){ - if( iDbfStatus != XB_UPDATED ){ - iDbfStatus = XB_UPDATED; - memcpy( RecBuf2, RecBuf, uiRecordLen ); // save off original before making updates - } - RecBuf[0] = 0x20; - } - return XB_NO_ERROR; - } - else - return XB_INVALID_RECORD; -} - -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT -//! @brief Update memo field -/*! - This routine updates a memo field. - \param iFieldNo - Memo field number to update. - \param sMemoData - Memo data for update. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::UpdateMemoField( xbInt16 iFieldNo, const xbString &sMemoData ){ - return Memo->UpdateMemoField( iFieldNo, sMemoData ); -} -/************************************************************************/ -//! @brief Update memo field -/*! - This routine updates a memo field. - \param sFieldName - Memo field name to update. - \param sMemoData - Memo data for update. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::UpdateMemoField( const xbString & sFieldName, const xbString & sMemoData ){ - return Memo->UpdateMemoField( GetFieldNo( sFieldName ), sMemoData ); -} -#endif - - -/************************************************************************/ -#ifdef XB_INDEX_SUPPORT -//! @brief Update SchemaIxFlag -/*! - This routine can be called from the DeleteTag routine if a tag has been deleted and the flag needs reset - \param iFldNo - Which field the index flag needs changed on - \param cVal - Value to change it to -*/ - -void xbDbf::UpdateSchemaIxFlag( xbInt16 iFldNo, unsigned char cVal ){ - if( cVal != 0x00 || cVal != 0x01 ) - SchemaPtr[iFldNo].cIxFlag = cVal; -} - -/************************************************************************/ - -//! @brief Update tag list. -/*! - This routine updates the internal tag list of open index tags. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::UpdateTagList(){ - - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - xbInt32 lTagCnt; - - try{ - ClearTagList(); - - // For each active index - xbIxList *p = GetIxList(); - xbIx *ixp; - while( p ){ - ixp = p->ix; - // for each tag within the file - lTagCnt = ixp->GetTagCount(); - for( xbInt32 l = 0; l < lTagCnt; l++ ){ - xbTag *pTag = new xbTag( ixp, ixp->GetTag( l ), *p->sFmt, ixp->GetTagName( ixp->GetTag( l )), - ixp->GetKeyExpression( ixp->GetTag( l )), ixp->GetKeyFilter( ixp->GetTag( l )), - ixp->GetUnique( ixp->GetTag( l )), ixp->GetSortOrder( ixp->GetTag( l ))); - - // append it to the llTags list - llTags.InsertAtEnd( pTag ); - } - p = p->next; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::UpdateTagList() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INDEX_SUPPORT - -/************************************************************************/ -// @brief Write Header -/* - Protected method. - - \param iPositionOption 0 - Don't fseek to beginning of file before read.<br> - 1 - Go to beginning of file before read. - \param iWriteOption 0 - Write entire 32 byte header.<br> - 1 - Write first eight bytes needed for table updates - last update date and number of records. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::WriteHeader( xbInt16 iPositionOption, xbInt16 iWriteOption ) -{ - char buf[32]; - xbInt32 lWriteLen; - - if(iPositionOption) - xbRewind(); - - memset(buf, 0, 32); - if( iWriteOption == 1 ) - lWriteLen = 8; - else{ - lWriteLen = 32; - ePutUInt16( &buf[8], uiHeaderLen ); - ePutUInt16( &buf[10], uiRecordLen ); - buf[14] = cTransactionFlag; - buf[15] = cEncryptionFlag; - buf[28] = cIndexFlag; - buf[29] = cLangDriver; - } - memcpy(&buf[0], &cVersion, 4); - ePutUInt32( &buf[4], ulNoOfRecs); - if(xbFwrite(buf, (size_t) lWriteLen, 1) != XB_NO_ERROR) - return XB_WRITE_ERROR; - - return XB_NO_ERROR; -} -/************************************************************************/ -//! @brief Zap (remove) everything from the file, -/*! - This routine eliminates everything from the dbf file and dbt memo file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf::Zap(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif // XB_LOCKING_SUPPORT - - try{ - if( iDbfStatus != XB_OPEN ){ - iErrorStop = 100; - iRc = XB_DBF_FILE_NOT_OPEN; - throw iRc; - } - #ifdef XB_LOCKING_SUPPORT - if( iAutoLock ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - #endif - - xbDate d; - d.Sysdate(); - cUpdateYY = (char) d.YearOf() - 1900; - cUpdateMM = (char) d.MonthOf(); - cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); - ulNoOfRecs = 0; - - // rewrite the header record - if(( iRc = WriteHeader( 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - // truncate the file to the new size - if(( iRc = xbTruncate( uiHeaderLen )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - BlankRecord(); - ulCurRec = 0; - - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt ){ - if(( iRc = Memo->Zap()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - } - #endif - #ifdef XB_INDEX_SUPPORT - xbLinkListNode<xbTag *> *llN = GetTagList(); - xbTag *pTag; - xbIx *pIx; - void *vpTag; - while( llN ){ - pTag = llN->GetKey(); - pIx = pTag->GetIx(); - vpTag = pTag->GetVpTag(); - if(( iRc = pIx->Reindex( &vpTag )) != XB_NO_ERROR ){ - iErrorStop = 60; - throw iRc; - } - llN = llN->GetNextNode(); - } - - #endif // XB_INDEX_SUPPORT - } - catch (xbInt16 iRc ){ - if( iRc != XB_LOCK_FAILED ){ - xbString sMsg; - sMsg.Sprintf( "xbdbf::Zap() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - } - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - LockTable( XB_UNLOCK ); - } - #endif // XB_LOCKING_SUPPORT - 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/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf3.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf3.cpp deleted file mode 100755 index 926cc0d..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf3.cpp +++ /dev/null @@ -1,768 +0,0 @@ -/* xbdbf3.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 - -*/ - -#include "xbase.h" - - -#ifdef XB_DBF3_SUPPORT - -namespace xb{ - - -/************************************************************************/ -//! @brief Constructor. - -xbDbf3::xbDbf3(xbXBase * x) : xbDbf( x ) { - #ifdef XB_MEMO_SUPPORT - ulCreateMemoBlockSize = 512; - #endif - iFileVersion = 3; -}; - -/************************************************************************/ -//! @brief Destructor. - -xbDbf3::~xbDbf3() {}; - -/************************************************************************/ -//! @brief Create Version 3 table. -/*! - This routine creates a Dbase III Plus (tm) DBF file. - - \param sTableName DBF table name. - \param sAlias Table alias - \param pSchema Pointer to schema structure with field definitions. - \param iOverlay xbTrue - Overlay.<br> xbFalse - Don't overlay. - \param iShareMode XB_SINGLE_USER<br>XB_MULTI_USER - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbDbf3::CreateTable( const xbString & sTableName, const xbString & sAlias, xbSchema *pSchema, xbInt16 iOverlay, xbInt16 iShareMode ){ - - xbInt16 i, k, k2; - xbInt16 rc = 0; - xbInt16 iErrorStop = 0; - iDbfStatus = XB_CLOSED; - - xbString sNfn; - try{ - sNfn = sTableName; - xbase->GetLogStatus(); - - rc = NameSuffixMissing( sNfn, 1 ); - if( rc > 0 ) - sNfn += ".DBF"; - - SetFileName( sNfn ); - this->sAlias = sAlias; - - /* check if the file already exists */ - if( FileExists( 0 )){ - if( !iOverlay ){ - iErrorStop = 100; - rc = XB_FILE_EXISTS; - throw rc; - } - - // remove other files if they exist - xbString sMname = sNfn; - xbUInt32 iMnameLen = sMname.Len(); - sMname.PutAt( iMnameLen-2, 'I' ); - sMname.PutAt( iMnameLen-1, 'N' ); - sMname.PutAt( iMnameLen, 'F' ); - xbFile fTemp( xbase ); - fTemp.SetFileName( sMname ); - if( fTemp.FileExists() ) - fTemp.xbRemove(); - - sMname.PutAt( iMnameLen-2, 'D' ); - sMname.PutAt( iMnameLen-1, 'B' ); - sMname.PutAt( iMnameLen, 'T' ); - fTemp.SetFileName( sMname ); - if( fTemp.FileExists() ) - fTemp.xbRemove(); - - sMname.PutAt( iMnameLen-2, 'M' ); - sMname.PutAt( iMnameLen-1, 'D' ); - sMname.PutAt( iMnameLen, 'X' ); - fTemp.SetFileName( sMname ); - if( fTemp.FileExists() ) - fTemp.xbRemove(); - } - - /* check if we already have a file with this alias */ - if(( rc = xbase->AddTblToTblList( this, GetFqFileName(), sAlias )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - - rc = ValidateSchema( pSchema ); - if( rc < 0 ){ - iErrorStop = 120; - throw rc; - } else - iNoOfFields = rc; - - #ifdef XB_MEMO_SUPPORT - // if we have memo fields - iMemoFieldCnt = 0; - i = 0; - while( pSchema[i].cType != 0){ - if( pSchema[i].cType == 'M' ) - iMemoFieldCnt++; /* number of memo fields in the incoming definition */ - i++; - } - - if( iMemoFieldCnt > 0 ){ - xbString sMfn = sNfn; /* memo file name, same as filename except ends with a "t", not an "f" */ - xbUInt32 iMfnLen = sMfn.Len(); - sMfn.PutAt( iMfnLen, 'T' ); - - // dont overlay the memo file if it exists, and Overlay switch is off - xbFile fTemp( xbase ); - fTemp.SetFileName( sMfn ); - if( fTemp.FileExists() && !iOverlay ){ - iErrorStop = 130; - rc = XB_FILE_EXISTS; - throw rc; - } - - Memo = new xbMemoDbt3( this, fTemp.GetFqFileName()); - - if(( rc = Memo->CreateMemoFile()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw rc; - } - } - #endif - - /* this is the dBase III version of the class */ - cVersion = 0x03; // 0x03 for Dbase level 5 - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ){ -// cVersion = cVersion |= 0x80; // Version III memo, compiler complaints - cVersion |= 0x80; // Version III memo - } - #endif - - if(( rc = xbFopen( "w+b", iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw rc; - } - uiRecordLen++; /* add one byte for 0x0D */ - - if(( RecBuf = (char *) malloc( uiRecordLen )) == NULL ){ - iErrorStop = 160; - throw rc; - } - - if(( RecBuf2 = (char *) malloc( uiRecordLen )) == NULL ){ - iErrorStop = 170; - rc = XB_NO_MEMORY; - throw rc; - } - - /* BlankRecord(); */ - memset( RecBuf, 0x20, uiRecordLen ); - memset( RecBuf2, 0x20, uiRecordLen ); - ulCurRec = 0L; - uiHeaderLen = 33 + iNoOfFields * 32; - xbDate d; - d.Sysdate(); - cUpdateYY = (char) (d.YearOf() - 1900); - cUpdateMM = (char) d.MonthOf(); - cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); - - /* write the header prolog */ - if(( rc = WriteHeader( 0, 0 )) != XB_NO_ERROR ){ - iErrorStop = 180; - rc = XB_WRITE_ERROR; - throw rc; - } - if((SchemaPtr = (xbSchemaRec *) malloc( (size_t) iNoOfFields * sizeof( xbSchemaRec ))) == NULL){ - iErrorStop = 190; - rc = XB_NO_MEMORY; - throw rc; - } - - /* write the field information into the header */ - for( i = 0, k = 1; i < iNoOfFields; i++ ){ - - memset( SchemaPtr[i].cFieldName, 0x00, 11 ); - for( int x = 0; x < 10 && pSchema[i].cFieldName[x]; x++ ) - SchemaPtr[i].cFieldName[x] = pSchema[i].cFieldName[x]; - - SchemaPtr[i].cType = pSchema[i].cType; - SchemaPtr[i].cFieldLen = (unsigned char) pSchema[i].iFieldLen; - SchemaPtr[i].cNoOfDecs = (unsigned char) pSchema[i].iNoOfDecs; - - if( SchemaPtr[i].cNoOfDecs > SchemaPtr[i].cFieldLen ){ - iErrorStop = 200; - rc = XB_WRITE_ERROR; - throw rc; - } - - k2 = k; - k += SchemaPtr[i].cFieldLen; - - if(( xbFwrite( &SchemaPtr[i].cFieldName, 1, 11 )) != XB_NO_ERROR ) { - iErrorStop = 210; - rc = XB_WRITE_ERROR; - throw rc; - } - - if(( xbFwrite( &SchemaPtr[i].cType, 1, 1 )) != XB_NO_ERROR ) { - iErrorStop = 220; - rc = XB_WRITE_ERROR; - throw rc; - } - - for( int j = 0; j < 4; j++ ) - xbFputc( 0x00 ); - - if(( xbFwrite( &SchemaPtr[i].cFieldLen, 1, 1 )) != XB_NO_ERROR ) { - iErrorStop = 230; - rc = XB_WRITE_ERROR; - throw rc; - } - - if(( xbFwrite( &SchemaPtr[i].cNoOfDecs, 1, 1 )) != XB_NO_ERROR ) { - iErrorStop = 240; - rc = XB_WRITE_ERROR; - throw rc; - } - - /* 14 bytes reserved */ - for( int j = 0; j < 14; j++ ) - xbFputc( 0x00 ); - - SchemaPtr[i].pAddress = RecBuf + k2; - SchemaPtr[i].pAddress2 = RecBuf2 + k2; - } - - /* write the header terminator */ - if(( xbFputc( XB_CHARHDR )) != XB_NO_ERROR ){ - iErrorStop = 250; - rc = XB_WRITE_ERROR; - throw rc; - } - } - catch( xbInt16 rc ) - { - xbString sMsg; - sMsg.Sprintf( "xbdbf3::CreateTable() Exception Caught Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - - sMsg.Sprintf( "Table Name = [%s]", GetFqFileName().Str()); - xbase->WriteLogMessage( sMsg ); - sMsg.Sprintf( "Alias Name = [%s]", sAlias.Str()); - xbase->WriteLogMessage( sMsg ); - - xbFclose(); - if( RecBuf ){ - free( RecBuf ); - RecBuf = NULL; - } - if( RecBuf2 ){ - free( RecBuf2 ); - RecBuf2 = NULL; - } - if( SchemaPtr ){ - free( SchemaPtr ); - SchemaPtr = NULL; - } - - InitVars(); - if( rc != XB_FILE_EXISTS ) - xbase->RemoveTblFromTblList( sAlias ); - } - - if( rc == XB_NO_ERROR ) - iDbfStatus = XB_OPEN; - - return rc; -} - -/************************************************************************/ -//! @brief Get version. -/*! - The version info can be retrieved to determine - which class is being used for a given dbf instance. - \returns 3 -*/ - -xbInt16 xbDbf3::GetVersion() const { - return 3; -} - - - -/************************************************************************/ -//! @brief Open dbf file/table. -/*! - \param sTableName DBF table name. - \param sAlias Table alias - \param iOpenMode XB_READ<br>XB_READ_WRITE - \param iShareMode XB_SINGLE_USER<br>XB_MULTI_USER - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf3::Open( const xbString & sTableName, const xbString & sAlias, - xbInt16 iOpenMode, xbInt16 iShareMode ){ - xbInt16 i, j, iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char buf[33]; - char *p; - - #ifdef XB_MEMO_SUPPORT - iMemoFieldCnt = 0; - #endif - - try{ - - /* verify the file is not already open */ - if( iDbfStatus != XB_CLOSED ){ - iErrorStop = 100; - iRc = XB_ALREADY_OPEN; - throw iRc; - } - /* copy the file name to the class variable */ - SetFileName( sTableName ); - this->sAlias = sAlias; - - if( !FileExists()){ - iErrorStop = 110; - iRc = XB_FILE_NOT_FOUND; - throw iRc; - } - - if(( iRc = xbase->AddTblToTblList( this, GetFqFileName(), sAlias )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - /* open the file */ - if(( iRc = xbFopen( iOpenMode, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - /* copy the header into memory */ - if(( iRc = ReadHeader( 1, 0 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - /* check the version */ - if(( cVersion & 0x07 ) != 3 ){ - // if( xFileVersion != 3 && xFileVersion != 4 ){ - iErrorStop = 150; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - } - iFileVersion = 3; - - /* calculate the number of fields */ - if( cVersion == (char)0x30 ) { - iNoOfFields = ( uiHeaderLen - 296 ) / 32 ; - } else { - iNoOfFields = ( uiHeaderLen - 33 ) / 32; - } - - if(( RecBuf = (char *) malloc( (size_t) uiRecordLen )) == NULL ){ - iErrorStop = 160; - iRc = XB_NO_MEMORY; - throw iRc; - } - - if(( RecBuf2 = (char *) malloc( uiRecordLen )) == NULL ) { - iErrorStop = 170; - iRc = XB_NO_MEMORY; - throw iRc; - } - - if((SchemaPtr=(xbSchemaRec *)malloc( (size_t) iNoOfFields * sizeof( xbSchemaRec ))) == NULL){ - iErrorStop = 180; - iRc = XB_NO_MEMORY; - throw iRc; - } - - memset( SchemaPtr, 0x00, ( (size_t) iNoOfFields * sizeof(xbSchemaRec) )); - /* copy field info into memory */ - for( i = 0, j = 1; i < iNoOfFields; i++ ){ - xbFseek( ((xbInt64)i*32+32), SEEK_SET ); - xbFread( &buf, 1, 32 ); - p = buf; - for( int x = 0; x < 10 && buf[x]; x++ ){ - SchemaPtr[i].cFieldName[x] = buf[x]; - } - p = buf + 11; - SchemaPtr[i].cType = *p++; - SchemaPtr[i].pAddress = RecBuf + j; - SchemaPtr[i].pAddress2 = RecBuf2 + j; - SchemaPtr[i].cFieldLen = (unsigned char) *( p + 4 ); - SchemaPtr[i].cNoOfDecs = (unsigned char) *( p + 5 ); - j += SchemaPtr[i].cFieldLen; - #ifdef XB_MEMO_SUPPORT - if( (SchemaPtr[i].cType == 'M' || SchemaPtr[i].cType == 'B' || SchemaPtr[i].cType == 'O' )) - iMemoFieldCnt++; - #endif - } - ulCurRec = 0L; - iDbfStatus = XB_OPEN; - if(( iRc = BlankRecord()) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ){ /* does this table have memo fields ? */ - - // build the file name - xbString sMfn = GetFqFileName(); /* memo file name, same as filename except ends with a "t", not an "f" */ - xbUInt32 ulMfnLen = sMfn.Len(); - if( sMfn[ulMfnLen] == 'F' ) - sMfn.PutAt( ulMfnLen, 'T' ); - else - sMfn.PutAt( ulMfnLen, 't' ); - xbFile fTemp( xbase ); - fTemp.SetFileName( sMfn );; - - Memo = new xbMemoDbt3( this, fTemp.GetFqFileName()); - - if(( iRc = Memo->OpenMemoFile()) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - } - #endif // XB_MEMO_SUPPORT - - } - catch ( xbInt16 iRc ) - { - xbString sMsg; - 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(); - if( RecBuf ){ - free( RecBuf ); - RecBuf = NULL; - } - if( RecBuf2 ){ - free( RecBuf2 ); - RecBuf2 = NULL; - } - if( SchemaPtr ){ - free( SchemaPtr ); - SchemaPtr = NULL; - } - InitVars(); - - #ifdef XB_MEMO_SUPPORT - if( Memo ){ - Memo->CloseMemoFile(); - delete Memo; - Memo = NULL; - } - #endif // XB_MEMO_SUPPORT - } - - if( iRc == XB_NO_ERROR ) - iDbfStatus = XB_OPEN; - - return iRc; -} -/************************************************************************/ -//! @brief Rename table. -/*! - This routine renames a give table, associated memo and inf files - \param sNewName - New file name. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf3::Rename( const xbString sNewName ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbString sNewDbf; - - xbBool bDbfRenamed = xbFalse; - - #ifdef XB_INF_SUPPORT - xbString sNewInf; - xbString sThisInf; - xbBool bInfRenamed = xbFalse; - #endif - - #ifdef XB_MEMO_SUPPORT - xbString sNewDbt; - xbString sThisDbt; - xbBool bDbtRenamed = xbFalse; - #endif // XB_MEMO_SUPPORT - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif - - try{ - - xbString sDir; - xbString sFile; - xbString sExt; - - xbString sNewNameWoExt; - sNewNameWoExt.Set( sNewName ); - if( sNewName.Pos( ".DBF" ) > 0 ) - sNewNameWoExt.Left( sNewName.Len() - 4 ); - - GetFileDirPart ( sDir ); - GetFileNamePart( sFile ); - GetFileExtPart ( sExt ); - - if( FileExists( sNewDbf )) return XB_FILE_EXISTS; - sNewDbf.Sprintf( "%s%s.DBF", sDir.Str(), sNewNameWoExt.Str()); - - #ifdef XB_MEMO_SUPPORT - sNewDbt.Sprintf( "%s%s.DBT", sDir.Str(), sNewNameWoExt.Str()); - if( FileExists( sNewDbt )) return XB_FILE_EXISTS; - sThisDbt.Sprintf( "%s%s.DBT", sDir.Str(), sFile.Str()); - #endif - - #ifdef XB_INF_SUPPORT - sNewInf.Sprintf( "%s%s.INF", sDir.Str(), sNewNameWoExt.Str()); - if( FileExists( sNewInf )) return XB_FILE_EXISTS; - sThisInf.Sprintf( "%s%s.INF", sDir.Str(), sFile.Str()); - #endif // XB_INF_SUPPORT - - #ifdef XB_LOCKING_SUPPORT - if( GetAutoLock() && GetTableLocked() ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - bLocked = xbTrue; - } - #endif - - xbInt16 iOpenMode = GetOpenMode(); - xbInt16 iShareMode = GetShareMode(); - xbBool bWasOpen = xbFalse; - if( FileIsOpen() ){ - bWasOpen = xbTrue; - if(( iRc = xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - - if(( iRc = xbRename( GetFqFileName().Str(), sNewDbf.Str())) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } else { - bDbfRenamed = xbTrue; - } - xbString sNameWext; - sNameWext.Sprintf( "%s.DBF", sNewNameWoExt.Str()); - SetFileName( sNameWext ); - - if( bWasOpen ){ - if(( iRc = xbFopen( iOpenMode, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - - #ifdef XB_MEMO_SUPPORT - if( FileExists( sThisDbt )){ - if( bWasOpen ){ - if(( iRc = Memo->xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - } - if(( xbRename( sThisDbt.Str(), sNewDbt.Str())) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - Memo->SetFileName( sNewDbt ); - if( bWasOpen ){ - if(( iRc = Memo->xbFopen( iOpenMode, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - } - bDbtRenamed = xbTrue; - } - #endif // XB_MEMO_SUPPORT - - #ifdef XB_INF_SUPPORT - if( FileExists( sThisInf )){ - if(( iRc = xbRename( sThisInf.Str(), sNewInf.Str())) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } else { - bInfRenamed = xbTrue; - } - } - #endif // XB_INF_SUPPORT - - // rname the table in the table list - xbTblList *tle = xbase->GetTblListEntry( this ); - if( tle ){ - // std::cout << "setting [" << GetFqFileName().Str() << "][" << sNewNameWoExt.Str() << "]\n"; - 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 ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - - // attempt to reverse things out if unsuccessful - if( bDbfRenamed ){ - #ifdef XB_MEMO_SUPPORT - if( bDbtRenamed ){ - xbRename( sNewDbt.Str(), sThisDbt.Str()); - } - #endif // XB_MEMO_SUPPORT - #ifdef XB_INF_SUPPORT - if( bInfRenamed ){ - xbRename( sNewInf.Str(), sNewInf.Str()); - } - #endif // XB_INF_SUPPORT - } - - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - LockTable( XB_UNLOCK ); - } - #endif - - } - return iRc; -} - - -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT -//! @brief Create memo block size. -/*! - This routine sets the memo file block size. This value is used when - the memo file is created so you if you want to change it, this must be - called before creating the table. - - DBF III Plus uses a block size of 512. - - \param ulBlockSize - Block size, must be evenly divisible by 512. - \returns XB_INVALID_BLOCK_SIZE<br>XB_NO_ERROR -*/ - -xbInt16 xbDbf3::SetCreateMemoBlockSize( xbUInt32 ulBlockSize ){ - - if( ulBlockSize != 512 ) - return XB_INVALID_BLOCK_SIZE; - else - ulCreateMemoBlockSize = 512; - - return XB_NO_ERROR; -} -#endif - -/************************************************************************/ -//! @brief Set version. -/*! - Sets the version to 3. The version info can be retrieved to determine - which class is being used for a given dbf instance. - \returns 3 -*/ - -xbInt16 xbDbf3::SetVersion() { - iFileVersion = 3; - return iFileVersion; -} - - -/************************************************************************/ -//! @brief Validate schema -/*! - This routine verifies the field types are valid for Dbase III Plus (tm). - - \param s Pointer to schema structure with field definitions. - - \returns Number of fields or XB_INVALID_FIELD_TYPE. -*/ - -xbInt16 xbDbf3::ValidateSchema( xbSchema * s ){ - -// This routine validates an input schema -// Negative return value is an error -// Positive return value is the number of fields -// On success, the class variable uiRecordLen will be updated with the record length of the combined total of the fields - - xbInt16 iFieldCnt = 0; - uiRecordLen = 0; - - /* count the number of fields and check paramaters */ - xbInt16 i = 0; - while( s[i].cType != 0 ){ - iFieldCnt++; - // Version 3 field types - if( s[i].cType != 'C' && - s[i].cType != 'N' && - s[i].cType != 'D' && - #ifdef XB_MEMO_SUPPORT - s[i].cType != 'M' && - #endif // XB_MEMO_SUPPORT - s[i].cType != 'L' ){ - return XB_INVALID_FIELD_TYPE; - } - - if(s[i].cType == 'D'){ - s[i].iFieldLen = 8; - s[i].iNoOfDecs = 0; - } - - else if(s[i].cType == 'C') - s[i].iNoOfDecs = 0; - - // check for numeric fields which are too long - else if( s[i].cType == 'N' && s[i].iFieldLen > 19 ){ - return XB_INVALID_FIELD_LEN; - } - // field len must be >= no of decimals - else if( s[i].cType == 'N' && s[i].iFieldLen < s[i].iNoOfDecs ){ - return XB_INVALID_FIELD_LEN; - } - - #ifdef XB_MEMO_SUPPORT - else if(s[i].cType == 'M'){ - s[i].iFieldLen = 10; - s[i].iNoOfDecs = 0; - } - #endif // XB_MEMO_SUPPORT - - uiRecordLen += s[i].iFieldLen; - i++; - } - return iFieldCnt; -} - -} /* namespace */ -#endif /* XB_DBF3_SUPPORT */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf4.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf4.cpp deleted file mode 100755 index a1f770e..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbdbf4.cpp +++ /dev/null @@ -1,885 +0,0 @@ -/* xbdbf4.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 - -*/ - -#include "xbase.h" - - -#ifdef XB_DBF4_SUPPORT - -namespace xb{ - - -/************************************************************************/ -//! @brief Constructor. -xbDbf4::xbDbf4(xbXBase * x) : xbDbf( x ) { - - iFileVersion = 4; - #ifdef XB_MEMO_SUPPORT - ulCreateMemoBlockSize = 1024; - #endif -}; - -/************************************************************************/ -//! @brief Destructor. -xbDbf4::~xbDbf4() {}; - -/************************************************************************/ -//! @brief Create Version 4 table. -/*! - This routine creates a Dbase IV (tm) DBF file. - - \param sTableName DBF table name. - \param sAlias Table alias - \param pSchema Pointer to schema structure with field definitions. - \param iOverlay xbTrue - Overlay.<br> xbFalse - Don't overlay. - \param iShareMode XB_SINGLE_USER<br>XB_MULTI_USER - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf4::CreateTable( const xbString &sTableName, const xbString &sAlias, xbSchema * pSchema, xbInt16 iOverlay, xbInt16 iShareMode ){ - - xbInt16 i, k, k2; - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - iDbfStatus = XB_CLOSED; - - xbString sNfn; - - try{ - sNfn = sTableName; - xbase->GetLogStatus(); - - rc = NameSuffixMissing( sNfn, 1 ); - if( rc > 0 ) - sNfn += ".DBF"; - - SetFileName( sNfn ); - this->sAlias = sAlias; - - /* check if the file already exists */ - if( FileExists( 0 )){ - if( !iOverlay ){ - iErrorStop = 100; - rc = XB_FILE_EXISTS; - throw rc; - } - - // remove other files if they exist - xbString sMname = sNfn; - xbUInt32 iMnameLen = sMname.Len(); - sMname.PutAt( iMnameLen-2, 'I' ); - sMname.PutAt( iMnameLen-1, 'N' ); - sMname.PutAt( iMnameLen, 'F' ); - xbFile fTemp( xbase ); - fTemp.SetFileName( sMname ); - if( fTemp.FileExists() ) - fTemp.xbRemove(); - - sMname.PutAt( iMnameLen-2, 'D' ); - sMname.PutAt( iMnameLen-1, 'B' ); - sMname.PutAt( iMnameLen, 'T' ); - fTemp.SetFileName( sMname ); - if( fTemp.FileExists() ) - fTemp.xbRemove(); - - sMname.PutAt( iMnameLen-2, 'M' ); - sMname.PutAt( iMnameLen-1, 'D' ); - sMname.PutAt( iMnameLen, 'X' ); - fTemp.SetFileName( sMname ); - if( fTemp.FileExists() ) - fTemp.xbRemove(); - } - - /* check if we already have a file with this alias */ - if(( rc = xbase->AddTblToTblList( this, GetFqFileName(), sAlias )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - - rc = ValidateSchema( pSchema ); - if( rc < 0 ){ - iErrorStop = 120; - throw rc; - } else - iNoOfFields = rc; - - #ifdef XB_MEMO_SUPPORT - // if we have memo fields - iMemoFieldCnt = 0; - i = 0; - while( pSchema[i].cType != 0){ - if( pSchema[i].cType == 'M' ) - iMemoFieldCnt++; /* number of memo fields in the incoming definition */ - i++; - } - - if( iMemoFieldCnt > 0 ){ - xbString sMfn = sNfn; /* memo file name, same as filename except ends with a "t", not an "f" */ - xbUInt32 ulMfnLen = sMfn.Len(); - sMfn.PutAt( ulMfnLen, 'T' ); - - // dont overlay the memo file if it exists, and Overlay switch is off - xbFile fTemp( xbase ); - fTemp.SetFileName( sMfn ); - if( fTemp.FileExists() && !iOverlay ){ - iErrorStop = 130; - rc = XB_FILE_EXISTS; - throw rc; - } - - Memo = new xbMemoDbt4( this, fTemp.GetFqFileName()); - - if(( rc = Memo->CreateMemoFile()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw rc; - } - } - #endif - - /* this is the dBase IV version of the class */ - cVersion = 0x03; // 0x03 for Dbase level 5 - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ){ -// cVersion = cVersion |= 0x88; // version IV memos, compiler complains about this - cVersion |= 0x88; // version IV memos - } - #endif - - if(( rc = xbFopen( "w+b", iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw rc; - } - uiRecordLen++; /* add one byte for 0x0D */ - - if(( RecBuf = (char *) malloc( uiRecordLen )) == NULL ){ - iErrorStop = 160; - throw rc; - } - - if(( RecBuf2 = (char *) malloc( uiRecordLen )) == NULL ){ - iErrorStop = 170; - rc = XB_NO_MEMORY; - throw rc; - } - - /* BlankRecord(); */ - memset( RecBuf, 0x20, uiRecordLen ); - memset( RecBuf2, 0x20, uiRecordLen ); - ulCurRec = 0L; - uiHeaderLen = 33 + iNoOfFields * 32; - xbDate d; - d.Sysdate(); - 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; - - /* write the header prolog */ - if(( rc = WriteHeader( 0, 0 )) != XB_NO_ERROR ){ - iErrorStop = 180; - rc = XB_WRITE_ERROR; - throw rc; - } - if((SchemaPtr=(xbSchemaRec *)malloc( (size_t) iNoOfFields * sizeof( xbSchemaRec ))) == NULL){ - iErrorStop = 190; - rc = XB_NO_MEMORY; - throw rc; - } - - /* write the field information into the header */ - for( i = 0, k = 1; i < iNoOfFields; i++ ){ - - memset( SchemaPtr[i].cFieldName, 0x00, 11 ); - for( int x = 0; x < 10 && pSchema[i].cFieldName[x]; x++ ) - SchemaPtr[i].cFieldName[x] = pSchema[i].cFieldName[x]; - - SchemaPtr[i].cType = pSchema[i].cType; - SchemaPtr[i].cFieldLen = (unsigned char) pSchema[i].iFieldLen; - SchemaPtr[i].cNoOfDecs = (unsigned char) pSchema[i].iNoOfDecs; - - if( SchemaPtr[i].cNoOfDecs > SchemaPtr[i].cFieldLen ){ - iErrorStop = 110; - rc = XB_WRITE_ERROR; - throw rc; - } - - k2 = k; - k += SchemaPtr[i].cFieldLen; - - if(( xbFwrite( &SchemaPtr[i].cFieldName, 1, 11 )) != XB_NO_ERROR ) { - iErrorStop = 200; - rc = XB_WRITE_ERROR; - throw rc; - } - - if(( xbFwrite( &SchemaPtr[i].cType, 1, 1 )) != XB_NO_ERROR ) { - iErrorStop = 210; - rc = XB_WRITE_ERROR; - throw rc; - } - - for( int j = 0; j < 4; j++ ) - xbFputc( 0x00 ); - - if(( xbFwrite( &SchemaPtr[i].cFieldLen, 1, 1 )) != XB_NO_ERROR ) { - iErrorStop = 220; - rc = XB_WRITE_ERROR; - throw rc; - } - - if(( xbFwrite( &SchemaPtr[i].cNoOfDecs, 1, 1 )) != XB_NO_ERROR ) { - iErrorStop = 230; - rc = XB_WRITE_ERROR; - throw rc; - } - - /* 14 bytes reserved */ - for( int j = 0; j < 14; j++ ) - xbFputc( 0x00 ); - - SchemaPtr[i].pAddress = RecBuf + k2; - SchemaPtr[i].pAddress2 = RecBuf2 + k2; - } - - /* write the header terminator */ - if(( xbFputc( XB_CHARHDR )) != XB_NO_ERROR ){ - iErrorStop = 240; - rc = XB_WRITE_ERROR; - throw rc; - } - } - catch( xbInt16 rc ) - { - xbString sMsg; - sMsg.Sprintf( "xbdbf4::CreateTable() Exception Caught Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - - sMsg.Sprintf( "Table Name = [%s]", GetFqFileName().Str()); - xbase->WriteLogMessage( sMsg ); - sMsg.Sprintf( "Alias Name = [%s]", sAlias.Str()); - xbase->WriteLogMessage( sMsg ); - - xbFclose(); - if( RecBuf ){ - free( RecBuf ); - RecBuf = NULL; - } - if( RecBuf2 ){ - free( RecBuf2 ); - RecBuf2 = NULL; - } - if( SchemaPtr ){ - free( SchemaPtr ); - SchemaPtr = NULL; - } - - InitVars(); - if( rc != XB_FILE_EXISTS ) - xbase->RemoveTblFromTblList( sAlias ); - } - - if( rc == XB_NO_ERROR ) - iDbfStatus = XB_OPEN; - - return rc; -} - -/************************************************************************/ -//! @brief Get version. -/*! - The version info can be retrieved to determine - which class is being used for a given dbf instance. - \returns 4 -*/ - -xbInt16 xbDbf4::GetVersion() const { - return 4; -} - -/************************************************************************/ -//! @brief Open dbf file/table. -/*! - \param sTableName DBF table name. - \param sAlias Table alias - \param iOpenMode XB_READ<br>XB_READ_WRITE - \param iShareMode XB_SINGLE_USER<br>XB_MULTI_USER - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbDbf4::Open( const xbString & sTableName, const xbString & sAlias, - xbInt16 iOpenMode, xbInt16 iShareMode ){ - xbInt16 i, j, iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char buf[33]; - char *p; - - #ifdef XB_MEMO_SUPPORT - iMemoFieldCnt = 0; - #endif - - try{ - /* verify the file is not already open */ - if( iDbfStatus != XB_CLOSED ){ - iErrorStop = 100; - iRc = XB_ALREADY_OPEN; - throw iRc; - } - /* copy the file name to the class variable */ - SetFileName( sTableName ); - this->sAlias = sAlias; - - if( !FileExists()){ - iErrorStop = 110; - iRc = XB_FILE_NOT_FOUND; - throw iRc; - } - - if(( iRc = xbase->AddTblToTblList( this, GetFqFileName(), sAlias )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - /* open the file */ - if(( iRc = xbFopen( iOpenMode, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - /* copy the header into memory */ - if(( iRc = ReadHeader( 1, 0 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - /* check the version */ - //if(( xFileVersion = DetermineXbaseTableVersion( cVersion )) != 4 ){ - if(( cVersion & 0x07 ) != 3 ){ - iErrorStop = 150; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - } - iFileVersion = 4; - - /* calculate the number of fields */ - if( cVersion == (char)0x30 ) { - iNoOfFields = ( uiHeaderLen - 296 ) / 32 ; - } else { - iNoOfFields = ( uiHeaderLen - 33 ) / 32; - } - - if(( RecBuf = (char *) malloc( uiRecordLen )) == NULL ){ - iErrorStop = 160; - iRc = XB_NO_MEMORY; - throw iRc; - } - - if(( RecBuf2 = (char *) malloc( uiRecordLen )) == NULL ) { - iErrorStop = 170; - iRc = XB_NO_MEMORY; - throw iRc; - } - - if((SchemaPtr=(xbSchemaRec *)malloc((size_t) iNoOfFields * sizeof( xbSchemaRec ))) == NULL){ - iErrorStop = 180; - iRc = XB_NO_MEMORY; - throw iRc; - } - - memset( SchemaPtr, 0x00, (size_t) iNoOfFields * (size_t) sizeof( xbSchemaRec )); - /* copy field info into memory */ - for( i = 0, j = 1; i < iNoOfFields; i++ ){ - xbFseek( ((xbInt64)i*32+32), SEEK_SET ); - xbFread( &buf, 1, 32 ); - p = buf; - for( int x = 0; x < 10 && buf[x]; x++ ){ - SchemaPtr[i].cFieldName[x] = buf[x]; - } - p = buf + 11; - SchemaPtr[i].cType = *p++; - SchemaPtr[i].pAddress = RecBuf + j; - SchemaPtr[i].pAddress2 = RecBuf2 + j; - SchemaPtr[i].cFieldLen = (unsigned char) *( p + 4 ); - SchemaPtr[i].cNoOfDecs = (unsigned char) *( p + 5 ); - SchemaPtr[i].cIxFlag = (unsigned char) *( p + 19 ); - j += SchemaPtr[i].cFieldLen; - #ifdef XB_MEMO_SUPPORT - if( (SchemaPtr[i].cType == 'M' || SchemaPtr[i].cType == 'B' || SchemaPtr[i].cType == 'O' )) - iMemoFieldCnt++; - #endif - } - ulCurRec = 0L; - iDbfStatus = XB_OPEN; - if(( iRc = BlankRecord()) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - - - #ifdef XB_MEMO_SUPPORT - if( iMemoFieldCnt > 0 ){ /* does this table have memo fields ? */ - - // build the file name - xbString sMfn = GetFqFileName(); /* memo file name, same as filename except ends with a "t", not an "f" */ - xbUInt32 ulMfnLen = sMfn.Len(); - if( sMfn[ulMfnLen] == 'F' ) - sMfn.PutAt( ulMfnLen, 'T' ); - else - sMfn.PutAt( ulMfnLen, 't' ); - xbFile fTemp( xbase ); - fTemp.SetFileName( sMfn ); - - Memo = new xbMemoDbt4( this, fTemp.GetFqFileName()); - - if(( iRc = Memo->OpenMemoFile()) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - } - #endif - - #ifdef XB_MDX_SUPPORT - -// printf( "cIndexFlag [%x]\n", cIndexFlag ); - - if( cIndexFlag ){ - // create the file name - xbString sIxFileName = GetFqFileName(); - sIxFileName.Trim(); - xbUInt32 lLen = sIxFileName.Len(); - sIxFileName.PutAt( lLen-2, 'M' ); - sIxFileName.PutAt( lLen-1, 'D' ); - sIxFileName.PutAt( lLen, 'X' ); - if(( iRc = OpenIndex( "MDX", sIxFileName )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - } - #endif - - } - catch ( xbInt16 iRc ) - { - xbString sMsg; - 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(); - if( RecBuf ){ - free( RecBuf ); - RecBuf = NULL; - } - if( RecBuf2 ){ - free( RecBuf2 ); - RecBuf2 = NULL; - } - if( SchemaPtr ){ - free( SchemaPtr ); - SchemaPtr = NULL; - } - InitVars(); - -#ifdef XB_MEMO_SUPPORT - if( Memo ){ - Memo->CloseMemoFile(); - delete Memo; - Memo = NULL; - } -#endif - } - - if( iRc == XB_NO_ERROR ) - iDbfStatus = XB_OPEN; - - return iRc; -} - -/************************************************************************/ -//! @brief Rename table. -/*! - This routine renames a table, associated memo, mdx and inf files - \param sNewName - New file name. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbDbf4::Rename( const xbString sNewName ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbString sNewDbf; - - #ifdef XB_MEMO_SUPPORT - xbString sNewDbt; - xbBool bDbtRenamed = xbFalse; - xbString sThisDbt; - #endif - - #ifdef XB_MDX_SUPPORT - xbString sNewMdx; - xbBool bMdxRenamed = xbFalse; - xbString sThisMdx; - #endif - - #ifdef XB_INF_SUPPORT - xbString sNewInf; - xbString sThisInf; - xbBool bInfRenamed = xbFalse; - #endif // XB_INF_SUPPORT - - xbBool bDbfRenamed = xbFalse; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif // XB_LOCKIN_SUPPORT - - - try{ - - xbString sDir; - xbString sFile; - xbString sExt; - xbString sNewNameWoExt; - sNewNameWoExt.Set( sNewName ); - if( sNewName.Pos( ".DBF" ) > 0 ) - sNewNameWoExt.Left( sNewName.Len() - 4 ); - -// std::cout << "NewName wo ext = [" << sNewNameWoExt.Str() << "]\n"; - - GetFileDirPart ( sDir ); - GetFileNamePart( sFile ); - GetFileExtPart ( sExt ); - - sNewDbf.Sprintf( "%s%s.DBF", sDir.Str(), sNewNameWoExt.Str()); - - #ifdef XB_MEMO_SUPPORT - sNewDbt.Sprintf( "%s%s.DBT", sDir.Str(), sNewNameWoExt.Str()); - if( FileExists( sNewDbt )) return XB_FILE_EXISTS; - sThisDbt.Sprintf( "%s%s.DBT", sDir.Str(), sFile.Str()); - #endif - - #ifdef XB_MDX_SUPPORT - sNewMdx.Sprintf( "%s%s.MDX", sDir.Str(), sNewNameWoExt.Str()); - if( FileExists( sNewMdx )) return XB_FILE_EXISTS; - sThisMdx.Sprintf( "%s%s.MDX", sDir.Str(), sFile.Str()); - #endif - - #ifdef XB_INF_SUPPORT - sNewInf.Sprintf( "%s%s.INF", sDir.Str(), sNewNameWoExt.Str()); - if( FileExists( sNewInf )) return XB_FILE_EXISTS; - sThisInf.Sprintf( "%s%s.INF", sDir.Str(), sFile.Str()); - #endif // XB_INF_SUPPORT - - -/* - std::cout << "xbDbf3::Rename dir = [" << sDir.Str() << "] file = [" << sFile.Str() << "] ext = [" << sExt.Str() << "]\n"; - std::cout << "xbDbf3::Rename new dbf = [" << sNewDbf.Str() << "]\n"; - std::cout << "xbDbf3::Rename new dbt = [" << sNewDbt.Str() << "]\n"; - std::cout << "xbDbf3::Rename new inf = [" << sNewInf.Str() << "]\n"; - std::cout << "xbDbf3::Rename new mdx = [" << sNewMdx.Str() << "]\n"; -*/ - - if( FileExists( sNewDbf )) return XB_FILE_EXISTS; - - #ifdef XB_LOCKING_SUPPORT - if( GetAutoLock() ){ - if(( iRc = LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - bLocked = xbTrue; - } - #endif - - xbInt16 iOpenMode = GetOpenMode(); - xbInt16 iShareMode = GetShareMode(); - xbBool bWasOpen = xbFalse; - if( FileIsOpen() ){ - bWasOpen = xbTrue; - if(( iRc = xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - - if(( iRc = xbRename( GetFqFileName().Str(), sNewDbf.Str())) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } else { - bDbfRenamed = xbTrue; - } - xbString sNameWext; - sNameWext.Sprintf( "%s.DBF", sNewNameWoExt.Str()); - SetFileName( sNameWext ); - - - if( bWasOpen ){ - if(( iRc = xbFopen( iOpenMode, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - - #ifdef XB_MEMO_SUPPORT - if( FileExists( sThisDbt )){ - if(( iRc = Memo->xbFseek( 8, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - sNewNameWoExt.PadRight( ' ', 8 ); - for( int i = 1; i < 9; i++ ) - Memo->xbFputc( sNewNameWoExt[i] ); - - if( bWasOpen ){ - if(( iRc = Memo->xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - - Memo->SetFileName( sNewDbt ); - if(( xbRename( sThisDbt.Str(), sNewDbt.Str())) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - - if( bWasOpen ){ - if(( iRc = Memo->xbFopen( iOpenMode, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - - bDbtRenamed = xbTrue; - } - #endif - - #ifdef XB_MDX_SUPPORT - if( FileExists( sThisMdx )){ - xbIxMdx *ixMdx; - xbString s; - xbBool bMdxFound = xbFalse; - xbIxList *ixList = GetIxList(); - while( ixList && !bMdxFound ){ - s = ixList->sFmt->Str(); - if( s == "MDX" ){ - ixMdx = (xbIxMdx *) ixList->ix; - bMdxFound = xbTrue; - } - } - - if( bMdxFound ){ - if(( iRc = ixMdx->xbFseek( 4, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - - sNewNameWoExt.PadRight( ' ', 8 ); - for( int i = 1; i < 9; i++ ) - ixMdx->xbFputc( sNewNameWoExt[i] ); - - if( bWasOpen ){ - if(( iRc = ixMdx->xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - } - - ixMdx->SetFileName( sNewMdx ); - if(( xbRename( sThisMdx.Str(), sNewMdx.Str())) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - - if( bWasOpen ){ - if(( iRc = ixMdx->xbFopen( iOpenMode, iShareMode )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - } - bMdxRenamed = xbTrue; - } - } - #endif // XB_MDX_SUPPORT - - #ifdef XB_INF_SUPPORT - if( FileExists( sThisInf )){ - if(( xbRename( sThisInf.Str(), sNewInf.Str())) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } else { - bInfRenamed = xbTrue; - } - } - #endif // XB_INF_SUPPORT - - // rename the table in the table list - xbTblList *tle = xbase->GetTblListEntry( this ); - if( tle ){ - tle->psFqTblName->Set( GetFqFileName().Str()); - tle->psTblAlias->Set( sNewNameWoExt.Str()); - } - - - } - catch ( xbInt16 iRc ) - { - xbString sMsg; - sMsg.Sprintf( "xbdbf4::Rename() Exception Caught Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - - // attempt to reverse things out if unsuccessful - if( bDbfRenamed ){ - - #ifdef XB_MEMO_SUPPORT - if( bDbtRenamed ){ - xbRename( sNewDbt.Str(), sThisDbt.Str()); - } - #endif - - #ifdef XB_MDX_SUPPORT - if( bMdxRenamed ){ - xbRename( sNewMdx.Str(), sThisMdx.Str()); - } - #endif - - #ifdef XB_INF_SUPPORT - if( bInfRenamed ){ - xbRename( sNewInf.Str(), sNewInf.Str()); - } - #endif // XB_INF_SUPPORT - } - - #ifdef XB_LOCKING_SUPPORT - if( GetAutoLock() ){ - iRc = LockTable( XB_UNLOCK ); - } - #endif - - } - - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - LockTable( XB_UNLOCK ); - } - #endif - - return iRc; -} - -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT - -//! @brief Create memo block size. -/*! - This routine sets the memo file block size. This value is used when - the memo file is created so you if you want to change it, this must be - called before creating the table. - - The default size for version 4 is 1024. - - \param ulBlockSize - Block size, must be evenly divisible by 512. - \returns XB_INVALID_BLOCK_SIZE<br>XB_NO_ERROR -*/ - -xbInt16 xbDbf4::SetCreateMemoBlockSize( xbUInt32 ulBlockSize ){ - - if( ulBlockSize % 512 ) - return XB_INVALID_BLOCK_SIZE; - else - ulCreateMemoBlockSize = ulBlockSize; - - return XB_NO_ERROR; -} -#endif // XB_MEMO_SUPPORT -/************************************************************************/ -//! @brief Set version. -/*! - Sets the version to 4. The version info can be retrieved to determine - which class is being used for a given dbf instance. - \returns 4 -*/ -xbInt16 xbDbf4::SetVersion() { - iFileVersion = 4; - return iFileVersion; -} -/************************************************************************/ -//! @brief Validate schema -/*! - This routine verifies the field types are valid for Dbase IV (tm). - - \param s Pointer to schema structure with field definitions. - - \returns Number of fields or XB_INVALID_FIELD_TYPE. -*/ - - -xbInt16 xbDbf4::ValidateSchema( xbSchema * s ){ - - xbInt16 iFieldCnt = 0; - uiRecordLen = 0; - - // Count the number of fields and check paramaters - xbInt16 i = 0; - while( s[i].cType != 0 ){ - iFieldCnt++; - // Version IV field types - if( s[i].cType != 'C' && - s[i].cType != 'N' && - s[i].cType != 'F' && - s[i].cType != 'D' && - #ifdef XB_MEMO_SUPPORT - s[i].cType != 'M' && - #endif /* XB_MEMO_SUPPORT */ - s[i].cType != 'L' ){ - return XB_INVALID_FIELD_TYPE; - } - - if(s[i].cType == 'D'){ - s[i].iFieldLen = 8; - s[i].iNoOfDecs = 0; - } - - else if(s[i].cType == 'C') - s[i].iNoOfDecs = 0; - - // check for numeric fields which are too long - else if((s[i].cType == 'N' || s[i].cType == 'F') && s[i].iFieldLen > 19 ){ - return XB_INVALID_FIELD_LEN; - } - - // field len must be greater then number of decimals - else if((s[i].cType == 'N' || s[i].cType == 'F') && s[i].iFieldLen < s[i].iNoOfDecs ){ - return XB_INVALID_FIELD_LEN; - } - - #ifdef XB_MEMO_SUPPORT - else if(s[i].cType == 'M'){ - s[i].iFieldLen = 10; - s[i].iNoOfDecs = 0; - } - #endif // XB_MEMO_SUPPORT - - uiRecordLen += s[i].iFieldLen; - i++; - } - return iFieldCnt; -} - -} /* namespace */ -#endif /* XB_DBF4_SUPPORT */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbexp.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbexp.cpp deleted file mode 100755 index b2d4db9..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbexp.cpp +++ /dev/null @@ -1,2721 +0,0 @@ -/* xbexp.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014,2017,2021,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 is part of the expression logic and has the code -for parsing various tokens out of an expression - -*/ - -#include "xbase.h" - -#ifdef XB_EXPRESSION_SUPPORT - -namespace xb{ - -/*************************************************************************/ -//! Constructor -/*! - \param x Pointer to xbXBase instance. -*/ - -xbExp::xbExp( xbXBase *x ){ - xbase = x; - dbf = NULL; - nTree = NULL; -} - -/*************************************************************************/ -//! Constructor -/*! - \param x Pointer to xbXBase instance. - \param d Pointer to xbDbf instance. -*/ -xbExp::xbExp( xbXBase *x, xbDbf *d ){ - xbase = x; - dbf = d; - nTree = NULL; -} - -/*************************************************************************/ -//! Deconstrucor. - -xbExp::~xbExp() { - - if( nTree ) - delete nTree; -} - -/*************************************************************************/ -//! Calulate expression return length -/*! - - This function returns the maximum possible length of an expression - The create index functions use this for determining the fixed length keys - It sets the return length field in the node. - - \param n Start node - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::CalcFunctionResultLen( xbExpNode * n ) const{ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 iReturnLenCalc = 0;; - xbInt32 lReturnLenVal = 0; - xbString sNodeText; - - - try{ - - n->GetNodeText( sNodeText ); - char cReturnType = 0; - if(( iRc = xbase->GetFunctionInfo( sNodeText, cReturnType, iReturnLenCalc, lReturnLenVal )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - if( iReturnLenCalc == 1 ){ - // use the value from iReturnLenVal - n->SetResultLen( (xbUInt32) lReturnLenVal ); - } - else if( iReturnLenCalc == 2 ){ - // use the length from the child node identified in lReturnLenVal - xbExpNode *nChild = n->GetChild( (xbUInt32) lReturnLenVal - 1 ); - if( !nChild ){ - iErrorStop = 110; - iRc = XB_PARSE_ERROR; - throw iRc; - } - n->SetResultLen( nChild->GetResultLen()); - } - - else if( iReturnLenCalc == 3 ){ - // use the length from the child node identified in lReturnLenVal - xbExpNode *nChild = n->GetChild( (xbUInt32) lReturnLenVal - 1 ); - if( !nChild ){ - iErrorStop = 120; - iRc = XB_PARSE_ERROR; - throw iRc; - } - n->SetResultLen( (xbUInt32) nChild->GetNumericResult()); - } - else if( iReturnLenCalc == 4 ){ - // use the value from the length in parm 1 multiplied by the value in parm 2 (REPLICATE) - xbExpNode *nChild1 = n->GetChild( 0 ); - xbExpNode *nChild2 = n->GetChild( 1 ); - if( !nChild1 || !nChild2 ){ - iErrorStop = 130; - iRc = XB_PARSE_ERROR; - throw iRc; - } - n->SetResultLen( nChild1->GetResultLen() * (xbUInt32) nChild2->GetNumericResult()); - } - else if( iReturnLenCalc == 5 ){ - // use the larger of the length of the value in parm2 or parm 3 (IIF statement) - xbExpNode *nChild2 = n->GetChild( 1 ); - xbExpNode *nChild3 = n->GetChild( 2 ); - if( !nChild2 || !nChild3 ){ - iErrorStop = 140; - iRc = XB_PARSE_ERROR; - throw iRc; - } - if( nChild2->GetResultLen() >= nChild3->GetResultLen()) - n->SetResultLen( nChild2->GetResultLen()); - else - n->SetResultLen( nChild3->GetResultLen()); - } - - else if( iReturnLenCalc == 6 ){ - - if( n->GetChildCnt() >= 2 ){ - xbExpNode *nChild2 = n->GetChild( 1 ); - n->SetResultLen( (xbUInt32) nChild2->GetNumericResult()); - } else { - n->SetResultLen( (xbUInt32) lReturnLenVal ); - } - - } else { - iErrorStop = 150; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::GetFunctionResultLen() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} - -/*************************************************************************/ -//! Check parens and quotes -/*! - This routine looks for unbalanced parens and quotes - - \param sExpression Expression to examine. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbExp::CheckParensAndQuotes( const xbString &sExpression ){ - - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbBool bInQuotes = xbFalse; - xbInt16 iLparenCtr = 0; - xbInt16 iRparenCtr = 0; - xbInt16 iQuoteType = 0; - const char *s = sExpression; - - try{ - - while( *s ){ - if( !bInQuotes ){ - if( *s == '(' ){ - iLparenCtr++; - } else if( *s == ')' ){ - iRparenCtr++; - } else if( *s == '\'' ){ - bInQuotes++; - iQuoteType = 0; - } else if( *s == '"' ){ - bInQuotes++; - iQuoteType = 1; - } - } else { - if(( *s == '\'' && iQuoteType == 0 ) || (*s == '"' && iQuoteType == 1 )) - bInQuotes--; - } - s++; - } - if( iLparenCtr != iRparenCtr ){ - iErrorStop = 100; - iRc = XB_UNBALANCED_PARENS; - throw iRc; - } - if( bInQuotes ){ - iErrorStop = 110; - iRc = XB_UNBALANCED_QUOTES; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::CheckParensAndQuots() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( sExpression ); - } - return iRc; -} -/*************************************************************************/ -//! Clear tree handle. -/*! - This routine clears the expression tree and frees any associated memory. - \returns void. -*/ - -void xbExp::ClearTreeHandle(){ - if( nTree ){ - nTree = NULL; - } -} - -/*************************************************************************/ -#ifdef XB_DEBUG_SUPPORT -//! Dump the tree. -/*! - \param iOption - Output opton. - \returns void. -*/ - -void xbExp::DumpTree( xbInt16 iOption ){ - nTree->DumpNode( iOption ); -} - -//! Dump token -/*! - \param iOption - Output opton. - \returns void. -*/ - - -void xbExp::DumpToken( xbExpToken &t, xbInt16 iOption ){ - - xbString sMsg; - sMsg = "Processing Token"; - xbase->WriteLogMessage( sMsg.Str(), iOption ); - - sMsg.Sprintf( "Expression = [%s]", t.sExpression.Str()); - xbase->WriteLogMessage( sMsg.Str(), iOption ); - - sMsg.Sprintf( "Token = [%s]", t.sToken.Str()); - xbase->WriteLogMessage( sMsg.Str(), iOption ); - - sMsg.Sprintf( "NodeType = [%c]", t.cNodeType ); - xbase->WriteLogMessage( sMsg.Str(), iOption ); - - sMsg.Sprintf( "ReturnType = [%c]", t.cReturnType ); - xbase->WriteLogMessage( sMsg.Str(), iOption ); - - sMsg.Sprintf( "Sts = [%d]", t.iSts ); - xbase->WriteLogMessage( sMsg.Str(), iOption ); - - sMsg.Sprintf( "PrevNodeType = [%c]", t.cPrevNodeType ); - xbase->WriteLogMessage( sMsg.Str(), iOption ); - - sMsg.Sprintf( "PrevReturnType = [%c]", t.cPrevReturnType ); - xbase->WriteLogMessage( sMsg.Str(), iOption ); -} - -#endif - -/*************************************************************************/ -//! Get date result. -/*! - If the expression generates a date return type, this method retrieves the date value. - \param dtResult - Output date value. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetDateResult( xbDate &dtResult ){ - if( nTree ){ - dtResult.JulToDate8( (xbInt32) nTree->GetNumericResult() ); - return XB_NO_ERROR; - } - else{ - //dtResult = ?; - return XB_PARSE_ERROR; - } -} -/*************************************************************************/ -//! Get bool result. -/*! - If the expression generates a boolean return type, this method retrieves the boolean value. - \param bResult - Output boolean value. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbExp::GetBoolResult( xbBool &bResult){ - if( nTree ){ - bResult = nTree->GetBoolResult(); - return XB_NO_ERROR; - } - else{ - return XB_PARSE_ERROR; - } -} - -/*************************************************************************/ -//! Get the next node in the tree. -/*! - \param n Node to starting point. To get the first node of the entire tree, set n = NULL - \returns Pointer to next node. -*/ - -xbExpNode *xbExp::GetNextNode( xbExpNode * n ) const { - - // to get the first node of the entire tree, set n = NULL - // std::cout << "In GetNextNode\n"; - - if( n == nTree ) - return NULL; - - else if( !n ){ - if( !nTree ) - return NULL; - else - return nTree->GetFirstNode(); - } - return n->GetNextNode(); -} - -/*************************************************************************/ -//! GetNextToken -/*! This method returns the next token in an expression of one or more tokens - \param t Token - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetNextToken( xbExpToken &t ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - t.iSts = XB_NO_ERROR; - t.sExpression.Ltrim(); - - if( t.sExpression.Len() == 0 ){ - t.iSts = XB_END_OF_EXPRESSION; - return XB_NO_ERROR; - } - - // Check for date constant - if((t.sExpression.Len() >= 10 && t.sExpression[1] == '{' && t.sExpression[4] == '/' && t.sExpression[7] == '/') && - (t.sExpression[10] == '}' || (t.sExpression.Len() >= 12 && t.sExpression[12] == '}'))){ - if(( iRc = GetTokenDateConstant( t )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - // Check for parens - else if( t.sExpression[1] == '(' || t.sExpression[1] == '{' ){ - if(( iRc = GetTokenParen( t )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - // Check for a char constant - else if( t.sExpression[1] == '"' || t.sExpression[1] == '\'' ){ - if(( iRc = GetTokenCharConstant( t )) != XB_NO_ERROR ){ - iErrorStop = 120; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - // Check for logical constant - else if( IsLogicalConstant( t.sExpression )){ - if(( iRc = GetTokenLogicalConstant( t )) != XB_NO_ERROR ){ - iErrorStop = 130; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - // check for numeric constant - else if( IsNumericConstant( t.sExpression, t.cPrevNodeType )){ - if(( iRc = GetTokenNumericConstant( t )) != XB_NO_ERROR ){ - iErrorStop = 140; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - // check for operator - else if( IsOperator( t.sExpression )){ - if(( iRc = GetTokenOperator( t )) != XB_NO_ERROR ){ - iErrorStop = 150; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - // check for function - else if( IsFunction( t.sExpression, t.cReturnType )){ - if(( iRc = GetTokenFunction( t )) != XB_NO_ERROR ){ - iErrorStop = 160; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - else if(( iRc = GetTokenDatabaseField( t )) != XB_NO_ERROR ){ - iErrorStop = 170; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() );sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() );sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() );sMsg.Sprintf( "xbexp::GetNextToken() Exception Caught. Error Stop = [%d] iRc = [%d] Expression = [%s]", iErrorStop, iRc, t.sExpression.Str() ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} - -/*************************************************************************/ -//! Get numeric result. -/*! - If the expression generates a numeric return type, this method retrieves the numeric value. - \param dResult - Output numeric value. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetNumericResult( xbDouble &dResult){ - if( nTree ){ - dResult = nTree->GetNumericResult(); - return XB_NO_ERROR; - } - else{ - dResult = 0; - return XB_PARSE_ERROR; - } -} -/*************************************************************************/ -//! Get result length. -/*! - This routine returns the result length. - \returns Result length. -*/ - -xbInt16 xbExp::GetResultLen() const{ - if( nTree ) - return nTree->GetResultLen(); - else - return 0; -} - -/*************************************************************************/ -//! Get return type. -/*! - \returns Expression return type. -*/ - -char xbExp::GetReturnType() const{ - if( nTree ) - return nTree->GetReturnType(); - else - return ' '; -} - -/*************************************************************************/ -//! Get string result. -/*! - If the expression generates a string return type, this method retrieves the string value. - \param sResult - Output string value. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetStringResult( xbString &sResult){ - if( nTree ){ - sResult = nTree->GetStringResult(); - return XB_NO_ERROR; - } - else{ - sResult = ""; - return XB_PARSE_ERROR; - } -} - -/*************************************************************************/ -//! Get string result. -/*! - If the expression generates a string return type, this method retrieves the string value. - \param vpResult - Pointer to user supplied buffer for result. - \param ulLen - Max size of buffer. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbExp::GetStringResult( char * vpResult, xbUInt32 ulLen ){ - if( nTree ){ - nTree->GetStringResult().strncpy((char *) vpResult, ulLen ); - return XB_NO_ERROR; - } - else{ - return XB_PARSE_ERROR; - } -} - - - -/*************************************************************************/ -//! GetTokenCharConstant -/*! This method returns the character constant in a pair of quotes - - This routine returns the tokens inside a set of matching quotes in sOutToken - If there is nothing between the quotes then sOutToken is returned empty - sOutRemainder contains whatever remains to the right of the right quote - - \param t Token - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbExp::GetTokenCharConstant( xbExpToken &t ){ - - const char *s = t.sExpression; - const char *sToken; // pointer to beginning of token - xbInt16 iQuoteType; - xbUInt32 ulTokenLen = 0; - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbBool bDone = xbFalse; - - try{ - if( *s == '"' ) - iQuoteType = 0; - else - iQuoteType = 1; - s++; - sToken = s; - while( *s && !bDone ){ - if(( *s == '"' && iQuoteType == 0 ) || (*s == '\'' && iQuoteType == 1 )) - bDone = xbTrue; - s++; - ulTokenLen++; - } - if( bDone ){ // found matching paren - t.cNodeType = XB_EXP_CONSTANT; - t.cReturnType = XB_EXP_CHAR; - t.sToken.Set( sToken, ulTokenLen - 1 ); - t.sExpression.Ltrunc( ulTokenLen + 1 ); - } else { - iRc = XB_PARSE_ERROR; - t.iSts = XB_UNBALANCED_QUOTES; - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::GetTokenCharConstant() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} - - -/*************************************************************************/ -//! GetTokenDateConstant -/*! This method returns the date constant in a pair of {} - - Date format is one of {mm/dd/yy} or {mm/dd/yyyy} - \param t Token. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetTokenDateConstant( xbExpToken &t ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char wBuf[13]; - xbDate dt; - - try{ - memset( wBuf, 0x00, 13 ); - t.cNodeType = XB_EXP_CONSTANT; - t.cReturnType = XB_EXP_DATE; - - if( t.sExpression[10] == '}' ){ - for( xbInt16 i = 0; i < 8; i++ ) - wBuf[i] = t.sExpression[i+2]; - - if(( iRc = dt.CTOD( wBuf )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - t.sToken.Set( dt.Str() ); - t.sExpression.Ltrunc( 10 ); - - } else if( t.sExpression[12] == '}' ){ - - wBuf[0] = t.sExpression[8]; - wBuf[1] = t.sExpression[9]; - wBuf[2] = t.sExpression[10]; - wBuf[3] = t.sExpression[11]; - wBuf[4] = t.sExpression[2]; - wBuf[5] = t.sExpression[3]; - wBuf[6] = t.sExpression[5]; - wBuf[7] = t.sExpression[6]; - - t.sToken.Set( wBuf ); - t.sExpression.Ltrunc( 12 ); - } else { - iRc = XB_PARSE_ERROR; - t.iSts = XB_INVALID_DATE; - iErrorStop = 110; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::GetTokenDateConstant() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} -/*************************************************************************/ -//! GetTokenField -/*! This method gets a database field token - - Looks for a xbase field in one of the following formats - - FIELDNAME - or - TABLENAME->FIELDNAME - - \param t Token. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetTokenDatabaseField( xbExpToken &t ){ - - const char *s = t.sExpression; - xbUInt32 ulTokenLen = 0; - xbUInt32 ulTokenLen2 = 0; - - while( *s && !IsTokenSeparator( *s ) && !IsWhiteSpace( *s )) { - ulTokenLen++; - s++; - } - - // go past any white space - while( *s && !IsTokenSeparator( *s ) && IsWhiteSpace( *s )) { - ulTokenLen2++; - s++; - } - - // look for -> - // 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++; - s++; - } - // go to the end - while( *s && !IsTokenSeparator( *s ) && !IsWhiteSpace( *s )) { - ulTokenLen2++; - s++; - } - ulTokenLen += ulTokenLen2; - } - t.cNodeType = XB_EXP_FIELD; - t.cReturnType = XB_EXP_UNKNOWN; - t.sToken.Set( t.sExpression, ulTokenLen ); - t.sExpression.Ltrunc( ulTokenLen ); - - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! GetTokenFunction -/*! - This method gets a function and everything between the following quotes - \param t Token - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbExp::GetTokenFunction( xbExpToken &t ){ - - xbUInt32 lPos = t.sExpression.Pos( '(' ); - if( lPos == 0 ) - return XB_PARSE_ERROR; - - xbBool bDone = xbFalse; - xbUInt32 lLen = t.sExpression.Len(); - xbInt16 iDepthCtr = 1; - - while( ++lPos <= lLen && !bDone ){ - if( t.sExpression[lPos] == ')' ){ - iDepthCtr--; - if( iDepthCtr == 0 ) - bDone = xbTrue; - } else if( t.sExpression[lPos] == '(' ){ - iDepthCtr++; - } - } - - t.cNodeType = XB_EXP_FUNCTION; - t.sToken.Set( t.sExpression, lPos-1 ); - t.sExpression.Ltrunc( lPos-1 ); - -// std::cout << "lPos = [" << lPos << "] done= [" << bDone << "][" << t.sExpression << "] len=[" << lLen << "] return type = [" << t.cReturnType << "]\n"; - - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! GetTokenCharConstant -/*! This method returns the character constant in a pair of quotes - - This routine returns the tokens inside a set of matching quotes in sOutToken - If there is nothing between the quotes then sOutToken is returned empty - sOutRemainder contains whatever remains to the right of the right quote - - \param t Token - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetTokenLogicalConstant( xbExpToken &t ){ - - t.cNodeType = XB_EXP_CONSTANT; - t.cReturnType = XB_EXP_LOGICAL; - t.sToken = t.sExpression[2]; - - if( t.sExpression[3] == '.' ) - t.sExpression.Ltrunc( 3 ); - else if( t.sExpression[6] == '.' ) - t.sExpression.Ltrunc( 6 ); - else if( t.sExpression[7] == '.' ) - t.sExpression.Ltrunc( 7 ); - - return XB_NO_ERROR; -} - - -/*************************************************************************/ -//! GetTokenNumericConstant -/*! This method returns a numeric constant in - - This routine returns a numeric constant token - sOutRemainder contains whatever remains to the right of the right quote - - \param t Token - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::GetTokenNumericConstant( xbExpToken &t ){ - - const char * s = t.sExpression; - xbUInt32 ulTokenLen = 0; - t.sToken = ""; - - t.cNodeType = XB_EXP_CONSTANT; - t.cReturnType = XB_EXP_NUMERIC; - - // capture the leading sign - if( *s == '-' || *s == '+' || *s == '.' ){ - t.sToken = *s; - ulTokenLen++; - s++; - - // go past any white space between sign and number - while( *s && IsWhiteSpace( *s )){ - s++; - ulTokenLen++; - } - } - - // add the number to the token - while( *s && (isdigit( *s ) || *s == '.' )){ - t.sToken += *s; - s++; - ulTokenLen++; - } - t.sExpression.Ltrunc( ulTokenLen ); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! GetTokenOperator -/*! This method returns the operator - - \param t Token - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbExp::GetTokenOperator( xbExpToken &t ){ - - const char *s = t.sExpression; - - // Logical operators - if((strncmp( s, "<>", 2 ) == 0 ) || (strncmp( s, "!=", 2 ) == 0 ) || - (strncmp( s, "<=", 2 ) == 0 ) || (strncmp( s, ">=", 2 ) == 0 )){ - t.cReturnType = XB_EXP_LOGICAL; - t.sToken.Assign( s, 1, 2 ); - t.sExpression.Ltrunc( 2 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - if( *s == '=' || *s == '<' || *s == '>' || *s == '$' || *s == '#' ){ - t.cReturnType = XB_EXP_LOGICAL; - t.sToken.Assign( s, 1, 1 ); - t.sExpression.Ltrunc( 1 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - if( (strncmp( s, ".NOT.", 5 ) == 0 ) || (strncmp( s, ".AND.", 5 ) == 0 )){ - t.cReturnType = XB_EXP_LOGICAL; - t.sToken.Assign( s, 1, 5 ); - t.sExpression.Ltrunc( 5 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - if( (strncmp( s, "NOT ", 4 ) == 0 ) || (strncmp( s, "AND ", 4 ) == 0 )){ - t.cReturnType = XB_EXP_LOGICAL; - t.sToken.Assign( s, 1, 3 ); - t.sExpression.Ltrunc( 3 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - if( strncmp( s, ".OR.", 4 ) == 0 ) { - t.cReturnType = XB_EXP_LOGICAL; - t.sToken.Assign( s, 1, 4 ); - t.sExpression.Ltrunc( 4 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - if( strncmp( s, "OR ", 3 ) == 0 ) { - t.cReturnType = XB_EXP_LOGICAL; - t.sToken.Assign( s, 1, 2 ); - t.sExpression.Ltrunc( 2 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - // Numeric operators - if(( strncmp( s, "**", 2 ) == 0 ) || ( strncmp( s, "+=", 2 ) == 0 ) || - ( strncmp( s, "-=", 2 ) == 0 ) || ( strncmp( s, "*=", 2 ) == 0 ) || ( strncmp( s, "/=", 2 ) == 0 )){ - t.cReturnType = XB_EXP_NUMERIC; - t.sToken.Assign( s, 1, 2 ); - t.sExpression.Ltrunc( 2 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - // Pre/post increment/decrement operators ++ or -- - if(( strncmp( s, "--", 2 ) == 0 ) || ( strncmp( s, "++", 2 ) == 0 )){ - t.cReturnType = XB_EXP_NUMERIC; - t.sToken.Assign( s, 1, 2 ); - t.sExpression.Ltrunc( 2 ); - if( t.sExpression.Len() > 0 && (isdigit( t.sExpression[1] ) || isalpha( t.sExpression[1] ))) - t.cNodeType = XB_EXP_PRE_OPERATOR; - else - t.cNodeType = XB_EXP_POST_OPERATOR; - - return XB_NO_ERROR; - } - - if( *s == '*' || *s == '/' || *s == '%' || *s == '^' ){ - t.cReturnType = XB_EXP_NUMERIC; - t.sToken.Assign( s, 1, 1 ); - t.sExpression.Ltrunc( 1 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - - // multi return type operators - t.cReturnType = XB_EXP_UNKNOWN; - if( *s == '+' || *s == '-' ){ - t.sToken.Assign( s, 1, 1 ); - t.sExpression.Ltrunc( 1 ); - t.cNodeType = XB_EXP_OPERATOR; - return XB_NO_ERROR; - } - return XB_PARSE_ERROR; -} - -/*************************************************************************/ -//! GetTokenParen -/*! This method returns the tokens in a pair of enclosed parens - - This routine returns the tokens inside a set of matching parens in sOutToken - If there is nothing between the parens then sOutToken is returned empty - sOutRemainder contains whatever remains to the right of the right paren - - \param t Token - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbExp::GetTokenParen( xbExpToken &t ){ - - const char * s = t.sExpression; - const char * sToken; // pointer to beginning of token - xbInt16 iParenType = 0; - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 iDepthCtr = 0; // depth inside of nested parens - xbUInt32 ulTokenLen = 0; - xbBool bDone = xbFalse; - - try{ - if( *s == '{' ) - iParenType = 0; - else - iParenType = 1; - iDepthCtr = 1; - s++; - sToken = s; - - while( *s && !bDone ){ - if(( *s == ')' && iParenType == 1 ) || (*s == '}' && iParenType == 0 )){ - iDepthCtr--; - if( iDepthCtr == 0 ) - bDone = xbTrue; - } else if(( *s == '(' && iParenType == 1 ) || (*s == '{' && iParenType == 0 )){ - iDepthCtr++; - } - s++; - ulTokenLen++; - } - - if( bDone ){ // found matching paren - t.cNodeType = XB_EXP_NOTROOT; - t.cReturnType = XB_EXP_UNKNOWN; - t.sToken.Set( sToken, ulTokenLen - 1 ); - t.sExpression.Ltrunc( ulTokenLen + 1 ); - } else { - t.sToken = ""; - t.cNodeType = XB_EXP_NOTROOT; - t.cReturnType = XB_EXP_UNKNOWN; - t.iSts = XB_UNBALANCED_PARENS; - iRc = XB_PARSE_ERROR; - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::GetTokenParen() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - } - return iRc; -} - -/*************************************************************************/ -//! Get the expression tree handle. -/*! - \returns Pointer to the top most node in the expression tree. -*/ -xbExpNode *xbExp::GetTreeHandle(){ - return nTree; -} - -/*************************************************************************/ -//! Is Function -/*! This method determines if the next token is a function. - - \param sExpression - String expression to be evaluated. - \param cReturnType Output - Return type. - \returns xbTrue - Is a function.<br> - xbFalse - Is not a function. -*/ - -xbBool xbExp::IsFunction( const xbString & sExpression, char &cReturnType ){ - - xbInt16 i = 0; - xbInt32 l = 0; - if( sExpression.Pos( '(' ) > 0 ){ - if( xbase->GetFunctionInfo( sExpression, cReturnType, i, l ) == XB_NO_ERROR ) - return xbTrue; - } - return xbFalse; -} - -/*************************************************************************/ -//! Is Logical constant -/*! This method determines if the next token is a logical constant (T/F, etc). - - \param sExpression - String expression to be evaluated. - \returns xbTrue - Is a logical constant.<br> - xbFalse - Is not a logical constant. -*/ - -xbBool xbExp::IsLogicalConstant( const xbString & sExpression ){ - - const char *s = sExpression; - if(( strncmp( s, ".T.", 3 ) == 0 ) || ( strncmp( s, ".F.", 3 ) == 0 )) - return xbTrue; - else if( strncmp( s, ".TRUE.", 6 ) == 0 ) - return xbTrue; - else if( strncmp( s, ".FALSE.", 7 ) == 0 ) - return xbTrue; - - return xbFalse; -} - -/*************************************************************************/ -//! Is Numeric constant -/*! This method determines if the next token is a numeric constant. - - \param sExpression - String expression to be evaluated. - \param cPrevNodeType - Type of previous node. - \returns xbTrue - Is a numeric constant.<br> - xbFalse - Is not a numeric constant. -*/ -xbBool xbExp::IsNumericConstant( const xbString & sExpression, char cPrevNodeType ){ - - // check for positive, negative or decimal number constants - - const char *s = sExpression; - if(( *s == '-' && ( cPrevNodeType == 'O' || cPrevNodeType == 0 )) || - ( *s == '+' && ( cPrevNodeType == 'O' || cPrevNodeType == 0 ))){ - s++; - while( *s && IsWhiteSpace( *s )) - s++; - } - if( *s == '.' ) - s++; - - if( isdigit( *s )) - return xbTrue; - else - return xbFalse; -} - -/*************************************************************************/ -//! Is Operator. -/*! This method determines if the next token is an operator. - - \param sExpression - String expression to be evaluated. - \returns xbTrue - Is an operator.<br> - xbFalse - Is not an operator. -*/ -xbBool xbExp::IsOperator( const xbString & sExpression ){ - - const char *s = sExpression; - if( *s == '+' || *s == '-' || *s == '/' || *s == '^' || *s == '=' || *s == '$' || - *s == '#' || *s == '*' || *s == '<' || *s == '>' || *s == '%' ) - return xbTrue; - - if( strncmp( s, "!=", 2 ) == 0 ) - return xbTrue; - - if((strncmp( s, ".NOT.", 5 ) == 0 ) || (strncmp( s, ".OR.", 4 ) == 0 ) || (strncmp( s, ".AND.", 5 ) == 0 )) - return xbTrue; - - if((strncmp( s, "NOT ", 4 ) == 0 ) || (strncmp( s, "OR ", 3 ) == 0 ) || (strncmp( s, "AND ", 4 ) == 0 )) - return xbTrue; - - return xbFalse; -} - -/*************************************************************************/ -//! Is Token separator -/*! This method determines if the next token is a separator. - - \param sExpression - String expression to be evaluated. - \returns xbTrue - Is a token separator.<br> - xbFalse - Is not a token separator. -*/ -char xbExp::IsTokenSeparator( char c ){ - if( c == '-' || c == '+' || c == '*' || c == '/' || c == '$' || c == '#' || - c == '<' || c == '>' || c == '^' || c == '=' || c == '.' || c == '!' ) - return c; - else - return 0; -} -/*************************************************************************/ -//! Is White space -/*! This method determines if a given character is white space. - - \param c - Character to be evaluated. - \returns xbTrue - Is white space.<br> - xbFalse - Is not white space. -*/ -xbBool xbExp::IsWhiteSpace( char c ){ - return(( c == 0x20 )? 1 : 0 ); -} - -/*************************************************************************/ -//! Get operator weight. -/*! - This method determines the priority of an operator - - Operator precendence - 10 .AND. .OR. .NOT. (not really an operator) - 9 > or < (includes <= or >=) - 6 unary plus or minus (+,-) -- not passed this routine - 5 prefix increment and/or decrement (++,--) - 4 exponentiation ** or ^ - 3 multiplication,division or modulus (*,/,%) - 2 Addition, subtraction (+,-) - 1 Postfix increment and/or decrement (++,--) - - \param sOper - Operator. - \returns Operator weight - -*/ - -xbInt16 xbExp::OperatorWeight( const xbString &sOper ){ - - if( sOper == "" || sOper.Len() > 5 ) - return 0; - - else if( sOper == "--0" || sOper == "++0" ) // 0 is prefix - return 9; - else if( sOper == "**" || sOper == "^" ) - return 8; - else if( sOper == "*" || sOper == "/" || sOper == "%" || sOper == "*=" || sOper == "/=" ) - return 7; - else if( sOper == "+" || sOper == "-" || sOper == "+=" || sOper == "-=" ) - return 6; - else if( sOper == "--1" || sOper == "++1" ) // 1 is post fix - return 5; - else if( sOper == ">" || sOper == ">=" || sOper == "<" || sOper == "<=" || - sOper == "<>" || sOper == "!=" || sOper == "#" || sOper == "$" || sOper == "=" ) - return 4; - else if( sOper == ".NOT." || sOper == "NOT" ) - return 3; - else if( sOper == ".AND." || sOper == "AND" ) - return 2; - else if( sOper == ".OR." || sOper == "OR" ) - return 1; - - return 0; -} - - -/*************************************************************************/ -//! Parse expression. -/*! - \param sExpression - Expression to parse. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::ParseExpression( const xbString &sExpression ){ - return ParseExpression( sExpression, (xbInt16) 0 ); -} - -/*************************************************************************/ -//! Parse expression. -/*! - \param dbf - Pointer to xbDbf instance. - \param sExpression - Expression to parse. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::ParseExpression( xbDbf *dbf, const xbString &sExpression ){ - this->dbf = dbf; - return ParseExpression( sExpression, (xbInt16) 0 ); -} - -/*************************************************************************/ -//! Parse expression. -/*! - \param sExpression - Expression to parse. - \param iWeight. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbExp::ParseExpression( const xbString &sExpression, xbInt16 iWeight ){ - - xbExpNode *n = NULL; - xbExpNode *nLastNode = NULL; // pointer to the last node processed - xbExpToken t; - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbString s; - xbBool bNewNode = xbFalse; - - try { - - if( nTree ) - delete nTree; - - if(( iRc = CheckParensAndQuotes( sExpression )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - t.sExpression = sExpression; - - xbString sOriginalExp; - while( t.iSts == XB_NO_ERROR && iRc == XB_NO_ERROR ){ - - sOriginalExp = t.sExpression; // test code - iRc = GetNextToken( t ); - if( !iRc && !t.iSts ){ - - // comment / uncomment debug / live - // DumpToken( t, 0 ); - - if( t.cNodeType == XB_EXP_NOTROOT ){ - xbExp enr( xbase, dbf ); - if(( iRc = enr.ParseExpression( t.sToken, iWeight + 10 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - n = enr.GetTreeHandle(); - enr.ClearTreeHandle(); - - } else { - - switch( t.cNodeType ) { - - case XB_EXP_CONSTANT: - n = new xbExpNode( t.sToken, t.cNodeType ); - bNewNode = xbTrue; - if(( iRc = ParseExpressionConstant( t, n )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - break; - - case XB_EXP_FUNCTION: - n = new xbExpNode( t.cNodeType ); - bNewNode = xbTrue; - if(( iRc = ParseExpressionFunction( t, n, iWeight )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - break; - - case XB_EXP_FIELD: - n = new xbExpNode( t.cNodeType ); - bNewNode = xbTrue; - if(( iRc = ParseExpressionField( t, n )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - break; - - case XB_EXP_OPERATOR: - case XB_EXP_PRE_OPERATOR: - case XB_EXP_POST_OPERATOR: - n = new xbExpNode( t.sToken, t.cNodeType ); - bNewNode = xbTrue; - if(( iRc = ParseExpressionOperator( t, n, iWeight )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - break; - - default: - iErrorStop = 160; - iRc = XB_PARSE_ERROR; - throw iRc; - // break; - } - } - t.cPrevNodeType = t.cNodeType; - t.cPrevReturnType = t.cReturnType; - - // determine where in the expression tree to insert the latest node "n" - // Is this the first node to be added to the tree? - if( !nTree ){ - nTree = n; - } - - // else if last node was XB_EXB_PRE_OPERATOR then append this as child to last node - else if( nLastNode && nLastNode->GetNodeType() == XB_EXP_PRE_OPERATOR ){ - n->SetParent( nLastNode ); - nLastNode->AddChild( n ); - } - - // else if last node was XB_EXB_POST_OPERATOR then append this as child to last node - else if( nLastNode && n->GetNodeType() == XB_EXP_POST_OPERATOR ){ - n->AddChild( nLastNode ); - nLastNode->SetParent( n ); - if( nLastNode == nTree ){ - nTree = n; - } else { - nLastNode->GetParent()->RemoveLastChild(); - nLastNode->GetParent()->AddChild( n ); - n->SetParent( nLastNode->GetParent() ); - } - } - - else if( n->GetNodeType() == XB_EXP_OPERATOR ){ - xbExpNode * nWorkNode = nLastNode; - while( nWorkNode && ( nWorkNode->GetNodeType() != XB_EXP_OPERATOR || n->GetWeight() <= nWorkNode->GetWeight())){ - nWorkNode = nWorkNode->GetParent(); - } - - if( !nWorkNode ){ // we are at the top - nTree->SetParent( n ); - n->AddChild( nTree ); - nTree = n; - - } else if( nWorkNode->GetChildCnt() == 1 ){ - nWorkNode->AddChild( n ); - n->SetParent( nWorkNode ); - - } else if( nWorkNode->GetChildCnt() == 2 ){ - xbExpNode * nChild2 = nWorkNode->GetChild(1); - n->AddChild( nChild2 ); - nWorkNode->RemoveLastChild(); - nWorkNode->AddChild( n ); - n->SetParent( nWorkNode ); - - } else{ - // should not be stopping on anything but an operator node with one or two children - iErrorStop = 170; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } else { - n->SetParent( nLastNode ); - nLastNode->AddChild( n ); - } - nLastNode = n; - n = NULL; - } - } - - // for each node in the tree, calculate the length if it's not already set - xbExpNode * nWork = GetNextNode( NULL ); - xbExpNode * nChild1; - xbExpNode * nChild2; - - while( nWork ){ - if( nWork->GetReturnType() == XB_EXP_UNKNOWN ){ - nWork->GetNodeText( s ); - - // std::cout << "XB_EXP_UNKNOWN logic [" << s << "][" << nWork->GetChildCnt() << "]\n"; - // if this is "-" and child 1 and child 2 are both dates, set this result type to numeric - if( s == "-" && nWork->GetChildCnt() == 2 && - nWork->GetChild(0)->GetReturnType() == XB_EXP_DATE && nWork->GetChild(1)->GetReturnType() == XB_EXP_DATE ) - nWork->SetReturnType( XB_EXP_NUMERIC ); - else if( nWork->GetChildCnt() > 0 ) - nWork->SetReturnType( nWork->GetChild(0)->GetReturnType()); - else{ - iErrorStop = 180; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - if( nWork->GetResultLen() == 0 ){ - - switch( nWork->GetReturnType() ){ - - case XB_EXP_NUMERIC: - nWork->SetResultLen( 4 ); - break; - - case XB_EXP_CHAR: - if( nWork->GetNodeType() != XB_EXP_OPERATOR ){ - iErrorStop = 190; - iRc = XB_PARSE_ERROR; - throw iRc; - } - if( nWork->GetChildCnt() < 2 ){ - iErrorStop = 200; - iRc = XB_PARSE_ERROR; - throw iRc; - } - nChild1 = nWork->GetChild( 0 ); - nChild2 = nWork->GetChild( 1 ); - nWork->SetResultLen( nChild1->GetResultLen() + nChild2->GetResultLen()); - break; - - case XB_EXP_DATE: - nWork->SetResultLen( 8 ); - break; - - case XB_EXP_LOGICAL: - nWork->SetResultLen( 1 ); - break; - - default: - iErrorStop = 210; - iRc = XB_PARSE_ERROR; - throw iRc; - // break; - } - } - if( nWork->IsUnaryOperator() ){ - if( nWork->GetChildCnt() != 1 ){ - iErrorStop = 220; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } else if( nWork->IsOperator() && nWork->GetChildCnt() != 2 ){ - iErrorStop = 230; - iRc = XB_PARSE_ERROR; - throw iRc; - } - nWork = GetNextNode( nWork ); - } - } - catch (xbInt16 iRc ){ - if( bNewNode && n ) - delete n; - xbString sMsg; - sMsg.Sprintf( "xbexp::ParseExpression() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} -/*************************************************************************/ -//! Parse expression constant. -/*! - \param t - Token. - \param n - Node. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbExp::ParseExpressionConstant( xbExpToken &t, xbExpNode *n ){ - - xbDate dtWork; - n->SetReturnType( t.cReturnType ); - - // std::cout << "parse expression constant[" << t.sToken << "]\n"; - - switch( t.cReturnType ){ - case XB_EXP_CHAR: - n->SetResultLen( t.sToken.Len() ); - n->SetResult( t.sToken ); - break; - - case XB_EXP_DATE: - n->SetResultLen( 8 ); - dtWork.Set( t.sToken ); - n->SetResult( dtWork ); - break; - - case XB_EXP_LOGICAL: - n->SetResultLen( 1 ); - if( strncmp( t.sToken, "T", 1 ) == 0 ) - n->SetResult( (xbBool) xbTrue ); - else - n->SetResult( (xbBool) xbFalse ); - break; - - case XB_EXP_NUMERIC: - n->SetResultLen( 4 ); - n->SetResult( strtod( t.sToken, 0 )); - n->SetResult( t.sToken ); - break; - - default: - return XB_PARSE_ERROR; - // break; - } - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! Parse expression field. -/*! - \param t - Token. - \param n - Node. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbExp::ParseExpressionField( xbExpToken &t, xbExpNode *n ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbDbf * pDbf; - xbString sFieldName; - - // do the db lookup and set the field number for the field - - try{ - - xbUInt32 lPos; - - if(( lPos = t.sToken.Pos( "->" )) > 0 ){ - // table name is part of the token - xbString sTableName = t.sToken; - sTableName.Left( lPos-1 ); - 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; - sFieldName = t.sToken; - } - if( !pDbf ){ - iErrorStop = 100; - iRc = XB_INVALID_FIELD; - throw iRc; - } - xbInt16 iFieldNo = 0; - - if(( iRc = pDbf->GetFieldNo( sFieldName, iFieldNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - char cFieldType; - if(( iRc = pDbf->GetFieldType( iFieldNo, cFieldType )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - n->SetDbfInfo( pDbf, iFieldNo ); - switch( cFieldType ){ - case XB_CHAR_FLD: - n->SetReturnType( XB_EXP_CHAR ); - break; - - case XB_LOGICAL_FLD: - n->SetReturnType( XB_EXP_LOGICAL ); - break; - - case XB_NUMERIC_FLD: - case XB_FLOAT_FLD: - n->SetReturnType( XB_EXP_NUMERIC ); - break; - - case XB_DATE_FLD: - n->SetReturnType( XB_EXP_DATE ); - break; - - case XB_MEMO_FLD: - default: - iErrorStop = 130; - iRc = XB_PARSE_ERROR; - throw iRc; - // break; - } - n->SetNodeText( sFieldName ); - xbInt16 iResultLen = 0; - if(( iRc = pDbf->GetFieldLen( iFieldNo, iResultLen )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - n->SetResultLen( (xbUInt32) iResultLen ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::ParseExpressionField() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} - -/*************************************************************************/ -//! Parse expression function. -/*! - \param t - Token. - \param n - Node. - \param iWeight - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbExp::ParseExpressionFunction( xbExpToken &t, xbExpNode *n, xbInt16 iWeight ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - // find the first "(" - xbUInt32 lPos = t.sToken.Pos( '(' ); - if( lPos == 0 ){ - iErrorStop = 100; - iRc = XB_INVALID_FUNCTION; - throw iRc; - } - // Get the function name and look it up in the table - - - xbString sFunc = t.sToken; - sFunc.Left( lPos - 1 ).Trim(); - char cReturnType; - xbInt16 i = 0; - xbInt32 l = 0; - if(( iRc = xbase->GetFunctionInfo( sFunc, cReturnType, i, l )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - n->SetNodeText( sFunc ); - - - // Get the function parms - xbString sParms = t.sToken; - sParms.Mid( lPos+1, t.sToken.Len() - lPos ); - lPos = sParms.GetLastPos( ')' ); - if( lPos == 0 ){ - iErrorStop = 120; - iRc = XB_INVALID_FUNCTION; - throw iRc; - } - - // remove the trailing ")" paren - sParms.Left( lPos - 1 ).Trim(); - - // if this function has parms, put them in the tree - if( sParms.Len() > 0 ){ - xbExp enr( xbase, dbf ); - - // create a linked list of parms - xbLinkList<xbString> llParms; - if(( iRc = ParseExpressionFunctionParms( sParms, llParms )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - // for each function parm, recursively process it - xbLinkListNode<xbString> * llN = llParms.GetHeadNode(); - xbString sParm; - while( llN ){ - sParm = llN->GetKey(); - if(( iRc = enr.ParseExpression( sParm, iWeight + 10 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - n->AddChild( enr.GetTreeHandle()); - enr.ClearTreeHandle(); - llN = llN->GetNextNode(); - } - llParms.Clear(); - } - - if( cReturnType == '1' ){ - if( n->GetChildCnt() > 0 ){ - xbExpNode *n1 = n->GetChild( 0 ); - n->SetReturnType( n1->GetReturnType()); - } - - } else { - n->SetReturnType( cReturnType ); - } - - if(( iRc = CalcFunctionResultLen( n )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::ParseExpressionFunction() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} - -/*************************************************************************/ -//! Parse expression function. -/*! - - Creates a linked list of function parms as xbStrings - This function pulls out the parms and addresses embedded parens and quotes within the parms - - \param sParms - \param lParms - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::ParseExpressionFunctionParms( const xbString &sParms, xbLinkList<xbString> & llParms ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 iParenCtr = 0; - xbInt16 iInQuotes = 0; - xbInt16 iDoubleQuotes = 0; - xbInt16 iSingleQuotes = 0; - xbInt32 lStartPos = 0; - xbInt32 lParmLen = 0; - - xbString sParm; - - try{ - const char *sp = sParms; - - while( *sp ){ - if( *sp == '(') - iParenCtr++; - else if( *sp == ')' ) - iParenCtr--; - else if( !iInQuotes && *sp == '"' ){ - iInQuotes++; - iDoubleQuotes++; - } else if( iInQuotes && *sp == '"' ){ - iInQuotes--; - iDoubleQuotes--; - } - else if( !iInQuotes && *sp == '\'' ){ - iInQuotes++; - iSingleQuotes++; - } else if( iInQuotes && *sp == '\'' ){ - iInQuotes--; - iSingleQuotes--; - - } else if( !iInQuotes && !iParenCtr && *sp == ',' ){ - // found a valid comma - at the end of a parm - // add it to the end of the linked list - sParm = sParms; - sParm.Mid( (xbUInt32) lStartPos + 1, (xbUInt32) lParmLen ).Trim(); // mid is one based - llParms.InsertAtEnd( sParm ); - - // set the start pos for the next one on the list - lStartPos += lParmLen + 1; - lParmLen = -1; - // lParmLen = 0; - } - lParmLen++; - sp++; - } - if( lParmLen > 0 ){ - // get the last parm, it didn't end with a comma - sParm = sParms; - sParm.Mid( (xbUInt32) lStartPos + 1, (xbUInt32) lParmLen ).Trim(); - llParms.InsertAtEnd( sParm ); - } - - } - // try / catch not used in this method, structure added for potential future use - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::ParseExpressionFunctionParms() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} -/*************************************************************************/ -//! Parse expression operator. -/*! - \param t - Token. - \param n - Node. - \param iWeight - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbExp::ParseExpressionOperator( xbExpToken &t, xbExpNode *n, xbInt16 iWeight ){ - - n->SetResult( t.sToken ); - n->SetWeight( iWeight + OperatorWeight( t.sToken) ); - -// std::cout << "ParseExpressionOperator [" << t.cPrevNodeType << "][" << t.sToken << "] Weight = [" << iWeight; -// std::cout << "] PrevReturnType [" << t.cPrevReturnType; -// std::cout << "] Operator weight [" << OperatorWeight( t.sToken ) << "] getweight [" << n->GetWeight() << "]\n"; - - if( t.sToken == "**" || t.sToken == "^" || - t.sToken == "*" || t.sToken == "/" || t.sToken == "%" || t.sToken == "*=" || t.sToken == "/=" ) - n->SetReturnType( XB_EXP_NUMERIC ); - - else if( t.sToken == "--" || t.sToken == "++" || t.sToken == "+=" || t.sToken == "-=" ) // could be date or numeric - n->SetReturnType( XB_EXP_UNKNOWN ); - - else if( t.cPrevReturnType == XB_EXP_CHAR && ( t.sToken == "+" || t.sToken == "-" )) - n->SetReturnType( XB_EXP_CHAR ); - - else if( t.sToken == ".AND." || t.sToken == ".OR." || t.sToken == ".NOT." || - t.sToken == "AND" || t.sToken == "OR" || t.sToken == "NOT" || - t.sToken == ">" || t.sToken == ">=" || t.sToken == "<" || - t.sToken == "<=" || t.sToken == "<>" || t.sToken == "!=" || - t.sToken == "$" || t.sToken == "#" || t.sToken == "=" ) - n->SetReturnType( XB_EXP_LOGICAL ); - - - else if( t.cPrevReturnType == XB_EXP_UNKNOWN ) - n->SetReturnType( XB_EXP_UNKNOWN ); - - // added for date constant logic 10/28/17 - else if(( t.sToken == "+" || t.sToken == "-" ) && t.cPrevReturnType == XB_EXP_DATE ) - n->SetReturnType( XB_EXP_DATE ); - - else if( t.sToken == "+" || t.sToken == "-" ) - n->SetReturnType( XB_EXP_NUMERIC ); - - return XB_NO_ERROR; -} - - -/************************************************************************/ -//! ProcessExpression -/*! This method processes an expression tree leaving the result in the - root node of the tree -*/ -xbInt16 xbExp::ProcessExpression(){ - return ProcessExpression( 0 ); -} -/************************************************************************/ -//! ProcessExpression -/*! This method processes a parsed expression tree leaving the result in the - root node of the tree - \param iRecBufSw Record buffer to use when evaluating expression.<br> - 0 - Current record buffer.<br> - 1 - Original record buffer. -*/ - -xbInt16 xbExp::ProcessExpression( xbInt16 iRecBufSw ){ - -// iRecBufSw 0 - Record Buffer -// 1 - Original Record Buffer - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - - xbExpNode * nWork = GetNextNode( NULL ); - xbExpNode * nChild1; - xbDbf * dbf; - xbString sWork1; - xbString sWork2; - xbString sOperator; - xbDate dtWork1; - - xbBool bWork; - xbDouble dWork; - - while( nWork ){ - switch( nWork->GetNodeType() ){ - - case XB_EXP_CONSTANT: - break; - - case XB_EXP_PRE_OPERATOR: // increment value before setting in head node - if( nWork->GetChildCnt() != 1 ){ - iErrorStop = 100; - iRc = XB_PARSE_ERROR; - throw iRc; - } - nChild1 = nWork->GetChild( 0 ); - //if( nChild1->GetReturnType() == XB_EXP_DATE ) - // nChild1->SetResult( (xbDouble) nChild1->GetDateResult().JulianDays()); - - nWork->GetNodeText( sWork1 ); - if( sWork1 == "++" ) - nChild1->SetResult( nChild1->GetNumericResult() + 1 ); - else - nChild1->SetResult( nChild1->GetNumericResult() - 1 ); - - nWork->SetResult( nChild1->GetNumericResult()); - - //if( nChild1->GetReturnType() == XB_EXP_DATE ){ - // dtWork1.JulToDate8( (xbInt32) nChild1->GetNumericResult()); - // nChild1->SetResult( dtWork1 ); - // nWork->SetResult( dtWork1 ); - // } - break; - - case XB_EXP_POST_OPERATOR: // increment value after setting in head node - if( nWork->GetChildCnt() != 1 ){ - iErrorStop = 110; - iRc = XB_PARSE_ERROR; - throw iRc; - } - nChild1 = nWork->GetChild( 0 ); - //if( nChild1->GetReturnType() == XB_EXP_DATE ){ - // nWork->SetResult( nChild1->GetDateResult()); - // nChild1->SetResult( (xbDouble) nChild1->GetDateResult().JulianDays()); - //} - //else - nWork->SetResult( nChild1->GetNumericResult()); - - nWork->GetNodeText( sWork1 ); - if( sWork1 == "++" ) - nChild1->SetResult( nChild1->GetNumericResult() + 1 ); - else - nChild1->SetResult( nChild1->GetNumericResult() - 1 ); - - //if( nChild1->GetReturnType() == XB_EXP_DATE ){ - // dtWork1.JulToDate8( (xbInt32) nChild1->GetNumericResult()); - // nChild1->SetResult( dtWork1 ); - // } - break; - - case XB_EXP_FIELD: - - if(( dbf = nWork->GetDbf()) == NULL ){ - iErrorStop = 120; - iRc = XB_PARSE_ERROR; - throw iRc; - } - switch( nWork->GetReturnType()){ - case XB_EXP_CHAR: - if(( iRc = dbf->GetField( nWork->GetFieldNo(), sWork1, iRecBufSw )) < XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - nWork->SetResult( sWork1 ); - break; - - case XB_EXP_DATE: - - if(( iRc = dbf->GetField( nWork->GetFieldNo(), sWork1, iRecBufSw )) < XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if( sWork1 == " " ){ - // std::cout << "xbExp::ProcessExpression() line 1938 sWork is spaces\n"; - //nWork->SetResult( (xbDouble) 21474835648 ); // dbase sets a date value in both ndx and mdx index files to this if spaces on dbf record - nWork->SetResult( (xbDouble) XB_NULL_DATE ); - } else { - dtWork1.Set( sWork1 ); - nWork->SetResult( (xbDouble) dtWork1.JulianDays() ); - } - break; - - case XB_EXP_LOGICAL: - if(( iRc = dbf->GetLogicalField( nWork->GetFieldNo(), bWork, iRecBufSw )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - nWork->SetResult( bWork ); - break; - - case XB_EXP_NUMERIC: - if(( iRc = dbf->GetDoubleField( nWork->GetFieldNo(), dWork, iRecBufSw )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - nWork->SetResult( dWork ); - break; - - default: - iErrorStop = 170; - iRc = XB_PARSE_ERROR; - throw iRc; - // break; - } - break; - - - case XB_EXP_OPERATOR: - if(( iRc = ProcessExpressionOperator( nWork )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - - break; - - case XB_EXP_FUNCTION: - if(( iRc = ProcessExpressionFunction( nWork, iRecBufSw )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - break; - - default: - iErrorStop = 200; - iRc = XB_PARSE_ERROR; - throw iRc; - // break; - } - nWork = GetNextNode( nWork ); - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::ProcessExpression() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} -/*************************************************************************/ -//! ProcessExpression -/*! This method processes an expression tree for a given node. -*/ - -xbInt16 xbExp::ProcessExpressionFunction( xbExpNode * n, xbInt16 iRecBufSw ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - - xbString sFunction; - xbString sResult; - xbDouble dResult; - xbDate dtResult; - xbBool bResult; - - n->GetNodeText( sFunction ); - - // process functions with no children first - xbExpNode * nChild1; - if( n->GetChildCnt() == 0 ){ - if( sFunction == "DATE" ){ - if(( iRc = xbase->DATE( dtResult )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - n->SetResult( dtResult ); - } else if( sFunction == "DEL" ){ - if(( iRc = xbase->DEL( dbf, sResult, iRecBufSw )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "DELETED" ){ - if(( iRc = xbase->DELETED( dbf, bResult, iRecBufSw )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - n->SetResult( bResult ); - } else if( sFunction == "RECCOUNT" ){ - if(( iRc = xbase->RECCOUNT( dbf, dResult )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "RECNO" ){ - if(( iRc = xbase->RECNO( dbf, dResult )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - n->SetResult( dResult ); - } - // process functions with one child - } else if( n->GetChildCnt() == 1 ){ - - nChild1 = n->GetChild( 0 ); - - if( sFunction == "ABS" ){ - if(( iRc = xbase->ABS( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "ALLTRIM" ){ - if(( iRc = xbase->ALLTRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "ASC" ){ - if(( iRc = xbase->ASC( nChild1->GetStringResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "CDOW" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->CDOW( d, sResult )) != XB_NO_ERROR ){ - iErrorStop = 230; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "CHR" ){ - if(( iRc = xbase->CHR( nChild1->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 240; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "CMONTH" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->CMONTH( d, sResult )) != XB_NO_ERROR ){ - iErrorStop = 250; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "CTOD" ){ - if(( iRc = xbase->CTOD( nChild1->GetStringResult(), dtResult )) != XB_NO_ERROR ){ - iErrorStop = 260; - throw iRc; - } - n->SetResult( dtResult ); - } else if( sFunction == "DAY" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->DAY( d, dResult )) != XB_NO_ERROR ){ - iErrorStop = 270; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "DESCEND" ){ - - if( n->GetReturnType() == XB_EXP_CHAR ){ - if(( iRc = xbase->DESCEND( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 280; - throw iRc; - } - n->SetResult( sResult ); - - } else if( n->GetReturnType() == XB_EXP_DATE ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->DESCEND( d, dtResult )) != XB_NO_ERROR ){ - iErrorStop = 290; - throw iRc; - } - n->SetResult( dtResult ); - - } else if( n->GetReturnType() == XB_EXP_NUMERIC ){ - if(( iRc = xbase->DESCEND( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 300; - throw iRc; - } - n->SetResult( dResult ); - - } else { - iErrorStop = 310; - iRc = XB_PARSE_ERROR; - throw iRc; - } - - } else if( sFunction == "DOW" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->DOW( d, dResult )) != XB_NO_ERROR ){ - iErrorStop = 320; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "DTOC" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->DTOC( d, sResult )) != XB_NO_ERROR ){ - iErrorStop = 330; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "DTOS" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->DTOS( d, sResult )) != XB_NO_ERROR ){ - iErrorStop = 340; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "EXP" ){ - if(( iRc = xbase->EXP( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 350; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "INT" ){ - if(( iRc = xbase->INT( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 360; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "ISALPHA" ){ - if(( iRc = xbase->ISALPHA( nChild1->GetStringResult(), bResult )) != XB_NO_ERROR ){ - iErrorStop = 370; - throw iRc; - } - n->SetResult( bResult ); - } else if( sFunction == "ISLOWER" ){ - if(( iRc = xbase->ISLOWER( nChild1->GetStringResult(), bResult )) != XB_NO_ERROR ){ - iErrorStop = 380; - throw iRc; - } - n->SetResult( bResult ); - } else if( sFunction == "ISUPPER" ){ - if(( iRc = xbase->ISUPPER( nChild1->GetStringResult(), bResult )) != XB_NO_ERROR ){ - iErrorStop = 390; - throw iRc; - } - n->SetResult( bResult ); - } else if( sFunction == "LEN" ){ - if(( iRc = xbase->LEN( nChild1->GetStringResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 400; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "LOG" ){ - if(( iRc = xbase->LOG( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 410; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "LTRIM" ){ - if(( iRc = xbase->LTRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 420; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "LOWER" ){ - if(( iRc = xbase->LOWER( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 430; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "MONTH" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->MONTH( d, dResult )) != XB_NO_ERROR ){ - iErrorStop = 440; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "RTRIM" ){ - if(( iRc = xbase->RTRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 450; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "STOD" ){ - if(( iRc = xbase->STOD( nChild1->GetStringResult(), dtResult )) != XB_NO_ERROR ){ - iErrorStop = 460; - throw iRc; - } - n->SetResult( dtResult ); - } else if( sFunction == "SPACE" ){ - if(( iRc = xbase->SPACE( (xbInt32) nChild1->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 470; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "SQRT" ){ - if(( iRc = xbase->SQRT( nChild1->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 480; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "STR" ){ - if(( iRc = xbase->STR( nChild1->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 490; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "TRIM" ){ - if(( iRc = xbase->TRIM( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 500; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "UPPER" ){ - if(( iRc = xbase->UPPER( nChild1->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 510; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "VAL" ){ - if(( iRc = xbase->VAL( nChild1->GetStringResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 520; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "YEAR" ){ - xbDate d( (xbInt32) nChild1->GetNumericResult()); - if(( iRc = xbase->YEAR( d, dResult )) != XB_NO_ERROR ){ - iErrorStop = 530; - throw iRc; - } - n->SetResult( dResult ); - } else { - iErrorStop = 540; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } else if( n->GetChildCnt() == 2 ){ - xbExpNode * nChild2; - nChild1 = n->GetChild( 0 ); - nChild2 = n->GetChild( 1 ); - - if( sFunction == "AT" ){ - if(( iRc = xbase->AT( nChild1->GetStringResult(), nChild2->GetStringResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 700; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "LEFT" ){ - if(( iRc = xbase->LEFT( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 710; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "MAX" ){ - if(( iRc = xbase->MAX( nChild1->GetNumericResult(), nChild2->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 720; - throw iRc; - } - n->SetResult( dResult ); - } else if( sFunction == "MIN" ){ - if(( iRc = xbase->MIN( nChild1->GetNumericResult(), nChild2->GetNumericResult(), dResult )) != XB_NO_ERROR ){ - iErrorStop = 730; - throw iRc; - } - n->SetResult( dResult ); - } - else if( sFunction == "REPLICATE" ){ - if(( iRc = xbase->REPLICATE( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 800; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "RIGHT" ){ - if(( iRc = xbase->RIGHT( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 810; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "STR" ){ - if(( iRc = xbase->STR( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 820; - throw iRc; - } - n->SetResult( sResult ); - } else { - iErrorStop = 830; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } else if( n->GetChildCnt() == 3 ){ - xbExpNode * nChild2; - xbExpNode * nChild3; - nChild1 = n->GetChild( 0 ); - nChild2 = n->GetChild( 1 ); - nChild3 = n->GetChild( 2 ); - - if( sFunction == "IIF" ){ - if(( iRc = xbase->IIF( nChild1->GetBoolResult(), nChild2->GetStringResult(), nChild3->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 900; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "STR" ){ - if(( iRc = xbase->STR( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(), (xbUInt32) nChild3->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 910; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "STRZERO" ){ - if(( iRc = xbase->STRZERO( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(), (xbUInt32) nChild3->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 920; - throw iRc; - } - n->SetResult( sResult ); - } else if( sFunction == "SUBSTR" ){ - if(( iRc = xbase->SUBSTR( nChild1->GetStringResult(), (xbUInt32) nChild2->GetNumericResult(), (xbUInt32) nChild3->GetNumericResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 930; - throw iRc; - } - n->SetResult( sResult ); - } else { - iErrorStop = 950; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } else if( n->GetChildCnt() == 4 ){ - xbExpNode * nChild2; - xbExpNode * nChild3; - xbExpNode * nChild4; - nChild1 = n->GetChild( 0 ); - nChild2 = n->GetChild( 1 ); - nChild3 = n->GetChild( 2 ); - nChild4 = n->GetChild( 3 ); - - if( sFunction == "STR" ){ - if(( iRc = xbase->STR( nChild1->GetNumericResult(), (xbUInt32) nChild2->GetNumericResult(), - (xbUInt32) nChild3->GetNumericResult(), nChild4->GetStringResult(), sResult )) != XB_NO_ERROR ){ - iErrorStop = 1000; - throw iRc; - } - n->SetResult( sResult ); - } else { - iErrorStop = 1010; - iRc = XB_PARSE_ERROR; - throw iRc; - } - - } else { - iErrorStop = 2000; - iRc = XB_PARSE_ERROR; - throw iRc; - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::ProcessExpressionFunction() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} -/*************************************************************************/ -//! Process Expression Operator -/*! This method processes an expression operator for a given node. -*/ - -xbInt16 xbExp::ProcessExpressionOperator( xbExpNode * n ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbExpNode * nChild1 = NULL; - xbExpNode * nChild2 = NULL; - xbString sOperator; - xbString sWork1; - xbString sWork2; - xbDate dtWork1; - - xbString sMsg; - - try{ - n->GetNodeText( sOperator ); - nChild1 = n->GetChild( 0 ); - if( !n->IsUnaryOperator()) - nChild2 = n->GetChild( 1 ); - - switch( n->GetReturnType()){ - case XB_EXP_CHAR: - if( sOperator == "+" ){ - sWork1 = nChild1->GetStringResult(); - sWork1 += nChild2->GetStringResult(); - n->SetResult( sWork1 ); - } else if( sOperator == "-" ){ - sWork1 = nChild1->GetStringResult(); - sWork1.Rtrim(); - sWork1 += nChild2->GetStringResult(); - sWork1.PadRight( ' ', n->GetResultLen()); - n->SetResult( sWork1 ); - } else { - iErrorStop = 100; - iRc = XB_PARSE_ERROR; - throw iRc; - } - break; - - case XB_EXP_NUMERIC: - if( sOperator == "+" ) - n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult()); - else if( sOperator == "-" ){ - n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult()); - - } - else if( sOperator == "*" ) - n->SetResult( nChild1->GetNumericResult() * nChild2->GetNumericResult()); - else if( sOperator == "/" ) - n->SetResult( nChild1->GetNumericResult() / nChild2->GetNumericResult()); - else if( sOperator == "^" || sOperator == "**" ) - n->SetResult( pow( nChild1->GetNumericResult(), nChild2->GetNumericResult())); - else if( sOperator == "+=" ){ - n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult()); - nChild1->SetResult( n->GetNumericResult() ); - } - else if( sOperator == "-=" ){ - n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult()); - nChild1->SetResult( n->GetNumericResult() ); - } - else if( sOperator == "*=" ){ - n->SetResult( nChild1->GetNumericResult() * nChild2->GetNumericResult()); - nChild1->SetResult( n->GetNumericResult() ); - } - else if( sOperator == "/=" ){ - n->SetResult( nChild1->GetNumericResult() / nChild2->GetNumericResult()); - nChild1->SetResult( n->GetNumericResult() ); - } else { - iErrorStop = 200; - iRc = XB_PARSE_ERROR; - throw iRc; - } - break; - - - case XB_EXP_DATE: - // if date values in the leaf nodes, convert to numeric for operator logic - - if( sOperator == "+" ) - n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult()); - else if( sOperator == "-" ){ - n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult()); - xbDate d( (xbInt32) n->GetNumericResult()); - } - else if( sOperator == "+=" ){ - n->SetResult( nChild1->GetNumericResult() + nChild2->GetNumericResult()); - nChild1->SetResult( n->GetNumericResult() ); - } - else if( sOperator == "-=" ){ - n->SetResult( nChild1->GetNumericResult() - nChild2->GetNumericResult()); - nChild1->SetResult( n->GetNumericResult() ); - } else { - iErrorStop = 300; - iRc = XB_PARSE_ERROR; - throw iRc; - } - break; - - case XB_EXP_LOGICAL: - - if( !n->IsUnaryOperator() && (nChild1->GetReturnType() != nChild2->GetReturnType())){ - iErrorStop = 400; - iRc = XB_INCOMPATIBLE_OPERANDS; - throw iRc; - } - - if( sOperator == ".AND." || sOperator == "AND" ) - n->SetResult((xbBool) (nChild1->GetBoolResult() && nChild2->GetBoolResult()) ); - - else if( sOperator == ".OR." || sOperator == "OR" ) - n->SetResult((xbBool) (nChild1->GetBoolResult() || nChild2->GetBoolResult()) ); - - else if( sOperator == ".NOT." || sOperator == "NOT" ){ - if( nChild1->GetBoolResult()) - n->SetResult((xbBool) xbFalse ); - else - n->SetResult((xbBool) xbTrue ); - } - - else if( sOperator == ">" ){ - - if( nChild1->GetReturnType() == XB_EXP_CHAR ) - n->SetResult((xbBool)(nChild1->GetStringResult() > nChild2->GetStringResult())); - - else if( nChild1->GetReturnType() == XB_EXP_NUMERIC ) - n->SetResult((xbBool)(nChild1->GetNumericResult() > nChild2->GetNumericResult())); - - else if( nChild1->GetReturnType() == XB_EXP_DATE ){ - xbDouble d1 = nChild1->GetNumericResult(); - xbDouble d2 = nChild2->GetNumericResult(); - if( d1 == XB_NULL_DATE ) d1 = 0; - if( d2 == XB_NULL_DATE ) d2 = 0; - n->SetResult((xbBool)( d1 > d2)); - // n->SetResult((xbBool)(nChild1->GetNumericResult() > nChild2->GetNumericResult())); - - } else { - iErrorStop = 410; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - - else if( sOperator == ">=" ){ - if( nChild1->GetReturnType() == XB_EXP_CHAR ) - n->SetResult((xbBool)(nChild1->GetStringResult() >= nChild2->GetStringResult())); - - else if( nChild1->GetReturnType() == XB_EXP_NUMERIC ) - n->SetResult((xbBool)(nChild1->GetNumericResult() >= nChild2->GetNumericResult())); - - else if( nChild1->GetReturnType() == XB_EXP_DATE ){ - xbDouble d1 = nChild1->GetNumericResult(); - xbDouble d2 = nChild2->GetNumericResult(); - if( d1 == XB_NULL_DATE ) d1 = 0; - if( d2 == XB_NULL_DATE ) d2 = 0; - n->SetResult((xbBool)( d1 >= d2)); - //n->SetResult((xbBool)(nChild1->GetNumericResult() >= nChild2->GetNumericResult())); - - } else { - iErrorStop = 420; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - - else if( sOperator == "<" ){ - - if( nChild1->GetReturnType() == XB_EXP_CHAR ){ - n->SetResult((xbBool)( nChild1->GetStringResult() < nChild2->GetStringResult())); - - } else if( nChild1->GetReturnType() == XB_EXP_NUMERIC ){ - n->SetResult((xbBool)( nChild1->GetNumericResult() < nChild2->GetNumericResult())); - - } else if( nChild1->GetReturnType() == XB_EXP_DATE ){ - xbDouble d1 = nChild1->GetNumericResult(); - xbDouble d2 = nChild2->GetNumericResult(); - if( d1 == XB_NULL_DATE ) d1 = 0; - if( d2 == XB_NULL_DATE ) d2 = 0; - - n->SetResult((xbBool)( d1 < d2)); - - // std::cout << "xbexp() line 2567 [" << nChild1->GetNumericResult() << "][" << nChild2->GetNumericResult() << "]\n"; - - } else { - iErrorStop = 430; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - - else if( sOperator == "<=" ){ - - if( nChild1->GetReturnType() == XB_EXP_CHAR ) - n->SetResult((xbBool)( nChild1->GetStringResult() <= nChild2->GetStringResult())); - - else if( nChild1->GetReturnType() == XB_EXP_NUMERIC ) - n->SetResult((xbBool)( nChild1->GetNumericResult() <= nChild2->GetNumericResult())); - - else if( nChild1->GetReturnType() == XB_EXP_DATE ){ - xbDouble d1 = nChild1->GetNumericResult(); - xbDouble d2 = nChild2->GetNumericResult(); - if( d1 == XB_NULL_DATE ) d1 = 0; - if( d2 == XB_NULL_DATE ) d2 = 0; - n->SetResult((xbBool)( d1 <= d2)); - // n->SetResult((xbBool)( nChild1->GetNumericResult() <= nChild2->GetNumericResult())); - - } else { - iErrorStop = 440; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - - else if( sOperator == "<>" || sOperator == "#" || sOperator == "!=" ){ - - if( nChild1->GetReturnType() == XB_EXP_CHAR ) - n->SetResult((xbBool)( nChild1->GetStringResult() != nChild2->GetStringResult())); - - else if( nChild1->GetReturnType() == XB_EXP_NUMERIC ) - n->SetResult((xbBool)( nChild1->GetNumericResult() != nChild2->GetNumericResult())); - - else if( nChild1->GetReturnType() == XB_EXP_DATE ){ - xbDouble d1 = nChild1->GetNumericResult(); - xbDouble d2 = nChild2->GetNumericResult(); - if( d1 == XB_NULL_DATE ) d1 = 0; - if( d2 == XB_NULL_DATE ) d2 = 0; - n->SetResult((xbBool)( d1 != d2)); - // n->SetResult((xbBool)( nChild1->GetNumericResult() != nChild2->GetNumericResult())); - - } else { - iErrorStop = 450; - iRc = XB_PARSE_ERROR; - throw iRc; - } - } - - else if( sOperator == "$" ){ - if( nChild1->GetReturnType() == XB_EXP_CHAR ) - if( nChild2->GetStringResult().Pos( nChild1->GetStringResult()) > 0 ) - n->SetResult((xbBool) xbTrue ); - else - n->SetResult((xbBool) xbFalse ); - else { - iErrorStop = 460; - iRc = XB_INCOMPATIBLE_OPERANDS; - throw iRc; - } - } - - else if( sOperator == "=" ){ - - if( nChild1->GetReturnType() == XB_EXP_CHAR ){ - xbString sChld1 = nChild1->GetStringResult(); - xbString sChld2 = nChild2->GetStringResult(); - sChld1.Rtrim(); - sChld2.Rtrim(); - n->SetResult((xbBool)( sChld1 == sChld2 )); - - } else if( nChild1->GetReturnType() == XB_EXP_NUMERIC ){ - n->SetResult((xbBool)( nChild1->GetNumericResult() == nChild2->GetNumericResult())); - - } else if( nChild1->GetReturnType() == XB_EXP_DATE ){ - xbDouble d1 = nChild1->GetNumericResult(); - xbDouble d2 = nChild2->GetNumericResult(); - if( d1 == XB_NULL_DATE ) d1 = 0; - if( d2 == XB_NULL_DATE ) d2 = 0; - n->SetResult((xbBool)( d1 == d2)); - // n->SetResult((xbBool)( nChild1->GetNumericResult() == nChild2->GetNumericResult())); - - } else { - iErrorStop = 470; - iRc = XB_PARSE_ERROR; - throw iRc; - } - - - } else { - iErrorStop = 500; - iRc = XB_PARSE_ERROR; - throw iRc; - } - - break; - - default: - iErrorStop = 600; - iRc = XB_PARSE_ERROR; - throw iRc; - // break; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbexp::ProcessExpressionOperator() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - } - return iRc; -} - -/*************************************************************************/ -}; // namespace -#endif // XB_EXPRESSION_SUPPORT -/*************************************************************************/ diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbexpnode.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbexpnode.cpp deleted file mode 100755 index d11e8cc..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbexpnode.cpp +++ /dev/null @@ -1,562 +0,0 @@ -/* xbexpnode.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014,2017,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 - -*/ - -#include "xbase.h" - -#ifdef XB_EXPRESSION_SUPPORT - -namespace xb{ -/************************************************************************/ -//! @brief Constructor -xbExpNode::xbExpNode(){ - sNodeText = ""; - cReturnType = 0; - cNodeType = 0; - dResult = 0; - iFieldNo = 0; - ulResultLen = 0; - iWeight = 0; - nParent = NULL; - dbf = NULL; -} - -/************************************************************************/ -//! @brief Constructor -/*! - \param sNodeText Node text. - \param cReturnType Return type. - \param cNodeType Node type. -*/ - -xbExpNode::xbExpNode( xbString &sNodeText, char cReturnType, char cNodeType ){ - this->sNodeText = sNodeText; - this->cReturnType = cReturnType; - this->cNodeType = cNodeType; - dResult = 0; - iFieldNo = 0; - ulResultLen = 0; - iWeight = 0; - nParent = NULL; - dbf = NULL; -} - -/************************************************************************/ -//! @brief Constructor -/*! - \param sNodeText Node text. - \param cNodeType Node type. -*/ -xbExpNode::xbExpNode( xbString &sNodeText, char cNodeType ){ - this->sNodeText = sNodeText; - this->cReturnType = 0x00; - this->cNodeType = cNodeType; - dResult = 0; - iFieldNo = 0; - ulResultLen = 0; - iWeight = 0; - nParent = NULL; - dbf = NULL; -} - -/************************************************************************/ -//! @brief Constructor -/*! - \param cNodeType Node type. -*/ -xbExpNode::xbExpNode( char cNodeType ){ - this->cReturnType = 0x00; - this->cNodeType = cNodeType; - dResult = 0; - iFieldNo = 0; - ulResultLen = 0; - iWeight = 0; - nParent = NULL; - dbf = NULL; -} - -/************************************************************************/ -//! @brief Deconstructor -xbExpNode::~xbExpNode(){ - - xbExpNode * n; - while( llChildren.GetNodeCnt() > 0 ){ - llChildren.RemoveFromFront( n ); - delete n; - } -} - -/************************************************************************/ -//! @brief Add child node to linked list. -/*! - \param n Pointer to node to add to linked list. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbExpNode::AddChild( xbExpNode *n ){ - n->SetParent( this ); - return llChildren.InsertAtEnd( n ); -} - -/************************************************************************/ -#ifdef XB_DEBUG_SUPPORT - -//! @brief Dump Node. -/*! - \param iOption xbTrue - Print child info if they exist.<bt> - xbFalse - Don't print child info. - \returns void. -*/ -void xbExpNode::DumpNode( xbInt16 iOption ) const { - xbString sMsg; - std::cout << "Me=[" << this << "] "; - if( nParent ) - std::cout << "Par=[" << nParent << "] "; - - std::cout << "nTyp=[" << cNodeType << "] "; - std::cout << "dTyp=[" << cReturnType << "] "; - if( iWeight != 0 ) - std::cout << "W=[" << iWeight << "] "; - - if( cNodeType == XB_EXP_FIELD ) - std::cout << "FieldNo=[" << iFieldNo << "] "; - - std::cout << "Txt=[" << sNodeText << "] "; - if( sResult != "" ) - std::cout << "sVal=[" << sResult << "] "; - - if( ulResultLen > 0 ) - std::cout << "Len=[" << ulResultLen << "] "; - if( cReturnType == XB_EXP_DATE ){ - xbDate d( (xbInt32) dResult ); - std::cout << "dtVal=[" << d.Str() << "] "; - } - - if( cReturnType == XB_EXP_DATE || cReturnType == XB_EXP_NUMERIC ){ - sMsg.Sprintf( "dVal=[%f]\n", dResult ); - std::cout << sMsg.Str(); - } - - if( cReturnType == XB_EXP_LOGICAL ){ - sMsg.Sprintf( "lVal=[%d]\n", (xbInt32) dResult ); - std::cout << sMsg.Str(); - } - - if( iOption ){ - xbLinkListNode<xbExpNode *> *lln = llChildren.GetHeadNode(); - xbExpNode *n; - if( lln ){ - std::cout << " Children: "; - while( lln ){ - n = lln->GetKey(); - std::cout << " [" << n << "]"; - lln = lln->GetNextNode(); - } - std::cout << std::endl; - - lln = llChildren.GetHeadNode(); - while( lln ){ - n = lln->GetKey(); - n->DumpNode( iOption ); - lln = lln->GetNextNode(); - } - } - } - - std::cout << std::endl; -} -#endif - -/************************************************************************/ -//! @brief Get boolean result. -/*! - \returns Boolean result. -*/ - -xbBool xbExpNode::GetBoolResult() const { - return (xbBool) dResult; -} - -/************************************************************************/ -//! @brief Get pointer to child. -/*! - \param ulChildNo - Which child? 1,2 or3 - \returns Pointer to child node or null if none exists. -*/ -xbExpNode *xbExpNode::GetChild( xbUInt32 ulChildNo ) const { - - xbLinkListNode<xbExpNode *> *lln = llChildren.GetNodeForNo( ulChildNo ); - if( lln ) - return lln->GetKey(); - else - return 0x00; -} -/************************************************************************/ -//! @brief Get child count. -/*! - \returns Child count. -*/ -xbUInt32 xbExpNode::GetChildCnt() const{ - return llChildren.GetNodeCnt(); -} - -/************************************************************************/ -//! @brief Get the current child number for this node. -/*! - \returns Child number: 1, 2 or 3. -*/ - -xbUInt32 xbExpNode::GetChildNo() const { - - if( !nParent ) - return 0; - - for( xbUInt32 i = 0; i < nParent->GetChildCnt(); i++ ){ - if( this == nParent->GetChild( i )){ - // std::cout << "get child no [" << this << "][" << nParent->GetChild(i) << "]\n"; - return i; - } - } - return 0; -} - -/************************************************************************/ -//! @brief Get the dbf pointer. -/*! - \returns Pointer to dbf. -*/ -xbDbf *xbExpNode::GetDbf() const { - return dbf; -} -/************************************************************************/ -//! @brief Get the field number. -/*! - \returns Field number for field node. -*/ - -xbInt16 xbExpNode::GetFieldNo() const { - return iFieldNo; -} - -/*************************************************************************/ -//! @brief Get the first node. -/*! - \returns Pointer to left most child node or *this if childless. -*/ - -xbExpNode *xbExpNode::GetFirstNode() { - xbExpNode *n = this; - while( n && n->GetChildCnt() > 0 ) - n = n->GetChild(0); - return n; -} - -/*************************************************************************/ -//! @brief Get the next node. -/*! - \returns Pointer to right node or parent if right node does not exist. -*/ - -xbExpNode *xbExpNode::GetNextNode() const { - - if( HasRightSibling()) - return GetRightSibling()->GetFirstNode(); - else - return nParent; -} - -/************************************************************************/ -//! @brief Get the node text. -/*! - \param sOutText Output string containing node text. - \returns void -*/ - -void xbExpNode::GetNodeText( xbString &sOutText ) const{ - sOutText = sNodeText; -} - -/************************************************************************/ -//! @brief Get the node type. -/*! - \returns Node type. -*/ - -char xbExpNode::GetNodeType() const{ - return cNodeType; -} - -/************************************************************************/ -//! @brief Get numeric result. -/*! - \returns Numeric result. -*/ - -xbDouble xbExpNode::GetNumericResult() const { - return dResult; -} - -/************************************************************************/ -//! @brief Get parent. -/*! - \returns Pointer to parent node. -*/ - -xbExpNode *xbExpNode::GetParent() const{ - return nParent; -} - -/************************************************************************/ -//! @brief Get result length. -/*! - \returns Result length. -*/ -xbUInt32 xbExpNode::GetResultLen() const{ - return ulResultLen; -} -/************************************************************************/ -//! @brief Get result type. -/*! - \returns Result type. -*/ -char xbExpNode::GetReturnType() const{ - return cReturnType; -} - -/*************************************************************************/ -//! @brief Get right sibling. -/*! - \returns Pointer to right sibling. -*/ - -xbExpNode *xbExpNode::GetRightSibling() const { - - xbExpNode * nParent; - if(( nParent = GetParent()) == NULL ) - return NULL; - - if( nParent->GetChildCnt() <= 0 ) - return NULL; - - xbUInt32 ulChildNo = GetChildNo(); - - if( ulChildNo < (nParent->GetChildCnt() - 1)) - return nParent->GetChild( ulChildNo + 1 ); - else - return NULL; -} -/************************************************************************/ -//! @brief Get string result. -/*! - \returns String result. -*/ -xbString &xbExpNode::GetStringResult(){ - return sResult; -} -/************************************************************************/ -//! @brief Get node weight. -/*! - Each node is assigned a weight used internally to detmerine processing sequence. - \returns Node weight. -*/ - -xbInt16 xbExpNode::GetWeight() const { - return iWeight; -} - -/*************************************************************************/ -//! @brief Determine if node has a right sibling. -/*! - \returns xbTrue - Node has right sibling.<br> - xbFalse - Node has no right sibling. -*/ - -xbBool xbExpNode::HasRightSibling() const { - - // std::cout << "in HasRightSibling [" << sNodeText << "]\n"; - - if( nParent == NULL ) - return xbFalse; - - xbUInt32 ulChildNo = GetChildNo(); - - if( ulChildNo < (nParent->GetChildCnt() - 1)){ - // std::cout << "Has Right Sibling = " << iChildNo << "] of [" << nParent->GetChildCnt() << "]\n"; - return xbTrue; -} - else - return xbFalse; -} - - -/*************************************************************************/ -//! @brief Determine if node is an operator. -/*! - \returns xbTrue - Node is an operator.<br> - xbFalse - Node is not an operator. -*/ - -xbBool xbExpNode::IsOperator() const { - - if( cNodeType == XB_EXP_OPERATOR ) - return xbTrue; - else - return xbFalse; -} - -/*************************************************************************/ -//! @brief Determine if node is a unary operator. -/*! - \returns xbTrue - Node is a unary operator.<br> - xbFalse - Node is not a unary operator. -*/ -xbBool xbExpNode::IsUnaryOperator() const { - - if( cNodeType == XB_EXP_PRE_OPERATOR || cNodeType == XB_EXP_POST_OPERATOR ) - return xbTrue; - else if( cNodeType == XB_EXP_OPERATOR && (sNodeText == ".NOT." || sNodeText == "NOT" )) - return xbTrue; - else - return xbFalse; -} -/************************************************************************/ -//! @brief Remove last child from node. -/*! - \returns void. -*/ - -void xbExpNode::RemoveLastChild(){ - xbExpNode *n; - llChildren.RemoveFromEnd( n ); -} - -/************************************************************************/ -//! @brief Set dbf info on node. -/*! - \param dbf Pointer to dbf. - \param iFieldNo Field number of field. - \returns void. -*/ -void xbExpNode::SetDbfInfo( xbDbf *dbf, xbInt16 iFieldNo ){ - this->dbf = dbf; - this->iFieldNo = iFieldNo; -} - -/************************************************************************/ -//! @brief Set dbf info on node. -/*! - \param dbf Pointer to dbf. - \returns void. -*/ -void xbExpNode::SetDbfInfo( xbDbf *dbf ){ - this->dbf = dbf; -} -/************************************************************************/ -//! @brief Set node type. -/*! - \param cNodeType Node type. - \returns void. -*/ -void xbExpNode::SetNodeType( char cNodeType ){ - this->cNodeType = cNodeType; -} - -/************************************************************************/ -//! @brief Set node text. -/*! - \param sNodeText Node text. - \returns void. -*/ -void xbExpNode::SetNodeText( xbString & sNodeText ){ - this->sNodeText = sNodeText; -} - -/************************************************************************/ -//! @brief Set parent. -/*! - \param n Pointer to parent. - \returns void. -*/ -void xbExpNode::SetParent( xbExpNode *n ){ - this->nParent = n; -} - -/************************************************************************/ -//! @brief Set date result. -/*! - \param dtResult Date result. - \returns void. -*/ -void xbExpNode::SetResult( xbDate &dtResult ){ - this->dResult = dtResult.JulianDays(); -} - -/************************************************************************/ -//! @brief Set boolean result. -/*! - \param bResult Boolean result. - \returns void. -*/ -void xbExpNode::SetResult( xbBool bResult ){ - this->dResult = bResult; -} -/************************************************************************/ -//! @brief Set numeric result. -/*! - \param dResult Double numeric result. - \returns void. -*/ -void xbExpNode::SetResult( xbDouble dResult ){ - this->dResult = dResult; -} -/************************************************************************/ -//! @brief Set string result. -/*! - \param sResult String result. - \returns void. -*/ -void xbExpNode::SetResult( xbString &sResult ){ - this->sResult = sResult; -} -/************************************************************************/ -//! @brief Set result length. -/*! - \param ulResultLen Set result length. - \returns void. -*/ -void xbExpNode::SetResultLen( xbUInt32 ulResultLen ){ - this->ulResultLen = ulResultLen; -} -/************************************************************************/ -//! @brief Set return type. -/*! - \param cReturnType Return Type. - \returns void. -*/ -void xbExpNode::SetReturnType( char cReturnType ){ - this->cReturnType = cReturnType; -} -/************************************************************************/ -//! @brief Set weight. -/*! - \param iWeight Weight to set this node at. - \returns void. -*/ -void xbExpNode::SetWeight( xbInt16 iWeight ){ - this->iWeight = iWeight; -} -/*************************************************************************/ -}; // namespace -#endif // XB_EXPRESSION_SUPPORT -/*************************************************************************/ diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfields.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbfields.cpp deleted file mode 100755 index 85ac145..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfields.cpp +++ /dev/null @@ -1,1189 +0,0 @@ -/* xbfields.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 - -*/ - -#include "xbase.h" - -namespace xb{ - -/************************************************************************/ -//! @brief Get xbDouble field for field name. -/*! - \param sFieldName Name of field to retrieve. - \param dFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetDoubleField( const xbString &sFieldName, xbDouble &dFieldValue ) const { - return GetDoubleField( GetFieldNo( sFieldName ), dFieldValue ); -} - -/************************************************************************/ -//! @brief Get xbDouble field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param dFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetDoubleField( xbInt16 iFieldNo, xbDouble &dFieldValue ) const { - xbInt16 iRc = XB_NO_ERROR; - char buf[21]; - memset( buf, 0x00, 21 ); - if(( iRc = GetRawField( iFieldNo, buf, 21, 0 )) >= XB_NO_ERROR ){ - dFieldValue = strtod( buf, NULL ); - return XB_NO_ERROR; - } else - return iRc; -} -/************************************************************************/ -//! @brief Get xbDouble field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param dFieldValue Output field value. - \param iRecBufSw 0 - Record buffer with any updates.<br>1 - Record buffer with original data. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetDoubleField( xbInt16 iFieldNo, xbDouble &dFieldValue, xbInt16 iRecBufSw ) const { - xbInt16 iRc = XB_NO_ERROR; - char buf[21]; - memset( buf, 0x00, 21 ); - if(( iRc = GetRawField( iFieldNo, buf, 21, iRecBufSw )) >= XB_NO_ERROR ){ - dFieldValue = strtod( buf, NULL ); - return XB_NO_ERROR; - } else - return iRc; -} - -/************************************************************************/ -//! @brief Get xbDate field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param dtFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetDateField( xbInt16 iFieldNo, xbDate &dtFieldValue ) const{ - xbString s; - xbInt16 iRc; - if(( iRc = GetField( iFieldNo, s )) != XB_NO_ERROR ) - return iRc; - return dtFieldValue.Set( s ); - // return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Get xbDate field for field name. -/*! - \param sFieldName Name of field to retrieve. - \param dtFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetDateField( const xbString &sFieldName, xbDate &dtFieldValue ) const{ - xbString s; - xbInt16 iRc; - if(( iRc = GetField( sFieldName, s )) != XB_NO_ERROR ) - return iRc; - return dtFieldValue.Set( s ); - // return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Get xbString field for field name. -/*! - \param sFieldName Name of field to retrieve - \param sFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetField( const xbString &sFieldName, xbString &sFieldValue ) const{ - return GetField( GetFieldNo( sFieldName ), sFieldValue, 0 ); -} -/************************************************************************/ -//! @brief Get field data for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param sFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetField( xbInt16 iFieldNo, xbString &sFieldValue ) const{ - return GetField( iFieldNo, sFieldValue, 0 ); -} -/************************************************************************/ -//! @brief Get field data for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param sFieldValue Output field value. - \param iRecBufSw 0 - Record buffer with any updates.<br>1 - Record buffer with original data. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetField( xbInt16 iFieldNo, xbString &sFieldValue, xbInt16 iRecBufSw) const -{ - xbUInt32 iLen; - if( iFieldNo < 0 || iFieldNo >= iNoOfFields ) { - sFieldValue = ""; - return XB_INVALID_FIELD_NO; - } - iLen = SchemaPtr[iFieldNo].cFieldLen; - sFieldValue = ""; - if( iRecBufSw ) - sFieldValue.Append( (char *) SchemaPtr[iFieldNo].pAddress2, iLen ); // original record buffer - else - sFieldValue.Append( (char *) SchemaPtr[iFieldNo].pAddress, iLen ); // current record buffer - return XB_NO_ERROR; -} - - -/************************************************************************/ -//! @brief Get decimal for field name. -/*! - This routine retreives a field's decimal length. - \param sFieldName Name of field to retrieve - \param iFieldDecimal Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetFieldDecimal( const xbString &sFieldName, xbInt16 & iFieldDecimal ) const { - return GetFieldDecimal( GetFieldNo( sFieldName ), iFieldDecimal ); -} - - -/************************************************************************/ -//! @brief Get decimal for field number. -/*! - This routine retreives a field's decimal length. - \param iFieldNo Number of field to retrieve - \param iFieldDecimal Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetFieldDecimal( xbInt16 iFieldNo, xbInt16 & iFieldDecimal ) const { - - if( iFieldNo < 0 || iFieldNo >= iNoOfFields ) { - return XB_INVALID_FIELD_NO; - } - iFieldDecimal = SchemaPtr[iFieldNo].cNoOfDecs; - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Get field length for field name. -/*! - - This function retrieves a field's length. - - \param sFieldName Name of field to retrieve - \param iFieldLen Output field length value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetFieldLen( const xbString &sFieldName, xbInt16 &iFieldLen ) const { - return GetFieldLen( GetFieldNo( sFieldName ), iFieldLen ); -} - - -/************************************************************************/ -//! @brief Get field length for field number. -/*! - This function retrieves a field's length. - - \param iFieldNo Name of field to retrieve - \param iFieldLen Output field length value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetFieldLen( xbInt16 iFieldNo, xbInt16 &iFieldLen ) const { - if( iFieldNo >= 0 && iFieldNo < iNoOfFields ){ - iFieldLen = SchemaPtr[iFieldNo].cFieldLen; - return XB_NO_ERROR; - } else - return XB_INVALID_FIELD_NO; -} - -/************************************************************************/ -//! @brief Get the field number for name. -/*! Returns the field number for the named field. - - All field get/put methods require either a field number or field name as - one of the parameters. Using the methods that take the field numbers will - yield slightly better performance because the methods that take a name, have - to look up the number. - - \param sFieldName Name of field. - \param iFieldNo Output field number for the given name. - \returns Number of field named fldName. -*/ - -xbInt16 xbDbf::GetFieldNo( const xbString & sFieldName, xbInt16 &iFieldNo ) const -{ - int i; - - if( sFieldName.Len() > 10 ) - return XB_INVALID_FIELD_NAME; - - for( i = 0; i < iNoOfFields; i++ ){ - if( sFieldName == SchemaPtr[i].cFieldName ){ - iFieldNo = i; - return XB_NO_ERROR; - } - } - return XB_INVALID_FIELD_NAME; -} - -/************************************************************************/ -//! Get field ID number for a given field name. -/*! Returns the field number for the named field. - - \param sFieldName Name of field. - \returns Number of field or XB_INVALID_FIELD_NAME. -*/ - -xbInt16 xbDbf::GetFieldNo( const xbString &sFieldName ) const { - int i; - - if( sFieldName.Len() > 10 ) - return XB_INVALID_FIELD_NAME; - - for( i = 0; i < iNoOfFields; i++ ){ - if( sFieldName == SchemaPtr[i].cFieldName ) - return i; - } - return XB_INVALID_FIELD_NAME; -} - -/************************************************************************/ -//! Get field type for field number. -/*! - \param iFieldNo Field number. - \param cFieldType Output field type. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetFieldType( xbInt16 iFieldNo, char & cFieldType ) const{ - - if( iFieldNo >= 0 && iFieldNo < iNoOfFields ){ - cFieldType = SchemaPtr[iFieldNo].cType; - return XB_NO_ERROR; - } - else - return XB_INVALID_FIELD_NO; -} - -/************************************************************************/ -//! Get field type for field name. -/*! - \param sFieldName Field name. - \param cFieldType Output field type. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetFieldType( const xbString &sFieldName, char & cFieldType ) const{ - return( GetFieldType( GetFieldNo( sFieldName ), cFieldType)); -} - -/************************************************************************/ -//! @brief Returns the name of the specified field. -/*! Returns a pointer to the name for the field specified by iFieldNo. - - \param iFieldNo Number of field. - \param sFieldName Output variable containing the field name. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetFieldName( xbInt16 iFieldNo, xbString &sFieldName ) const{ - if( iFieldNo >= 0 && iFieldNo < iNoOfFields ){ - sFieldName = SchemaPtr[iFieldNo].cFieldName; - return XB_NO_ERROR; - } - else - return XB_INVALID_FIELD_NO; -} - -/************************************************************************/ -//! @brief Get xbFloat field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param fFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetFloatField( xbInt16 iFieldNo, xbFloat & fFieldValue ) const { - - char cFieldType; - xbInt16 rc = GetFieldType( iFieldNo, cFieldType ); - if( rc < 0 ) - return rc; - - if( cFieldType != 'N' && cFieldType != 'F' ) - return XB_INVALID_FIELD_TYPE; - - xbString sTemp; - rc = GetField( iFieldNo, sTemp, 0 ); - if( rc < 0 ) - return rc; - - fFieldValue = (xbFloat) atof( sTemp.Str()); - return XB_NO_ERROR; -} - - -/************************************************************************/ -//! @brief Get xbFloat field for field name. -/*! - \param sFieldName Number of field to retrieve. - \param fFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetFloatField( const xbString & sFieldName, xbFloat & fFieldValue ) const { - return GetFloatField( GetFieldNo(sFieldName ), fFieldValue ); -} - -/************************************************************************/ -//! @brief Get logical field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param sFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetLogicalField( xbInt16 iFieldNo, xbString &sFieldValue ) const { - - char cFieldType; - xbInt16 iRc = GetFieldType( iFieldNo, cFieldType ); - if( iRc < 0 ) - return iRc; - else if( cFieldType != 'L' ) - return XB_INVALID_FIELD_TYPE; - - if(( iRc = GetField( iFieldNo, sFieldValue )) < XB_NO_ERROR ) - return iRc; - else - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Get logical field for field name. -/*! - \param sFieldName Name of field to retrieve. - \param sFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetLogicalField( const xbString &sFieldName, xbString &sFieldValue ) const { - return GetLogicalField( GetFieldNo( sFieldName ), sFieldValue ); -} - - -/************************************************************************/ -//! @brief Get logical field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param bFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetLogicalField( xbInt16 iFieldNo, xbBool &bFieldValue ) const { - return GetLogicalField( iFieldNo, bFieldValue, 0 ); -} - -/************************************************************************/ -//! @brief Get logical field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param bFieldValue Output field value. - \param iRecBufSw 0 - Record buffer with any updates.<br>1 - Record buffer with original data. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetLogicalField( xbInt16 iFieldNo, xbBool &bFieldValue, xbInt16 iRecBufSw ) const { - - char cFieldType; - xbInt16 iRc = GetFieldType( iFieldNo, cFieldType ); - if((iRc = GetFieldType( iFieldNo, cFieldType )) != XB_NO_ERROR ) - return iRc; - - if( cFieldType != 'L' ) - return XB_INVALID_FIELD_TYPE; - - xbString sFieldValue; - if(( iRc = GetField( iFieldNo, sFieldValue, iRecBufSw )) < XB_NO_ERROR ) - return iRc; - - if( sFieldValue == 'T' || sFieldValue == 't' || sFieldValue == 'Y' || sFieldValue == 'y' ) - bFieldValue = xbTrue; - else - bFieldValue = xbFalse; - - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Get logical field for field name. -/*! - \param sFieldName Name of field to retrieve. - \param bFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetLogicalField( const xbString &sFieldName, xbBool &bFieldValue ) const { - return GetLogicalField( GetFieldNo( sFieldName ), bFieldValue ); -} -/************************************************************************/ -//! @brief Get long field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param lFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetLongField( xbInt16 iFieldNo, xbInt32 & lFieldValue ) const { - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - char cFieldType; - xbString sTemp; - - try{ - - if(( iRc = GetFieldType( iFieldNo, cFieldType )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - if( cFieldType != 'N' && cFieldType != 'F' && cFieldType != 'M' ){ - iErrorStop = 110; - iRc = XB_INVALID_FIELD_TYPE; - throw iRc; - } - - if(( iRc = GetField( iFieldNo, sTemp, 0 )) < 0 ){ - iErrorStop = 120; - throw iRc; - } - sTemp.Trim(); - - if( !sTemp.ValidNumericValue() ){ - iErrorStop = 130; - iRc = XB_INVALID_DATA; - throw iRc; - } - - if( sTemp.Pos( '.' ) > 0){ - iErrorStop = 140; - iRc = XB_INVALID_DATA; - throw iRc; - } - - lFieldValue = atol( sTemp.Str()); - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbDbf::GetLongField() Exception Caught. Error Stop = [%d] rc = [%d] [%s]", iErrorStop, iRc, sTemp.Str() ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - return XB_NO_ERROR; -} - -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT -//! @brief Get memo field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param sMemoValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetMemoField( xbInt16 iFieldNo, xbString &sMemoValue ){ - return Memo->GetMemoField( iFieldNo, sMemoValue ); -} -/************************************************************************/ -//! @brief Get memo field for field name. -/*! - - \param sFieldName Name of field to retrieve. - \param sMemoValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetMemoField( const xbString & sFieldName, xbString & sMemoValue ){ - return Memo->GetMemoField( GetFieldNo( sFieldName ), sMemoValue ); -} - -/************************************************************************/ -//! @brief Get the memo field count for this table. -/*! - \returns Returns the number of memo fields in the table, -*/ -xbInt16 xbDbf::GetMemoFieldCnt() const { - return iMemoFieldCnt; -} -/************************************************************************/ -//! @brief Get memo field length for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param ulMemoFieldLen Output memo field value length. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetMemoFieldLen( xbInt16 iFieldNo, xbUInt32 & ulMemoFieldLen ){ - return Memo->GetMemoFieldLen( iFieldNo, ulMemoFieldLen ); -} -/************************************************************************/ -//! @brief Get memo field length for field name. -/*! - \param sFieldName Name of field to retrieve. - \param ulMemoFieldLen Output memo field value length. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetMemoFieldLen( const xbString &sFieldName, xbUInt32 &ulMemoFieldLen ){ - return Memo->GetMemoFieldLen( GetFieldNo( sFieldName ), ulMemoFieldLen ); -} - -#endif // XB_MEMO_SUPPORT - -/************************************************************************/ -//! @brief Get field null status -/*! - \param iFieldNo Number of field to retrieve. - \param bIsNull Output field value. If field is all spaces on record buffer, returns true. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetNullSts( xbInt16 iFieldNo, xbBool &bIsNull ) const { - return GetNullSts( iFieldNo, bIsNull, 0 ); -} - -/************************************************************************/ -//! @brief Get field null status -/*! - \param iFieldName Field Name of field to retrieve. - \param bIsNull Output field value. If field is all spaces on record buffer, returns true. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetNullSts( const xbString &sFieldName, xbBool &bIsNull ) const { - return GetNullSts( GetFieldNo( sFieldName ), bIsNull, 0 ); -} - -/************************************************************************/ -//! @brief Get field null status -/*! - \param iFieldNo Number of field to retrieve. - \param bIsNull Output field value. If field is all spaces on record buffer, returns true. - \param iRecBufSw 0 - Record buffer with any updates.<br>1 - Record buffer with original data. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetNullSts( xbInt16 iFieldNo, xbBool &bIsNull, xbInt16 iRecBufSw ) const -{ - if( iFieldNo < 0 || iFieldNo >= iNoOfFields ) { - return XB_INVALID_FIELD_NO; - } - bIsNull = xbTrue; - char *p; - if( iRecBufSw ) - p = (char *) SchemaPtr[iFieldNo].pAddress2; - else - p = (char *) SchemaPtr[iFieldNo].pAddress; - - xbUInt32 ulLen = SchemaPtr[iFieldNo].cFieldLen; - xbUInt32 ul = 0; - - while( ul < ulLen && bIsNull ){ - if( *p++ != ' ' ) - bIsNull = xbFalse; - else - ul++; - } - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Get unsigned long field for field number. -/*! - \param iFieldNo Number of field to retrieve. - \param ulFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::GetULongField( xbInt16 iFieldNo, xbUInt32 & ulFieldValue ) const { - - xbInt16 rc = 0; - xbInt16 iErrorStop = 0; - char cFieldType; - - try{ - - if(( rc = GetFieldType( iFieldNo, cFieldType )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - if( cFieldType != 'N' && cFieldType != 'F' && cFieldType != 'M' ){ - iErrorStop = 110; - rc = XB_INVALID_FIELD_TYPE; - throw rc; - } - xbString sTemp; - if(( rc = GetField( iFieldNo, sTemp, 0 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - sTemp.Trim(); - if( !sTemp.ValidNumericValue() || ((int) sTemp.Pos( '.' ) > 0)){ - iErrorStop = 130; - rc = XB_INVALID_DATA; - throw rc; - } - ulFieldValue = strtoul( sTemp.Str(), NULL, 10 ); - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbDbf::GetULongField() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Get long field for field name. -/*! - \param sFieldName Number of field to retrieve. - \param lFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetLongField( const xbString &sFieldName, xbInt32 &lFieldValue ) const { - return GetLongField( GetFieldNo( sFieldName ), lFieldValue ); -} - -/************************************************************************/ -//! @brief Get unsigned long field for field name. -/*! - \param sFieldName Number of field to retrieve. - \param ulFieldValue Output field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::GetULongField( const xbString &sFieldName, xbUInt32 &ulFieldValue ) const { - return GetULongField( GetFieldNo( sFieldName ), ulFieldValue ); -} - -/************************************************************************/ -//! @brief Get raw field data for field number. -/*! - - This is a protected method, used by other methods. This method would be - subject to buffer overflows if made public. - - \param iFieldNo Number of field to retrieve. - \param cBuf Pointer to buffer area provided by calling application program. - \param ulBufSize Size of data to copy - \param iRecBufSw 0 - Record buffer with any updates.<br>1 - Record buffer with original data. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - - -xbInt16 xbDbf::GetRawField( xbInt16 iFieldNo, char *cBuf, xbUInt32 ulBufSize, xbInt16 iRecBufSw ) const -{ - if( iFieldNo < 0 || iFieldNo >= iNoOfFields ) { - return XB_INVALID_FIELD_NO; - } - - size_t stCopySize; - if( ulBufSize > (size_t) (SchemaPtr[iFieldNo].cFieldLen )) - stCopySize = (size_t) (SchemaPtr[iFieldNo].cFieldLen ); - else - stCopySize = ulBufSize - 1; - - if( iRecBufSw ) - memcpy( cBuf, SchemaPtr[iFieldNo].pAddress2, stCopySize ); - else - memcpy( cBuf, SchemaPtr[iFieldNo].pAddress, stCopySize ); - - cBuf[stCopySize] = 0x00; - return XB_NO_ERROR; -} - - -/************************************************************************/ -//! @brief Put double field for field name. -/*! - \param sFieldName Name of field to update. - \param dFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::PutDoubleField( const xbString &sFieldName, xbDouble dFieldValue ){ - return PutDoubleField( GetFieldNo( sFieldName ), dFieldValue ); -} - -/************************************************************************/ -//! @brief Put double field for field number. -/*! - \param iFieldNo Number of field to update. - \param dFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutDoubleField( xbInt16 iFieldNo, xbDouble dFieldValue ){ - - xbInt16 rc; - xbString sDoubleFmt; - xbString sDoubleFmt2; - xbString sDoubleVal; - xbInt16 iFieldLen; - xbInt16 iNoOfDecs; - - if(( rc = GetFieldDecimal( iFieldNo, iNoOfDecs )) != XB_NO_ERROR ) - return rc; - - if(( rc = GetFieldLen( iFieldNo, iFieldLen )) != XB_NO_ERROR ) - return rc; - - sDoubleFmt.Sprintf( "%d.%df", iFieldLen, iNoOfDecs ); - sDoubleFmt2 = "%-"; - sDoubleFmt2 += sDoubleFmt; - sDoubleVal.Sprintf( sDoubleFmt2.Str(), dFieldValue ); - sDoubleVal.Rtrim(); - return PutField( iFieldNo, sDoubleVal ); -} - -/************************************************************************/ -//! @brief Put date field for field name. -/*! - \param sFieldName Name of field to update. - \param dtFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutDateField(const xbString &sFieldName, const xbDate &dtFieldValue ){ - return PutField( GetFieldNo( sFieldName ), dtFieldValue.Str() ); -} - -/************************************************************************/ -//! @brief Put date field for field number. -/*! - \param iFieldNo Number of field to update. - \param dtFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::PutDateField( xbInt16 iFieldNo, const xbDate &dtFieldValue ){ - return PutField( iFieldNo, dtFieldValue.Str() ); -} - -/************************************************************************/ -//! @brief Put field for field name. -/*! - \param sFieldName Name of field to update. - \param sFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::PutField(const xbString &sFieldName, const xbString &sFieldValue ) { - return PutField( GetFieldNo( sFieldName ), sFieldValue ); -} -/************************************************************************/ -//! @brief Put field for field number. -/*! - \param iFieldNo Number of field to update. - \param sFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutField( xbInt16 iFieldNo, const xbString &sFieldValue ) { - xbInt16 iLen; - xbInt16 iDecPos; /* Decimal Position */ - char * startpos; - char * tp; /* Target Pointer */ - - if( iFieldNo < 0 || iFieldNo >= iNoOfFields ) - return XB_INVALID_FIELD_NO; - - if( SchemaPtr[iFieldNo].cType == 'L' && !sFieldValue.ValidLogicalValue()) - return XB_INVALID_DATA; - - else if( SchemaPtr[iFieldNo].cType == 'D' ){ - xbDate d; - if( !d.DateIsValid( sFieldValue )) - return XB_INVALID_DATA; - iLen = 8; - } - else - { - iLen = (xbInt16) sFieldValue.Len(); - if( SchemaPtr[iFieldNo].cType == 'F' || SchemaPtr[iFieldNo].cType == 'N' || SchemaPtr[iFieldNo].cType == 'M' ){ - if( !sFieldValue.ValidNumericValue()) { - return XB_INVALID_DATA; - } - else { - iDecPos = (xbInt16) sFieldValue.Pos( "." ); // 0 is no decimal - int mlod; // max no of digits left of decimal point digit count - - - if( SchemaPtr[iFieldNo].cNoOfDecs > 0 ) - mlod = SchemaPtr[iFieldNo].cFieldLen - SchemaPtr[iFieldNo].cNoOfDecs - 1; - else - mlod = iLen; - - if( iDecPos == 0 ){ // no decimal in incoming data - - // check digits to the left of the decimal - if( SchemaPtr[iFieldNo].cNoOfDecs > 0 && iLen > mlod ) /* no decimal in incoming data */ - return XB_INVALID_DATA; - - else if( SchemaPtr[iFieldNo].cNoOfDecs == 0 && iLen > SchemaPtr[iFieldNo].cFieldLen ) - return XB_INVALID_DATA; - - } - else // decimal in incoming data - { - if( (iDecPos-1) > mlod ) // too many digits to the left of dec in incoming data - return XB_INVALID_DATA; - - // check digits to the right of the decimal - else if((iLen - iDecPos) > SchemaPtr[iFieldNo].cNoOfDecs ) - return XB_INVALID_DATA; - } - } - } - } - - // do all field edits before this point - if( iDbfStatus != XB_UPDATED ){ - iDbfStatus = XB_UPDATED; - memcpy( RecBuf2, RecBuf, uiRecordLen ); // save the original record bufer before making updates - } - - memset( SchemaPtr[iFieldNo].pAddress, 0x20, SchemaPtr[iFieldNo].cFieldLen ); - - if( iLen > SchemaPtr[iFieldNo].cFieldLen ) - iLen = SchemaPtr[iFieldNo].cFieldLen; - - if( SchemaPtr[iFieldNo].cType == 'F' || SchemaPtr[iFieldNo].cType == 'N' - || SchemaPtr[iFieldNo].cType == 'M') { - - xbInt16 iDecPos = (xbInt16) sFieldValue.Pos( "." ); - if( iDecPos == 0 ){ - iLen = (xbInt16) sFieldValue.Len(); - iDecPos = 0; - } - else{ - iLen = iDecPos - 1; - } - - if( SchemaPtr[iFieldNo].cNoOfDecs > 0 ){ - tp = SchemaPtr[iFieldNo].pAddress; - tp += SchemaPtr[iFieldNo].cFieldLen - SchemaPtr[iFieldNo].cNoOfDecs - 1; - *tp++ = '.'; - - if( iDecPos == 0 ){ - for( xbInt32 i = 0; i < SchemaPtr[iFieldNo].cNoOfDecs; i++ ) - *tp++ = '0'; - } else { - xbInt32 j = iDecPos + 1; - for( xbInt32 i = 0; i < SchemaPtr[iFieldNo].cNoOfDecs; i++, j++ ){ - if( j <= (xbInt32) sFieldValue.Len()) - *tp++ = sFieldValue[j]; - else - *tp++ = '0'; - } - } - startpos= SchemaPtr[iFieldNo].pAddress + - SchemaPtr[iFieldNo].cFieldLen - - SchemaPtr[iFieldNo].cNoOfDecs - iLen - 1; - - } - else - startpos=SchemaPtr[iFieldNo].pAddress+SchemaPtr[iFieldNo].cFieldLen-iLen; - } - else - startpos = SchemaPtr[iFieldNo].pAddress; - - memcpy( startpos, sFieldValue.Str(), (size_t) iLen ); - return 0; -} - -/************************************************************************/ -//! @brief Put float field for field number. -/*! - \param iFieldNo Number of field to update. - \param fFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::PutFloatField( xbInt16 iFieldNo, xbFloat fFieldValue ){ - - xbInt16 rc; - xbString sFloatFmt; - xbString sFloatFmt2; - xbString sFloatVal; - xbInt16 iFieldLen; - xbInt16 iNoOfDecs; - - if(( rc = GetFieldDecimal( iFieldNo, iNoOfDecs )) != XB_NO_ERROR ) - return rc; - - if(( rc = GetFieldLen( iFieldNo, iFieldLen )) != XB_NO_ERROR ) - return rc; - - sFloatFmt.Sprintf( "%d.%df", iFieldLen, iNoOfDecs ); - sFloatFmt2 = "%-"; - sFloatFmt2 += sFloatFmt; - sFloatVal.Sprintf( sFloatFmt2.Str(), fFieldValue ); - sFloatVal.Rtrim(); - return PutField( iFieldNo, sFloatVal ); -} - -/************************************************************************/ -//! @brief Put float field for field name. -/*! - \param sFieldName Name of field to update. - \param fFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutFloatField( const xbString &sFieldName, xbFloat fFieldValue ){ - return PutFloatField( GetFieldNo( sFieldName ), fFieldValue ); -} - -/************************************************************************/ -//! @brief Put logical field for field number. -/*! - \param iFieldNo Number of field to update. - \param sFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutLogicalField( xbInt16 iFieldNo, const xbString &sFieldValue ) { - return PutField( iFieldNo, sFieldValue ); -} - -/************************************************************************/ -//! @brief Put logical field for field name. -/*! - \param sFieldName Name of field to update. - \param sFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::PutLogicalField( const xbString &sFieldName, const xbString &sFieldValue ) { - return PutField( GetFieldNo( sFieldName ), sFieldValue ); -} - -/************************************************************************/ -//! @brief Put logical field for field number. -/*! - \param iFieldNo Number of field to update. - \param bFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutLogicalField( xbInt16 iFieldNo, xbBool bFieldValue ) { - - if( bFieldValue ) - return PutField( iFieldNo, "T" ); - else - return PutField( iFieldNo, "F" ); -} - -/************************************************************************/ -//! @brief Put logical field for field name. -/*! - \param sFieldName Name of field to update. - \param bFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ -xbInt16 xbDbf::PutLogicalField( const xbString &sFieldName, xbBool bFieldValue ) { - return PutLogicalField( GetFieldNo( sFieldName ), bFieldValue ); -} - -/************************************************************************/ -//! @brief Put long field for field number. -/*! - \param iFieldNo Number of field to update. - \param lFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutLongField( xbInt16 iFieldNo, xbInt32 lFieldValue ) { - xbString sLong; - sLong.Sprintf( "%ld", (xbInt32) lFieldValue ); - return PutField( iFieldNo, sLong.Str() ); -} - -/************************************************************************/ -//! @brief Put long field for field name. -/*! - \param sFieldName Name of field to update. - \param lFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutLongField( const xbString &sFieldName, xbInt32 lFieldValue ) { - return PutLongField( GetFieldNo( sFieldName ), lFieldValue ); -} - -/************************************************************************/ -//! @brief Put unsigned long field for field number. -/*! - \param iFieldNo Number of field to update. - \param ulFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutULongField( xbInt16 iFieldNo, xbUInt32 ulFieldValue ) { - xbString sLong; - sLong.Sprintf( "%lu", (xbInt32) ulFieldValue ); - return PutField( iFieldNo, sLong.Str() ); -} - -/************************************************************************/ -//! @brief Put unsigned long field for field name. -/*! - \param sFieldName Name of field to update. - \param ulFieldValue Field value. - \returns The field routines return one of:<br> - XB_NO_ERROR<br>XB_INVALID_DATA<br>XB_INVALID_FIELD_NO<br>XB_INVALID_FIELD_NAME<br> - XB_INVALID_FIELD_TYPE<br>XB_INVALID_DATA -*/ - -xbInt16 xbDbf::PutULongField( const xbString &sFieldName, xbUInt32 ulFieldValue ) { - return PutLongField( GetFieldNo( sFieldName ), (xbInt32) ulFieldValue ); -} - -/************************************************************************/ -#ifdef XB_MEMO_SUPPORT -//! @brief Check if memo field exists for field name. -/*! - \param sFieldName Name of field to check. - \returns xbTrue Field exists.<br> xbFale Field does not exist. -*/ - -xbBool xbDbf::MemoFieldExists( const xbString &sFieldName ) const{ - return MemoFieldExists( GetFieldNo( sFieldName )); -} - -/************************************************************************/ -//! @brief Check if memo field exists for field number. -/*! - \param iFieldNo Number of field to check. - \returns xbTrue Field exists.<br> xbFale Field does not exist. -*/ - -xbBool xbDbf::MemoFieldExists( xbInt16 iFieldNo ) const{ - - xbInt32 lFld = 0L; - GetLongField( iFieldNo, lFld ); - if( lFld == 0L ) - return xbFalse; - else - return xbTrue; -} - -#endif - -} /* namespace */ - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfile.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbfile.cpp deleted file mode 100755 index 6376e9a..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfile.cpp +++ /dev/null @@ -1,2217 +0,0 @@ -/* xbfile.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 all the low level file I/O and is the base class -for the table, memo and index classes - -*/ - -#include "xbase.h" - -namespace xb{ - -/************************************************************************/ -//! @brief Class Constructor. -xbFile::xbFile( xbXBase * x ){ - fp = NULL; - bFileOpen = xbFalse; - ulBlockSize = 0; - iFileNo = 0; - xbase = x; - if( GetMultiUser() == xbTrue ) - iShareMode = XB_MULTI_USER; - else - iShareMode = XB_SINGLE_USER; - iOpenMode = 0; - #ifdef XB_LOCKING_SUPPORT - iLockRetries = -1; - #endif - #ifdef HAVE_SETENDOFFILE_F - fHandle = NULL; - #endif -} - -/************************************************************************/ -//! @brief Class Destructor. -xbFile::~xbFile(){ - if( bFileOpen ) - xbFclose(); -} - -/************************************************************************/ -//! @brief Create a unique file name. -/*! - Given a directory and file extension as inputs, create a unique file name. - - \param sDirIn Directory - \param sExtIn File Extension - \param sFqnOut A fully qualifed unique file name as output - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -/* -xbInt16 xbFile::CreateUniqueFileName( const xbString & sDirIn, const xbString & sExtIn, xbString &sFqnOut ){ - return CreateUniqueFileName( sDirIn, sExtIn, sFqnOut, 0 ); -} -*/ -/************************************************************************/ -//! @brief Create a unique file name. -/*! - Given a directory and file extension as inputs, create a unique file name. - - \param sDirIn Directory - \param sExtIn File Extension - \param iOption 0 - look only for one file for a given directory and extension<br> - 1 - if file name extension is "dbf" or "DBF", verify unique dbt or DBT (memo) file is also available<br> - \param sFqnOut A fully qualifed unique file name as output - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::CreateUniqueFileName( const xbString & sDirIn, const xbString & sExtIn, xbString &sFqnOut, xbInt16 iOption ){ - - xbBool bUniqueFileNameFound = xbFalse; - xbFile f( xbase); - xbInt32 l = 1; - xbString sMemoFileName; - - xbString sDir = sDirIn; - char c = GetPathSeparator(); - if( sDirIn.Len() > 0 && sDirIn[sDirIn.Len()] != c ) - sDir += c; - - while( !bUniqueFileNameFound ){ - sFqnOut.Sprintf( "%sxbTmp%03d.%s", sDir.Str(), l, sExtIn.Str()); - if( iOption == 1 && sExtIn == "DBF" ){ - sMemoFileName.Sprintf( "%sxbTmp%03d.DBT", sDirIn.Str(), l ); - } - else if( iOption == 1 && sExtIn == "dbf" ){ - sMemoFileName.Sprintf( "%sxbTmp%03d.dbt", sDirIn.Str(), l ); - } - if( f.FileExists( sFqnOut ) || ( sMemoFileName.Len() > 0 && f.FileExists( sMemoFileName ))){ - l++; - } - else - { - bUniqueFileNameFound = xbTrue; - } - if( l > 999 ) - return XB_FILE_EXISTS; - } - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Determine which version the memo (dbt) file is. -/*! - - This routine uses the first byte in the dbf file to determine which memo - file version is in use. The main difference between version 3 and 4 is that - version 4 will reuse blocks if they become available. Version 3 does not. - - \param cFileTypeByte is an output field and is one of:<br> - <br> - 0 - none<br> - 3 - Dbase III+<br> - 4 - Dbase IV<br> - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::DetermineXbaseMemoVersion( unsigned char cFileTypeByte ) const { - - - if( BitSet( cFileTypeByte, 3 ) && BitSet( cFileTypeByte, 7 )) - return 4; - else if( BitSet( cFileTypeByte, 7 )) - return 3; - - return 0; -} -/*************************************************************************/ -//! @brief Determine xbase dbf version. -/*! - - This routine is used to determine which version of the Xbase classes can - be used for a given DBF file.<br> - - It attempts to use the highest version compiled into the library.<br> - - References:<br> - This routine uses the first byte from the dbf file.<br> - Per DBase documentation:<br> - Valid dBASE for Windows table file, bits 0-2 indicate version number: 3 for dBASE Level 5, 4 for dBASE Level 7.<br> - Bit 3 and bit 7 indicate presence of a dBASE IV or dBASE for Windows memo file;<br> - Bits 4-6 indicate the presence of a dBASE IV SQL table;<br> - Bit 7 indicates the presence of any .DBT memo file (either a dBASE III PLUS type or a dBASE IV or dBASE for Windows memo file).<br> -<br> - Bachmann spec (used extensively in library build), page 7 - does not match DBase documentation<br> -<br> - returns<br> - 0 - unknown<br> - 3 - Dbase level 3<br> - 4 - Dbase level 4<br> - 5 - Dbase Level 5 (future)<br> - 7 - Dbase Level 7 (future)<br> -<br> - 1x - Clipper files (future)<br> - 2x - Foxbase files (future)<br> -<br> -*/ - -xbInt16 xbFile::DetermineXbaseTableVersion( unsigned char cFileTypeByte ) const { - - xbInt16 iMemoVersion = DetermineXbaseMemoVersion(cFileTypeByte); - char cDbfLevel = cFileTypeByte & 0x07; - - #ifdef XB_DBF4_SUPPORT - if( cDbfLevel == 3 && iMemoVersion != 3 ) - return 4; - #endif - - #ifdef XB_DBF3_SUPPORT - if( cDbfLevel == 3 && iMemoVersion != 4 ) - return 3; - #endif - - return 0; -} - -/*************************************************************************/ -//! @brief Get a portable double value. -/*! - - This routine returns a double value from an 8 byte character stream, - accounting for endian type. - - Converts a double (64 bit floating point) value stored at p from a portable - format to the machine format. - - \param p pointer to memory containing the portable double value - - \returns the double value. -*/ - -xbDouble xbFile::eGetDouble( const char *p ) const { - xbDouble d; - const char *sp; - char *tp; - xbInt16 i; - - tp = (char *) &d; - sp = p; - if( iEndianType == 'L' ) - for( i = 0; i < 8; i++ ) *tp++ = *sp++; - else - { - sp+=7; - for( i = 0; i < 8; i++ ) *tp++ = *sp--; - } - - return d; -} - -/*************************************************************************/ -//! @brief Get a portable long value. - -/*! - This routine returns a long int value from a 4 byte character stream, - accounting for endian type. - - \param p pointer to memory containing the portable long value - - \returns the long value. -*/ - -xbInt32 xbFile::eGetInt32( const char *p ) const { - xbInt32 l; - char *tp; - xbInt16 i; - - tp = (char *) &l; - if( iEndianType == 'L' ) - for( i = 0; i < 4; i++ ) *tp++ = *p++; - else { - p+=3; - for( i = 0; i < 4; i++ ) *tp++ = *p--; - } - return l; - -} -/*************************************************************************/ -//! @brief Get a portable unsigned long value. - -/*! - This routine returns an unsigned long int value from a 4 byte character stream, - accounting for endian type. - - \param p pointer to memory containing the portable long value - - \returns the unsigned long value. -*/ - -xbUInt32 xbFile::eGetUInt32( const char *p ) const { - xbUInt32 ul; - xbInt16 i; - char *tp; - - tp = (char *) &ul; - if( iEndianType == 'L' ) - for( i = 0; i < 4; i++ ) *tp++ = *p++; - else{ - p+=3; - for( i = 0; i < 4; i++ ) *tp++ = *p--; - } - return ul; -} - -/*************************************************************************/ -//! @brief Get a portable short value. - -/*! - This routine returns a short int value from a 2 byte character stream, - accounting for endian type. - - \param p pointer to memory containing the portable long value - - \returns the short value. -*/ - -xbInt16 xbFile::eGetInt16(const char *p) const { - xbInt16 s, i; - char *tp; - tp = (char *) &s; - if( iEndianType == 'L' ) - for( i = 0; i < 2; i++ ) *tp++ = *p++; - else{ - p++; - for( i = 0; i < 2; i++ ) *tp++ = *p--; - } - return s; -} -/*************************************************************************/ -//! @brief Get a portable unsigned short value. - -/*! - This routine returns a short unsigned int value from a 2 byte character stream, - accounting for endian type. - - \param p pointer to memory containing the portable long value - - \returns the short value. -*/ - -xbUInt16 xbFile::eGetUInt16(const char *p) const { - xbInt16 i; - xbUInt16 uI; - char *tp; - - tp = (char *) &uI; - if( iEndianType == 'L' ) - for( i = 0; i < 2; i++ ) *tp++ = *p++; - else{ - p++; - for( i = 0; i < 2; i++ ) *tp++ = *p--; - } - return uI; -} - - -/*************************************************************************/ -//! @brief Write a portable double value to memory location. -/*! - Converts a double (64 bit floating point) value from machine format to a - portable format and stores the converted value in the memory referenced - by c. - - This routine puts a double value to an 8 byte character stream - - \param c Pointer to memory to hold converted value - \param d Input value to be converted -*/ - -void xbFile::ePutDouble( char *c, xbDouble d ){ - const char *sp; - char *tp; - xbInt16 i; - - tp = c; - sp = (const char *) &d; - if( iEndianType == 'L' ) - for( i = 0; i < 8; i++ ) *tp++ = *sp++; - else - { - sp+=7; - for( i = 0; i < 8; i++ ) *tp++ = *sp--; - } - return; -} - -/*************************************************************************/ -//! @brief Write a portable short value to memory location. -/*! - Converts a short (16 bit integer) value from machine format to a - portable format and stores the converted value in the memory referenced - by c. - - This routine puts a short value to a 2 byte character stream - - \param c Pointer to memory to hold converted value - \param s Input value to be converted -*/ - -void xbFile::ePutInt16( char * c, xbInt16 s ){ - const char *sp; - char *tp; - xbInt16 i; - - tp = c; - sp = (const char *) &s; - - if( iEndianType == 'L' ) - for( i = 0; i < 2; i++ ) *tp++ = *sp++; - else{ /* big endian */ - sp++; - for( i = 0; i < 2; i++ ) *tp++ = *sp--; - } - return; -} -/*************************************************************************/ -//! @brief Write a portable unsigned short value to memory location. -/*! - Converts an unsigned short (16 bit integer) value from machine format to a - portable format and stores the converted value in the memory referenced - by c. - - This routine puts an unsigned short value to a 2 byte character stream - - \param c Pointer to memory to hold converted value - \param s Input value to be converted -*/ - -void xbFile::ePutUInt16( char * c, xbUInt16 s ){ - const char *sp; - char *tp; - xbInt16 i; - - tp = c; - sp = (const char *) &s; - - if( iEndianType == 'L' ) - for( i = 0; i < 2; i++ ) *tp++ = *sp++; - else{ /* big endian */ - sp++; - for( i = 0; i < 2; i++ ) *tp++ = *sp--; - } - return; -} - -/*************************************************************************/ -//! @brief Write a portable long value to memory location. -/*! - Converts a long (32 bit integer) value from machine format to a - portable format and stores the converted value in the memory referenced - by c. - - This routine puts a long value to a 4 byte character stream. - - \param c Pointer to memory to hold converted value - \param l Input value to be converted -*/ - -void xbFile::ePutInt32( char * c, xbInt32 l ) -{ - const char *sp; - char *tp; - xbInt16 i; - - tp = c; - sp = (const char *) &l; - if( iEndianType == 'L' ) - for( i = 0; i < 4; i++ ) *tp++ = *sp++; - else { - sp+=3; - for( i = 0; i < 4; i++ ) *tp++ = *sp--; - } - return; -} - - -/*************************************************************************/ -//! @brief Write a portable unsigned long value to memory location. -/*! - Converts an unsigned long (32 bit integer) value from machine format to a - portable format and stores the converted value in the memory referenced - by c. - - This routine puts an unsigned long value to a 4 byte character stream. - - \param c Pointer to memory to hold converted value - \param ul Input value to be converted -*/ - -void xbFile::ePutUInt32( char * c, xbUInt32 ul ) -{ - const char *sp; - char *tp; - xbInt16 i; - - tp = c; - sp = (const char *) &ul; - if( iEndianType == 'L' ) - for( i = 0; i < 4; i++ ) *tp++ = *sp++; - else - { - sp+=3; - for( i = 0; i < 4; i++ ) *tp++ = *sp--; - } - return; -} - -/************************************************************************/ -//! @brief Determines if a file exists. -/*! - \returns xbTrue if file exists<br> - xbFalse if file does not exist - -*/ -xbBool xbFile::FileExists() const { - return FileExists( sFqFileName, 0 ); -} -/************************************************************************/ -//! @brief Determines if a file exists. -/*! - \param iOption if 1, assume this is a request for a dbf file and - check for the a dbt memo file also, returns true if both files are found - - \returns xbTrue if both files exist<br> - xbFalse if file does not exist - -*/ -xbBool xbFile::FileExists( xbInt16 iOption ) const { - return FileExists( sFqFileName, iOption ); -} - -/************************************************************************/ -//! @brief Determines if a file exists. -/*! - \param sFileName - file name to check for - - \returns xbTrue if file exists<br> - xbFalse if file does not exist -*/ - -xbBool xbFile::FileExists(const xbString &sFileName ) const { - return FileExists( sFileName, 0 ); -} - -/************************************************************************/ -//! @brief Determines if a file exists. -/*! - \param sFileName - file name to check for - \param iOption if 1, assume this is a request for a dbf file and - check for the a dbt memo file also, returns true if both files are found - - \returns xbTrue if both dbf and dbt files exist<br> - xbFalse if file does not exist -*/ - -xbBool xbFile::FileExists( const xbString & sFileName, xbInt16 iOption ) const { - - struct stat buffer; - if(( stat( sFileName.Str(), &buffer ) != 0 )){ - return xbFalse; - } - - #ifdef XB_MEMO_SUPPORT - if( iOption == 1 ){ - xbString sFileName2 = sFileName; - - if( sFileName2[sFileName2.Len()] == 'F' ) - sFileName2.PutAt( sFileName2.Len(), 'T' ); - else - sFileName2.PutAt( sFileName2.Len(), 't' ); - - if(( stat( sFileName2.Str(), &buffer) != 0 )) - return xbFalse; - } - #endif - return xbTrue; -} - -/************************************************************************/ -//! @brief Determines if file is open. -/*! - - \returns xbTrue if file is open<br> - xbFalse if file is not open -*/ - -xbBool xbFile::FileIsOpen() const { - return bFileOpen; -} -/************************************************************************/ -//! @brief Get the block size. -/*! - \returns Block Size -*/ - -xbUInt32 xbFile::GetBlockSize() const { - return ulBlockSize; -} - -/************************************************************************/ -//! @brief Get the directory name. -/*! - \returns the directory name of the file -*/ - -const xbString & xbFile::GetDirectory() const { - return sDirectory; -} - -/************************************************************************/ -//! @brief Get the directory part of the file name. -/*! - \param sFileDirPartOut - the returned directory name - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::GetFileDirPart( xbString & sFileDirPartOut ) const { - return GetFileDirPart( sFqFileName, sFileDirPartOut ); -} - -/************************************************************************/ -//! @brief Get the directory part of the file name. -/*! - \param sCompleteFileNameIn - a fully qualfied input file name - \param sFileDirPartOut - the returned directory name part out of sCompleteFileNameIn - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbFile::GetFileDirPart( const xbString & sCompleteFileNameIn, xbString & sFileDirPartOut ) const { - - sFileDirPartOut = sCompleteFileNameIn; - sFileDirPartOut.SwapChars( '\\', '/' ); - xbUInt32 iPos = sFileDirPartOut.GetLastPos( '/' ); - - if( iPos > 0 ){ - xbString sTemp = sFileDirPartOut; - sFileDirPartOut.Assign( sTemp, 1, iPos ); - return XB_NO_ERROR; - } - return XB_INVALID_DATA; -} - -/************************************************************************/ -//! @brief Get the extension part of the file name. -/*! - \param sFileNameExtOut - the returned extension part out of sCompleteFileNameIn - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::GetFileExtPart( xbString & sFileNameExtOut ) const { - return GetFileExtPart( sFqFileName, sFileNameExtOut ); -} - -/************************************************************************/ -//! @brief Get the extension part of the file name. -/*! - \param sCompleteFileNameIn - a fully qualfied input file name - - \param sFileExtPartOut - the returned directory name part out of sCompleteFileNameIn - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbFile::GetFileExtPart( const xbString & sCompleteFileNameIn, xbString & sFileExtPartOut ) const { - - - sFileExtPartOut = sCompleteFileNameIn; - xbUInt32 iPos = sFileExtPartOut.GetLastPos( '.' ); - if( iPos > 0 ){ /* get rid of the directory part of the name */ - sFileExtPartOut.Ltrunc( iPos ); - return XB_NO_ERROR; - } - return XB_INVALID_DATA; -} -/************************************************************************/ -//! @brief Get the time of last file modification timestamp as reported by the OS. -/*! - \param mtime - returned time of last file modification - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::GetFileMtime( time_t &mtime ){ - - struct stat buffer; - if( stat( sFqFileName.Str(), &buffer )) - return XB_FILE_NOT_FOUND; - else{ - mtime = buffer.st_mtime; - return XB_NO_ERROR; - } -} -/************************************************************************/ -//! @brief Get the file name. -/*! - \returns the file name portion of the file -*/ - -const xbString & xbFile::GetFileName() const { - return sFileName; -} - - -/************************************************************************/ -//! @brief Get the name part of the file name. -/*! - \param sFileNamePartOut - the returned file name part out of sCompleteFileNameIn - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbFile::GetFileNamePart( xbString & sFileNamePartOut ) const { - return GetFileNamePart( sFqFileName, sFileNamePartOut ); -} - -/************************************************************************/ -//! @brief Get the name part of the file name. -/*! - \param sCompleteFileNameIn - a fully qualified input file name - \param sFileNamePartOut - the returned file name part out of sCompleteFileNameIn - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -//*********** fixme should this be static????? - -xbInt16 xbFile::GetFileNamePart( const xbString & sCompleteFileNameIn, xbString & sFileNamePartOut ) const { - /* extract the file name part out of the string */ - - sFileNamePartOut = sCompleteFileNameIn; - sFileNamePartOut.SwapChars( '\\', '/' ); - xbUInt32 iPos = sFileNamePartOut.GetLastPos( '/' ); - if( iPos > 0 ) /* get rid of the directory part of the name */ - sFileNamePartOut.Ltrunc( iPos ); - iPos = sFileNamePartOut.Pos( '.' ); - if( iPos > 0 ){ /* get rid of the extension part of the name */ - xbString sTemp = sFileNamePartOut; - sFileNamePartOut.Assign( sTemp, 1, iPos-1 ); - } - return XB_NO_ERROR; -} - - -/************************************************************************/ -//! @brief Get the size of the file as reported by the OS. -/*! - \param ullFileSize - unsigned long long field as output - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::GetFileSize( xbUInt64 &ullFileSize ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - - if(( iRc = xbFseek( 0, SEEK_END )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - ullFileSize = xbFtell(); - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::GetFileSize() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -//! @brief Get the file type aka Capitalized file extension -/*! - \param sFileTypeOut - the returned extension part out of sCompleteFileNameIn - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::GetFileType( xbString & sFileTypeOut ) const { - - xbInt16 iRc = GetFileExtPart( sFqFileName, sFileTypeOut ); - sFileTypeOut.ToUpperCase(); - return iRc; -} -/************************************************************************/ -//! @brief Get the fully qualified file name. -/*! - \returns the fully qualfied name of the file -*/ - -const xbString & xbFile::GetFqFileName() const { - return sFqFileName; -} - -/************************************************************************/ -//! @brief Get the open mode of the file. -/*! - \returns XB_READ<br> - XB_READ_WRITE<br> - XB_WRITE<BR> -*/ - -xbInt16 xbFile::GetOpenMode() const { - return iOpenMode; -} - -/************************************************************************/ -//! @brief Get the share mode of the file. -/*! - \returns XB_SINGLE_USER - (file buffering on><br> - XB_MULTI_USER - (file buffering off)<br> -*/ - -xbInt16 xbFile::GetShareMode() const { - return iShareMode; -} - -/************************************************************************/ -//! @brief Get the file type byte and version of the dbf file. -/*! - - Pull the first bye off the DBF file for further inspection. - First byte has various bits set to determine what the file format is. - - \param sFileName - Name of file to examine - \param iVersion - Returned file version - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::GetXbaseFileTypeByte( const xbString &sFileName, xbInt16 &iVersion ) -{ - unsigned char cFileTypeByte; - return GetXbaseFileTypeByte( sFileName, cFileTypeByte, iVersion ); -} - -/************************************************************************/ -//! @brief Get the file type byte and version of the dbf file. -/*! - Pull the first bye off the DBF file for further inspection. - First byte has various bits set to determine what the file format is. - - \param sFileName - Name of file to examine - \param cFileTypeByte - Retruned first byte of dbf file - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbFile::GetXbaseFileTypeByte( const xbString &sFileName, unsigned char &cFileTypeByte ) -{ - xbInt16 iVersion; - return GetXbaseFileTypeByte( sFileName, cFileTypeByte, iVersion ); -} - -/************************************************************************/ -//! @brief Get the file type byte and version of the dbf file. -/*! - Pull the first bye off the DBF file for further inspection. - First byte has various bits set to determine what the file format is. - - - \param sFileName - Name of file to examine - \param cFileTypeByte - Returned first byte of dbf file - \param iVersion - Returned file version - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::GetXbaseFileTypeByte( const xbString &sFileName, unsigned char &cFileTypeByte, xbInt16 &iVersion ){ - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - size_t stRc; - FILE *tfp; - - try{ - - iVersion = 0; - cFileTypeByte = 0x00; - #ifdef HAVE__FSOPEN_F - // 0x40 is SH_DENYNO or _SH_DENYNO - if(( tfp = _fsopen( sFileName.Str(), "r", 0x40 )) == NULL ){ - iErrorStop = 100; - iRc = XB_OPEN_ERROR; - throw iRc; - } - #else - if(( tfp = fopen( sFileName.Str(), "r" )) == NULL ){ - iErrorStop = 110; - iRc = XB_OPEN_ERROR; - throw iRc; - } - #endif - - #ifdef HAVE_FSEEKO_F - iRc = fseeko( tfp, 0, SEEK_SET ); - #else - iRc = fseek( tfp, 0, SEEK_SET ); - #endif - - if( iRc != 0 ){ - iErrorStop = 120; - iRc = XB_SEEK_ERROR; - throw iRc; - } - stRc = fread( &cFileTypeByte, (size_t) 1, (size_t) 1, tfp ); - if( stRc != (size_t) 1 ){ - iErrorStop = 130; - iRc = XB_READ_ERROR; - throw iRc; - } - iRc = XB_NO_ERROR; - fclose( tfp ); - iVersion = DetermineXbaseTableVersion( cFileTypeByte ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::GetXbaseFileType() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -//! @brief Determines status of file extension. -/*! - - \param sFileName - Name of file to examine - \param iOption - Inspection type<br> - 1 check for DBF<br> - 2 check for NDX<br> - 3 check for MDX<br> - 4 check for NTX<br> - - \returns 0 if suffix found<br> - 1 if suffix not found, lower case<br> - 2 is suffix not found, upper case<br> - -*/ - -xbInt16 xbFile::NameSuffixMissing( const xbString & sFileName, xbInt16 iOption ) const { - - xbUInt32 ulLen = sFileName.Len(); - if( ulLen <= 4 ){ - if( sFileName[ulLen] >= 'A' && sFileName[ulLen] <= 'Z' ) - return 2; - else - return 1; - } - if( iOption == 1 && sFileName[ulLen-3] == '.' && - ( sFileName[ulLen-2] == 'd' || sFileName[ulLen-2] == 'D' ) && - ( sFileName[ulLen-1] == 'b' || sFileName[ulLen-1] == 'B' ) && - ( sFileName[ulLen] == 'f' || sFileName[ulLen] == 'F' ) - ) - return 0; - if( iOption == 2 && sFileName[ulLen-3] == '.' && - ( sFileName[ulLen-2] == 'n' || sFileName[ulLen-2] == 'N' ) && - ( sFileName[ulLen-1] == 'd' || sFileName[ulLen-1] == 'D' ) && - ( sFileName[ulLen] == 'x' || sFileName[ulLen] == 'X' ) - ) - return 0; - if( iOption == 3 && sFileName[ulLen-3] == '.' && - ( sFileName[ulLen-2] == 'm' || sFileName[ulLen-2] == 'M' ) && - ( sFileName[ulLen-1] == 'd' || sFileName[ulLen-1] == 'D' ) && - ( sFileName[ulLen] == 'x' || sFileName[ulLen] == 'X' ) - ) - return 0; - if( iOption == 4 && sFileName[ulLen-3] == '.' && - ( sFileName[ulLen-2] == 'n' || sFileName[ulLen-2] == 'N' ) && - ( sFileName[ulLen-1] == 't' || sFileName[ulLen-1] == 'T' ) && - ( sFileName[ulLen] == 'x' || sFileName[ulLen] == 'X' ) - ) - return 0; - // next line might be problematic if file naem has mixed case and extension is missing - if( sFileName[ulLen-4] >= 'A' && sFileName[ulLen-4] <= 'Z' ) - return 2; - else - return 1; -} - -/***********************************************************************/ -//! @brief Read a block of data from file. -/*! - - \param ulBlockNo - block number to read - \param lReadSize - size of data to read at block location, set to 0 to read blocksize - \param *buf - pointer to buffer to write output data, assumed to be previosuly allocated - and large enough to contain data - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbFile::ReadBlock( xbUInt32 ulBlockNo, size_t lReadSize, void * buf ){ - return ReadBlock( ulBlockNo, ulBlockSize, lReadSize, buf ); -} - -/***********************************************************************/ -//! @brief Read a block of data from file. -/*! - - \param ulBlockNo - block number to read - \param ulBlockSize - block size - \param lReadSize - size of data to read at block location, set to 0 to read blocksize - \param buf - pointer to buffer to write output data, assumed to be previosuly allocated - and large enough to contain data - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbFile::ReadBlock( xbUInt32 ulBlockNo, xbUInt32 ulBlockSize, size_t lReadSize, void * buf ){ - - xbInt16 iErrorStop = 0; - xbInt16 iRc = XB_NO_ERROR; - - try{ - if( ulBlockSize <= 0 ){ - iErrorStop = 100; - iRc = XB_INVALID_BLOCK_SIZE; - throw iRc; - } - - if(( iRc = xbFseek(((xbInt64) ulBlockNo*ulBlockSize ), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 110; - iRc = XB_SEEK_ERROR; - throw iRc; - } - - if( lReadSize <= 0 ) - lReadSize = ulBlockSize; - - if(( iRc = xbFread( buf, lReadSize, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - iRc = XB_READ_ERROR; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::ReadBlock() Exception Caught. Error Stop = [%d] iRc = [%d] BlkNo=[%ld] BlkSize=[%ld] ReadSize=[%ld]", iErrorStop, iRc, ulBlockNo, ulBlockSize, lReadSize ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -//! @brief Set the block size. -/*! - - \param ulBlockSize - unsigned long block size, divisible by 512 - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::SetBlockSize( xbUInt32 ulBlockSize ){ - if( ulBlockSize %512 != 0 ) - return XB_INVALID_BLOCK_SIZE; - - this->ulBlockSize = ulBlockSize; - return XB_NO_ERROR; -} -/************************************************************************/ -//! @brief Set the directory. -/*! - \param sDirectory - Valid directory name -*/ - -void xbFile::SetDirectory( const xbString & sDirectory ){ - - this->sDirectory = sDirectory; - char cLastChar = sDirectory[sDirectory.Len()]; - if( cLastChar != '/' && cLastChar != '\\' ) - sFqFileName.Sprintf( "%s/%s", sDirectory.Str(), sFileName.Str()); - else - sFqFileName.Sprintf( "%s%s", sDirectory.Str(), sFileName.Str()); - - #ifdef WIN32 - sFqFileName.SwapChars( '/', '\\' ); - #else - sFqFileName.SwapChars( '\\', '/' ); - #endif -} - -/************************************************************************/ -//! @brief Set the filename. -/*! - This routine builds out two internal variables from the input file name<br> - sFileName - the file name part<br> - sFqFileName - the fully qualified file name<br> - - - \param sFileName - Input file name -*/ -void xbFile::SetFileName( const xbString & sFileName ){ - - if( sFileName == "" ){ - sFqFileName = ""; - return; - } - - char cPathSep = sFileName.GetPathSeparator(); - - if( cPathSep ){ - - xbString sName; - xbString sExt; - // GetFileDirPart( this->sDirectory ); - GetFileNamePart( sFileName, sName ); - GetFileExtPart( sFileName, sExt ); - this->sFileName.Sprintf( "%s.%s", sName.Str(), sExt.Str()); - sFqFileName = sFileName; - - } else { - - this->sFileName = sFileName; - if( sDirectory.Len() == 0 ){ - sDirectory = GetDataDirectory(); - char cLastChar = sDirectory[sDirectory.Len()]; - if( cLastChar != '/' && cLastChar != '\\' ) - sFqFileName.Sprintf( "%s/%s", sDirectory.Str(), sFileName.Str() ); - else - sFqFileName = sDirectory + sFileName; - } - else{ - char cLastChar = sDirectory[sDirectory.Len()]; - if( cLastChar != '/' && cLastChar != '\\' ) - sFqFileName.Sprintf( "%s/%s", sDirectory.Str(), sFileName.Str() ); - else - sFqFileName = sDirectory + sFileName; - } - } - - #ifdef WIN32 - sFqFileName.SwapChars( '/', '\\' ); - #else - sFqFileName.SwapChars( '\\', '/' ); - #endif -} - -/************************************************************************/ -//! @brief Set the fully qualifed filename. -/*! - \param sFqFileName - Fully qualifed input file name -*/ - -void xbFile::SetFqFileName( const xbString & sFqFileName ){ - this->sFqFileName = sFqFileName; - - xbString sDir; - xbString sName; - xbString sExt; - - GetFileDirPart ( sFqFileName, sDir ); - GetFileNamePart( sFqFileName, sName ); - GetFileExtPart ( sFqFileName, sExt ); - - sDirectory = sDir; - sFileName.Sprintf( "%s.%s", sName.Str(), sExt.Str() ); - - #ifdef WIN32 - this->sDirectory.SwapChars ( '/', '\\' ); - this->sFqFileName.SwapChars( '/', '\\' ); - #else - this->sDirectory.SwapChars ( '\\', '/' ); - this->sFqFileName.SwapChars( '\\', '/' ); - #endif -} - -/************************************************************************/ -//! @brief Set Home Folders. -/*! - Create xbase64 log, data and temp 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 cPathSeparator; - 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 - cPathSeparator = '\\'; - #else - cPathSeparator = '/'; - #endif - sDflt.Sprintf( ".%c", cPathSeparator ); - // 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()] != cPathSeparator ) - sHomeDir += cPathSeparator; - - 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(), cPathSeparator ); - // 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(), cPathSeparator ); - // 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 - } - - sWork.Sprintf( "%sxbase64%ctemp%c", sHomeDir.Str(), cPathSeparator, cPathSeparator ); - // std::cout << "tempdir = " << sWork.Str() << "\n"; - if( FileExists( sWork ) == xbFalse ){ - #ifdef WIN32 - if( CreateDirectory( sWork.Str(), NULL ) == 0 ){ - iErrorStop = 150; - iRc = XB_DIRECTORY_ERROR; - throw iRc; - } - #else - if( mkdir( sWork.Str(), 0777 ) == -1 ){ - iErrorStop = 160; - iRc = XB_DIRECTORY_ERROR; - throw iRc; - } - #endif - } - xbase->SetTempDirectory( 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 Write a block of data to file. -/*! - - \param ulBlockNo - block number to write - \param lWriteSize - size of data to write, set to 0 to write blocksize - \param *buf - pointer to buffer of data to be written - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbFile::WriteBlock( xbUInt32 ulBlockNo, size_t lWriteSize, void * buf ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - - if( ulBlockSize == 0 ){ - iErrorStop = 100; - iRc = XB_INVALID_BLOCK_SIZE; - throw iRc; - } - if( lWriteSize <= 0 ) - lWriteSize = ulBlockSize; - if(( iRc = xbFseek(( (xbInt64) ulBlockNo*ulBlockSize), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if(( iRc = xbFwrite( buf, lWriteSize, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::WriteBlock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fclose. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFclose(){ - - int iRc = 0; - if( bFileOpen ){ - iRc = fclose( fp ); - if( iRc != 0 ){ - return XB_CLOSE_ERROR; - } - else{ - bFileOpen = xbFalse; - } - iFileNo = 0; - } - return XB_NO_ERROR; -} - - - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary feof. -/*! - \returns non zero if end-of-file is set for the stream. -*/ -xbInt16 xbFile::xbFeof(){ - return feof( fp ); -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fflush. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFflush() { - - if( fflush( fp ) ) - return XB_WRITE_ERROR; - else - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fgetc. -/*! - \param c - output integer returned by fgetc - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFgetc( xbInt32 &c ) { - - int i; - - i = fgetc( fp ); - if( i == EOF ) - return XB_EOF; - - c = i; - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fgetc. -/*! - \param c - output character returned by fgetc - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFgetc( char &c ) { - - int i; - i = fgetc( fp ); - if( i == EOF ) - return XB_EOF; - - c = (char) i; - return XB_NO_ERROR; -} -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fgets. -/*! - \param lSize - reads in at most, one character less than lSize - \param s - an xbString containing data returned by fseek - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFgets( size_t lSize, xbString &s ) { - - s = ""; - if( feof( fp )) - return XB_EOF; - - char *sBuf = (char *) malloc( lSize + 1 ); - - if( fgets( sBuf, (xbInt32) lSize, fp ) == NULL ){ - free( sBuf ); - return XB_EOF; - } - s.Set( sBuf ); - free( sBuf ); - return XB_NO_ERROR; -} -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fopen. -/*! - - This routine supports all the standard C library open modes. The Xbase routines only - use "r" and "r+b". - - \param sOpenMode - <table> - <tr><th>OpenMode<th>Description - <tr><td>r<td>Reading - <tr><td>r+<td>Reading and Writing - <tr><td>w<td>Open for writing. Truncate to zero bytes if it exists - <tr><td>w+<td>Open for reading and writing, truncate to zero bytes if it exists - <tr><td>a<td>Open for append - <tr><td>a+<td>Open for reading and writing (at end). - </table> - The mode can also include the letter "b" for binary ie; "r+b". The "b" is ignored on - POSIX compliant systems, but is included for cross platform compatibility. - \param sFileName File name to open - \param iShareMode - XB_SINGLE_USER<br> - XB_MULTI_USER<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFopen( const xbString &sOpenMode, const xbString &sFileName, xbInt16 iShareMode ) { - if( sFileName == "" || sFqFileName == "" ) - SetFileName( sFileName ); - return xbFopen( sOpenMode, iShareMode ); -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fopen. -/*! - - This routine supports all the standard C library open modes. The Xbase routines only - use "r" and "r+". - - - \param sOpenMode - <table> - <tr><th>OpenMode<th>Description - <tr><td>r<td>Reading - <tr><td>r+<td>Reading and Writing - <tr><td>w<td>Open for writing. Truncate to zero bytes if it exists - <tr><td>w+<td>Open for reading and writing, truncate to zero bytes if it exists - <tr><td>a<td>Open for append - <tr><td>a+<td>Open for reading and writing (at end). - </table> - The mode can also include the letter "b" for binary ie; "r+b". The "b" is ignored on - POSIX compliant systems, but is included for cross platform compatibility. - \param iShareMode - XB_SINGLE_USER<br> - XB_MULTI_USER<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFopen( const xbString & sOpenMode, xbInt16 iShareMode ) { - - #ifdef HAVE__FSOPEN_F - if(( fp = _fsopen( sFqFileName.Str(), sOpenMode.Str(), 0x40 )) != NULL ){ - #else - if(( fp = fopen( sFqFileName.Str(), sOpenMode.Str())) != NULL ){ - #endif - - if( sOpenMode == "r" ) - iOpenMode = XB_READ; - else if( sOpenMode == "w" ) - iOpenMode = XB_WRITE; - else - iOpenMode = XB_READ_WRITE; - - bFileOpen = xbTrue; - this->iShareMode = iShareMode; - - #ifdef HAVE__FILENO_F - iFileNo = _fileno( fp ); - #else - iFileNo = fileno( fp ); - #endif - - #ifdef HAVE_SETENDOFFILE_F - //used by visual studio, 32 bit - fHandle = (HANDLE) _get_osfhandle( iFileNo ); - #endif - - #ifdef XB_LOCKING_SUPPORT - if( iShareMode ) - xbFTurnOffFileBuffering(); - #endif - - return XB_NO_ERROR; - } - else - return XB_OPEN_ERROR; -} -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fopen. -/*! - \param iOpenMode - XB_READ<br> - XB_READ_WRITE<br> - \param iShareMode - XB_SINGLE_USER<br> - XB_MULTI_USER<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFopen( xbInt16 iOpenMode, xbInt16 iShareMode ) { - this->iOpenMode = iOpenMode; - if( iOpenMode == XB_READ_WRITE ) - return xbFopen( "r+b", iShareMode ); - else if( iOpenMode == XB_READ ) - return xbFopen( "r", iShareMode ); - else - return XB_INVALID_OPTION; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fputc. -/*! - \param c Character to write - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbFile::xbFputc( xbInt32 c ) { - return xbFputc( c, 1 ); -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fputc. -/*! - \param c Character to write - \param iNoOfTimes Number of times to write the character - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbFile::xbFputc( xbInt32 c, xbInt32 iNoOfTimes ) { - - for( xbInt32 l = 0; l < iNoOfTimes; l++ ) - if( fputc( c, fp ) != (int) c ) - return XB_WRITE_ERROR; - - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fputs. -/*! - \param s xbString to write to file - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFputs( const xbString & s ){ - if( fputs( s.Str(), fp ) < 0 ) - return XB_WRITE_ERROR; - else - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fread. -/*! - \param p Pointer to data to write - \param size size of write - \param nmemb Number of times to read it - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFread( void *p, size_t size, size_t nmemb ) { - - size_t iRc; - iRc = fread( p, size, nmemb, fp ); - if( iRc == nmemb ) - return XB_NO_ERROR; - else - return XB_READ_ERROR; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fseek. -/*! - \param lOffset Position in file to seek to - \param iWhence SEEK_SET - from beginning of file<br> - SEEK_CUR - from current position<br> - SEEK_END - from end of file<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbFseek( xbInt64 lOffset, xbInt32 iWhence ) { - - xbInt32 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try { - - #if defined(HAVE_FSEEKO_F) - iRc = fseeko( fp, lOffset, iWhence ); - if( iRc != 0 ){ - iErrorStop = 100; - throw iRc; - } - - #elif defined(HAVE__FSEEKI64_F) - iRc = _fseeki64( fp, lOffset, iWhence ); - if( iRc != 0 ){ - iErrorStop = 110; - throw iRc; - } - #else - #ifdef XB_PLATFORM_32 - /* if request is larger than 2 gig,this is a part of a locking request, - assuming offset is less than 4 gig, split the request into 2 fseek calls */ - if( lOffset > 2147483647 && iWhence == SEEK_SET ){ - /* move forward max amt - 2G */ - if(( iRc = fseek( fp, 2147483647, SEEK_SET )) != 0 ){ - iErrorStop = 120; - throw iRc; - } - lOffset -= 2147483647; - iWhence = SEEK_CUR; - } - #endif - iRc = fseek( fp, (long) lOffset, iWhence ); - if( iRc != 0 ){ - iErrorStop = 310; - throw iRc; - } - #endif - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::xbFseek() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - iRc = XB_SEEK_ERROR; - } - return iRc; -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary ftell. -/*! - Returns the current file position. - \returns Current file position. -*/ - -size_t xbFile::xbFtell() { - return (size_t) ftell( fp ); -} - -/************************************************************************/ -//! @brief Turn off file buffering. -/*! - Turns off file buffering. File buffering can't be used while in multi user mode. - -*/ - -void xbFile::xbFTurnOffFileBuffering() { - setvbuf( fp, NULL, _IONBF, 0 ); -} - -/************************************************************************/ -//! @brief Xbase wrapper for standard libary fwrite. -/*! - \param p Pointer to data buffer to write - \param size Size of data to write - \param nmemb Number of times to write data buffer - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::xbFwrite( const void *p, size_t size, size_t nmemb ) { - - size_t iRc; - iRc = fwrite( p, size, nmemb, fp ); - if( iRc == nmemb ) - return XB_NO_ERROR; - else - return XB_READ_ERROR; -} - -/************************************************************************/ -//! @brief Read file until a particular character is encountered on input stream. -/*! - This routine will read until cDelim is encountered or eof, which ever occurs first. - - \param cDelim Delimiter to stop writing at. - \param sOut Output xbString containing data read - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbReadUntil( const char cDelim, xbString &sOut ){ - - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char c; - - try{ - sOut = ""; - if(( iRc = xbFgetc( c )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - sOut = c; - while( iRc == XB_NO_ERROR && c != cDelim ){ - if(( iRc = xbFgetc( c )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - sOut += c; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::xbReadUntil() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -//! @brief Delete file. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::xbRemove() { - return xbRemove( sFqFileName.Str(), 0 ); -} - -/************************************************************************/ -//! @brief Delete file. -/*! - \param sFileNameIn Name of file to delete - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbRemove( const xbString & sFileNameIn ) { - return xbRemove( sFileNameIn, 0 ); -} - - -/************************************************************************/ -//! @brief Delete file. -/*! - \param sFileNameIn Name of file to delete - \param iOption If Set to 1, assume this is a delete request for a dbf file, and should rename the dbt file also - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::xbRemove( const xbString & sFileNameIn, xbInt16 iOption ) { - - xbInt32 iRc = remove( sFileNameIn.Str()); - - if( iRc != 0 ) - return XB_DELETE_FAILED; - - if( iOption == 1 ){ - xbString sFileName2 = sFileNameIn; - - if( sFileName2[sFileName2.Len()] == 'F' ) - sFileName2.PutAt( sFileName2.Len(), 'T' ); - else - sFileName2.PutAt( sFileName2.Len(), 't' ); - - iRc = remove( sFileName2.Str()); - if( iRc != 0 ) - return XB_DELETE_FAILED; - } - - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Rename file. -/*! - \param sOldName Original file name - \param sNewName New file name - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbFile::xbRename( const xbString & sOldName, const xbString & sNewName ){ - if( rename( sOldName.Str(), sNewName.Str())) - return XB_RENAME_ERROR; - else - return XB_NO_ERROR; -} - -/************************************************************************/ -//! @brief Xbase wrapper for rewind. -/*! - Set file pointer at beginning of file. -*/ - -void xbFile::xbRewind() { - rewind( fp ); -} - -/************************************************************************/ -//! @brief Xbase wrapper for ftruncate. -/*! - Set file size to llSize - \param llSize New file size. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::xbTruncate( xbInt64 llSize ) { - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - try{ - #ifdef HAVE_FTRUNCATE_F - if(( iRc = ftruncate( iFileNo, llSize )) != 0 ){ - iErrorStop = 100; - iRc = XB_WRITE_ERROR; - throw iRc; - } - #elif defined(HAVE_SETENDOFFILE_F) - if(( iRc = xbFseek( llSize, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if(( iRc = SetEndOfFile( fHandle )) == 0 ){ - iErrorStop = 120; - iRc = XB_WRITE_ERROR; - throw iRc; - } else { - iRc = XB_NO_ERROR; - } - #else - - // check that cmake can find function SetEndOfFile - - // cmake could not find for Borland 5.5 - FATAL_COMPILE_ERROR - CANT_LOCATE_FUNCTION_ftruncate_or_SetEndOfFile - - #endif - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::xbTruncate() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ - -#ifdef XB_LOCKING_SUPPORT - -//! @brief Lock / unlock file. -/*! - \param iFunction XB_LOCK<br> - XB_UNLOCK<br> - \param lOffset Position in file to lock - \param stLen Length to lock - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::xbLock( xbInt16 iFunction, xbInt64 lOffset, size_t stLen ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbInt16 iTries = 0; - - try{ - #ifdef HAVE_FCNTL_F - /* Unix lock function */ - - if(( iRc = xbFseek( lOffset, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - struct flock fl; - switch( iFunction ){ - case( XB_LOCK ): - fl.l_type = F_WRLCK; - break; - case( XB_UNLOCK ): - fl.l_type = F_UNLCK; - break; - default: - iErrorStop = 110; - iRc = XB_INVALID_LOCK_OPTION; - throw iRc; - break; - } - fl.l_whence = SEEK_CUR; - fl.l_start = 0; - fl.l_len = (xbInt32) stLen; - do{ - iRc = fcntl( iFileNo, F_SETLK, &fl ); - if( iRc && (errno == EACCES || errno == EAGAIN )){ - iTries++; - xbase->xbSleep( GetDefaultLockWait() ); - } else if( iRc ){ - iErrorStop = 120; - iRc = XB_LOCK_FAILED; - throw iRc; - } - } while( iRc && iTries < GetLockRetryCount()); - if( iRc ) - iRc = XB_LOCK_FAILED; // lock failed, don't log an exception - - #elif defined(HAVE_LOCKFILE_F) - /* Windows 64 byte lock functions */ - /* split a quad word into two double words */ - typedef union{ - size_t Qword; - xbUInt32 Dword[2]; - } Qsplit; - - Qsplit lPos; - Qsplit lLen; - lPos.Qword = (size_t) lOffset; - lLen.Qword = stLen; - - do{ - if( iFunction == XB_LOCK ){ - if(( iRc = LockFile( fHandle, lPos.Dword[0], lPos.Dword[1], lLen.Dword[0], lLen.Dword[1] )) == 0 ){ - iTries++; - xbase->xbSleep( GetDefaultLockWait() ); - } - } - else if( iFunction == XB_UNLOCK ){ - if(( iRc = UnlockFile( fHandle, lPos.Dword[0], lPos.Dword[1], lLen.Dword[0], lLen.Dword[1] )) == 0 ){ - iTries++; - xbase->xbSleep( GetDefaultLockWait() ); - } - } - else - { - iErrorStop = 130; - iRc = XB_INVALID_LOCK_OPTION; - throw iRc; - } - } while( iRc == 0 && iTries < GetLockRetryCount()); - if( iRc == 0 ) - iRc = XB_LOCK_FAILED; // lock failed, don't log an exception - else - iRc = XB_NO_ERROR; - - #elif defined(HAVE_LOCKING_F) || defined(HAVE__LOCKING_F) - - /* older 32 bit locking functions */ - xbInt32 iLockType; - if( iFunction == XB_LOCK ){ - iLockType = 2; - } else if( iFunction == XB_UNLOCK ){ - iLockType = 0; - } else { - iErrorStop = 140; - iRc = XB_INVALID_LOCK_OPTION; - throw iRc; - } - - if(( iRc = xbFseek( lOffset, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 150; - iRc = XB_SEEK_ERROR; - throw iRc; - } - - do{ - #ifdef HAVE__LOCKING_F - if(( iRc = _locking( iFileNo, iLockType, stLen )) != 0 ){ - #else - if(( iRc = locking( iFileNo, iLockType, stLen )) != 0 ){ - #endif - iTries++; - xbase->xbSleep( GetDefaultLockWait() ); - } - } while( iRc != 0 && iTries < GetLockRetryCount()); - - if( iRc != 0 ) - iRc = XB_LOCK_FAILED; // lock failed, don't log an exception - else - iRc = XB_NO_ERROR; - - #else - - FATAL ERROR - CANT BUILD LIBRARY IN CURRENT CONFIG - MISSING - no file locking function defined in xbfile.cpp - - #endif - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFile::xbLock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - return iRc; - - -} - -//! @brief Return the locking retry setting. -/*! - - \returns The lock retry setting for this file or ths system default setting if the lock retry for the file - has not been set. -*/ - -xbInt16 xbFile::GetLockRetryCount() const { - - if( iLockRetries == -1 ) - return xbase->GetDefaultLockRetries(); - else - return iLockRetries; -} - -//! @brief Set the lock retry countr for this specific file. -/*! - \param iLockRetries The number of retries to attempt before returning failure for this file -*/ - -void xbFile::SetLockRetryCount( xbInt16 iLockRetries ) { - this->iLockRetries = iLockRetries; -} - -#endif - - -/***********************************************************************/ -#ifdef XB_DEBUG_SUPPORT -//! @brief Debugging routine - dump mem to the log file. -/*! - This routine dumps data from meemory to the log file. This is - primarily used for debugging and analysis purposes. - - \param p Pointer to data to write - \param lBlxkSize Size of block - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbFile::DumpMemToDisk( char *p, size_t lSize ){ - - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbString sDir; - xbString sFn; - - FILE *fpd = NULL; - - try{ - - // sDir = GetLogDirectory(); - sDir = xbase->GetLogDirectory(); - - char cLastChar = sDir[sDir.Len()]; - - // build logfile name - if( cLastChar != '/' && cLastChar != '\\' ) - sFn.Sprintf( "%s/MemDump.txt", sDir.Str()); - else - sFn.Sprintf( "%sMemDump.txt", sDir.Str()); - - // 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 = 100; - iRc = XB_OPEN_ERROR; - throw iRc; - } - - int i; - // dump the block to the file - for( size_t l = 0; l < lSize; l++ ){ - i = *p; - if( fputc( i, fpd ) == EOF ){ - iErrorStop = 110; - iRc = XB_WRITE_ERROR; - throw iRc; - } - p++; - } - // 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(); - sDir = xbase->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 ) - free( buf ); - } - 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( buf ) - free( buf ); - if( fpd ) - fclose( fpd ); - } - return iRc; -} -#endif -/***********************************************************************/ -} /* namespace xb */ - - - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfilter.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbfilter.cpp deleted file mode 100755 index 5c5f276..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfilter.cpp +++ /dev/null @@ -1,544 +0,0 @@ -/* xbfilter.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 uda (user data area) methods - -*/ - -#include "xbase.h" - - -// might need to change thisto XB_EXPRESSION_SUPPORT -#ifdef XB_FILTER_SUPPORT - - -namespace xb{ - -/************************************************************************/ -xbFilter::xbFilter( xbDbf *dbf ) { - this->dbf = dbf; - this->exp = NULL; - lLimit = 0; // max number of responses - lCurQryCnt = 0; // current number, this query + = moving fwd - // - = moving backwards - - #ifdef XB_INDEX_SUPPORT - pIx = NULL; // if index is set, the class uses the index tag, otherwise table - vpTag = NULL; - #endif // XB_INDEX_SUPPORT - -} -/************************************************************************/ -xbFilter::~xbFilter() { - if( exp ) - delete exp; -} -/************************************************************************/ -xbInt32 xbFilter::GetLimit() const { - return lLimit; -} -/************************************************************************/ -xbInt32 xbFilter::GetQryCnt() const { - return lCurQryCnt; -} -/************************************************************************/ -void xbFilter::SetLimit( xbInt32 lLimit ){ - this->lLimit = lLimit; -} -/************************************************************************/ -void xbFilter::ResetQryCnt(){ - this->lCurQryCnt = 0; -} - -/************************************************************************/ -xbInt16 xbFilter::Set( const char *sFilter ) { - xbString sFilt( sFilter ); - return Set( sFilt ); -} - -/************************************************************************/ -xbInt16 xbFilter::Set( xbString &sFilter ) { - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( exp ) - delete exp; - - exp = new xbExp( dbf->GetXbasePtr(), dbf ); - if(( iRc = exp->ParseExpression( sFilter.Str() )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if( exp->GetReturnType() != XB_EXP_LOGICAL ){ - iErrorStop = 110; - iRc = XB_INVALID_EXPRESSION; - delete exp; - exp = NULL; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::SetExpression() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -xbInt16 xbFilter::GetFirstRecord( xbInt16 iOption ) { - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - - lCurQryCnt = 0; - if(( iRc = dbf->GetFirstRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EMPTY || iRc == XB_EOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - if(( iRc = dbf->GetNextRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt++; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetFirstRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -xbInt16 xbFilter::GetNextRecord( xbInt16 iOption ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - - if( lLimit != 0 && abs( lCurQryCnt ) >= lLimit ) - return XB_LIMIT_REACHED; - - if(( iRc = dbf->GetNextRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - if(( iRc = dbf->GetNextRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt++; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetNextRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -xbInt16 xbFilter::GetPrevRecord( xbInt16 iOption ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - - if( lLimit != 0 && abs( lCurQryCnt ) >= lLimit ) - return XB_LIMIT_REACHED; - - if(( iRc = dbf->GetPrevRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_BOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - if(( iRc = dbf->GetPrevRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_BOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt--; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetPrevRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -xbInt16 xbFilter::GetLastRecord( xbInt16 iOption ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - - lCurQryCnt = 0; - if(( iRc = dbf->GetLastRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - if(( iRc = dbf->GetPrevRecord( iOption )) != XB_NO_ERROR ){ - if( iRc == XB_BOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt--; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetLastRecord() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ - -#ifdef XB_INDEX_SUPPORT - -/************************************************************************/ -xbInt16 xbFilter::GetFirstRecordIx( xbInt16 iOption ) { - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - - lCurQryCnt = 0; - if(( iRc = dbf->GetCurIx()->GetFirstKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EMPTY || iRc == XB_EOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - // if(( iRc = pIx->GetNextKey( vpTag, iOption )) != XB_NO_ERROR ){ - if(( iRc = dbf->GetCurIx()->GetNextKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt++; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetFirstRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -xbInt16 xbFilter::GetNextRecordIx( xbInt16 iOption ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - - if( lLimit != 0 && abs( lCurQryCnt ) >= lLimit ) - return XB_LIMIT_REACHED; - - if(( iRc = dbf->GetCurIx()->GetNextKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - // if(( iRc = pIx->GetNextKey( vpTag, iOption )) != XB_NO_ERROR ){ - if(( iRc = dbf->GetCurIx()->GetNextKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt++; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetNextRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -xbInt16 xbFilter::GetPrevRecordIx( xbInt16 iOption ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - - if( lLimit != 0 && abs( lCurQryCnt ) >= lLimit ) - return XB_LIMIT_REACHED; - - if(( iRc = dbf->GetCurIx()->GetPrevKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_BOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - //if(( iRc = pIx->GetPrevKey( vpTag, iOption )) != XB_NO_ERROR ){ - if(( iRc = dbf->GetCurIx()->GetPrevKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_BOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt--; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetPrevRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -/************************************************************************/ -xbInt16 xbFilter::GetLastRecordIx( xbInt16 iOption ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - if( !exp ){ - iErrorStop = 100; - throw iRc; - } - lCurQryCnt = 0; - if(( iRc = dbf->GetCurIx()->GetLastKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_EOF ) - return iRc; - else{ - iErrorStop = 110; - throw iRc; - } - } - xbBool bFound = xbFalse; - while( !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = exp->ProcessExpression()) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = exp->GetBoolResult( bFound )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( !bFound ){ - if(( iRc = dbf->GetCurIx()->GetPrevKey( dbf->GetCurTag(), iOption )) != XB_NO_ERROR ){ - if( iRc == XB_BOF ){ - return iRc; - } else { - iErrorStop = 140; - throw iRc; - } - } - } - } - lCurQryCnt--; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbFilter::GetLastRecordIx() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - dbf->GetXbasePtr()->WriteLogMessage( sMsg.Str() ); - dbf->GetXbasePtr()->WriteLogMessage( dbf->GetXbasePtr()->GetErrorMessage( iRc )); - } - return iRc; -} -#endif // XB_INDEX_SUPPORT - - -/************************************************************************/ -} /* namespace */ -#endif /* XB_FILTER_SUPPORT */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfuncs.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbfuncs.cpp deleted file mode 100755 index f127211..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbfuncs.cpp +++ /dev/null @@ -1,851 +0,0 @@ -/* xbfuncs.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014,2017,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 - -*/ - -#include "xbase.h" - -#ifdef XB_FUNCTION_SUPPORT - -namespace xb{ - - -// All funtions have a similar structure, return an xbInt16 return code -// Have a variable number of input operands and one output operand - -/************************************************************************/ -//! @brief Calculate absolute value of a numeric expression. -/*! - Expression function ABS(). - \param dIn Input - Numeric expression. - \param dOut Output - Absolute value. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbXBase::ABS( xbDouble dIn, xbDouble &dOut ){ - if( dIn < 0 ) - dOut = dIn * -1; - else - dOut = dIn; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Trim leading and trailing white space from a string. -/*! - Expression function ALLTRIM(). - \param sIn Input - Input string to trim. - \param sOut Output - Trimmed string. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbXBase::ALLTRIM( const xbString &sIn, xbString &sOut ){ - sOut = sIn; - sOut.Trim(); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return ASCII code for the first character in a string. -/*! - Expression function ASC(). - \param sIn Input - Input character string. - \param dAscOut Output - Ascii code of first character in string. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::ASC( const xbString &sIn, xbDouble &dAscOut ){ - if( sIn == "" ) - return XB_PARSE_ERROR; - - dAscOut = sIn[1]; - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Return number indicating starting position of string within a string. -/*! - Expression function AT(). - \param s1 Input - Input string to search for. - \param s2 Input - Input string to search. - \param dPos Output - Position of string s1 within s2. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::AT( const xbString &s1, const xbString &s2, xbDouble &dPos ){ - /* looks for s1 in s2 */ - xbInt32 lCnt = 0; - const char *p; - const char *p2 = s2; - if( strlen( s1 ) > strlen( s2 )) return 0; - if(( p = strstr( s2, s1 )) == NULL ) - return XB_NO_ERROR; - while( p2++ != p ) lCnt++; - dPos = lCnt + 1; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return character weekday name for date. -/*! - Expression function CDOW(). - \param dInDate Input - Input date. - \param sOutDow Output - Character day of week. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::CDOW( xbDate &dInDate, xbString &sOutDow ){ - return dInDate.CharDayOf( sOutDow ); -} - -/*************************************************************************/ -//! @brief Convert numeric expression to a character. -/*! - Expression function CHR(). - \param dAsciCd Input - Numeric expression. - \param sOut Output - Character result. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::CHR( xbDouble dAsciCd, xbString &sOut ){ - static char buf[2]; - buf[0] = (char) dAsciCd; - buf[1] = 0x00; - sOut = buf; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return character month name for date. -/*! - Expression function CMONTH(). - \param dInDate Input - Input date. - \param sOutMonth Output - Character month. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::CMONTH( xbDate &dInDate, xbString &sOutMonth ){ - return dInDate.CharMonthOf( sOutMonth ); -} -/*************************************************************************/ -//! @brief Return date from character input date. -/*! - Expression function CTOD(). - \param sInDate Input - Input date in MM/DD/YY format. - \param dOutDate Output - Output date. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::CTOD( const xbString &sInDate, xbDate &dOutDate ){ - return dOutDate.CTOD( sInDate ); -} -/*************************************************************************/ -//! @brief Return system date. -/*! - Expression function DATE(). - \param dOutDate Output - Output date. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::DATE( xbDate &dOutDate ){ - return dOutDate.Sysdate(); -} -/*************************************************************************/ -//! @brief Return the day of the month from a date. -/*! - Expression function DAY(). - \param dInDate Input - Input date. - \param dOutDay Output - Output day of month. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::DAY( const xbDate &dInDate, xbDouble &dOutDay ){ - xbInt16 iOutDay;; - iOutDay = dInDate.DayOf( XB_FMT_MONTH ); - if( iOutDay < 0 ){ - return iOutDay; - }else{ - dOutDay = iOutDay; - return XB_NO_ERROR; - } -} -/*************************************************************************/ -//! @brief Return record deletion status for current record. -/*! - Expression function DEL(). - \param dbf Input - Table to check record deletion status. - \param iRecBufSw Input - Which buffer. 0 = Current record buffer, 1 = Original record buffer - \param sOut Output - "*" if record is deleted, otherise space. - \returns XB_NO_ERROR<br>XB_PARSE_ERROR. - -*/ -xbInt16 xbXBase::DEL( xbDbf *dbf , xbString &sOut, xbInt16 iRecBufSw ) { - - if( dbf ){ - if( dbf->RecordDeleted( iRecBufSw )) - sOut = "*"; - else - sOut = " "; - return XB_NO_ERROR; - } else { - return XB_PARSE_ERROR; - } -} - -/*************************************************************************/ -//! @brief Return record deletion status for current record. -/*! - Expression function DELETED(). - \param dbf Input - Table to check record deletion status for. - \param iRecBufSw Input - Which buffer. 0 = Current record buffer, 1 = Original record buffer - \param bOut Output - xbTrue if record is deleted.<br>xbFalse if record is not deleted. - \returns XB_NO_ERROR<br>XB_PARSE_ERROR. -*/ -xbInt16 xbXBase::DELETED( xbDbf *dbf , xbBool &bOut, xbInt16 iRecBufSw ) { - - if( dbf ){ - bOut = dbf->RecordDeleted( iRecBufSw ); - return XB_NO_ERROR; - } else { - return XB_PARSE_ERROR; - } -} - -/*************************************************************************/ -//! @brief Clipper DESCEND function. -/*! - Expression function DESCEND(). - \param dtInDate Input - Input date. - \param dtOutDate Output - Output date. - \returns XB_NO_ERROR. -*/ -xbInt16 xbXBase::DESCEND( const xbDate &dtInDate, xbDate &dtOutDate ){ - xbDate d( "29991231" ); - dtOutDate.JulToDate8( 2415021 + d.JulianDays() - dtInDate.JulianDays()); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Clipper DESCEND function. -/*! - Expression function DESEND(). - \param dIn Input - Input number. - \param dOut Output - Output number. - \returns XB_NO_ERROR. -*/ -xbInt16 xbXBase::DESCEND( xbDouble dIn, xbDouble &dOut ){ - dOut = dIn * -1; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Clipper DESCEND function. -/*! - Expression function DESEND(). - \param sIn Input - Input string. - \param sOut Output - Output string. - \returns XB_NO_ERROR. -*/ -xbInt16 xbXBase::DESCEND( const xbString &sIn, xbString &sOut ){ - - sOut = sIn; - for( xbUInt32 l = 0; l < sIn.Len(); l++ ) - sOut.PutAt( l+1, (char) (255 - sOut[l+1])); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return number of day of week. -/*! - Expression function DOW(). - \param dtInDate Input - Input date. - \param dDowOut Output - Output day of week. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::DOW( const xbDate &dtInDate, xbDouble &dDowOut ){ - xbInt16 iDow; - iDow = dtInDate.DayOf( XB_FMT_WEEK ); - if( iDow < 0 ){ - return XB_PARSE_ERROR; - }else{ - dDowOut = iDow; - return XB_NO_ERROR; - } -} - -/*************************************************************************/ -//! @brief Return character date from input date. -/*! - Expression function DTOC(). - \param dInDate Input - Input date. - \param sOutFmtDate Output - Output date. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::DTOC( xbDate &dInDate, xbString &sOutFmtDate ){ - return dInDate.FormatDate( "MM/DD/YY", sOutFmtDate ); -} -/*************************************************************************/ -//! @brief Return char CCYYMMDD date from input date. -/*! - Expression function DTOS(). - \param dtInDate Input - Input date. - \param sOutFmtDate Output - Output date. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::DTOS( xbDate &dtInDate, xbString &sOutFmtDate ){ - return dtInDate.FormatDate( "YYYYMMDD", sOutFmtDate ); -} -/*************************************************************************/ -//! @brief Return exponent value. -/*! - Expression function EXP(). - This function returns e**x where e is approximately 2.71828 and x is dIn. - - \param dIn Input - exp value. - \param dOut Output - value. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::EXP( xbDouble dIn, xbDouble &dOut ) -{ - dOut = exp( dIn ); - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Immediate if. -/*! - Expression function IIF(). - \param bResult Input - boolean expression. - \param sTrueResult Input - value if boolean expression is true. - \param sFalseResult Input - value if boolean expression is false. - \param sResult Output - sTrueResult or sFalseResult depending on bResultvalue. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::IIF( xbBool bResult, const xbString &sTrueResult, const xbString &sFalseResult, xbString &sResult ) -{ - if( sFalseResult.Len() != sTrueResult.Len()) - return XB_INCONSISTENT_PARM_LENS; - if( bResult ) - sResult = sTrueResult; - else - sResult = sFalseResult; - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Convert number to integer, truncate any decimals. -/*! - Expression function INT(). - \param dIn Input - Input number. - \param dOut Output - integer. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::INT( xbDouble dIn, xbDouble &dOut ) -{ - xbInt64 ll = (xbInt64) dIn; - dOut = (xbDouble) ll; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Check if string begins with alpha character. -/*! - Expression function ISALPHA(). - \param sIn Input - Input string. - \param bResult Output - xbTrue if string begins with alpha character.<br>xbFalse if string does not begin with alpha character. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::ISALPHA( const xbString &sIn, xbBool &bResult ){ - if( isalpha(sIn[1])) - bResult = 1; - else - bResult = 0; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Check if string begins with lower case alpha character. -/*! - Expression function ISLOWER(). - \param sIn Input - Input string. - \param bResult Output - xbTrue if string begins with lower case alpha character.<br> - xbFalse if string does not begin with lower case alpha character. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::ISLOWER( const xbString &sIn, xbBool &bResult ){ - if( islower(sIn[1])) - bResult = 1; - else - bResult = 0; - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Check if string begins with upper case alpha character. -/*! - Expression function ISUPPER(). - \param sIn Input - Input string. - \param bResult Output - xbTrue if string begins with upper case alpha character.<br> - xbFalse if string does not begin with upper case alpha character. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::ISUPPER( const xbString &sIn, xbBool &bResult ){ - if( isupper(sIn[1])) - bResult = 1; - else - bResult = 0; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return left characters from string. -/*! - Expression function LEFT(). - \param sIn Input - string. - \param ulCharCnt Input - number of characters to extract from string. - \param sOut Output - resultant string. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::LEFT( const xbString &sIn, xbUInt32 ulCharCnt, xbString &sOut ){ - sOut.Assign( sIn, 1, ulCharCnt ); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return length of string. -/*! - Expression function LEN(). - \param sIn Input - Input string. - \param dOut Output - string length. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::LEN( const xbString &sIn, xbDouble &dOut ){ - dOut = sIn.Len(); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Calculate logarithm. -/*! - Expression function LOG(). - \param dIn Input - numeric expression. - \param dOut Output - numeric log value. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::LOG( xbDouble dIn, xbDouble &dOut ){ - dOut = log( dIn ); - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Trim left side of string. -/*! - Expression function LTRIM(). - \param sIn Input - string. - \param sOut Output - string result. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::LTRIM( const xbString &sIn, xbString &sOut ){ - sOut = sIn; - sOut.Ltrim(); - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Convert upper case to lower case. -/*! - Expression function LOWER(). - \param sIn Input - string. - \param sOut Output - string result. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::LOWER( const xbString &sIn, xbString &sOut ){ - sOut = sIn; - sOut.ToLowerCase(); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return higher of two values. -/*! - Expression function MAX(). - \param d1 Input - Numeric value 1. - \param d2 Input - Numeric value 2. - \param dOut Output - Higher of d1 or d2. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::MAX( xbDouble d1, xbDouble d2, xbDouble &dOut ) -{ - if( d1 > d2 ) - dOut = d1; - else - dOut = d2; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return lessor of two values. -/*! - Expression function MIN(). - \param d1 Input - Numeric value 1. - \param d2 Input - Numeric value 2. - \param dOut Output - Lessor of d1 or d2. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::MIN( xbDouble d1, xbDouble d2, xbDouble &dOut ) -{ - if( d1 < d2 ) - dOut = d1; - else - dOut = d2; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return number of month for a given date. -/*! - Expression function MONTH(). - \param dInDate Input date. - \param dOutMonth - Month number. - \returns XB_NO_ERROR.<br>XB_PARSE_ERROR. -*/ -xbInt16 xbXBase::MONTH( xbDate &dInDate, xbDouble &dOutMonth ){ - - xbInt16 iRc = dInDate.MonthOf(); - if( iRc < 0 ) - return XB_PARSE_ERROR; - else{ - dOutMonth = iRc; - return XB_NO_ERROR; - } -} - -/*************************************************************************/ -//! @brief Return number of records in a given table. -/*! - Expression function RECCOUNT(). - \param dbf - Table. - \param dOut - Number of records. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::RECCOUNT( xbDbf *dbf , xbDouble &dOut ) { - - xbUInt32 ulRecCnt; - xbInt16 iRc = dbf->GetRecordCnt( ulRecCnt ); - dOut = (xbDouble) ulRecCnt; - return iRc; - -} - -/*************************************************************************/ -//! @brief Return current record number for a given table. -/*! - Expression function RECNO(). - \param dbf - Table. - \param dOut - Record number. - \returns XB_NO_ERROR.<br>XB_PARSE_ERROR. -*/ - -xbInt16 xbXBase::RECNO( xbDbf *dbf , xbDouble &dOut ) { - if( dbf ){ - dOut = (xbDouble) dbf->GetCurRecNo(); - return XB_NO_ERROR; - } else { - dOut = -1; - return XB_PARSE_ERROR; - } -} - -/*************************************************************************/ -//! @brief Repeat character expression N times. -/*! - Expression function REPLICATE(). - \param sIn Inout - String to replicate. - \param ulRepCnt Input - Number of times to repeat. - \param sOut Output - String result. - \returns XB_NO_ERROR.<br>XB_PARSE_ERROR. -*/ -xbInt16 xbXBase::REPLICATE( const xbString &sIn, xbUInt32 ulRepCnt, xbString &sOut ){ - sOut = ""; - for( xbUInt32 i = 0; i < ulRepCnt; i++ ) - sOut += sIn; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Return right characters from string. -/*! - Expression function RIGHT(). - \param sIn Input - string. - \param ulCharCnt Input - number of characters to extract from string. - \param sOut Output - resultant string. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::RIGHT( const xbString &sIn, xbUInt32 ulCharCnt, xbString &sOut ){ - if( sIn.Len() < ulCharCnt ) - sOut = sIn; - else - sOut.Assign( sIn, sIn.Len() - ulCharCnt + 1, ulCharCnt ); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Trim right side of string. -/*! - Expression function RTRIM(). - \param sIn Input - string. - \param sOut Output - string result. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::RTRIM( const xbString &sIn, xbString &sOut ){ - sOut = sIn; - sOut.Rtrim(); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Generate a string of N spaces. -/*! - Expression function SPACE(). - \param lCnt Input - Number of spaces. - \param sOut Output - Output string consisting of specified number of spaces. - \returns XB_NO_ERROR. -*/ -xbInt16 xbXBase::SPACE( xbInt32 lCnt, xbString &sOut ){ - sOut = ""; - for( xbInt32 i = 0; i < lCnt; i++ ) - sOut += ' '; - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Calculate a square root. -/*! - Expression function SQRT(). - \param dBase Input - Base number. - \param dSqrRoot Output - Square root. - \returns XB_NO_ERROR. -*/ - -xbInt16 xbXBase::SQRT( xbDouble dBase, xbDouble &dSqrRoot ) -{ - dSqrRoot = sqrt( dBase ); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Converts a valid 8 byte (CCYYMMDD) input date into a date class. -/*! - Expression function STOD(). - \param sInDate Input - Input date. - \param dtOutDate Output - Output date. - \returns XB_NO_ERROR.<br>XB_INVALID_DATE. -*/ - -xbInt16 xbXBase::STOD( const xbString &sInDate, xbDate &dtOutDate ){ - - if( dtOutDate.DateIsValid( sInDate )){ - dtOutDate = sInDate; - return XB_NO_ERROR; - } else { - return XB_INVALID_DATE; - } -} - -/*************************************************************************/ -//! @brief Convert number to a character string. -/*! - Expression function STR(). - \param dIn Input - Number. - \param sOut Output - String. - \returns XB_NO_ERROR. -*/ - -xbInt16 xbXBase::STR( xbDouble dIn, xbString &sOut) { - xbString sPadChar = " "; - return STR( dIn, 10, 0, sPadChar, sOut ); -} - -/*************************************************************************/ -//! @brief Convert number to a character string. -/*! - Expression function STR(). - \param dIn Input - Number. - \param ulLen Input - Length. - \param sOut Output - String. - \returns XB_NO_ERROR. -*/ -xbInt16 xbXBase::STR( xbDouble dIn, xbUInt32 ulLen, xbString &sOut) { - xbString sPadChar = " "; - return STR( dIn, ulLen, 0, sPadChar, sOut ); -} - -/*************************************************************************/ -//! @brief Convert number to a character string. -/*! - Expression function STR(). - \param dIn Input - Number. - \param ulLen Input - Length. - \param ulDec Input - Number of decimals. - \param sOut Output - String. - \returns XB_NO_ERROR. -*/ - -xbInt16 xbXBase::STR( xbDouble dIn, xbUInt32 ulLen, xbUInt32 ulDec, xbString &sOut) { - xbString sPadChar = " "; - return STR( dIn, ulLen, ulDec, sPadChar, sOut ); -} - -/*************************************************************************/ -//! @brief Convert number to a character string. -/*! - Expression function STR(). - \param dIn Input - Number. - \param ulLen Input - Length. - \param ulDec Input - Number of decimals. - \param sPadChar Input - Left pad character, typically zero or space. - \param sOut Output - String. - \returns XB_NO_ERROR. -*/ - -xbInt16 xbXBase::STR( xbDouble dIn, xbUInt32 ulLen, xbUInt32 ulDec, xbString &sPadChar, xbString &sOut) { - - xbString sFmt; - sFmt.Sprintf( "%c%d.%df", '%', ulLen, ulDec ); - sOut.Sprintf( sFmt.Str(), dIn, 0 ); - - // convert to all "*" if result is too long - if( sOut.Len() > ulLen ){ - sOut = "*"; - do{ - sOut += "*"; - } while( ulLen > sOut.Len()); - } else if( sPadChar.Len() > 0 && sPadChar != " " ){ - // this logic doesn't make sense when processing negative numbers, - // but it does behave like the original dbase - // you could end up with something like 0000-12.17 when you really want -000012.17 - // that is probably why the STRZERO function came into being - xbUInt32 l = 1; - while( sOut[l] == ' ' ){ - sOut.PutAt( l, sPadChar[1]); - l++; - } - } - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Convert number to a character string with leading zeroes. -/*! - Expression function STRZERO(). - \param dIn Input - Number. - \param ulLen Input - Length. - \param ulDec Input - Number of decimals. - \param sOut Output - String. - \returns XB_NO_ERROR. -*/ -xbInt16 xbXBase::STRZERO( xbDouble dIn, xbUInt32 ulLen, xbUInt32 ulDec, xbString &sOut){ - - xbString sFmt; - if( dIn < 0 ) - sFmt.Sprintf( "%c+0%d.%df", '%', ulLen, ulDec ); - else - sFmt.Sprintf( "%c0%d.%df", '%', ulLen, ulDec ); - sOut.Sprintf( sFmt.Str(), dIn ); - - // convert to all "*" if result is too long - if( sOut.Len() > ulLen ){ - sOut = "*"; - do{ - sOut += "*"; - } while( ulLen > sOut.Len()); - } - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Extract a portion of a string from another string. -/*! - Expression function SUBSTR(). - \param sIn Input - Source string. - \param ulStartPos Input - Starting position for string extraction. - \param ulLen Input - Number of characters to extract. - \param sOut Output - String. - \returns XB_NO_ERROR. -*/ -xbInt16 xbXBase::SUBSTR( const xbString &sIn, xbUInt32 ulStartPos, xbUInt32 ulLen, xbString &sOut ){ - sOut = sIn; - sOut.Mid( ulStartPos, ulLen ); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Trim left and right sides of string. -/*! - Expression function TRIM(). - \param sIn Input - string. - \param sOut Output string result. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::TRIM( const xbString &sIn, xbString &sOut ){ - return RTRIM( sIn, sOut ); -} - -/*************************************************************************/ -//! @brief Convert lower case to upper case. -/*! - Expression function UPPER(). - \param sIn Input - string. - \param sOut Output - string result. - \returns XB_NO_ERROR -*/ -xbInt16 xbXBase::UPPER( const xbString &sIn, xbString &sOut ){ - sOut = sIn; - sOut.ToUpperCase(); - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @brief Convert numeric characters to number. -/*! - Expression function VAL(). - \param sIn Input - string. - \param dOut Output - numeric result. - \returns XB_NO_ERROR -*/ - -xbInt16 xbXBase::VAL( const xbString &sIn, xbDouble &dOut ) -{ - if( sIn ) - // strtod(nptr,NULL); - dOut = atof( sIn ); - else - dOut = 0; - return XB_NO_ERROR; -} -/*************************************************************************/ -//! @brief Return year for a given date. -/*! - Expression function YEAR(). - \param dInDate Input date. - \param dOutYear - Year. - \returns XB_NO_ERROR.<br>XB_PARSE_ERROR. -*/ - -xbInt16 xbXBase::YEAR( xbDate &dInDate, xbDouble &dOutYear ){ - - xbInt16 iRc = dInDate.YearOf(); - if( iRc < 0 ) - return XB_PARSE_ERROR; - else{ - dOutYear = iRc; - return XB_NO_ERROR; - } -} -/*************************************************************************/ -}; // namespace -#endif // XB_FUNCTION_SUPPORT -/*************************************************************************/ diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixbase.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbixbase.cpp deleted file mode 100755 index e2f929c..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixbase.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/* 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 <a href="xbretcod_8h.html">Return Codes</a> -*/ - -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<br>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.<br> - 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 <a href="xbretcod_8h.html">Return Codes</a> -*/ -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 <a href="xbretcod_8h.html">Return Codes</a> -*/ - -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.<br> - N - Numeric BCD compare.<br> - D - Numeric compare.<br> - F - Numeric compare.<br> - \param v1 Left compare.<br>v2 - Right Compare. - \param iSearchKeyLen Length of key compare. - \returns 1 - Left operand is greater then right operand.<br> - 0 - Left operand is equal to right operand.<br> - -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.<br> - 1 Append Mode, Create key for an append, only use rec buf 0, set updated switch.<br> - 2 Update Mode, Create old version and new version keys, check if different, set update switch appropriately. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -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 <a href="xbretcod_8h.html">Return Codes</a> -*/ -//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<br> - 1 = Syslog<br> - 2 = Both<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -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.<br> - xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.<br> - XB_NOT_FOUND - Key not found.<br> - <a href="xbretcod_8h.html">Return Codes</a> -*/ -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.<br> - xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.<br> - XB_NOT_FOUND - Key not found.<br> - <a href="xbretcod_8h.html">Return Codes</a> -*/ -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.<br> - xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.<br> - XB_NOT_FOUND - Key not found.<br> - <a href="xbretcod_8h.html">Return Codes</a> -*/ -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.<br> - xbFalse - Don't retrieve record, check for key existence only. - - \returns XB_NO_ERROR - Key found.<br> - XB_NOT_FOUND - Key not found.<br> - <a href="xbretcod_8h.html">Return Codes</a> -*/ -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.<br> - xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.<br> - XB_NOT_FOUND - Key not found.<br> - <a href="xbretcod_8h.html">Return Codes</a> -*/ -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<br> - 1 = Node is read into new xbIxNode, then added to the node chain, and sets CurNode with new node<br> - 2 = Node is read into new xbIxNode, not added to the node chain<br> - CurNode points to new node<br> - \param ulAddlBuf Additional buffer size added to memory - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -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 <a href="xbretcod_8h.html">Return Codes</a> -*/ -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 <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIx::GetFirstKey( void *vpTag ){ - return GetFirstKey( vpTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the last key for the current tag. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -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 <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIx::GetLastKey( void *vpTag ){ - return GetLastKey( 0, vpTag, 0 ); -} - -/***********************************************************************/ -//! @brief Get the file lock status. -/*! - \returns xbTrue - Index file is locked.<br>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 <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIx::GetNextKey(){ - return GetNextKey( vpCurTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the next key for the given tag. -/*! - \param vpTag Tag for next key operation. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIx::GetNextKey( void *vpTag ){ - return GetNextKey( vpTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the prev key for the current tag. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIx::GetPrevKey(){ - return GetPrevKey( vpCurTag, 0 ); -} -/***********************************************************************/ -//! @brief Get the previous key for the given tag. -/*! - \param vpTag Tag for previous key operation. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -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 <a href="xbretcod_8h.html">Return Codes</a> -*/ -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.<br>xbFalse - Set to unlocked. - \returns void -*/ -void xbIx::SetLocked( xbBool bLocked ){ - this->bLocked = bLocked; -} -/***********************************************************************/ -} /* namespace */ -#endif /* XB_INDEX_SUPPORT */ diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixmdx.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbixmdx.cpp deleted file mode 100755 index 0eef64b..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixmdx.cpp +++ /dev/null @@ -1,4844 +0,0 @@ -/* xbixmdx.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 - - - MDX indices are comprised of blocks and pages. - A page is 512 bytes. - A Block is one or more pages. - The default block size is two 512 byte pages per block. - Nodes are used for storing block images in memory - -*/ - -#include "xbase.h" - -#ifdef XB_MDX_SUPPORT - -namespace xb{ - -/***********************************************************************/ -xbIxMdx::xbIxMdx( xbDbf *dbf ) : xbIx( dbf ){ - Init(); -} -/***********************************************************************/ -//void xbIxMdx::Init( xbInt16 iOpt ){ -void xbIxMdx::Init( xbInt16 ){ - - cVersion = 0; - cCreateYY = 0; - cCreateMM = 0; - cCreateDD = 0; - sFileName = ""; - iBlockFactor = 0; - cProdIxFlag = 0; - cTagEntryCnt = 0; - iTagLen = 0; - iTagUseCnt = 0; - cNextTag = 0; - c1B = 0x0b; - ulPageCnt = 0; - ulFirstFreePage = 0; - ulNoOfBlockAvail = 0; - cUpdateYY = 0; - cUpdateMM = 0; - cUpdateDD = 0; - mdxTagTbl = NULL; - cNodeBuf = NULL; - bReuseEmptyNodes = xbTrue; -} -/***********************************************************************/ -xbIxMdx::~xbIxMdx(){ - if( cNodeBuf ) - free( cNodeBuf ); - - if( FileIsOpen()) - Close(); -} -/***********************************************************************/ -//! @brief Add key. -/*! - Add key. If this is a unique index, this logic assumes the duplicate - check logic was already done. - - \param vpTag Tag to update. - \param ulRecNo Record number to add key for. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ - - xbMdxTag * npTag = (xbMdxTag *) vpTag; - if( GetUniqueKeyOpt() == XB_EMULATE_DBASE && npTag->bFoundSts ) - return XB_NO_ERROR; - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 iHeadNodeUpdateOpt = 2; - xbIxNode * npRightNode = NULL; - xbUInt32 ulNewRightChild = 0; - - try{ - if(( iRc = xbIxMdx::KeySetPosAdd( npTag, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - xbInt32 lKeyCnt = GetKeyCount( npTag->npCurNode ); - if( lKeyCnt < npTag->iKeysPerBlock ){ - // Section A - add key to appropriate position if space available - // std::cout << "AddKey Section A begin\n"; - if(( iRc = InsertNodeL( npTag, npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->cpKeyBuf, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } else { - // land here with a full leaf node - iHeadNodeUpdateOpt = 1; - npRightNode = AllocateIxNode( npTag, GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, npTag->npCurNode->ulBlockNo * (xbUInt32) iBlockFactor ); - if( !npRightNode ){ - iErrorStop = 120; - iRc = XB_NO_MEMORY; - throw iRc; - } - - if(( npTag->npCurNode->ulBlockNo * (xbUInt32) iBlockFactor ) == npTag->ulRightChild ){ - ulNewRightChild = npRightNode->ulBlockNo * (xbUInt32) iBlockFactor; - } - - if(( iRc = xbIxMdx::SplitNodeL( npTag, npTag->npCurNode, npRightNode, npTag->npCurNode->iCurKeyNo, npTag->cpKeyBuf, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - xbUInt32 ulTempBlockNo = npRightNode->ulBlockNo; - - // section C - go up the tree, splitting nodes as necessary - xbIxNode * npParent = npTag->npCurNode->npPrev; - while( npParent && GetKeyCount( npParent ) >= npTag->iKeysPerBlock ){ - //std::cout << "Section C begin interior node is full\n"; - npRightNode = FreeNodeChain( npRightNode ); - npRightNode = AllocateIxNode( npTag, GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, npParent->ulBlockNo * (xbUInt32) iBlockFactor ); - //std::cout << "Section C - B new right node block number for interior node split= " << npRightNode->ulBlockNo << "\n"; - - if( !npRightNode ){ - iErrorStop = 140; - iRc = XB_NO_MEMORY; - throw iRc; - } - //std::cout << "Section C - going to split interior node C\n"; - - if(( iRc = SplitNodeI( npTag, npParent, npRightNode, npParent->iCurKeyNo, BlockToPage( ulTempBlockNo ))) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - // std::cout << "Section C - interior node split \n"; - ulTempBlockNo = npRightNode->ulBlockNo; - npTag->npCurNode = npParent; - npParent = npParent->npPrev; - } - - // section D - if cur node is split root, create new root - if(( npTag->npCurNode->ulBlockNo * (xbUInt32) iBlockFactor ) == npTag->ulRootPage ){ - if(( iRc = AddKeyNewRoot( npTag, npTag->npCurNode, npRightNode )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if( npRightNode ) - npRightNode = FreeNodeChain( npRightNode ); - - } 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; - throw iRc; - } - } - } - - // update the header - if(( iRc = WriteHeadBlock( iHeadNodeUpdateOpt )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - - // if adding the first key, set the cHasKeys field - if( !npTag->cHasKeys ){ - npTag->cHasKeys = 0x01; - if(( iRc = xbFseek( ((npTag->ulTagHdrPageNo * 512) + 246), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - if(( iRc = xbFwrite( &npTag->cHasKeys, 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - } - - if( ulNewRightChild > 0 ){ - - char cBuf[4]; - ePutUInt32( cBuf, ulNewRightChild ); - if(( iRc = xbFseek( ((npTag->ulTagHdrPageNo * 512) + 252), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - if(( iRc = xbFwrite( &cBuf, 4, 1 )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - npTag->ulRightChild = ulNewRightChild; - } - - if( npRightNode ) - npRightNode = FreeNodeChain( npRightNode ); - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npCurNode = NULL; - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::AddKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -void xbIxMdx::AppendNodeChain( void *vpTag, xbIxNode * npNode ){ - xbMdxTag * mdxTag = (xbMdxTag *) vpTag; - if( mdxTag->npNodeChain == NULL ){ - mdxTag->npNodeChain = npNode; - mdxTag->npCurNode = npNode; - } else { - npNode->npPrev = mdxTag->npCurNode; - mdxTag->npCurNode->npNext = npNode; - mdxTag->npCurNode = npNode; - } - // time stamp the node chain - GetFileMtime( mdxTag->tNodeChainTs ); -} - -/***********************************************************************/ -//! @brief Add new root node. -/*! - \param mpTag Tag to update. - \param npLeft Left node. - \param npRight Right node. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::AddKeyNewRoot( xbMdxTag *npTag, xbIxNode *npLeft, xbIxNode *npRight ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char *pLastKey = NULL; - - try{ - xbIxNode *npRoot = AllocateIxNode( npTag, GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, npRight->ulBlockNo * (xbUInt32) iBlockFactor ); - if( !npRoot ){ - iErrorStop = 100; - iRc = XB_NO_MEMORY; - throw iRc; - } - npTag->ulRootPage = npRoot->ulBlockNo; - - pLastKey = (char *) malloc( (size_t) npTag->iKeyLen ); - if(( iRc = GetLastKeyForBlockNo( npTag, npLeft->ulBlockNo, pLastKey )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - char * pTrg = npRoot->cpBlockData; - - // set no of keys to 1 - ePutUInt32( pTrg, 1 ); - - // set the left node number - pTrg += 8; - ePutUInt32( pTrg, npLeft->ulBlockNo * (xbUInt32) iBlockFactor ); - - // set the key - pTrg+= 4; - memcpy( pTrg, pLastKey, (size_t) npTag->iKeyLen ); - pTrg+= npTag->iKeyItemLen - 4; - ePutUInt32( pTrg, npRight->ulBlockNo * (xbUInt32) iBlockFactor ); - - // write out the new block - if(( iRc = WriteBlock( npRoot->ulBlockNo, GetBlockSize(), npRoot->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - // write out the new root node number in the tag header - // position the file - xbUInt32 ulPagePos = npTag->ulTagHdrPageNo * 512; - - // save the number to a buffer - char cBuf[4]; - ePutUInt32( cBuf, npRoot->ulBlockNo * ((xbUInt32) iBlockFactor )); - - if(( iRc = xbFseek( ulPagePos, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if(( iRc = xbFwrite( &cBuf, 4, 1 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - if( pLastKey ) - free( pLastKey ); - - npRoot = FreeNodeChain( npRoot ); - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::AddKeyNewRoot() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( pLastKey ) - free( pLastKey ); - } - return iRc; -} - - - -/***********************************************************************/ -//! @brief Allocate a node. -/*! - \param mpTag Pointer to mdx tag - \param ulBufSize Buffer size. - \param ulBlock2 Value to load in ulBlock2 field, bytes 4-7 in the first page of the block - \returns Pointer to new node. -*/ -xbIxNode * xbIxMdx::AllocateIxNode( xbMdxTag * mpTag, xbUInt32 ulBufSize, xbUInt32 ulBlock2 ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbIxNode *n = NULL; - - try{ - if(( n = xbIx::AllocateIxNode( ulBufSize )) == NULL ){ - iRc = XB_NO_MEMORY; - iErrorStop = 100; - throw iRc; - } - char *p = n->cpBlockData; - p += 4; - - if( ulFirstFreePage > 0 && bReuseEmptyNodes ){ - // have an empty node we can reuse - n->ulBlockNo = PageToBlock( ulFirstFreePage ); - if(( iRc = ReadBlock( n->ulBlockNo, GetBlockSize(), n->cpBlockData )) != XB_NO_ERROR ){ - iRc = 110; - throw iRc; - } - // update ulFirstFreePage - ulFirstFreePage = eGetUInt32( p ); - if(( iRc = xbFseek( 36, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = xbFwrite( p, 4, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - // memset cpBlockData to zeroes - memset( n->cpBlockData, 0x00, GetBlockSize()); - - } else { - n->ulBlockNo = ulPageCnt / (xbUInt32) iBlockFactor; - ulPageCnt += (xbUInt32) iBlockFactor; - } - - mpTag->ulTagSize += (xbUInt32) iBlockFactor; - if( ulBlock2 > 0 ){ - ePutUInt32( p, ulBlock2 ); - } - } - catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::AllocateIxNode() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( n ) - n = FreeNodeChain( n ); - } - return n; -} -/***********************************************************************/ -//! @brief Calculate B-tree pointers. -/*! - Set binary tree pointer value. The MDX tags are stored with binary - tree positions. This routine calculates the value in memory. - \returns void -*/ - -void xbIxMdx::CalcBtreePointers(){ - - xbInt16 iaLeftChild[48]; - xbInt16 iaRightChild[48]; - xbInt16 iaParent[48]; - - for( xbInt16 i = 0; i < 48; i++ ){ - iaLeftChild[i] = 0; - iaRightChild[i] = 0; - iaParent[i] = 0; - } - - // anything to do? - if( iTagUseCnt > 1 ){ - xbString sBaseTag; - xbString sThisTag; - xbString sWorkTag; - xbInt16 iWorkTagNo; - xbBool bDone; - sBaseTag = GetTagName( GetTag( 0 )); - - for( xbInt16 iThisTagNo = 1; iThisTagNo < iTagUseCnt; iThisTagNo++ ){ - iWorkTagNo = 0; - sWorkTag.Set( sBaseTag ); - sThisTag = GetTagName( GetTag( iThisTagNo )); - bDone = xbFalse; - while( !bDone ){ - if( sThisTag < sWorkTag ){ - if( iaLeftChild[iWorkTagNo] == 0 ) { - iaLeftChild[iWorkTagNo] = iThisTagNo + 1; - iaParent[iThisTagNo] = iWorkTagNo + 1; - bDone = xbTrue; - } else { - iWorkTagNo = iaLeftChild[iWorkTagNo]-1; - sWorkTag = GetTagName( GetTag( iWorkTagNo)); - } - } else { - if( iaRightChild[iWorkTagNo] == 0 ) { - iaRightChild[iWorkTagNo] = iThisTagNo + 1; - iaParent[iThisTagNo] = iWorkTagNo + 1; - bDone = xbTrue; - } else { - iWorkTagNo = iaRightChild[iWorkTagNo]-1; - sWorkTag = GetTagName( GetTag( iWorkTagNo )); - } - } - } - } - } - - xbString s; - xbMdxTag *mpTag = mdxTagTbl; - for( xbInt16 i = 0; i < iTagUseCnt; i++ ){ - mpTag->cLeftChild = (char ) iaLeftChild[i]; - mpTag->cRightChild = (char ) iaRightChild[i]; - mpTag->cParent = (char ) iaParent[i]; - mpTag = mpTag->next; - } -} - -/**************************************************************************************************************/ -//! @brief Calculate the page number for a given block -/*! - This routine is called by any function needing to calculate the page number for a given block. - Page numbers are stored internally in the physical file, and the library reads and writes in - blocks of one or more pages. - - Assumes valid data input - - \param ulBlockNo Block Number - \returns Calculated page number. -*/ - -inline xbUInt32 xbIxMdx::BlockToPage( xbUInt32 ulBlockNo ){ - return ulBlockNo * (xbUInt32) iBlockFactor; -} -/***********************************************************************/ -char xbIxMdx::CalcTagKeyFmt( xbExp &exp ){ - - xbExpNode *n = exp.GetTreeHandle(); - if( n->GetChildCnt() == 0 && n->GetNodeType() == XB_EXP_FIELD ) - return 0x01; - else - return 0; -} -/***********************************************************************/ -//! @brief Check for duplicate key. -/*! - \param vpTag Tag to check. - \returns XB_KEY_NOT_UNIQUE<br>XB_NO_ERROR -*/ - -xbInt16 xbIxMdx::CheckForDupKey( void *vpTag ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - mpTag->bFoundSts = xbFalse; - try{ - if( GetUnique( mpTag )){ - if( mpTag->iKeySts == XB_ADD_KEY || mpTag->iKeySts == XB_UPD_KEY ) - if( KeyExists( mpTag )){ - if( GetUniqueKeyOpt() == XB_EMULATE_DBASE ){ - mpTag->bFoundSts = xbTrue; - return 0; - } else { - return XB_KEY_NOT_UNIQUE; - } - } - } - return 0; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::CheckForDupKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Check tag integrity. -/*! - Check a tag for accuracy. - - \param vpTag Tag to create key for. - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iRc2; - xbInt16 iRc3; - xbInt16 iErrorStop = 0; - xbUInt32 ulIxCnt = 0; - xbUInt32 ulThisRecNo = 0; - xbUInt32 ulPrevRecNo = 0; - xbBool bDone = false; - xbString sMsg; - char cKeyType; - char *pPrevKeyBuf = NULL; - xbMdxTag *npTag = (xbMdxTag *) vpTag; - xbBool bDescending = npTag->cKeyFmt2 & 0x08; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif - - try{ - - #ifdef XB_LOCKING_SUPPORT - if( dbf->GetAutoLock() && !dbf->GetTableLocked() ){ - if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - bLocked = xbTrue; - } - #endif - - memset( npTag->cpKeyBuf2, 0x00, (size_t) npTag->iKeyLen ); - 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 - while( iRc == XB_NO_ERROR && !bDone ){ - ulIxCnt++; - - iRc = GetNextKey( vpTag, 0 ); - if( iRc == XB_NO_ERROR ){ - - // compare this key to prev key - iRc2 = CompareKey( cKeyType, GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), - pPrevKeyBuf, (size_t) npTag->iKeyLen ); - - if(( iRc2 < 0 && !bDescending ) || ( iRc2 > 0 && bDescending )){ - sMsg.Sprintf( "Key sequence error at key number [%ld].", ulIxCnt ); - xbase->WriteLogMessage( sMsg, iOpt ); - iErrorStop = 110; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - ulThisRecNo = 0; - if(( iRc3 = GetDbfPtr( vpTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulThisRecNo )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc3; - } - - if( iRc2 == 0 && (ulThisRecNo <= ulPrevRecNo )){ - sMsg.Sprintf( "Dbf record number sequence error at key number [%ld].", iOpt ); - xbase->WriteLogMessage( sMsg, iOpt ); - iErrorStop = 130; - iRc = XB_INVALID_INDEX; - throw iRc; - } - // save this key info to prev key - memcpy( pPrevKeyBuf, GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), (size_t) npTag->iKeyLen ); - ulPrevRecNo = ulThisRecNo; - } - } - - xbUInt32 ulDbfCnt = 0; - if(( iRc = dbf->GetRecordCnt( ulDbfCnt )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - xbUInt32 ulFiltCnt = 0; - xbBool bFiltered = xbTrue; - // verify each record in the dbf file has a corresponding index entry - xbUInt32 j = 0; - while( j < ulDbfCnt ){ - - if(( iRc = dbf->GetRecord( ++j )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if( npTag->cHasFilter ){ - if(( iRc = npTag->filter->ProcessExpression( 0 )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if(( iRc = npTag->filter->GetBoolResult( bFiltered )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - - if( bFiltered ){ - if(( iRc = FindKeyForCurRec( vpTag )) != XB_NO_ERROR ){ - ulThisRecNo = j; - iErrorStop = 180; - throw iRc; - } - ulFiltCnt++; - } - } - - if((GetUniqueKeyOpt() == XB_EMULATE_DBASE) && (GetUnique( vpTag ))){ - // can't compare counts if using XB_EMULATE_DBASE and it's a unique index - } else { - if( ulIxCnt != ulFiltCnt && GetUniqueKeyOpt() == XB_HALT_ON_DUPKEY ){ - if( npTag->cHasFilter ) - sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Filtered index entry count [%ld] does not match dbf record count [%ld] for tag [%s]", ulIxCnt, ulFiltCnt, npTag->cTagName ); - else - sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Index entry count [%ld] does not match dbf record count [%ld] for tag [%s]", ulIxCnt, ulFiltCnt, npTag->cTagName ); - - xbase->WriteLogMessage( sMsg, iOpt ); - iErrorStop = 190; - iRc = XB_INVALID_INDEX; - throw iRc; - } - if( npTag->cHasFilter ) - sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Filtered index entry count [%ld] matches dbf record count [%ld] for tag [%s]", ulIxCnt, ulFiltCnt, npTag->cTagName ); - else - sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Index entry count [%ld] matches dbf record count [%ld] for tag [%s]", ulIxCnt, ulFiltCnt, npTag->cTagName ); - xbase->WriteLogMessage( sMsg, iOpt ); - } - - if( pPrevKeyBuf ) - free( pPrevKeyBuf ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Exception Caught. Error Stop = [%d] iRc = [%d] Tag = [%s]", iErrorStop, iRc, npTag->cTagName ); - xbase->WriteLogMessage( sMsg, iOpt ); - xbase->WriteLogMessage( GetErrorMessage( iRc ), iOpt ); - if( pPrevKeyBuf ) - free( pPrevKeyBuf ); - - if( iErrorStop == 160 ){ - sMsg.Sprintf( "xbIxMdx::CheckTagIntegrity() Missing index entry for record [%d]", ulThisRecNo ); - xbase->WriteLogMessage( sMsg, iOpt ); - } - } - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - dbf->LockTable( XB_UNLOCK ); - } - #endif - - return iRc; -} - -/***********************************************************************/ -xbMdxTag *xbIxMdx::ClearTagTable(){ - - // clear the list of tags - xbMdxTag *tt = mdxTagTbl; - xbMdxTag *tt2; - while( tt ){ - tt2 = tt; - tt = tt->next; - tt2->npNodeChain = FreeNodeChain( tt2->npNodeChain ); - tt2->npCurNode = NULL; - if( tt2->cpKeyBuf ) - free( tt2->cpKeyBuf ); - if( tt2->cpKeyBuf2 ) - free( tt2->cpKeyBuf2 ); - if( tt2->exp ) - delete tt2->exp; - if( tt2->filter ) - delete tt2->filter; - if( tt2->sKeyExp ) - delete tt2->sKeyExp; - if( tt2->sTagName ) - delete tt2->sTagName; - if( tt2->sFiltExp ) - delete tt2->sFiltExp; - free( tt2 ); - } - return NULL; -} -/***********************************************************************/ -xbInt16 xbIxMdx::Close(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - mdxTagTbl = ClearTagTable(); - if(( iRc = xbIx::Close()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::Close() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Create key. -/*! - - \param vpTag Tag - \param iOpt 1 = Append, 2 = Update - \returns XB_KEY_NOT_UNIQUE<br>XB_NO_ERROR - - iKeySts 0 - No Updates - 1 - Add Key XB_ADD_KEY - 2 - Update Key XB_UPD_KEY - 3 - Delete Key XB_DEL_KEY - - bKeyFiltered xbFalse - Key filtered out - xbTrue - Key filtered in - - cpKeyBuf - Key buffer for add - cpKeyBuf2 - Key buffer for delete - -*/ - -xbInt16 xbIxMdx::CreateKey( void *vpTag, xbInt16 iOpt ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbBool bFilter0 = xbFalse; // filter against RecBuf, updated record buffer - xbBool bFilter1 = xbFalse; // filter against recBuf2, original record buffer - - try{ - - xbMdxTag *npTag = (xbMdxTag *) vpTag; - npTag->iKeySts = 0; - - // do tag filter logic - if( npTag->cHasFilter ){ - if(( iRc = npTag->filter->ProcessExpression( 0 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = npTag->filter->GetBoolResult( bFilter0 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } else { - bFilter0 = xbTrue; - } - - // if add request and filtered out, we're done - if( iOpt == 1 && !bFilter0 ) - return XB_NO_ERROR; - - if(( iRc = npTag->exp->ProcessExpression( 0 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if( npTag->exp->GetReturnType() == XB_EXP_CHAR ) - npTag->exp->GetStringResult( npTag->cpKeyBuf, (xbUInt32) npTag->iKeyLen ); - else if( npTag->exp->GetReturnType() == XB_EXP_NUMERIC ){ - xbDouble d; - npTag->exp->GetNumericResult( d ); - xbBcd bcd( d ); - bcd.ToChar( npTag->cpKeyBuf ); - } - else if( npTag->exp->GetReturnType() == XB_EXP_DATE ){ - xbDouble d; - npTag->exp->GetNumericResult( d ); - memcpy( npTag->cpKeyBuf, &d, 8 ); - } - - if( iOpt == 1 ) // Append - npTag->iKeySts = XB_ADD_KEY; - - else if( iOpt == 2 ){ // Update - if( npTag->cHasFilter ){ - if(( iRc = npTag->filter->ProcessExpression( 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if(( iRc = npTag->filter->GetBoolResult( bFilter1 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - } else { - bFilter1 = xbTrue; - } - - if(( iRc = npTag->exp->ProcessExpression( 1 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - if( npTag->exp->GetReturnType() == XB_EXP_CHAR ){ - npTag->exp->GetStringResult( npTag->cpKeyBuf2, (xbUInt32) npTag->iKeyLen ); - - } else if( npTag->exp->GetReturnType() == XB_EXP_NUMERIC ){ - xbDouble d; - npTag->exp->GetNumericResult( d ); - xbBcd bcd( d ); - bcd.ToChar( npTag->cpKeyBuf2 ); - - } else if( npTag->exp->GetReturnType() == XB_EXP_DATE ){ - xbDouble d; - npTag->exp->GetNumericResult( d ); - memcpy( npTag->cpKeyBuf2, &d, 8 ); - - } - - if( bFilter1 ){ // original key was indexed - if( bFilter0 ){ // new key s/b indexed, update it if changed - if( memcmp( npTag->cpKeyBuf, npTag->cpKeyBuf2, (size_t) npTag->iKeyLen )){ - npTag->iKeySts = XB_UPD_KEY; - } - } else { // original key indexed, new key not indexed, delete it - npTag->iKeySts = XB_DEL_KEY; - } - } else { // original key not indexed - if( bFilter0 ) - npTag->iKeySts = XB_ADD_KEY; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::CreateKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Create new tag. -/*! - This routine creates a new tag. When complete, sets the cur tag pointer to - the newly created tag. - - - \param sName Tag Name, including .MDX suffix - \param sKey Key Expression - \param sFilter Filter expression. - \param iDescending - \param iUnique xbtrue - Unique.<br>xbFalse - Not unique. - \param iOverLay xbTrue - Overlay if file already exists.<br>xbFalse - Don't overlay. - \param vpTag Output from method Pointer to vptag pointer. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbIxMdx::CreateTag( const xbString &sName, const xbString &sKey, const xbString &sFilter, xbInt16 iDescending, xbInt16 iUnique, xbInt16 iOverlay, void **vpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag *tte = NULL; - - try{ - // verify room for new tag - if( !( iTagUseCnt < 47 )){ - iErrorStop = 100; - iRc = XB_LIMIT_REACHED; - throw iRc; - } - - // verify valid tag name - xbString sWorker = sName; - sWorker.Trim(); - if( sWorker.Len() > 10 ){ - iErrorStop = 110; - iRc = XB_INVALID_TAG; - throw iRc; - } - - // verify tag not already defined - if( iTagUseCnt > 0 ){ - if( GetTag( sWorker )){ - iErrorStop = 120; - iRc = XB_INVALID_TAG; - throw iRc; - } - } - - // allocate a tag structure here - if(( tte = (xbMdxTag *) calloc( 1, (size_t) sizeof( xbMdxTag ))) == NULL ){ - iErrorStop = 130; - iRc = XB_NO_MEMORY; - throw iRc; - } - *vpTag = tte; - tte->sTagName = new xbString( sWorker ); - - //set up the key expression - sWorker = sFilter; - sWorker.Trim(); - if( sWorker.Len() > 0 ){ - if( sWorker.Len() == 0 || sWorker.Len() > 220 ){ - iRc = XB_INVALID_TAG; - iErrorStop = 140; - throw iRc; - } - tte->sFiltExp = new xbString( sWorker ); - tte->filter = new xbExp( dbf->GetXbasePtr()); - if(( iRc = tte->filter->ParseExpression( dbf, sWorker )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - if((tte->filter->GetReturnType()) != 'L' ){ - iRc = XB_INVALID_TAG; - iErrorStop = 160; - throw iRc; - } - tte->cHasFilter = 0x01; - } - - //set up the key expression - sWorker = sKey; - sWorker.Trim(); - if( sWorker.Len() == 0 || sWorker.Len() > 100 ){ - iRc = XB_INVALID_TAG; - iErrorStop = 170; - throw iRc; - } - tte->sKeyExp = new xbString( sWorker ); - tte->exp = new xbExp( dbf->GetXbasePtr()); - if(( iRc = tte->exp->ParseExpression( dbf, sWorker )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - - xbDate d; - d.Sysdate(); - if( iTagUseCnt == 0 ){ - // first tag, new mdx file - // create the file name - xbString sIxFileName = dbf->GetFqFileName(); - sIxFileName.Trim(); - xbUInt32 lLen = sIxFileName.Len(); - sIxFileName.PutAt( lLen-2, 'M' ); - sIxFileName.PutAt( lLen-1, 'D' ); - sIxFileName.PutAt( lLen, 'X' ); - - // copy the file name to the class variable - this->SetFileName( sIxFileName ); - if( FileExists() && !iOverlay ){ - iErrorStop = 190; - iRc = XB_FILE_EXISTS; - throw iRc; - } - - // first tag, need to create the file - if(( iRc = xbFopen( "w+b", dbf->GetShareMode())) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - cVersion = 2; - cCreateYY = (char) d.YearOf() - 1900; - cCreateMM = (char) d.MonthOf(); - cCreateDD = (char) d.DayOf( XB_FMT_MONTH ); - - GetFileNamePart( sFileName ); - sFileName.ToUpperCase(); - - SetBlockSize( (xbUInt32) dbf->GetCreateMdxBlockSize()); - iBlockFactor = GetBlockSize() / 512; - - cProdIxFlag = 1; - cTagEntryCnt = 48; - iTagLen = 32; - ulPageCnt = 4; - ulFirstFreePage = 0; - ulNoOfBlockAvail = 0; - cNextTag = 1; - c1B = 0x1B; - cUpdateYY = cCreateYY; - cUpdateMM = cCreateMM; - cUpdateDD = cCreateDD; - - if(( iRc = WriteHeadBlock( 0 )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - } - - // populate the tag table entry structure - tte->ulTagHdrPageNo = ulPageCnt; - ulPageCnt += (xbUInt32) iBlockFactor; - tte->sTagName->strncpy( tte->cTagName, 10 ); - - // cKeyFmt is always 0x10; - // tested 2+ZIPCD CITY+STATE or just standalone field - always 0x10 - tte->cKeyFmt = 0x10; // = CalcTagKeyFmt( *tte->exp ); - - switch( tte->exp->GetReturnType()){ - case XB_EXP_CHAR: - tte->cKeyType = 'C'; - tte->iKeyLen = tte->exp->GetResultLen(); - tte->iSecKeyType = 0; - break; - - case XB_EXP_NUMERIC: - tte->cKeyType = 'N'; - tte->iKeyLen = 12; - tte->iSecKeyType = 0; - break; - - case XB_EXP_DATE: - tte->cKeyType = 'D'; - tte->iKeyLen = 8; - tte->iSecKeyType = 1; - break; - - default: - iErrorStop = 200; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - tte->cpKeyBuf = (char *) malloc( (size_t) tte->iKeyLen + 1 ); - tte->cpKeyBuf2 = (char *) malloc( (size_t) tte->iKeyLen + 1 ); - - // write the new tte entry here - char tteBuf[21]; - memset( tteBuf, 0x00, 21 ); - - ePutUInt32( &tteBuf[0], tte->ulTagHdrPageNo ); - for( xbUInt32 l = 0; l < tte->sTagName->Len() && l < 10; l++ ){ - tteBuf[l+4] = tte->sTagName->GetCharacter(l+1); - } - tteBuf[15] = tte->cKeyFmt; - tteBuf[19] = 0x02; // appears to always be a 0x02 - tteBuf[20] = tte->cKeyType; - - if(( iRc = xbFseek( (iTagUseCnt * 32) + 544, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - if(( iRc = xbFwrite( tteBuf, 21, 1 )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - - // Begin Tag Header - tte->ulRootPage = ulPageCnt; - tte->ulTagSize = (xbUInt32) iBlockFactor; - ulPageCnt += 2; - tte->cKeyFmt2 = 0x10; - if( iDescending ) - tte->cKeyFmt2 += 0x08; - if( iUnique ){ - tte->cKeyFmt2 += 0x40; - tte->cUnique = 0x01; - } - - tte->cTag11 = 0x1B; // always 0x1b ? - tte->cSerialNo = 0x01; // version incremented with each tag update - tte->ulLeftChild = tte->ulRootPage; - tte->ulRightChild = tte->ulRootPage; - - tte->cTagYY = (char) d.YearOf() - 1900; - tte->cTagMM = (char) d.MonthOf(); - tte->cTagDD = (char) d.DayOf( XB_FMT_MONTH ); - - tte->cKeyType2 = tte->cKeyType; - tte->iKeyItemLen = tte->iKeyLen + 4; - while(( tte->iKeyItemLen % 4 ) != 0 ) tte->iKeyItemLen++; - - tte->iKeysPerBlock = (xbInt16) (GetBlockSize() - 12) / tte->iKeyItemLen; - tte->cKeyFmt3 = CalcTagKeyFmt( *tte->exp ); - - char *pBuf; - if(( pBuf = (char *) calloc( 1, (size_t) GetBlockSize())) == NULL ){ - iErrorStop = 230; - iRc = XB_NO_MEMORY; - throw iRc; - } - char *wPtr; - wPtr = pBuf; - ePutUInt32( wPtr, tte->ulRootPage ); - - wPtr += 4; - ePutUInt32( wPtr, tte->ulTagSize ); - - wPtr += 4; - *wPtr = tte->cKeyFmt2; - - wPtr++; - *wPtr = tte->cKeyType2; - - wPtr += 2; - *wPtr = tte->cTag11; - - wPtr += 1; - ePutInt16( wPtr, tte->iKeyLen ); - - wPtr += 2; - ePutInt16( wPtr, tte->iKeysPerBlock ); - - wPtr += 2; - ePutInt16( wPtr, tte->iSecKeyType ); - - wPtr += 2; - ePutInt16( wPtr, tte->iKeyItemLen ); - - wPtr += 2; - *wPtr = tte->cSerialNo; - - wPtr += 3; - *wPtr = tte->cUnique; - - wPtr++; - for( xbUInt32 l = 0; l < tte->sKeyExp->Len(); l++ ) - *wPtr++ = tte->sKeyExp->GetCharacter(l+1); - - wPtr = pBuf; - - tte->cHasKeys = 0x00; - pBuf[246] = tte->cHasKeys; - - wPtr += 248; - ePutUInt32( wPtr, tte->ulLeftChild ); - wPtr += 4; - ePutUInt32( wPtr, tte->ulRightChild ); - - pBuf[257] = tte->cTagYY; - pBuf[258] = tte->cTagMM; - pBuf[259] = tte->cTagDD; - pBuf[480] = tte->cKeyFmt3; - - if( sFilter.Len() > 0 ){ - pBuf[245] = tte->cHasFilter; - wPtr = pBuf; - wPtr += 762; - for( xbUInt32 l = 0; l < sFilter.Len(); l++ ) - *wPtr++ = sFilter.GetCharacter(l+1); - } - - if(( iRc = xbFseek( tte->ulTagHdrPageNo * 512, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 240; - throw iRc; - } - - if(( iRc = xbFwrite( pBuf, GetBlockSize(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 250; - throw iRc; - } - - memset( pBuf, 0x00, GetBlockSize() ); - if(( iRc = xbFwrite( pBuf, GetBlockSize(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 260; - throw iRc; - } - - iTagUseCnt++; - cNextTag++; - - if(( iRc = WriteHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 270; - throw iRc; - } - - // update the dbf file if needed - discreet field, has no filter - // 10/15/22 - dbase 7 does not update this field on index creation - if( tte->cKeyFmt3 == 0x01 && !tte->cHasFilter ){ - // printf( "cKeyFmt3 = [%x]\n", tte->cKeyFmt3 ); - xbInt16 iFldNo; - if(( iRc = dbf->GetFieldNo( sKey, iFldNo )) != XB_NO_ERROR ){ - iErrorStop = 280; - throw iRc; - } - xbInt64 lOffset = 31 + ((iFldNo + 1) * 32 ); - - if(( iRc = dbf->xbFseek( lOffset, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 290; - iRc = XB_SEEK_ERROR; - throw iRc; - } - char cBuf[2]; - cBuf[0] = 0x01; - cBuf[1] = 0x00; - - if(( iRc = dbf->xbFwrite( cBuf, 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 300; - throw iRc; - } - dbf->UpdateSchemaIxFlag( iFldNo, 0x01 ); - } - - // add the new entry to the end of the list of tags - if( mdxTagTbl == NULL ){ - mdxTagTbl = tte; - } else { - xbMdxTag *tteL = mdxTagTbl; - while( tteL->next ) - tteL = tteL->next; - tteL->next = tte; - } - - /* update the btree pointers */ - CalcBtreePointers(); - char bBuf[3]; - xbMdxTag *tteWork = mdxTagTbl; - - if(( iRc = xbFseek( 560, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 310; - throw iRc; - } - while( tteWork ){ - bBuf[0] = tteWork->cLeftChild; - bBuf[1] = tteWork->cRightChild; - bBuf[2] = tteWork->cParent; - - if(( iRc = xbFwrite( bBuf, 3, 1 )) != XB_NO_ERROR ){ - iErrorStop = 320; - throw iRc; - } - if( tteWork->next ){ - if(( iRc = xbFseek( 29, SEEK_CUR )) != XB_NO_ERROR ){ - iErrorStop = 330; - throw iRc; - } - } - tteWork = tteWork->next; - } - free( pBuf ); - } - - catch (xbInt16 iRc ){ - if( tte ){ - if( tte->cpKeyBuf ) - free( tte->cpKeyBuf ); - if( tte->cpKeyBuf2 ) - free( tte->cpKeyBuf2 ); - if( tte->exp ) - delete tte->exp; - if( tte->filter ) - delete tte->filter; - if( tte->sKeyExp ) - delete tte->sKeyExp; - if( tte->sFiltExp ) - delete tte->sFiltExp; - if( tte->sTagName ) - delete tte->sTagName; - free( tte ); - } - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::CreateTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - return iRc; -}; - -/***********************************************************************/ -//! @brief Delete a key from a node. -/*! - This routine deletes a key from a supplied node. - \param vpTag Tag to delete key on. - \param npNode Node to delete key on. - \param iSlotNo Slot number of key to delete. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::DeleteFromNode( void *vpTag, xbIxNode * npNode, xbInt16 iSlotNo ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag * npTag = (xbMdxTag *) vpTag; - - try{ - xbInt32 lKeyCnt = GetKeyCount( npNode ); - xbInt16 iLen = (lKeyCnt - iSlotNo - 1) * npTag->iKeyItemLen; - xbBool bLeaf = IsLeaf( vpTag, npNode ); - if( !bLeaf ) - iLen += 4; - - char *pTrg = npNode->cpBlockData; - if( iLen > 0 ){ - pTrg += (8 + (npTag->iKeyItemLen * (iSlotNo)) ); //lTrgPos; - // std::cout << "TrgSpot = " << (8 + (npTag->iKeyItemLen * (iSlotNo)) ) << "\n"; - char *pSrc = pTrg; - pSrc += npTag->iKeyItemLen; - memmove( pTrg, pSrc, (size_t) iLen ); - } - - // zap out the right most key - pTrg = npNode->cpBlockData; - if( bLeaf ){ - pTrg += (8 + (npTag->iKeyItemLen * ( lKeyCnt-1 ))); - - } else { - pTrg += (12 + (npTag->iKeyItemLen * ( lKeyCnt-1 ))); - - } - - for( xbInt16 i = 0; i < npTag->iKeyItemLen; i++ ) - *pTrg++ = 0x00; - - // set the new number of keys - ePutUInt32( npNode->cpBlockData, (xbUInt32) lKeyCnt - 1 ); - - // if node empty, add it to the free node chain - if( lKeyCnt < 2 ){ - if( bReuseEmptyNodes ){ - if( bLeaf && lKeyCnt == 1 ){ - if(( iRc = HarvestEmptyNode( npTag, npNode, 0 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - } - } - - // write out the block - if(( iRc = WriteBlock( npNode->ulBlockNo, GetBlockSize(), npNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::DeleteFromNode() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return XB_NO_ERROR; -} - -/***********************************************************************/ -//! @brief Delete a key. -/*! - This routine deletes a key. It assumes the key to delete - is the current key in the node chain. - - \param vpTag Tag to delete key on. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::DeleteKey( void *vpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag * npTag = (xbMdxTag *) vpTag; - - // save copy of node chain to reset to after delete completed - xbIxNode *npSaveNodeChain = npTag->npNodeChain; - npTag->npNodeChain = NULL; - xbIxNode * npSaveCurNode = npTag->npCurNode; - - try{ - xbString sMsg; - - if(( iRc = xbIxMdx::KeySetPosDel( npTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // Delete key needs to handle two scenarios - // 1 - if delete is on the only key of leaf, - // traverse up tree, trim as needed - // 2 - if last key on node is deleted, and key value is not the same - // as prev key, ascend tree looking for an interior node needing - // updated key value - - xbInt32 lOrigKeyCnt = GetKeyCount( npTag->npCurNode ); - if(( iRc = DeleteFromNode( npTag, npTag->npCurNode, npTag->npCurNode->iCurKeyNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - if( lOrigKeyCnt == 1 ){ - - // scenario 1 - xbBool bDone = xbFalse; - xbBool bIsLeaf = xbFalse; - xbInt32 lKeyCnt; - npTag->npCurNode = npTag->npCurNode->npPrev; - - while( npTag->npCurNode && !bDone ){ - lKeyCnt = GetKeyCount( npTag->npCurNode ); - bIsLeaf = IsLeaf( npTag, npTag->npCurNode ); - if( lKeyCnt > 0 ){ - if(( iRc = DeleteFromNode( npTag, npTag->npCurNode, npTag->npCurNode->iCurKeyNo )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } else if(( iRc = HarvestEmptyNode( npTag, npTag->npCurNode, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - if( (bIsLeaf && lKeyCnt > 1) || (!bIsLeaf && lKeyCnt > 0) ) - bDone = xbTrue; - else - npTag->npCurNode = npTag->npCurNode->npPrev; - } - - } else if( npTag->npCurNode->iCurKeyNo == (xbUInt32) lOrigKeyCnt - 1 ){ - - // scenario 2 - // if last two keys identical, then nothing to do, else go up looking for a key to change - if( memcmp( GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), - GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo-1, npTag->iKeyItemLen ), - (size_t) npTag->iKeyLen )){ - - xbIxNode *pNode = npTag->npCurNode->npPrev; - char *pSrc = GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo-1, npTag->iKeyItemLen ); - - while( pNode && pNode->ulBlockNo != npTag->ulRootPage && pNode->iCurKeyNo == (xbUInt32) GetKeyCount( pNode ) ) - pNode = pNode->npPrev; - - if( pNode ){ - if( pNode->iCurKeyNo < (xbUInt32) GetKeyCount( pNode )){ - char *pTrg = pNode->cpBlockData; - pTrg += 12 + (pNode->iCurKeyNo * (xbUInt32) npTag->iKeyItemLen); - for( xbInt16 i = 0; i < npTag->iKeyLen; i++ ) - *pTrg++ = *pSrc++; - // write out the block - if(( iRc = WriteBlock( pNode->ulBlockNo, GetBlockSize(), pNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - } - } - } - } - // restore node chain to pre delete status (which should be post add status) - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npNodeChain = npSaveNodeChain; - npTag->npCurNode = npSaveCurNode; - - // update the serial number - if(( iRc = TagSerialNo( 3, npTag )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::DeleteKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( npSaveNodeChain ){ - npTag->npNodeChain = npSaveNodeChain; - npSaveNodeChain = FreeNodeChain( npSaveNodeChain ); - npTag->npCurNode = npSaveCurNode; - } - } - return iRc; -} - -/***********************************************************************/ -//! @brief Delete a given tag -/*! - \param vpTag Input tag ptr for tag to be deleted<br> - \returns <a href="xbretcod_8h.html">Return Codes</a><br> - 1 = Deleted entire MDX file, only had one tag - -*/ - -xbInt16 xbIxMdx::DeleteTag( void *vpTag ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - xbIxNode *n = NULL; - xbBool bLoneTag = xbFalse; - - try{ - - if( !vpTag ){ - iErrorStop = 100; - iRc = XB_INVALID_TAG; - throw iRc; - } - - char cSaveHasFilter = mpTag->cHasFilter; - char cSaveKeyFmt3 = mpTag->cKeyFmt3; - xbString sSaveKey = mpTag->sKeyExp->Str(); - - if( iTagUseCnt == 1 ){ - // std::cout << "xbIxMdx::DeleteTag - one tag found, delete the mdx file\n"; - - // close the mdx file - if(( iRc = xbIxMdx::Close()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - // delete the file - xbRemove(); - - // init variables - needed? - // Init(); - // iRc > 0 defines this as the only tag in an MDX file, MDX file deleted. - // signals to the calling process to drop the MDX file from the - // list of updateable indices. - bLoneTag = xbTrue; - - } else { - - // harvest tag nodes - - if(( iRc = HarvestTagNodes( mpTag, xbTrue )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - // remove an entry from tag table - // which tag is this? - xbInt16 iTagNo = 0; - xbMdxTag *mp = mdxTagTbl; - xbMdxTag *mpPrev = NULL; - while( mp && mp->ulTagHdrPageNo != mpTag->ulTagHdrPageNo ){ - iTagNo++; - mpPrev = mp; - mp = mp->next; - } - - // remove it from the linked list of tags - if( !mpPrev ){ - mdxTagTbl = mp->next; - } else { - mpPrev->next = mp->next; - } - if( mp ){ - if( mp->cpKeyBuf ) free( mp->cpKeyBuf ); - if( mp->cpKeyBuf2 ) free( mp->cpKeyBuf2 ); - if( mp->exp ) delete mp->exp; - if( mp->filter ) delete mp->filter; - if( mp->sKeyExp ) delete mp->sKeyExp; - if( mp->sFiltExp ) delete mp->sFiltExp; - if( mp->sTagName ) delete mp->sTagName; - free( mp ); - } - xbInt32 iTarg = iTagNo * 32; - xbInt32 iSrc = iTarg + 32; - xbInt32 iLen = (iTagUseCnt - iTagNo) * 32; - - if(( iRc = xbFseek( 544, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - char Buf[1536]; // 47 tags + 1 in case tag #47 is deleted - memset( Buf, 0x00, 1536 ); - if(( iRc = xbFread( Buf, 1504, 1 )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - char *pTrg = Buf; - pTrg += iTarg; - char *pSrc = Buf; - pSrc += iSrc; - for( xbInt32 i = 0; i < iLen; i++ ) - *pTrg++ = *pSrc++; - - if(( iRc = xbFseek( 544, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - if(( iRc = xbFwrite( Buf, 1504, 1 )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - - iTagUseCnt--; - if(( iRc = WriteHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - - /* update the btree pointers */ - CalcBtreePointers(); - char bBuf[3]; - xbMdxTag *tteWork = mdxTagTbl; - - if(( iRc = xbFseek( 560, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - while( tteWork ){ - bBuf[0] = tteWork->cLeftChild; - bBuf[1] = tteWork->cRightChild; - bBuf[2] = tteWork->cParent; - - if(( iRc = xbFwrite( bBuf, 3, 1 )) != XB_NO_ERROR ){ - iErrorStop = 320; - throw iRc; - } - if( tteWork->next ){ - if(( iRc = xbFseek( 29, SEEK_CUR )) != XB_NO_ERROR ){ - iErrorStop = 330; - throw iRc; - } - } - tteWork = tteWork->next; - } - } - - // update the dbf file if needed, if discreet field with no filter - // printf( "cSaveKeyFmt3 = [%x] cSaveHasFilter=[%x] SaveKey = [%s]\n", cSaveKeyFmt3, cSaveHasFilter, sSaveKey.Str()); - - if( cSaveKeyFmt3 == 0x01 && !cSaveHasFilter ){ - xbInt16 iFldNo; - if(( iRc = dbf->GetFieldNo( sSaveKey, iFldNo )) != XB_NO_ERROR ){ - iErrorStop = 340; - throw iRc; - } - xbInt64 lOffset = 31 + ((iFldNo + 1) * 32 ); - - if(( iRc = dbf->xbFseek( lOffset, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 350; - iRc = XB_SEEK_ERROR; - throw iRc; - } - char cBuf[2]; - cBuf[0] = 0x00; - cBuf[1] = 0x00; - if(( iRc = dbf->xbFwrite( cBuf, 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 360; - throw iRc; - } - dbf->UpdateSchemaIxFlag( iFldNo, 0x00 ); - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::DeleteTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( n ) - free( n ); - } - if( bLoneTag && !iRc ) - return 1; - else - return iRc; -} - -/***********************************************************************/ -#ifdef XB_DEBUG_SUPPORT - -//! @brief Dump a given block for a tag -/*! - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \param ulBlockNo Block number to dump - \param mpTag Index tag pointer - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbIxMdx::DumpBlock( xbInt16 iOpt, xbUInt32 ulBlockNo, xbMdxTag *mpTag ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbString s, s2; - xbBool bLeaf; - char *p; - - try{ - if(( iRc = GetBlock( mpTag, ulBlockNo, 0 )) != XB_NO_ERROR ){ - iErrorStop = 10; - throw iRc; - } - p = cNodeBuf; - xbInt32 lNoOfKeys = eGetInt32( p ); - p+=4; - xbUInt32 ulNode2 = eGetUInt32( p ); - - if( !mpTag ){ - // if no tag info, print what is available without tag info and exit - s.Sprintf( "--- BlkNo = %ld Page = %ld NoOfKeys = %ld Node2 (opt NextFreePage) = %ld", ulBlockNo, BlockToPage( ulBlockNo ), lNoOfKeys, ulNode2 ); - xbase->WriteLogMessage( s, iOpt ); - return XB_NO_ERROR; - } - - p+=4; - p+= mpTag->iKeyItemLen * lNoOfKeys; - if( eGetUInt32( p ) == 0 ){ - bLeaf = xbTrue; - // std::cout << "No of keys = " << lNoOfKeys << "\n"; - s.Sprintf( "--- Leaf Node KeyCnt %d\t Page %d\t Block %d", lNoOfKeys, BlockToPage( ulBlockNo ), ulBlockNo ); - } else { - bLeaf = xbFalse; - s.Sprintf( "--- Interior Node KeyCnt %d\t Page %d\t Block %d", lNoOfKeys, BlockToPage( ulBlockNo ), ulBlockNo ); - } - if( ulNode2 > 0 ) - s.Sprintf( "%s Node2 (opt NextFreePage) = %d", s.Str(), ulNode2 ); - - xbase->WriteLogMessage( s, iOpt ); - - xbInt32 l; - for( l = 0; l < lNoOfKeys; l++ ){ - p = cNodeBuf + (8 + (l * mpTag->iKeyItemLen )); - s.Sprintf( "%08ld\t", eGetUInt32( p )); - p+=4; - if( mpTag->cKeyType2 == 'C' ){ //CHAR - for( xbInt32 l = 0; l < (mpTag->iKeyItemLen-4); l++ ) - s += *p++; - s.Trim(); - } else if( mpTag->cKeyType2 == 'N' ){ // NUMERIC - xbBcd bcd( p ); - bcd.ToString( s2 ); - s += s2; - } else if( mpTag->cKeyType2 == 'D' ){ // DATE - xbInt32 lDate = (xbInt32) eGetDouble( p ); - xbDate d( lDate ); - s.Sprintf( "%s\t%ld\t(%s)", s.Str(), lDate, d.Str()); - } else { - s.Sprintf( "Unknown key type [%c]", mpTag->cKeyType2 ); - } - xbase->WriteLogMessage( s, iOpt ); - } - if( !bLeaf ){ - // interior node has one extra key at the right most position - p = cNodeBuf + (8 + (l * mpTag->iKeyItemLen )); - s.Sprintf( "\t%08ld", eGetUInt32( p )); - xbase->WriteLogMessage( s, iOpt ); - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::DumpBlock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/**************************************************************************************************************/ -//! @brief Dump free blocks. -/*! - Dump free blocks for index debugging purposes. - - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ -xbInt16 xbIxMdx::DumpFreeBlocks( xbInt16 iOpt ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbString s; - char *pBuf = NULL; - char *pNextPage; - xbUInt32 ulNextPage; - - try{ - - if(( iRc = ReadHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - xbUInt32 ulLastBlock = PageToBlock( ulPageCnt ); - - pBuf = (char *) malloc( (size_t) GetBlockSize()); - if( !pBuf ){ - iErrorStop = 110; - iRc = XB_NO_MEMORY; - throw iRc; - } - - if( ulFirstFreePage > 0 ){ - xbUInt32 ulThisFreePage = ulFirstFreePage; - xbUInt32 ulNextFreePage = 0; - xbUInt32 ulCnt = 0; - xbase->WriteLogMessage( "*** Free Blocks ***", iOpt ); - s.Sprintf( "File Header - FirstFreePage = %ld Block = %ld", ulFirstFreePage, PageToBlock( ulFirstFreePage )); - xbase->WriteLogMessage( s, iOpt ); - while( ulThisFreePage > 0 ){ - if(( iRc = ReadBlock( PageToBlock( ulThisFreePage ), GetBlockSize(), pBuf )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - pNextPage = pBuf; - pNextPage+=4; - ulNextFreePage = eGetUInt32( pNextPage ); - s.Sprintf( "Free Page# = %ld\t(Block# = %ld)\tNext Free Page = %ld\t(Block = %ld)", ulThisFreePage, PageToBlock( ulThisFreePage ), ulNextFreePage, PageToBlock( ulNextFreePage )); - xbase->WriteLogMessage( s, iOpt ); - ulThisFreePage = ulNextFreePage; - ulCnt++; - } - s.Sprintf( "%ld free blocks (%ld pages)", ulCnt, BlockToPage( ulCnt )); - xbase->WriteLogMessage( s, iOpt ); - xbase->WriteLogMessage( "*** End Of Free Blocks ***", iOpt ); - } - - pNextPage = pBuf; - pNextPage+=4; - - s = "*** Beginning of Block2 Info ***"; - xbase->WriteLogMessage( s, iOpt ); - s = "ulBlock2 info. ulBlock2 is either one of a linked list of free nodes, or the id of the original node that this node was split from."; - xbase->WriteLogMessage( s, iOpt ); - s = "Stored in physical file as pages, processed in blocks"; - xbase->WriteLogMessage( s, iOpt ); - - xbUInt32 ulFirstBlock = 3; - - for( xbUInt32 ul = ulFirstBlock; ul < ulLastBlock; ul++ ){ - if(( iRc = ReadBlock( ul, GetBlockSize(), pBuf )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - ulNextPage = eGetUInt32( pNextPage ); - if( ulNextPage > 0 ){ - s.Sprintf( " Block# = %ld\tPage# = %ld\tulBlock2 = %ld\tulBlock2(Page) = %ld", ul, BlockToPage( ul ), PageToBlock( ulNextPage ), ulNextPage ); - xbase->WriteLogMessage( s, iOpt ); - } - } - s = "*** End of Block2 Info ***"; - xbase->WriteLogMessage( s, iOpt ); - - if( pBuf ) free( pBuf ); - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::DumpFreeBlocks() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( pBuf ) free( pBuf ); - } - return iRc; -} - -/**************************************************************************************************************/ -//! @brief Dump interior and leaf blocks for a given tag. -/*! - Dump blocks for given tag for index debugging purposes. - - A page is 512 bytes<br> - A block is one or more pages<br> - The default mdx block size is 2 pages, or 1024 bytes<br> - The first four pages or header pages<br> - - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \param vpTag Index tag pointer, defaults to all tags if null. - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbIxMdx::DumpTagBlocks( xbInt16 iOpt, void * vpTag ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbInt16 iCurTag = 0; - xbString s; - xbInt16 iBlockCtr = 0; - - try{ - - xbMdxTag * mpTag; - if( vpTag == NULL ) - mpTag = (xbMdxTag *) GetTag( iCurTag++ ); - else - mpTag = (xbMdxTag *) vpTag; - - if( mpTag == NULL ){ - iErrorStop = 100; - iRc = XB_INVALID_TAG; - throw iRc; - } - - xbIxNode *n; - xbString s; - xbString s2; - xbBool bDone = xbFalse; - - xbUInt32 ulBlkNo; - xbLinkListOrd<xbUInt32> ll; - xbLinkListNode<xbUInt32> * llN; - - ll.SetDupKeys( xbFalse ); - - s.Sprintf( "%s Root Page %ld (Block %ld)", mpTag->cTagName, mpTag->ulRootPage, PageToBlock( mpTag->ulRootPage ) ); - xbase->WriteLogMessage( s, iOpt ); - - // for each tag - while( !bDone ){ - - // clear out any history - ll.Clear(); - if( mpTag->npNodeChain ){ - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - } - - while( GetNextKey( mpTag, 0 ) == 0 ){ - n = mpTag->npNodeChain; - - while(n){ - ll.InsertKey( n->ulBlockNo, (xbUInt32) n->iCurKeyNo ); - n = n->npNext; - } - } - llN = ll.GetHeadNode(); - - while( llN ){ - - ulBlkNo = llN->GetKey(); - xbIxMdx::DumpBlock( iOpt, ulBlkNo, mpTag ); - llN = llN->GetNextNode(); - iBlockCtr++; - } - - if( vpTag || iCurTag >= GetTagCount()) - bDone = xbTrue; - else - mpTag = (xbMdxTag *) GetTag( iCurTag++ ); - } - - s.Sprintf( "\nTotal Blocks: %d", iBlockCtr ); - xbase->WriteLogMessage( s, iOpt ); - - if( mpTag->npNodeChain ){ - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::DumpTagBlocks() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Dump index file header. -/*! - Dump a index file header for debugging purposes. - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \param iFmtOpt Output Format<br> - 0, 1 = Header info only<br> - 2 = Tag info<br> - 3 = Header && Tag info<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::DumpHeader( xbInt16 iOpt, xbInt16 iFmtOpt ) -{ - - xbInt16 iRc = XB_NO_ERROR; - xbString s; - if(( iRc = ReadHeadBlock( 1 )) != XB_NO_ERROR ) - return iRc; - - char c, tfv, cDisplayMask = 1; - cDisplayMask = cDisplayMask << 7; - if( iFmtOpt != 2 && iFmtOpt != 4 ){ - s = "*** MDX Index Header ***"; - xbase->WriteLogMessage( s, iOpt ); - s = "Version = "; - tfv = cVersion; - for( c = 1; c<= 8; c++ ){ - //std::cout << (tfv & cDisplayMask ? '1' : '0'); - s+= (tfv & cDisplayMask ? '1' : '0'); - tfv <<= 1; - } - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Create Date = %d/%d/%d", (int) cCreateMM, (int) cCreateDD, (int) cCreateYY % 100 ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "File Name = %s", sFileName.Str() ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Block Factor = %d", iBlockFactor ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Block Size = %d", GetBlockSize() ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Prod Ix Flag = %d", (xbInt16) cProdIxFlag ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Tag Entry Cnt = %d", (xbInt16) cTagEntryCnt ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Tag Len = %d", iTagLen ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Next Tag = %d", (xbInt16) cNextTag ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Tag Use Cnt = %d", iTagUseCnt ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Page Cnt = %d", ulPageCnt ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "First Free Page = %d", ulFirstFreePage ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "No Of Block Avail = %d\n", ulNoOfBlockAvail ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Last update date = %d/%d/%d", (int) cCreateMM, (int) cCreateDD, (int) cCreateYY % 100 ); - xbase->WriteLogMessage( s, iOpt ); - - if( ulFirstFreePage > 0 ){ - xbString s; - xbUInt32 ulNfp = ulFirstFreePage; // next free page - xbInt16 lc = 0; - while( ulNfp && lc++ < 5 ){ - if( s.Len() > 0 ) - s += ","; - s.Sprintf( "%s%ld", s.Str(), ulNfp ); - if(( iRc = GetBlock( NULL, (xbUInt32) (ulNfp / (xbUInt32) iBlockFactor), 0 )) != 0 ) - return iRc; - ulNfp = eGetUInt32( cNodeBuf+4 ); - } - xbase->WriteLogMessage( s, iOpt ); - } - } - if( iFmtOpt > 1 ){ - xbMdxTag *tt = mdxTagTbl; - xbString s; - xbInt16 i = 0; - - if( tt ){ - while( tt ){ - i++; - if(( iRc = LoadTagDetail( 2, tt )) != XB_NO_ERROR ) - return iRc; - - s.Sprintf( "TTE (%d)\tName HdrPage\tFormat\tLeftChild\tRightChild\tParent\tKeyType", i ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "TTE (%d)\t%-12s %d\t\t%d\t%d\t\t%d\t\t%d\t%c\n", i, tt->cTagName, tt->ulTagHdrPageNo, tt->cKeyFmt, tt->cLeftChild, tt->cRightChild, tt->cParent, tt->cKeyType ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "TTH (%d)\tRoot\tTagSize\tKeyFmt2\tType2\tKeyLen\tKeysPerBlock\tSecType\tKeyItemLen\tSerial#\tHasKeys\tFilter\tDesc\tUnique\tLchild\tRchild\tKeyFmt3\tTagDate", i ); - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "TTH (%d)\t%d\t%d\t%d\t%c\t%d\t%d\t\t%d\t%d\t\t%x\t%x\t%d\t%d\t%d\t%d\t%d\t%d\t%d/%d/%d", - i, tt->ulRootPage, tt->ulTagSize, tt->cKeyFmt2, tt->cKeyType2, tt->iKeyLen, tt->iKeysPerBlock, tt->iSecKeyType, tt->iKeyItemLen, tt->cSerialNo, tt->cHasKeys, tt->cHasFilter, - (((tt->cKeyFmt2 & 0x08) > 0) ? 1 : 0), // descending? - tt->cUnique, tt->ulLeftChild, tt->ulRightChild, tt->cKeyFmt3, (int) tt->cTagMM, (int) tt->cTagDD, (int) tt->cTagYY % 100 ); - - xbase->WriteLogMessage( s, iOpt ); - - s.Sprintf( "Key (%d) %s", i, tt->sKeyExp->Str()); - xbase->WriteLogMessage( s, iOpt ); - - if( tt->cHasFilter ){ - s.Sprintf( "Flt (%d) %s", i, tt->sFiltExp->Str()); - xbase->WriteLogMessage( s, iOpt ); - } - xbase->WriteLogMessage( "", iOpt ); - tt = tt->next; - - } - } - } - return iRc; -} - -/***********************************************************************/ -xbInt16 xbIxMdx::DumpIxForTag( void *vpTag, xbInt16 iOutputOpt ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 iDepth = 0; - xbUInt32 lKeyCtr = 0; - xbInt32 iMinDepth = 999999; - xbInt32 iMaxDepth = 0; - - try{ - /* - get first node - while interior node - print the left key - level++ - go down one on the left - */ - - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - if( mpTag->npNodeChain ){ - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - } - - // Get the root - if(( iRc = LoadTagDetail( 2, mpTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // lRootBlock is now available - if(( iRc = GetBlock( vpTag, (mpTag->ulRootPage / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // if no keys on this node, then the index is empty - xbUInt32 ulKeyPtr = eGetUInt32( mpTag->npCurNode->cpBlockData ); - if( ulKeyPtr == 0 ){ - iErrorStop = 120; - iRc = XB_EMPTY; - throw iRc; - } - while( !IsLeaf( vpTag, mpTag->npCurNode )){ // go down the chain looking for a leaf node - PrintKey( vpTag, mpTag->npCurNode , 0, iDepth++, 'I', iOutputOpt ); - if(( iRc = GetKeyPtr( vpTag, 0, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - } - if(( iRc = GetKeyPtr( vpTag, 0, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - // loop through the leaf entries of left most leaf - if( iDepth < iMinDepth ) iMinDepth = iDepth; - if( iDepth > iMaxDepth ) iMaxDepth = iDepth; - xbUInt32 ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - for( xbUInt32 ul = 0; ul < ulNoOfKeys; ul++ ){ - PrintKey( vpTag, mpTag->npCurNode , ul, iDepth, 'L', iOutputOpt ); - lKeyCtr++; - } - - // if head node = start node, return - if( mpTag->npCurNode->ulBlockNo == ( mpTag->ulRootPage / (xbUInt32) iBlockFactor )) - return XB_NO_ERROR; - - xbBool bEof = false; - while( !bEof ){ - - // go up the chain, looking for an interior node with more keys on it - xbIxNode * TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - mpTag->npCurNode->npNext = NULL; - TempIxNode->npPrev = NULL; - TempIxNode = FreeNodeChain( TempIxNode ); - iDepth--; - - while( mpTag->npCurNode->iCurKeyNo >= eGetUInt32( mpTag->npCurNode->cpBlockData ) && - mpTag->npCurNode->ulBlockNo != ( mpTag->ulRootPage / (xbUInt32) iBlockFactor) ){ - TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - mpTag->npCurNode->npNext = NULL; - TempIxNode->npPrev = NULL; - TempIxNode = FreeNodeChain( TempIxNode ); - iDepth--; - } - // if head node && right most key, return - if( mpTag->npCurNode->ulBlockNo == (mpTag->ulRootPage / (xbUInt32) iBlockFactor) && - mpTag->npCurNode->iCurKeyNo == eGetUInt32( mpTag->npCurNode->cpBlockData )) - bEof = true; - - if( !bEof ){ - mpTag->npCurNode->iCurKeyNo++; - if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - PrintKey( vpTag, mpTag->npCurNode , mpTag->npCurNode->iCurKeyNo, iDepth++, 'I', iOutputOpt ); - - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - - // traverse down the left side of the tree - while( !IsLeaf( vpTag, mpTag->npCurNode )) // go down the chain looking for a leaf node - { - PrintKey( vpTag, mpTag->npCurNode , 0, iDepth++, 'I', iOutputOpt ); - if(( iRc = GetKeyPtr( vpTag, 0, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - } - if( iDepth < iMinDepth ) iMinDepth = iDepth; - if( iDepth > iMaxDepth ) iMaxDepth = iDepth; - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - for( xbUInt32 ul = 0; ul < ulNoOfKeys; ul++ ){ - PrintKey( vpTag, mpTag->npCurNode , ul, iDepth, 'L', iOutputOpt ); - lKeyCtr++; - } - } - } - xbString s; - s.Sprintf( "Total keys = [%ld] Min Depth = [%d] Max Depth = [%d]", lKeyCtr, iMinDepth, iMaxDepth ); - xbase->WriteLogMessage( s.Str(), 2 ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::DumpIxForTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/**************************************************************************************************************/ -void xbIxMdx::DumpIxNodeChain( void *vpTag, xbInt16 iOutputOpt ) const -{ - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - xbString s( "Dump Node Chain" ); - xbase->WriteLogMessage( s, 2 ); - - if( mpTag->npNodeChain ){ - xbIxNode *n = mpTag->npNodeChain; - xbInt16 iCtr = 0; - char cLeaf; - s.Sprintf( "Cnt\tThis Prev Next CurKeyNo BlockNo Page NoOfKeys Type" ); - xbase->WriteLogMessage( s, iOutputOpt ); - while( n ){ - IsLeaf( vpTag, n ) ? cLeaf = 'L' : cLeaf = 'I'; - s.Sprintf( "%d\t%08x %08x %08x %08d %08d %08d %08ld %c", - iCtr++, n, n->npPrev, n->npNext, n->iCurKeyNo, - n->ulBlockNo, n->ulBlockNo * (xbUInt32) iBlockFactor, - eGetUInt32( n->cpBlockData ), cLeaf ); - xbase->WriteLogMessage( s, 2 ); - n = n->npNext; - } - } else { - s = "Empty Node Chain"; - xbase->WriteLogMessage( s, 2 ); - } -} -#endif - -/***********************************************************************************************/ -xbInt16 xbIxMdx::FindKey( void *vpTag, xbDouble dKey, xbInt16 iRetrieveSw ){ - - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - if( mpTag->cKeyType2 == 'N' ){ // mdx indices store numeric keys as bcd values - xbBcd bcd( dKey ); - return xbIx::FindKey( vpTag, bcd, iRetrieveSw ); - } else // this would be a julian date inquiry - return FindKey( vpTag, &dKey, 8, iRetrieveSw ); -} - -/***********************************************************************************************/ -// iRetrieveSw = 1 - position db file to index position -// 0 - do not position dbf file - -xbInt16 xbIxMdx::FindKey( void *vpTag, const void * vpKey, - xbInt32 lSearchKeyLen, xbInt16 iRetrieveSw ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - // clean up any previous table updates before moving on - if( iRetrieveSw ){ - if( dbf->GetDbfStatus() == XB_UPDATED ){ - if( dbf->GetAutoCommit() == 1 ){ - if(( iRc = dbf->Commit()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } else { - if(( iRc = dbf->Abort()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - } - } - - xbUInt32 ulNoOfKeys; - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - char cKeyType = GetKeyType( vpTag ); - xbBool bDescending = mpTag->cKeyFmt2 & 0x08; - - if( mpTag->npNodeChain ){ - - // determine if the index has been updated since the last time it was used - time_t tFileTs; - if(( iRc = GetFileMtime( tFileTs )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if( mpTag->tNodeChainTs < tFileTs ){ - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - - } else { - // pop up the chain looking for appropriate starting point - xbBool bDone = false; - xbIxNode * TempIxNode; - while( mpTag->npCurNode && !bDone && - (mpTag->npCurNode->ulBlockNo != ( mpTag->ulRootPage / (xbUInt32) iBlockFactor ))){ // not root node - //if no keys on the node, pop up one - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - if( ulNoOfKeys == 0 ){ - TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - - } else { - - iRc = CompareKey( cKeyType, vpKey, GetKeyData( mpTag->npCurNode, 0, mpTag->iKeyItemLen ), (size_t) lSearchKeyLen ); - if( (!bDescending && iRc <= 0) || (bDescending && iRc >= 0 )){ - TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } else { - // get the number of keys on the block and compare the key to the rightmost key - xbUInt32 ulKeyCtr = eGetUInt32( mpTag->npCurNode->cpBlockData ) - 1; // IsLeaf( vpTag, mpTag->npCurNode ); - iRc = CompareKey( cKeyType, vpKey, GetKeyData( mpTag->npCurNode, ulKeyCtr, mpTag->iKeyItemLen), (size_t) lSearchKeyLen ); - - if( (!bDescending && iRc > 0) || (bDescending && iRc < 0 )){ - TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } else { - bDone = true; - } - } - } - } - } - } - - // either started empty, or cleared due to file time diff - if( !mpTag->npNodeChain ){ - // Get the root - if(( iRc = LoadTagDetail( 2, mpTag )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - // lRootBlock is now available - if(( iRc = GetBlock( vpTag, (mpTag->ulRootPage / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - // if this is a leaf node and no keys on this node, then the index is empty - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - if( ulNoOfKeys == 0 && IsLeaf( vpTag, mpTag->npCurNode )){ -// iRc = XB_EMPTY; - iRc = XB_NOT_FOUND; - return iRc; - } - } - - // should be in the appropriate position in the node chain to continue the search from here - // run down through the interior nodes - xbInt16 iSearchRc = 0; - xbUInt32 ulKeyPtr = 0; - - while( vpTag && !IsLeaf( vpTag, mpTag->npCurNode ) ){ - // get the number of keys on the block and compare the key to the rightmost key - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - - if( ulNoOfKeys == 0 ){ - mpTag->npCurNode->iCurKeyNo = 0; - - } else { - - iRc = CompareKey( cKeyType, vpKey, GetKeyData( mpTag->npCurNode, ulNoOfKeys - 1, mpTag->iKeyItemLen), (size_t) lSearchKeyLen ); - if( (!bDescending && iRc > 0) || (bDescending && iRc < 0)){ - mpTag->npCurNode->iCurKeyNo = ulNoOfKeys; - } - else - { - mpTag->npCurNode->iCurKeyNo = (xbUInt32) BSearchBlock( cKeyType, mpTag->npCurNode, - (xbInt32) mpTag->iKeyItemLen, vpKey, (xbInt32) lSearchKeyLen, iSearchRc, bDescending ); - } - } - - if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32)iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - } - - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - xbInt16 iCompRc = 0; - - if( ulNoOfKeys == 0 ){ - // iCompRc = -1; - // iRc = XB_EMPTY; - iRc = XB_NOT_FOUND; - return iRc; - - } else { - - iRc = BSearchBlock( cKeyType, mpTag->npCurNode, mpTag->iKeyItemLen, vpKey, lSearchKeyLen, iCompRc, bDescending ); - // iCompRc - // 0 found - // < 0 eof encountered, search key > last key in file - // > 0 not found, positioned to next key - - if( iCompRc >= 0 ){ - mpTag->npCurNode->iCurKeyNo = (xbUInt32) iRc; - - - if( iRetrieveSw ){ - - xbUInt32 ulKey = mpTag->npCurNode->iCurKeyNo; - if( ulKey >= ulNoOfKeys ) // if position past end of keys, need to go back one and position to last key - ulKey--; - - // if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - - if(( iRc = GetKeyPtr( vpTag, ulKey, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - } - } - } - - if( iCompRc == 0 ) - return XB_NO_ERROR; - else if( iCompRc > 0 ) - return XB_NOT_FOUND; - else - return XB_EOF; - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::FindKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -xbInt16 xbIxMdx::FindKeyForCurRec( void * vpTag ) -{ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 i = 0; - - try{ - if(( iRc = CreateKey( vpTag, 0 )) < XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::FindKeyForCurRec() 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 Get dbf record number for given key number. -/*! - \param vpTag Tag to retrieve dbf rec number on. - \param iKeyNo Key number for retrieval - \param np Pointer to node - \param ulDbfPtr- Output dbf record number - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::GetDbfPtr( void *vpTag, xbInt16 iKeyNo, xbIxNode *np, xbUInt32 &ulDbfPtr ) const { - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - #ifdef XB_DEBUG_SUPPORT - // turn this off in production mode for better performance - xbUInt32 ulNoOfKeys = eGetUInt32 ( np->cpBlockData ); - if( iKeyNo < 0 || iKeyNo > (xbInt16) --ulNoOfKeys ){ - iErrorStop = 100; - throw XB_INVALID_KEYNO; - } - #endif - - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - char *p = ( np->cpBlockData); - p += (8 + (iKeyNo * mpTag->iKeyItemLen)); - ulDbfPtr = eGetUInt32 ( p ); - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::GetDbfPtr() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -/*! - \param vpTag Tag to retrieve first key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw = 0 ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - // convert the tag pointer to mdx tag pointer - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - - - try{ - // clear out any history - if( mpTag->npNodeChain ){ - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - } - // Get the root - if(( iRc = LoadTagDetail( 2, mpTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // lRootPage is available - if(( iRc = GetBlock( vpTag, (mpTag->ulRootPage / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - // if no keys on this node, then the index is empty - // this is not true - - xbUInt32 ulKeyPtr = eGetUInt32( mpTag->npCurNode->cpBlockData ); - if( ulKeyPtr == 0 && IsLeaf( vpTag, mpTag->npCurNode )){ - iRc = XB_EMPTY; - return iRc; - } - - 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; - } - - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - - // retrieve record to data buf - if( iRetrieveSw ){ - if(( iRc = GetKeyPtr( vpTag, 0, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::GetFirstKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//xbBool xbIxMdx::GetIndexUpdated() const { -// std::cout << "xbIxMdx::GetIndexUpdate() FIX ME \n"; -// return xbFalse; -//} - -/***********************************************************************/ -//! @brief Get the key expression for the given tag. -/*! - \param vpTag Tag to retrieve key expression from tag. - \returns Key expression. -*/ - -xbString &xbIxMdx::GetKeyExpression( const void * vpTag ) const{ - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - return *mpTag->sKeyExp; -} - -/***********************************************************************/ -//! @brief Get the key expression for the given tag. -/*! - \param vpTag Tag to retrieve filter expression from tag (if it exists). - \returns Key filter. -*/ - -xbString &xbIxMdx::GetKeyFilter( const void * vpTag ) const{ - - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - - if( mpTag->sFiltExp ) - return *mpTag->sFiltExp; - else - return sNullString; - -} -/**************************************************************************************************/ -xbInt16 xbIxMdx::GetKeyPtr( void *vpTag, xbInt16 iKeyNo, xbIxNode *np, xbUInt32 &ulKeyPtr ) const { - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - - xbMdxTag *mdxTag = (xbMdxTag *) vpTag; - char *p = np->cpBlockData; - xbUInt32 ulKeyCnt = eGetUInt32( p ); - if( iKeyNo < 0 || iKeyNo > (xbInt16) ulKeyCnt ){ - iErrorStop = 100; - iRc = XB_INVALID_KEYNO; - throw iRc; - } - p+=8; // skip past first two four byte numeric fields - p+= (iKeyNo * mdxTag->iKeyItemLen); - ulKeyPtr = eGetUInt32( p ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::GetKeyPtr() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Returns key update status. -/*! - \param vpTag Tag to check status on. - \returns XB_UPD_KEY Key updated.<br> - XB_DEL_KEY Key deleted.<br> - XB_ADD_KEY Key added.<br> - 0 No key updates - -*/ -inline xbInt16 xbIxMdx::GetKeySts( void *vpTag ) const{ - - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - return mpTag->iKeySts; -} - -/***********************************************************************/ -char xbIxMdx::GetKeyType( const void *vpTag ) const { - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - return mpTag->cKeyType; -} - -/***********************************************************************/ -//! @brief Get the last key for the given tag. -/*! - \param vpTag Tag to retrieve last key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::GetLastKey( void *vpTag, xbInt16 iRetrieveSw ){ - return GetLastKey( 0, vpTag, iRetrieveSw ); -} - -/***********************************************************************/ -//! @brief Get the last key for the given tag and starting node. -/*! - \param ulBlockNo Starting node - \param vpTag Tag to retrieve last key on. - \param iRetrieveSw xbTrue - Retrieve the record if key found.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::GetLastKey( xbUInt32 ulBlockNo, void *vpTag, xbInt16 iRetrieveSw ){ - - // if UlNodeNo is zero, start at head node, otherwise start at ulNodeNo - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - // convert the tag pointer to mdx tag pointer - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - - try{ - xbUInt32 ulNoOfKeys = 0; - // clear out any history - if( mpTag->npNodeChain ){ - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - } - // Get the root - if( ulBlockNo == 0 ){ - if(( iRc = LoadTagDetail( 2, mpTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - //if(( iRc = GetBlock( vpTag, (mpTag->ulRootPage / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - if(( iRc = GetBlock( vpTag, PageToBlock( mpTag->ulRootPage ), 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - } else { - if(( iRc = GetBlock( vpTag, ulBlockNo, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - - if( ulNoOfKeys == 0 && IsLeaf( vpTag, mpTag->npCurNode )){ - iRc = XB_EMPTY; - return iRc; - } - - mpTag->npCurNode->iCurKeyNo = ulNoOfKeys; - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - - xbUInt32 ulKeyPtr = 0; - while( !IsLeaf( vpTag, mpTag->npCurNode )){ // go down the chain looking for a leaf node - // std::cout << "Considered an interior node\n"; - if(( iRc = GetKeyPtr( vpTag, ulNoOfKeys, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - mpTag->npCurNode->iCurKeyNo = ulNoOfKeys; - } - // leaf node has one fewer keys than the interior node - mpTag->npCurNode->iCurKeyNo--; - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - - // retrieve record to data buf - if( iRetrieveSw ){ - if(( iRc = GetKeyPtr( vpTag, (ulNoOfKeys-1), mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::GetLastKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Get the last key for a block number. -/*! - \param vpTag Tag to retrieve first key on. - \param ulBlockNo Block number for key retrieval. - \param cpBuf output buffer for key placement - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::GetLastKeyForBlockNo( void *vpTag, xbUInt32 ulBlockNo, char *cpBuf ){ - - // returns the last key for a given block number - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbMdxTag * npTag = (xbMdxTag *) vpTag; - - try{ - xbIxNode * npSaveNodeChain = npTag->npNodeChain; - xbIxNode * npSaveCurNode = npTag->npCurNode; - npTag->npNodeChain = NULL; - - if(( iRc = GetLastKey( ulBlockNo, npTag, 0 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - memcpy( cpBuf, GetKeyData( npTag->npCurNode, GetKeyCount( npTag->npCurNode ) - 1, npTag->iKeyItemLen ), (size_t) npTag->iKeyLen ); - - // free memory - FreeNodeChain( npTag->npNodeChain ); - npTag->npNodeChain = npSaveNodeChain; - npTag->npCurNode = npSaveCurNode; - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::GetLastKeyForBlockNo() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc ) ); - } - return iRc; -} -/***********************************************************************/ -//! @brief Get the next key for the given tag. -/*! - \param vpTag Tag to retrieve next key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::GetNextKey( void * vpTag, xbInt16 iRetrieveSw ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - // convert the tag pointer to mdx tag pointer - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - - try{ - if( !mpTag->npCurNode ) - return GetFirstKey( vpTag, iRetrieveSw ); - - // more keys on this node? - xbUInt32 ulKeyPtr; - if( (eGetUInt32( mpTag->npCurNode->cpBlockData ) - 1) > mpTag->npCurNode->iCurKeyNo ){ - mpTag->npCurNode->iCurKeyNo++; - - if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if( iRetrieveSw ){ - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } else { - return iRc; - } - } else { - return iRc; - } - } - - // if at end head node, then at eof - if( mpTag->npCurNode->ulBlockNo == ( mpTag->ulRootPage / (xbUInt32) iBlockFactor )) - return XB_EOF; - - // This logic assumes that interior nodes have n+1 left node no's where n is the number of keys in the node - xbIxNode * TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - - // While no more right keys && not head node, pop up one node - while( mpTag->npCurNode->iCurKeyNo >= eGetUInt32( mpTag->npCurNode->cpBlockData ) && - mpTag->npCurNode->ulBlockNo != ( mpTag->ulRootPage / (xbUInt32) iBlockFactor) ){ - - TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } - - // if head node && right most key, return eof - if( mpTag->npCurNode->ulBlockNo == (mpTag->ulRootPage / (xbUInt32) iBlockFactor) && - mpTag->npCurNode->iCurKeyNo == eGetUInt32( mpTag->npCurNode->cpBlockData )) - return XB_EOF; - - // move one to the right - mpTag->npCurNode->iCurKeyNo++; - if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - // traverse down the left side of the tree - 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 = 140; - throw iRc; - } - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - // retrieve record to data buf - if( iRetrieveSw ){ - if(( iRc = GetKeyPtr( vpTag, 0, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } else { - return iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::GetNextKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Get the previous key for the given tag. -/*! - \param vpTag Tag to retrieve previous key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::GetPrevKey( void * vpTag, xbInt16 iRetrieveSw ){ - - xbString s; - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - // convert the tag pointer to mdx tag pointer - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - - try{ - if( !mpTag->npCurNode ){ - return GetLastKey( 0, vpTag, iRetrieveSw ); - } - - xbUInt32 ulKeyPtr = 0; - // more keys on this assumed-leaf node? - - if( mpTag->npCurNode->iCurKeyNo > 0 ){ - mpTag->npCurNode->iCurKeyNo--; - - if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - if( iRetrieveSw ){ - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } else { - return iRc; - } - } else { - return iRc; - } - } - - //if head node = start node, at eof - if( mpTag->npCurNode->ulBlockNo == ( mpTag->ulRootPage / (xbUInt32) iBlockFactor )) - return XB_BOF; - - // This logic assumes that interior nodes have n+1 left node no's where n is the number of keys in the node - xbIxNode * TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - - // While no more left keys && not head node, pop up one node - while( mpTag->npCurNode->iCurKeyNo == 0 && - mpTag->npCurNode->ulBlockNo != ( mpTag->ulRootPage / (xbUInt32) iBlockFactor) ){ - TempIxNode = mpTag->npCurNode; - mpTag->npCurNode = mpTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } - - //if head node && left most key, return bof - if( mpTag->npCurNode->ulBlockNo == ( mpTag->ulRootPage / (xbUInt32) iBlockFactor) && mpTag->npCurNode->iCurKeyNo == 0 ) - return XB_BOF; - - // move one to the left - mpTag->npCurNode->iCurKeyNo--; - if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - // traverse down the right side of the tree - xbUInt32 ulNoOfKeys; - while( !IsLeaf( vpTag, mpTag->npCurNode )) // go down the chain looking for a leaf node - { - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - mpTag->npCurNode->iCurKeyNo = ulNoOfKeys; - - if(( iRc = GetKeyPtr( vpTag, ulNoOfKeys, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if(( iRc = GetBlock( vpTag, (ulKeyPtr / (xbUInt32) iBlockFactor), 1 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - - // ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - mpTag->npCurNode->iCurKeyNo = eGetUInt32( mpTag->npCurNode->cpBlockData ) - 1; - - // retrieve record to data buf - if( iRetrieveSw ){ - if(( iRc = GetKeyPtr( vpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } else { - return iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::GetPrevKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief GetReuseEmptyNode swuitch setting. -/*! - \returns xbFalse - Do not reuse empty MDX index nodes (Dbase 6. behavior). - xbTrue - Reuse empty MDX index nodes. -*/ - -xbBool xbIxMdx::GetReuseEmptyNodesSw() const { - return bReuseEmptyNodes; -} -/***********************************************************************/ -xbBool xbIxMdx::GetSortOrder( void *vpTag ) const { - - // return true if descending - xbMdxTag *mTag = (xbMdxTag *) vpTag; - if( mTag->cKeyFmt2 & 0x08 ) - return 0x01; - else - return 0x00; -} - -/***********************************************************************/ -//! @brief Get tag for tag number. -/*! - \param iTagNo - Zero based, which tag to retrieve. - \returns Pointer to mdx tag for a given tag number. -*/ - -void * xbIxMdx::GetTag( xbInt16 iTagNo ) const { - - xbMdxTag *tt = mdxTagTbl; - xbInt16 i = 0; - - while( i < iTagNo && tt->next ){ - tt = tt->next; - i++; - } - if( i == iTagNo ) - return (void *) tt; - else - return NULL; -} - -/***********************************************************************/ -//! @brief Get tag for tag name. -/*! - \sTagName - Tag name to retrieve. - \returns Pointer to mdx tag for a given tag number. -*/ - -void * xbIxMdx::GetTag( xbString &sTagName ) const { - - xbMdxTag *tt = mdxTagTbl; - - while( sTagName != tt->cTagName && tt->next ){ - tt = tt->next; - } - - if( sTagName == tt->cTagName ) - return (void *) tt; - else - return NULL; -} -/***********************************************************************/ -xbInt16 xbIxMdx::GetTagCount() const { - return iTagUseCnt; -} - -/***********************************************************************/ -void xbIxMdx::GetTagName( void *vpTag, xbString &sTagName ){ - - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - sTagName = mpTag->sTagName->Str(); -} - -/***********************************************************************/ -//const char *xbIxMdx::GetTagName( void *vpTag, xbInt16 iOpt ) const { - -const char *xbIxMdx::GetTagName( void *vpTag, xbInt16 ) const { - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - return mpTag->cTagName; -} - -/***********************************************************************/ -xbString &xbIxMdx::GetTagName( void *vpTag ) const { - - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - return *mpTag->sTagName; -} - -/***********************************************************************/ -void *xbIxMdx::GetTagTblPtr() const { - return (void *) mdxTagTbl; -} - -/***********************************************************************/ -xbBool xbIxMdx::GetUnique( void *vpTag ) const { -//! @brief Determine unique setting for given tag. -/*! - \param vpTag Tag to retrieve expression from. - \returns xbTrue if unique key. -*/ - xbMdxTag *mTag = (xbMdxTag *) vpTag; - return mTag->cUnique; -} - -/***********************************************************************/ -//! @brief Harvest Empty Node. -/*! - Harvest empty MDX node and add it to the chain of link nodes - - \param mpTag Tag to harvest. - \param iOpt - 0 Don't write the node info to disk, handled elsewhere (don't write it twice) - 1 Write the update into to disk - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::HarvestEmptyNode( xbMdxTag *mpTag, xbIxNode *npNode, xbInt16 iOpt, xbBool bHarvestRoot ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbBool bRootPage = xbFalse; - xbInt32 iOffset = 0; - - try{ - - if( mpTag->ulRootPage == BlockToPage( npNode->ulBlockNo ) && !bHarvestRoot ){ - bRootPage = xbTrue; - } - memset( npNode->cpBlockData, 0x00, GetBlockSize()); - - char *pTrg = npNode->cpBlockData; - if( !bRootPage ){ - pTrg += 4; - ePutUInt32( pTrg, ulFirstFreePage ); - } - - if( bRootPage ){ - if( mpTag->cHasKeys ){ - - // std::cout << "setting has keys\n"; - - mpTag->cHasKeys = 0x00; - if(( iRc = xbFseek( ((mpTag->ulTagHdrPageNo * 512) + 246), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = xbFwrite( &mpTag->cHasKeys, 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // might need to update left sibling and right sibling here. - // Fields don't seem to be updated consistently by other xbase tools, - // for now, not updating - } - - } else { - - // update header - // seek to position byte 13 - ulFirstFreePage = BlockToPage( npNode->ulBlockNo ); - if(( iRc = xbFseek( 36, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - // write it - char c4[4]; - ePutUInt32( c4, ulFirstFreePage ); - if(( iRc = xbFwrite( c4, 4, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - - if( iOpt == 1 ){ - if(( iRc = xbFseek( (xbInt64) ((npNode->ulBlockNo * GetBlockSize() )) + iOffset, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - // write out the block - if(( iRc = xbFwrite( npNode->cpBlockData, GetBlockSize(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::HarvestEmptyNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Harvest Tag Nodes. -/*! - Save all nodes for a given tag into the free node chain. - Used for reindexing or deleting a given tag. - - \param mpTag Tag for harvesting nodes - \param bHarvestRoot Set to True when deleting tag - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::HarvestTagNodes( xbMdxTag *mpTag, xbBool bHarvestRoot ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbUInt32 ulBlkNo; - xbLinkListOrd<xbUInt32> ll; - xbLinkListNode<xbUInt32> * llN; - xbIxNode * n; - - try{ - - ll.SetDupKeys( xbFalse ); - - // clear out any history - if( mpTag->npNodeChain ){ - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - } - - while( GetNextKey( mpTag, 0 ) == 0 ){ - n = mpTag->npNodeChain; - while(n){ - ll.InsertKey( n->ulBlockNo, (xbUInt32) n->iCurKeyNo ); - n = n->npNext; - } - } - - if( bHarvestRoot ) - ll.InsertKey( PageToBlock( mpTag->ulTagHdrPageNo ), 0 ); - - llN = ll.GetHeadNode(); - if(( n = xbIx::AllocateIxNode( GetBlockSize())) == NULL ){ - iErrorStop = 100; - iRc = XB_NO_MEMORY; - throw iRc; - } - - while( llN ){ - ulBlkNo = llN->GetKey(); - - // read in a block for the block number - if(( iRc = ReadBlock( ulBlkNo, GetBlockSize(), n->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // harvest it - n->ulBlockNo = ulBlkNo; - if(( iRc = HarvestEmptyNode( mpTag, n, 1, bHarvestRoot )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - llN = llN->GetNextNode(); - } - n = FreeNodeChain( n ); - mpTag->npNodeChain = FreeNodeChain( mpTag->npNodeChain ); - mpTag->npCurNode = NULL; - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::HarvestTagNodes() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Insert key into interior node. -/*! - Insert key into non-full interior node.<br> - Assumes valid inputs - - \param vpTag Tag in play. - \param npNode Node for insertion. - \param iSlotNo Slot number to insert key. - \param ulPtr Page number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::InsertNodeI( void *vpTag, xbIxNode *npNode, xbInt16 iSlotNo, xbUInt32 ulPtr ){ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char *pNewKeyPos; - char *pTrg; - char *pLastKey = NULL; - xbMdxTag * npTag; - npTag = (xbMdxTag *) vpTag; - xbInt16 iCopyLen; - xbInt16 iNewKeyPos = 8; - - try{ - xbInt32 lKeyCnt = GetKeyCount( npNode ); - iNewKeyPos += (iSlotNo * npTag->iKeyItemLen); - char *pSrc = npNode->cpBlockData; - - if( iSlotNo < lKeyCnt ) - iCopyLen = ((lKeyCnt - iSlotNo) * npTag->iKeyItemLen) + 4; - else - iCopyLen = 0; - - xbUInt32 ulRqdBufSize = (xbUInt32) ((lKeyCnt + 1) * npTag->iKeyItemLen) + 12; - if( ulRqdBufSize > npNode->ulBufSize ){ - npNode->ulBufSize += (xbUInt32) npTag->iKeyItemLen; - npNode->cpBlockData = (char *) realloc( npNode->cpBlockData, (size_t) npNode->ulBufSize ); - if( !npNode->cpBlockData ){ - iErrorStop = 100; - iRc = XB_NO_MEMORY; - throw iRc; - } - } - - // if not appending to the end of the node, make some room, move things to the right - pNewKeyPos = npNode->cpBlockData; - pNewKeyPos += iNewKeyPos; - - if( iSlotNo < lKeyCnt ){ - pTrg = pNewKeyPos; - pTrg += npTag->iKeyItemLen; - memmove( pTrg, pNewKeyPos, (size_t) iCopyLen ); - } - - // get the right most key for the left part of the split node - xbUInt32 ulKeyPtr2; - if(( iRc = GetKeyPtr( vpTag, npNode->iCurKeyNo, npNode, ulKeyPtr2 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - // get the new right key value for the freshly split node - pLastKey = (char *) malloc((size_t) npTag->iKeyLen); - if(( iRc = GetLastKeyForBlockNo( vpTag, PageToBlock( ulKeyPtr2 ), pLastKey )) != XB_NO_ERROR ){ - iRc = 120; - throw iRc; - } - - // write the key values - pTrg = pNewKeyPos; - pTrg += 4; - 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 ); - - // write out the updated block to disk - if(( iRc = WriteBlock( npNode->ulBlockNo, GetBlockSize(), npNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( pLastKey ) - free( pLastKey ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::InsertNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( pLastKey ) - free( pLastKey ); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Insert key into leaf node. -/*! - Insert key into non-full leaf node.<br> - Assumes valid inputs - - \param vpTag Tag in play. - \param npNode Node for insertion. - \param iSlotNo Slot number to insert key. - \param ulPtr Pointer number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::InsertNodeL( void *vpTag, xbIxNode *npNode, xbInt16 iSlotNo, char * cpKeyBuf, xbUInt32 ulPtr ){ - - // format of block data is - // 4 bytes number of keys on block - // 4 bytes - next free block or split block num - // repeating - // 4 bytes record number - // x bytes key data - - // Special processing note: when splitting node, new key is first inserted into full left node before - // the node is split. This routine will make additional room in the buffer for that scenario - - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char *pNewKeyPos; // pointer to position in record for new key composite - char *pTrg; - - xbInt16 iNewKeyPos = 8; // position in data block where new key begins. - // is the position of the record number, where the fmt is - // [four byte rec number][actual key data] repeats - - xbMdxTag * npTag = (xbMdxTag *) vpTag; - xbInt16 iCopyLen; - - try{ - xbInt32 lKeyCnt = GetKeyCount( npNode ); - iNewKeyPos += (iSlotNo * npTag->iKeyItemLen); - - // length of number of keys that need to be moved to the right - if( iSlotNo < lKeyCnt ) - iCopyLen = (lKeyCnt - iSlotNo) * npTag->iKeyItemLen; - else - iCopyLen = 0; - - // +8 is to include the first two 4 byte fields in the block - xbUInt32 ulRqdBufSize = (xbUInt32) ((lKeyCnt + 1) * npTag->iKeyItemLen) + 8; - - if( ulRqdBufSize > npNode->ulBufSize ){ - - npNode->ulBufSize += (xbUInt32) npTag->iKeyItemLen; - npNode->cpBlockData = (char *) realloc( npNode->cpBlockData, (size_t) npNode->ulBufSize ); - - // init the newly acquired buffer space - char *p = npNode->cpBlockData; - p += (npNode->ulBufSize - (xbUInt32) npTag->iKeyItemLen); - memset( p, 0x00, (size_t) npTag->iKeyItemLen ); - - if( !npNode->cpBlockData ){ - iErrorStop = 100; - iRc = XB_NO_MEMORY; - throw iRc; - } - } - - // if not appending to end, move things right - - pNewKeyPos = npNode->cpBlockData; - pNewKeyPos += iNewKeyPos; - - if( iSlotNo < lKeyCnt ) { - pTrg = pNewKeyPos; - pTrg += npTag->iKeyItemLen; - memmove( pTrg, pNewKeyPos, (size_t) iCopyLen ); - - } - - // write rec number - ePutUInt32( pNewKeyPos, ulPtr ); - - // write the key value - pTrg = pNewKeyPos; - pTrg += 4; - char * pSrc = cpKeyBuf; - for( xbInt16 i = 0; i < npTag->iKeyLen; i++ ) - *pTrg++ = *pSrc++; - - // update number of keys on the node - ePutInt32( npNode->cpBlockData, ++lKeyCnt ); - - // determine length of node, zap everything to the right of it - xbUInt32 iStartPos = 8 + ((xbUInt32) lKeyCnt * (xbUInt32) npTag->iKeyItemLen ); - xbUInt32 iClearLen = npNode->ulBufSize - iStartPos; - - char *p = npNode->cpBlockData; - p += iStartPos; - memset( p, 0x00, iClearLen ); - - // write out the updated block to disk - if(( iRc = WriteBlock( npNode->ulBlockNo, GetBlockSize(), npNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::InsertNodeL() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -inline xbBool xbIxMdx::IsLeaf( void *vpTag, xbIxNode *npNode ) const{ - - // for performance reasons, does no data checking - // will result in potentially hard to find segfaults if passing invalid npNode - - xbMdxTag *mTag = (xbMdxTag *) vpTag; - char *p = npNode->cpBlockData; - - xbInt32 lNoOfKeys = eGetInt32( p ); - // mdx interior nodes have a sibling number to the right of the right most key in the node - p+=8; - p+= mTag->iKeyItemLen * lNoOfKeys; - - if( eGetUInt32( p ) == 0 ){ - // std::cout << "leaf node\n"; - return true; - } else { - // std::cout << "interior node\n"; - return false; - } -} - -/***********************************************************************/ -xbInt16 xbIxMdx::KeyExists( void * vpTag ) -{ - // this method assumes the key has already been built - - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - xbInt16 iRc = FindKey( vpTag, mpTag->cpKeyBuf, mpTag->iKeyLen, 0 ); - - if( iRc == 0 ) - return 1; - else - return 0; - -} - -/***********************************************************************/ -//! @brief Set position for key add. -/*! - This routine is called by the AddKey() method and is used to position - the node chain to the position the new key should be added to the index. - - \param npTag Pointer to npTag. - \param ulAddRecNo Record number to add. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxMdx::KeySetPosAdd( xbMdxTag *mpTag, xbUInt32 ulAddRecNo ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - iRc = FindKey( mpTag, mpTag->cpKeyBuf, mpTag->iKeyLen, 0 ); - if( iRc == XB_NOT_FOUND || iRc == XB_EMPTY ) - return XB_NO_ERROR; // good position - else if( iRc != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // get here if key was found, get the right most instance of any non unique key for append, find correct spot for update - if( GetUnique( mpTag ) == 0 ){ - - xbUInt32 ulCurRecNo; - if(( iRc = GetDbfPtr( mpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulCurRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - xbBool bKeysMatch = xbTrue; - - while( bKeysMatch && ulAddRecNo > ulCurRecNo && iRc == XB_NO_ERROR ){ - if(( iRc = GetNextKey( mpTag, 0 )) == XB_NO_ERROR ){ - if( memcmp( GetKeyData( mpTag->npCurNode, mpTag->npCurNode->iCurKeyNo, mpTag->iKeyItemLen ), mpTag->cpKeyBuf, (size_t) mpTag->iKeyLen )) - bKeysMatch = xbFalse; - else{ - if(( iRc = GetDbfPtr( mpTag, mpTag->npCurNode->iCurKeyNo, mpTag->npCurNode, ulCurRecNo )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - } - } - } - if( iRc == XB_EOF ){ // eof condition - if(( iRc = GetLastKey( 0, mpTag, 0 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - mpTag->npCurNode->iCurKeyNo++; - return XB_NO_ERROR; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::KeySetPosAdd() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Set position for key delete. -/*! - This routine is called by the DeleteKey() method and is used to position - the node chain to the position the old key should be deleted from the index. - - \param npTag Pointer to npTag. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::KeySetPosDel( xbMdxTag *npTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbString sMsg; - - try{ - - iRc = FindKey( npTag, npTag->cpKeyBuf2, npTag->iKeyLen, 0 ); - if( iRc == XB_NOT_FOUND || iRc == XB_EMPTY ) - return XB_NO_ERROR; // good pos ition - else if( iRc != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - xbUInt32 ulIxRecNo; - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulIxRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - if( ulIxRecNo == dbf->GetCurRecNo()) - return XB_NO_ERROR; - - if( GetUnique( npTag ) == 1 ){ - iErrorStop = 120; - iRc = XB_NOT_FOUND; - throw iRc; - } - - xbBool bFound = xbFalse; - xbBool bKeysMatch = xbTrue; - while( bKeysMatch && !bFound && iRc == XB_NO_ERROR ){ - - if(( iRc = GetNextKey( npTag, 0 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( memcmp( GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), npTag->cpKeyBuf2, (size_t) npTag->iKeyLen )){ - bKeysMatch = xbFalse; - } else { - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulIxRecNo )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if( ulIxRecNo == dbf->GetCurRecNo()) - bFound = xbTrue; - } - } - - if( bFound ) - return XB_NO_ERROR; - else - return XB_NOT_FOUND; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::KeySetPosDel() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Returns key update status. -/*! - \param vpTag Tag to check status on. - \returns xbtrue - Key was updated.<br>xbFalse - Key not updated. -*/ -/* -inline xbBool xbIxMdx::KeyFiltered( void *vpTag ) const{ - - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - return mpTag->bKeyFiltered; -} -*/ -/***********************************************************************/ -xbInt16 xbIxMdx::LoadTagDetail( xbInt16 iOption, xbMdxTag *tte ){ - - // option 1 - Load the entire tag detail - // option 2 - Load the dynamic variables only - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - size_t iReadSize; - char *buf = NULL; - char *p; - - try{ - // set the read length based on the option - if( iOption == 1 ) - iReadSize = 1024; - - else if( iOption == 2 ) - // iReadSize = 4; - iReadSize = 260; - else{ - iRc = XB_INVALID_OPTION; - iErrorStop = 100; - throw iRc; - } - if(( buf = (char *) calloc( 1, (size_t) iReadSize )) == NULL ){ - iErrorStop = 110; - iRc = XB_NO_MEMORY; - throw iRc; - } - if(( iRc = ReadBlock( tte->ulTagHdrPageNo,(xbUInt32) (GetBlockSize() / (xbUInt16) iBlockFactor), - iReadSize, buf )) != XB_NO_ERROR ){ - free( buf ); - iErrorStop = 30; - throw iRc; - } - - p = buf; - tte->ulRootPage = eGetUInt32( p ); - - if( iOption == 1 ){ - p+=4; - tte->ulTagSize = eGetUInt32( p ); - p+=4; - tte->cKeyFmt2 = *p; - p++; - tte->cKeyType2 = *p; - p+=3; - tte->iKeyLen = eGetInt16( p ); - p+=2; - tte->iKeysPerBlock = *p; - p+=2; - tte->iSecKeyType = eGetInt16( p ); - p+=2; - tte->iKeyItemLen = eGetInt16( p ); - p+=2; - tte->cSerialNo = *p; - p+=3; - tte->cUnique = *p; - p++; - - // next line assumes expression is a null terminated string in the block - tte->sKeyExp = new xbString(); - tte->sKeyExp->Sprintf( "%s", p ); - - p+=221; - tte->cHasFilter = *p; - p+=1; - tte->cHasKeys = *p; - p+=2; - tte->ulLeftChild = eGetUInt32( p ); - p+=4; - tte->ulRightChild = eGetUInt32( p ); - p+=5; - tte->cTagYY = *p; - p++; - tte->cTagMM = *p; - p++; - tte->cTagDD = *p; - // p+=223; - - p+=221; - tte->cKeyFmt3 = *p; - - if( tte->cHasFilter ){ - p+=282; - tte->sFiltExp = new xbString(); - tte->sFiltExp->Sprintf( "%s", p ); - tte->filter = new xbExp( xbase, dbf ); - if(( iRc = tte->filter->ParseExpression( tte->sFiltExp->Str())) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - tte->npNodeChain = NULL; - tte->npCurNode = NULL; - tte->cpKeyBuf = (char *) malloc( (size_t) tte->iKeyLen + 1 ); - tte->cpKeyBuf2 = (char *) malloc( (size_t) tte->iKeyLen + 1 ); - tte->exp = new xbExp( xbase, dbf ); - if(( iRc = tte->exp->ParseExpression( tte->sKeyExp->Str() )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } else if( iOption == 2 ){ - // refresh the dynamic tag variables - p+=4; - tte->ulTagSize = eGetUInt32( p ); - p+= 16; - tte->cSerialNo = *p; - p+= 226; - tte->cHasKeys = *p; - p+=2; - tte->ulLeftChild = eGetUInt32( p ); - p+=4; - tte->ulRightChild = eGetUInt32( p ); - p+=5; - tte->cTagYY = *p; - p++; - tte->cTagMM = *p; - p++; - tte->cTagDD = *p; - } - if( buf ) - free( buf ); - - } - catch (xbInt16 iRc ){ - if( buf ) - free( buf ); - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::LoadTagDetail() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -xbInt16 xbIxMdx::LoadTagTable() -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char * buf = NULL; - - //std::cout << "xbIxMdx::LoadTagTable() tag use cnt = " << iTagUseCnt << "\n"; - - try{ - - if( iTagUseCnt > 46 ){ - iErrorStop = 100; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - xbInt16 iBufSize = (xbInt16) iTagLen * iTagUseCnt; - - if(( buf = (char *) malloc( (size_t) iBufSize )) == NULL ){ - iErrorStop = 110; - iRc = XB_NO_MEMORY; - throw iRc; - } - - if(( iRc = xbFseek( 544, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - if(( iRc = xbFread( buf, (size_t) iBufSize, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - xbInt16 iPos; - char *p; - xbMdxTag *tte; - xbMdxTag *ttel = NULL; - - for( xbInt16 i = 0; i < iTagUseCnt; i++ ){ - iPos = i * iTagLen; - p = buf + iPos; - - if(( tte = (xbMdxTag *) calloc( 1, (size_t) sizeof( xbMdxTag ))) == NULL ){ - iErrorStop = 140; - iRc = XB_NO_MEMORY; - throw iRc; - } - - // set the current tag to the first tag in the table - if( !vpCurTag ) - xbIx::SetCurTag( (void *) tte ); - - if( mdxTagTbl ) - ttel->next = tte; - else - mdxTagTbl = tte; - - ttel = tte; - tte->next = NULL; - tte->ulTagHdrPageNo = eGetUInt32( p ); - - p += 4; - for( xbUInt32 i = 0; i < 11; i ++ ) - tte->cTagName[i] = *p++; - - tte->cTagName[11] = 0x00; - tte->cKeyFmt = *p++; - tte->cLeftChild = *p++; - tte->cRightChild = *p++; - tte->cParent = *p++; - tte->c2 = *p++; - tte->cKeyType = *p; - tte->sTagName = new xbString(); - tte->sTagName->Set( tte->cTagName ); - tte->sTagName->Trim(); - - if(( iRc = LoadTagDetail( 1, tte )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - if( buf ) - free( buf ); - } - catch (xbInt16 iRc ){ - if( buf ) - free( buf ); - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::LoadTagTable() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - if( iErrorStop == 100 ){ - sMsg.Sprintf( "xbIxMdx::LoadTagTable() Invalid Tag Count: %d", iTagUseCnt ); - xbase->WriteLogMessage( sMsg.Str()); - } - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/**************************************************************************************************************/ -//! @brief Calculate the block number for a given page. -/*! - This routine is called by any function needing to calculate the block number for a given page. - Page numbers are stored internally in the physical file, and the library reads and writes in - blocks of one or more pages. - - Assumes valid data input - - \param ulPageNo Page Number - \returns Calculated block number. -*/ - -inline xbUInt32 xbIxMdx::PageToBlock( xbUInt32 ulPageNo ){ - return ulPageNo / (xbUInt32) iBlockFactor; -} - - - -/**************************************************************************************************************/ -#ifdef XB_DEBUG_SUPPORT -xbInt16 xbIxMdx::PrintKey( void *vpTag, xbIxNode *npNode, xbInt16 iKeyNo, xbInt16 iDepth, char cType, xbInt16 iOutputOpt ){ - - xbString sPre; - sPre.Sprintf( "%c ", cType ); - for( xbInt16 i = 0; i < iDepth; i++ ) - sPre += "|"; - - xbString sPost; - sPost.Sprintf( "\tThisBlock=[%ld] KeyNo=[%d] Depth=[%d]", npNode->ulBlockNo, iKeyNo, iDepth ); - - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - char *p = npNode->cpBlockData + (8 + (iKeyNo * mpTag->iKeyItemLen )); - - xbString sKeyPtr; - xbUInt32 ulNoOfKeys = 0; - if( cType == 'I' ) { // interior - sKeyPtr.Sprintf( " ptr=[%ld]", eGetUInt32( p )); - ulNoOfKeys = eGetUInt32( mpTag->npCurNode->cpBlockData ); - } - else if( cType == 'L' ) // leaf - sKeyPtr.Sprintf( " rec=[%ld]", eGetUInt32( p )); - p += 4; - - xbString s; - if(( cType == 'I' && iKeyNo < (xbInt16) ulNoOfKeys) || cType == 'L' ){ - if( mpTag->cKeyType2 == 'C' ){ //CHAR - for( xbInt32 l = 0; l < (mpTag->iKeyItemLen-4); l++ ) - s += *p++; - - } else if( mpTag->cKeyType2 == 'N' ){ // NUMERIC - xbBcd bcd( p ); - xbString s2; - bcd.ToString( s2 ); - s += s2; - - } else if( mpTag->cKeyType2 == 'D' ){ // DATE - xbInt32 lDate = (xbInt32) eGetDouble( p ); - xbDate d( lDate ); - //xbString s2; - //d.JulToDate8( lDate, s2 ); - s.Sprintf( "%s%s", s.Str(), d.Str()); - } - } else { - s = "Rightmost InteriorNode Pointer"; - } - - xbString sOut( sPre ); - sOut += s; - sOut += sPost; - sOut += sKeyPtr; - - xbase->WriteLogMessage( sOut, iOutputOpt ); - return XB_NO_ERROR; -} -#endif - -/***********************************************************************/ -//! @brief ReadHeadBlock. -/*! - Read values off head block in MDX file - \param iOpt 0 - Read entire block, initialize as needed.<br> - 1 - Read in only dynamic section of block<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> - -*/ - -xbInt16 xbIxMdx::ReadHeadBlock( xbInt16 iOpt ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - if( !FileIsOpen()){ - iRc = XB_NOT_OPEN; - iErrorStop = 100; - throw iRc; - } - char sBuf[48]; - memset( sBuf, 0x00, 48 ); - - if( iOpt == 0 ){ - if(( iRc = xbFseek( 0, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - if(( iRc = xbFread( sBuf, 47, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } else { - - if(( iRc = xbFseek( 28, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - if(( iRc = xbFread( sBuf, 19, 1 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - } - - char *p = sBuf; - if( iOpt == 0 ){ - cVersion = *p++; - cCreateYY = *p++; - cCreateMM = *p++; - cCreateDD = *p++; - sFileName.Assign( p, 1, 16 ); - p+=16; - iBlockFactor = eGetInt16( p ); - p+=2; - SetBlockSize( (xbUInt32) eGetInt16( p )); - p+=2; - cProdIxFlag = *p++; - cTagEntryCnt = *p++; - iTagLen = *p; - p+=2; - - iTagUseCnt = eGetInt16( p ); - //lTagUseCnt = eGetInt32( p ); - //p+=4; - p+=2; - cNextTag = *p++; - c1B = *p++; - - ulPageCnt = eGetUInt32( p ); - p+=4; - ulFirstFreePage = eGetUInt32( p ); - p+=4; - ulNoOfBlockAvail = eGetUInt32( p ); - p+=4; - cUpdateYY = *p++; - cUpdateMM = *p++; - cUpdateDD = *p; - - if( cNodeBuf ) - free( cNodeBuf ); - - if(( cNodeBuf = (char *) malloc( (size_t) GetBlockSize())) == NULL ){ - iErrorStop = 150; - throw XB_NO_MEMORY; - } - - if(( iRc = xbIxMdx::LoadTagTable()) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - - } else { - iTagUseCnt = eGetInt16( p ); - p+=4; - ulPageCnt = eGetUInt32( p ); - p+=4; - ulFirstFreePage = eGetUInt32( p ); - p+=4; - ulNoOfBlockAvail = eGetUInt32( p ); - p+=4; - cUpdateYY = *p++; - cUpdateMM = *p++; - cUpdateDD = *p; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::ReadHeadBlock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( cNodeBuf ) - free( cNodeBuf ); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Reindex -/*! - Reindex specifed tag or all tags - \param **vpTag &tag - Tag to reindex.<br> - NULL - Reindex all tags<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> - - If this method fails, the index is left in an undefined state - -*/ - -xbInt16 xbIxMdx::Reindex( void **vpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag * mpTag; - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif - - if( vpTag ) - mpTag = (xbMdxTag *) *vpTag; - else - mpTag = NULL; - - struct tagInfo{ - xbBool bUnique; - xbBool bDesc; - char sTagName[11]; - xbString *sKeyExp; - xbString *sFiltExp; - tagInfo *next; - }; - tagInfo *ti = NULL; - - try{ - - #ifdef XB_LOCKING_SUPPORT - if( dbf->GetAutoLock() && !dbf->GetTableLocked() ){ - if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - bLocked = xbTrue; - } - #endif - - if( mpTag == NULL ){ - // do all tags - xbMdxTag *tt = mdxTagTbl; - tagInfo *pHead = NULL; - tagInfo *pEnd = NULL; - - if( tt ){ - while( tt ){ - ti = (tagInfo *) calloc( 1, sizeof( tagInfo )); - ti->bUnique = tt->cUnique ? 1 : 0; - ti->bDesc = (((tt->cKeyFmt2 & 0x08) > 0) ? 1 : 0); - memcpy( ti->sTagName, tt->cTagName, 11 ); - ti->sKeyExp = new xbString( tt->sKeyExp->Str()); - if( tt->cHasFilter ) - ti->sFiltExp = new xbString( tt->sFiltExp->Str()); - else - ti->sFiltExp = new xbString( "" ); - if( !pHead ) - pHead = ti; - else - pEnd->next = ti; - pEnd = ti; - tt = tt->next; - } - } - - // get the file name and save it - xbString sMdxFileName = GetFqFileName(); - - // close the mdx file - if(( iRc = xbIxMdx::Close()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - // delete the file - xbRemove(); - - // init variables - Init(); - - tagInfo *p = pHead; - tagInfo *pDel; - - // create new file & add the tags - while( p ){ - - if(( iRc = CreateTag( p->sTagName, p->sKeyExp->Str(), p->sFiltExp->Str(), p->bDesc, p->bUnique, xbTrue, vpTag )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - delete p->sKeyExp; - delete p->sFiltExp; - pDel = p; - p = p->next; - free( pDel ); - } - } else { - if(( iRc = HarvestTagNodes( mpTag )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - - xbUInt32 ulRecCnt = 0; - if(( iRc = dbf->GetRecordCnt( ulRecCnt )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - xbInt16 iCurTag = 0; - xbBool bDone = xbFalse; - - for( xbUInt32 ulRec = 1; ulRec <= ulRecCnt; ulRec++ ){ - if(( iRc = dbf->GetRecord( ulRec )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - bDone = xbFalse; - iCurTag = 0; - if( !vpTag ) - mpTag = (xbMdxTag *) GetTag( iCurTag++ ); - - while( !bDone ){ - // do the tag things - // CreateKey - if(( iRc = CreateKey( mpTag, 1 )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if( mpTag->iKeySts == XB_ADD_KEY ){ - if( mpTag->cUnique ){ - if(( iRc = CheckForDupKey( mpTag )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - if(( iRc = AddKey( mpTag, ulRec )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - } - if( vpTag || iCurTag >= GetTagCount()) - bDone = xbTrue; - else - mpTag = (xbMdxTag *) GetTag( iCurTag++ ); - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::ReIndex() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - this->DeleteTag( mpTag ); - } - - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - dbf->LockTable( XB_UNLOCK ); - } - #endif - return iRc; -} - -/***********************************************************************/ -xbInt16 xbIxMdx::SetCurTag( xbString &sTagName ) { - - xbMdxTag *tt = (xbMdxTag *) GetTag( sTagName ); - if( tt ){ - xbIx::SetCurTag((void *) tt ); - return XB_NO_ERROR; - } else - return XB_INVALID_TAG; -} - -/***********************************************************************/ -xbInt16 xbIxMdx::SetCurTag( xbInt16 iTagNo ) { - - xbMdxTag *tt = (xbMdxTag *) GetTag( iTagNo ); - if( tt ){ - xbIx::SetCurTag((void *) tt ); - return XB_NO_ERROR; - } else - return XB_INVALID_TAG; -} - -/***********************************************************************/ -//! @brief SetReuseEmptyNode switch setting. -/*! - \param bEmptyNodeSw xbFalse - Do not reuse empty MDX index nodes (Dbase 6. behavior). - xbTrue - Reuse empty MDX index nodes. -*/ - -void xbIxMdx::SetReuseEmptyNodesSw( xbBool bEmptyNodesSw ) { - bReuseEmptyNodes = bEmptyNodesSw; -} - -/***********************************************************************/ -//! @brief Split an interior node -/*! - - This routine splits an interior node into two nodes, divided by dSplitFactor.<br> - This behaves differently than V7 Dbase. V7 does not balance the nodes.<br> - For V7, if adding a key to the end of a node, it will create a right node - with only one key, and the left node is still full.<br><br> - - Possible performance improvement options.<br> - Two modes when splitting:<br> - a) Split nodes in the middle - good for random access applications<br> - b) Split off right node with only one key - good for applications with - expectation of ascending keys added moving forward.<br> - - This routine first inserts the key into the left node in the appropriate location - then splits the node based on the split factor setting. - - \param vpTag Tag in play. - \param npLeft Left node to split. - \param npRight Right node to split. - \param iSlotNo Slot number for split. - \param ulPtr Pointer number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::SplitNodeI( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, xbInt16 iSlotNo, xbUInt32 ulPtr ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag * npTag = (xbMdxTag *) vpTag; - xbDouble dSplitFactor = .5; // split the nodes 50/50 - xbInt16 iLen; - char *pSrc; - char *pTrg; - - try{ - xbInt32 lKeyCnt = GetKeyCount( npLeft ); - xbInt32 lNewLeftKeyCnt = (xbInt32) ((lKeyCnt + 1) * dSplitFactor); - xbInt32 lNewRightKeyCnt = lKeyCnt - lNewLeftKeyCnt; - if(( iRc = InsertNodeI( vpTag, npLeft, iSlotNo, ulPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // move the right half of the left node to the right node - pSrc = npLeft->cpBlockData; - pSrc += 8 + ((lNewLeftKeyCnt+1) * npTag->iKeyItemLen); - pTrg = npRight->cpBlockData; - pTrg += 8; - iLen = (lNewRightKeyCnt * npTag->iKeyItemLen) + 4; - memmove( pTrg, pSrc, (size_t) iLen ); - - // eliminate chattle on the right - iLen = 12 + (lNewLeftKeyCnt * npTag->iKeyItemLen); - pSrc = npLeft->cpBlockData; - pSrc += iLen; - memset( pSrc, 0x00, npLeft->ulBufSize - (xbUInt32) iLen ); - - // write the new key counts into the nodes - pTrg = npLeft->cpBlockData; - ePutInt32( pTrg, lNewLeftKeyCnt ); - pTrg = npRight->cpBlockData; - ePutInt32( pTrg, lNewRightKeyCnt ); - - // write out the block - if(( iRc = WriteBlock( npLeft->ulBlockNo, GetBlockSize(), npLeft->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // write out the block - if(( iRc = WriteBlock( npRight->ulBlockNo, GetBlockSize(), npRight->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::SplitNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Split a leaf node. -/*! - This routine splits an index leaf into two nodes, divided by dSplitFactor.<br> - - Possible performance improvement options.<br> - Two modes when splitting:<br> - a) Split nodes in the middle - good for random access applications<br> - b) Split off right node with only one key - good for applications with - expectation of ascending keys added moving forward.<br> - - This routine first inserts the key into the left node in the appropriate location - then splits the node based on the split factor setting. - - \param vpTag Tag in play. - \param npLeft Left node to split. - \param npRight Right node to split. - \param iSlotNo Slot number for split. - \param ulPtr Pointer number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::SplitNodeL( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, - xbInt16 iSlotNo, char * cpKeyBuf, xbUInt32 ulPtr ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbDouble dSplitFactor = .5; // can adjust performance with this number - xbMdxTag *mpTag = (xbMdxTag *) vpTag; - xbString sMsg; - - xbInt16 iLen; - char *pSrc; - char *pTrg; - - // std::cout << "In xbIxMdx::SplitNodeL()\n"; - try{ - xbInt32 lKeyCnt = GetKeyCount( npLeft ); - xbInt32 lNewLeftKeyCnt = (xbInt32) ((lKeyCnt + 1) * dSplitFactor) + 1; - xbInt32 lNewRightKeyCnt = lKeyCnt + 1 - lNewLeftKeyCnt; - - if(( iRc = InsertNodeL( vpTag, npLeft, iSlotNo, cpKeyBuf, ulPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // move right half off of left node to the right node - pSrc = npLeft->cpBlockData; - pSrc += 8 + (lNewLeftKeyCnt * mpTag->iKeyItemLen); - pTrg = npRight->cpBlockData; - pTrg += 8; - iLen = lNewRightKeyCnt * mpTag->iKeyItemLen; - memmove( pTrg, pSrc, (size_t) iLen ); - - // write the new key counts into the nodes - pTrg = npLeft->cpBlockData; - ePutInt32( pTrg, lNewLeftKeyCnt ); - pTrg = npRight->cpBlockData; - ePutInt32( pTrg, lNewRightKeyCnt ); - - // zero out the next key number so this node is not confused with interior node - iLen = 8 + (lNewLeftKeyCnt * mpTag->iKeyItemLen); - pSrc = npLeft->cpBlockData; - pSrc += iLen; - memset( pSrc, 0x00, npLeft->ulBufSize - (xbUInt32) iLen ); - - // write out the left block - if(( iRc = WriteBlock( npLeft->ulBlockNo, GetBlockSize(), npLeft->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // write out the right block - if(( iRc = WriteBlock( npRight->ulBlockNo, GetBlockSize(), npRight->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::SplitNodeL() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/**************************************************************************************************************/ -//! @brief TagSerialNo. -/*! - This routine is used internally for reading or updating the serial number on a given tag when the tag. - - \param iOption 1 - Read tag serial number off disk, save in structure<br> - 2 - Write serial number from memory to disk<br> - 3 - Read serial number off disk, increment, write updated number to disk<br> - mpTag - Pointer to tag for serial number update - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::TagSerialNo( xbInt16 iOption, xbMdxTag * mpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - xbInt64 lPos = (mpTag->ulTagHdrPageNo * 512) + 20; - - if( iOption != 2 ){ - if(( iRc = xbFseek( lPos, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = xbFgetc( mpTag->cSerialNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - - if( iOption == 3 ) - mpTag->cSerialNo++; - - if( iOption != 1 ){ - if(( iRc = xbFseek( lPos, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = xbFwrite( &mpTag->cSerialNo, 1, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::UpdateSerialNo() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief UpdateTagKey -/*! - This routine updates a key or a given tag. - The file header is considered to be the first 2048 bytes in the file. - - \param cAction A - Add a key.<br> - D - Delete a key.<br> - R - Revise a key.<br> - \param vpTg - Pointer to tag.<br> - \param ulRecNo - Record number association with the action.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxMdx::UpdateTagKey( char cAction, void *vpTag, xbUInt32 ulRecNo ){ - - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag *npTag = (xbMdxTag *) vpTag; - - try{ - // save off any needed fields for updating - xbUInt32 ulTagSizeSave = npTag->ulTagSize; - - if( cAction == 'D' || cAction == 'R' ){ - // std::cout << "UpdateTagKey-delete going to DeleteKey \n"; - if(( iRc = DeleteKey( vpTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - - if( cAction == 'A' || cAction == 'R' ){ - if(( iRc = AddKey( vpTag, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - if( ulTagSizeSave != npTag->ulTagSize ){ - if(( iRc = UpdateTagSize( npTag, npTag->ulTagSize )) != XB_NO_ERROR) { - iErrorStop = 120; - throw iRc; - } - } - // update the serial number - if(( iRc = TagSerialNo( 3, npTag )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::UpdateTagKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/**************************************************************************************************************/ -//! @brief Write head block. -/*! - This routine updates the MDX file header and commits changes to disk. - The file header is considered to be the first 2048 bytes in the file. - - \param iOption 0 - Entire 2048 byte header, used for creating a new mdx file.<br> - 1 - Bytes 28 through 46, used when adding or deleting a tag.<br> - 2 - Bytes 32 through 46, used after updating keys in the file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbIxMdx::WriteHeadBlock( xbInt16 iOption ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - xbDate d; - d.Sysdate(); // set to system date, today - cUpdateYY = (char) d.YearOf() - 1900; - cUpdateMM = (char) d.MonthOf(); - cUpdateDD = (char) d.DayOf( XB_FMT_MONTH ); - - if( iOption > 0 ){ - char buf[48]; - memset( buf, 0x00, 48 ); - xbUInt32 ulStartPos = 0; - xbUInt32 ulLen = 0; - - if( iOption == 1 ){ - ePutInt16( &buf[28], iTagUseCnt ); - buf[30] = cNextTag; - buf[31] = 0x1b; - ulStartPos = 28; - ulLen = 19; - } else { - ulStartPos = 32; - ulLen = 16; - } - - ePutUInt32( &buf[32], ulPageCnt ); - ePutUInt32( &buf[36], ulFirstFreePage ); - ePutUInt32( &buf[40], ulNoOfBlockAvail ); - buf[44] = cUpdateYY; - buf[45] = cUpdateMM; - buf[46] = cUpdateDD; - - if(( iRc = xbFseek( ulStartPos, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - if(( iRc = xbFwrite( &buf[ulStartPos], ulLen, 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - } else if( iOption == 0 ){ - char buf[2048]; - memset( buf, 0x00, 2048 ); - - buf[0] = cVersion; - cCreateYY = cUpdateYY; - cCreateMM = cUpdateMM; - cCreateDD = cUpdateDD; - buf[1] = cCreateYY; - buf[2] = cCreateMM; - buf[3] = cCreateDD; - - - for( xbUInt32 l = 0; l < sFileName.Len() && l < 10; l++ ){ - buf[l+4] = sFileName[l+1]; - } - - ePutInt16( &buf[20], iBlockFactor ); - ePutInt16( &buf[22], (xbInt16) GetBlockSize() ); - - buf[24] = cProdIxFlag; - buf[25] = cTagEntryCnt; - ePutInt16 ( &buf[26], iTagLen ); - ePutInt16 ( &buf[28], iTagUseCnt ); - buf[30] = cNextTag; - buf[31] = c1B; - ePutUInt32( &buf[32], ulPageCnt ); - ePutUInt32( &buf[36], ulFirstFreePage ); - ePutUInt32( &buf[40], ulNoOfBlockAvail ); - buf[44] = cUpdateYY; - buf[45] = cUpdateMM; - buf[46] = cUpdateDD; - - // not sure what the following "1" is for in a sea of zeroes.... - // maybe it's current tag or default tag or something along those lines? - buf[529] = 0x01; - - xbRewind(); - if(( iRc = xbFwrite( buf, 2048, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } else { - iErrorStop = 130; - iRc = XB_INVALID_OPTION; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::WriteHeadBlock() Exception Caught. Error Stop = [%d] iRc = [%d] option = [%d]", iErrorStop, iRc, iOption ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -xbInt16 xbIxMdx::UpdateTagSize( xbMdxTag *mpTag, xbUInt32 ulTagSz ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char buf[4]; - try{ - ePutUInt32( &buf[0], ulTagSz ); - if(( iRc = xbFseek( (xbInt64) ((mpTag->ulTagHdrPageNo *512 )+ 4), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = xbFwrite( &buf[0], 4, 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxMdx::UpdateTagSize() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - - -/***********************************************************************/ -//void xbIxMdx::TestStub( char *s, void *vpTag ){ -void xbIxMdx::TestStub( char *, void * ){ -} -/***********************************************************************/ -} /* namespace */ -#endif /* XB_MDX_SUPPORT */ - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixndx.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbixndx.cpp deleted file mode 100755 index b28dd9d..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixndx.cpp +++ /dev/null @@ -1,2834 +0,0 @@ -/* xbixndx.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 - -*/ - -#include "xbase.h" - -#ifdef XB_NDX_SUPPORT - -namespace xb{ - - -/***********************************************************************/ -//! @brief Class constructor. -/*! - \param dbf Pointer to dbf instance. -*/ - -xbIxNdx::xbIxNdx( xbDbf *dbf ) : xbIx( dbf ){ - ndxTag = (xbNdxTag *) calloc( 1, sizeof( xbNdxTag )); - SetBlockSize( XB_NDX_BLOCK_SIZE ); - cNodeBuf = (char *) malloc( XB_NDX_BLOCK_SIZE ); -} -/***********************************************************************/ -//! @brief Class Destructor. -xbIxNdx::~xbIxNdx(){ - if( ndxTag ){ - ndxTag->npNodeChain = FreeNodeChain( ndxTag->npNodeChain ); - if( ndxTag->cpKeyBuf ) - free( ndxTag->cpKeyBuf ); - if( ndxTag->cpKeyBuf2 ) - free( ndxTag->cpKeyBuf2 ); - if( ndxTag->exp ){ - delete ndxTag->exp; - ndxTag->exp = NULL; - } - ndxTag->sKeyExpression.Set( NULL ); - ndxTag->sTagName.Set( NULL ); - free( ndxTag ); - ndxTag = NULL; - } - if( cNodeBuf ) - free( cNodeBuf ); -} -/***********************************************************************/ -//! @brief Add key. -/*! - Add key. If this is a unique index, this logic assumes the duplicate - check logic was already done. - - \param vpTag Tag to update. - \param ulRecNo Record number to add key for. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::AddKey( void * vpTag, xbUInt32 ulRecNo ){ - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - if( GetUniqueKeyOpt() == XB_EMULATE_DBASE && npTag->bFoundSts ) - return XB_NO_ERROR; - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbInt16 iHeadNodeUpdateOpt = 2; - - - try{ - - if(( iRc = xbIxNdx::KeySetPosAdd( npTag, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - xbInt32 lKeyCnt = GetKeyCount( npTag->npCurNode ); - if( lKeyCnt < npTag->iKeysPerBlock ){ - // Section A - add key to appropriate position if space available - if(( iRc = InsertNodeL( npTag, npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->cpKeyBuf, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - } else { - // land here with a full leaf node - iHeadNodeUpdateOpt = 1; - // section B - split the leaf node - xbIxNode * npRightNode = AllocateIxNode( GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, 1 ); - if( !npRightNode ){ - iErrorStop = 120; - iRc = XB_NO_MEMORY; - throw iRc; - } - if(( iRc = SplitNodeL( npTag, npTag->npCurNode, npRightNode, npTag->npCurNode->iCurKeyNo, npTag->cpKeyBuf, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - xbUInt32 ulTempBlockNo = npRightNode->ulBlockNo; - - // section C - go up the tree, splitting nodes as necessary - xbIxNode * npParent = npTag->npCurNode->npPrev; - while( npParent && GetKeyCount( npParent ) >= npTag->iKeysPerBlock ){ - npRightNode = FreeNodeChain( npRightNode ); - npRightNode = AllocateIxNode( GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, 1 ); - if( !npRightNode ){ - iErrorStop = 140; - iRc = XB_NO_MEMORY; - throw iRc; - } - if(( iRc = SplitNodeI( npTag, npParent, npRightNode, npParent->iCurKeyNo, ulTempBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - ulTempBlockNo = npRightNode->ulBlockNo; - npTag->npCurNode = npParent; - npParent = npParent->npPrev; - } - - // section D - if cur node is split root, create new root - if( npTag->npCurNode->ulBlockNo == npTag->ulRootBlock ){ - // xbase->WriteLogMessage( "Section d" ); - if(( iRc = AddKeyNewRoot( npTag, npTag->npCurNode, npRightNode )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - npRightNode = FreeNodeChain( npRightNode ); - - } else { - // else section E, put key in parent - if(( iRc = InsertNodeI( vpTag, npParent, npParent->iCurKeyNo, npRightNode->ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - npRightNode = FreeNodeChain( npRightNode ); - } - } - - // update the header - if(( iRc = WriteHeadBlock( iHeadNodeUpdateOpt )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - - // ---- free whatever is left of the node chain here, this might not be right, might need to restore it to - // the point right after SetKeyPosAdd - npTag->npNodeChain = FreeNodeChain( ndxTag->npNodeChain ); - npTag->npCurNode = NULL; - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::AddKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Add new root node. -/*! - \param npTag Tag to update. - \param npLeft Left node. - \param npRight Right node. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::AddKeyNewRoot( xbNdxTag *npTag, xbIxNode *npLeft, xbIxNode *npRight ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbString sMsg; - char *pLastKey = NULL; - - try{ - xbIxNode *npRoot = AllocateIxNode( GetBlockSize() + (xbUInt32) npTag->iKeyItemLen, 1 ); - if( !npRoot ){ - iErrorStop = 100; - iRc = XB_NO_MEMORY; - throw iRc; - } - npTag->ulRootBlock = npRoot->ulBlockNo; - pLastKey = (char *) malloc( (size_t) ndxTag->iKeyLen ); - if(( iRc = GetLastKeyForBlockNo( npTag, npLeft->ulBlockNo, pLastKey )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - char * pTrg = npRoot->cpBlockData; - - // set no of keys to 1 - ePutUInt32( pTrg, 1 ); - - // set the left node number - pTrg += 4; - ePutUInt32( pTrg, npLeft->ulBlockNo ); - - // set the key - pTrg+= 8; - memcpy( pTrg, pLastKey, (size_t) npTag->iKeyLen ); - - // set the right node number - pTrg+= (npTag->iKeyItemLen - 8); - ePutUInt32( pTrg, npRight->ulBlockNo ); - - // write out the block - if(( iRc = WriteBlock( npRoot->ulBlockNo, GetBlockSize(), npRoot->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if( pLastKey ) - free( pLastKey ); - NodeFree( npRoot ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::AddKeyNewRoot() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( pLastKey ) - free( pLastKey ); - } - return iRc; -} -/***********************************************************************/ -//! @brief Append node to node chain. -/*! - Append a node to the current node chain for a given tag. - - \param vpTag Tag to update. - \param npNode Node to add to node chain. - \returns void -*/ -void xbIxNdx::AppendNodeChain( void *vpTag, xbIxNode * npNode ){ - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - if( npTag->npNodeChain == NULL ){ - npTag->npNodeChain = npNode; - npTag->npCurNode = npNode; - } else { - npNode->npPrev = npTag->npCurNode; - npTag->npCurNode->npNext = npNode; - npTag->npCurNode = npNode; - } - // time stamp the node chain - GetFileMtime( npTag->tNodeChainTs ); -} - -/***********************************************************************/ -//! @brief Allocate a node. -/*! - \param ulBufSize Buffer size. - \param iOpt 0 - Don't update the node block number on the node. - 1 - Set node block number to the next available block number. - \returns Pointer to new node. -*/ - -xbIxNode * xbIxNdx::AllocateIxNode( xbUInt32 ulBufSize, xbInt16 iOpt ){ - xbIxNode *n = xbIx::AllocateIxNode( ulBufSize ); - if( n && iOpt == 1 ) n->ulBlockNo = ndxTag->ulTotalBlocks++; - return n; -} -/***********************************************************************/ -//! @brief Check for duplicate key. -/*! - \param vpTag Tag to check. - \returns XB_KEY_NOT_UNIQUE<br>XB_NO_ERROR -*/ -xbInt16 xbIxNdx::CheckForDupKey( void *vpTag ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag *npTag = (xbNdxTag *) vpTag; - npTag->bFoundSts = xbFalse; - try{ - if( GetUnique()){ - if( npTag->iKeySts == XB_ADD_KEY || npTag->iKeySts == XB_UPD_KEY ) - if( KeyExists( vpTag )){ - if( GetUniqueKeyOpt() == XB_EMULATE_DBASE ){ - npTag->bFoundSts = xbTrue; - return 0; - } else { - return XB_KEY_NOT_UNIQUE; - } - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::CheckForDupKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Check tag integrity. -/*! - Check a tag for accuracy. - - \param vpTag Tag to create key for. - \param iOpt Output message destination<br> - 0 = Syslog<br> - 1 = Stdout<br> - 2 = Both<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::CheckTagIntegrity( void *vpTag, xbInt16 iOpt ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iRc2; - xbInt16 iRc3; - xbInt16 iErrorStop = 0; - xbUInt32 ulIxCnt = 0; - xbUInt32 ulThisRecNo = 0; - xbUInt32 ulPrevRecNo = 0; - xbBool bDone = false; - xbString sMsg; - char cKeyType; - char *pPrevKeyBuf = NULL; - - #ifdef XB_LOCKING_SUPPORT - xbBool bLocked = xbFalse; - #endif - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - #ifdef XB_LOCKING_SUPPORT - if( dbf->GetAutoLock() && !dbf->GetTableLocked() ){ - if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - bLocked = xbTrue; - } - #endif - - memset( npTag->cpKeyBuf2, 0x00, (size_t) npTag->iKeyLen ); - cKeyType = GetKeyType( vpTag ); - - sMsg.Sprintf( "Checking index type [%c]", cKeyType ); - xbase->WriteLogMessage( sMsg, iOpt ); - - pPrevKeyBuf = (char *) calloc( 1, (size_t) ndxTag->iKeyLen ); - - // for each key in the index, make sure it is trending in the right direction - iRc = GetFirstKey( vpTag, 0 ); - while( iRc == XB_NO_ERROR && !bDone ){ - ulIxCnt++; - iRc = GetNextKey( vpTag, 0 ); - if( iRc == XB_NO_ERROR ){ - // compare this key to prev key - iRc2 = CompareKey( cKeyType, GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), - pPrevKeyBuf, (size_t) npTag->iKeyLen ); - - if( iRc2 < 0 ){ - sMsg.Sprintf( "Key sequence error at key number [%ld].", ulIxCnt ); - xbase->WriteLogMessage( sMsg, iOpt ); - iErrorStop = 110; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - ulThisRecNo = 0; - if(( iRc3 = GetDbfPtr( vpTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulThisRecNo )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc3; - } - - if( iRc2 == 0 && (ulThisRecNo <= ulPrevRecNo )){ - sMsg.Sprintf( "Dbf record number sequence error at key number [%ld].", iOpt ); - xbase->WriteLogMessage( sMsg, iOpt ); - iErrorStop = 130; - iRc = XB_INVALID_INDEX; - throw iRc; - } - // save this key info to prev key - memcpy( pPrevKeyBuf, GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), (size_t) npTag->iKeyLen ); - ulPrevRecNo = ulThisRecNo; - } - } - - // verify the index count matches the tag count - xbUInt32 ulDbfCnt = 0; - if(( iRc = dbf->GetRecordCnt( ulDbfCnt )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - if( GetUniqueKeyOpt() == XB_EMULATE_DBASE && GetUnique( vpTag )){ - // Can't compare counts if using XB_EMULATE_DBASE and it's a unique index - } else { - if( ulDbfCnt != ulIxCnt ){ - sMsg.Sprintf( "CheckTagIntegrity() Index entry count [%ld] does not match dbf record count [%ld]", ulIxCnt, ulDbfCnt ); - xbase->WriteLogMessage( sMsg, iOpt ); - iErrorStop = 150; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - // verify each record in the dbf file has a corresponding index entry - xbUInt32 j = 0; - while( j < ulDbfCnt ){ - if(( iRc = dbf->GetRecord( ++j )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if(( iRc = FindKeyForCurRec( vpTag )) != XB_NO_ERROR ){ - ulThisRecNo = j; - iErrorStop = 170; - throw iRc; - } - } - sMsg.Sprintf( "CheckTagIntegrity() Index entry count [%ld] matches dbf record count [%ld]", ulIxCnt, ulDbfCnt ); - xbase->WriteLogMessage( sMsg, iOpt ); - } - if( pPrevKeyBuf ) - free( pPrevKeyBuf ); - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::CheckTagIntegrity() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg, iOpt ); - xbase->WriteLogMessage( GetErrorMessage( iRc ), iOpt ); - if( pPrevKeyBuf ) - free( pPrevKeyBuf ); - - if( iErrorStop == 170 ){ - sMsg.Sprintf( "xbIxNdx::CheckTagIntegrity() Missing index entry for record [%d]", ulThisRecNo ); - xbase->WriteLogMessage( sMsg, iOpt ); - } - } - - #ifdef XB_LOCKING_SUPPORT - if( bLocked ){ - dbf->LockTable( XB_UNLOCK ); - } - #endif - return iRc; - -} -/***********************************************************************/ -//! @brief Create key for tag. -/*! - Append a node to the current node chain for a given tag. - - \param vpTag Tag to create key for. - \param iOpt 0 = Build a key for FindKey usage, only rec buf 0.<br> - 1 = Append Mode, Create key for an append, only use rec buf 0, set updated switch.<br> - 2 = Update Mode, Create old version and new version keys, check if different, set update switch appropriately. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::CreateKey( void * vpTag, xbInt16 iOpt ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - if(( iRc = npTag->exp->ProcessExpression( 0 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if( npTag->exp->GetReturnType() == XB_EXP_CHAR ){ - npTag->exp->GetStringResult( npTag->cpKeyBuf, (xbUInt32) npTag->iKeyLen ); - } - else if( npTag->exp->GetReturnType() == XB_EXP_NUMERIC ){ - xbDouble d; - npTag->exp->GetNumericResult( d ); - memcpy( npTag->cpKeyBuf, &d, 8 ); - } - else if( npTag->exp->GetReturnType() == XB_EXP_DATE ){ - xbDouble d; - npTag->exp->GetNumericResult( d ); - memcpy( npTag->cpKeyBuf, &d, 8 ); - } - - npTag->iKeySts = 0; - if( iOpt == 1 ) - npTag->iKeySts = XB_ADD_KEY; - - else if( iOpt == 2 ){ - if(( iRc = npTag->exp->ProcessExpression( 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if( npTag->exp->GetReturnType() == XB_EXP_CHAR ){ - npTag->exp->GetStringResult( npTag->cpKeyBuf2, (xbUInt32) npTag->iKeyLen ); - } else if( npTag->exp->GetReturnType() == XB_EXP_NUMERIC || npTag->exp->GetReturnType() == XB_EXP_DATE ){ - xbDouble d; - npTag->exp->GetNumericResult( d ); - memcpy( npTag->cpKeyBuf2, &d, 8 ); - } - if( memcmp( npTag->cpKeyBuf, npTag->cpKeyBuf2, (size_t) npTag->iKeyLen )) - npTag->iKeySts = XB_UPD_KEY; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::CreateKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Create new tag. -/*! - This routine creates a new tag. Since NDX files have only one tag, - this creates a new NDX file. - - \param sName Tag Name, including .NDX suffix - \param sKey Key Expression - \param sFilter Filter expression. Not supported by NDX indices. - \param iDescending Not supported by NDX indices. - \param iUnique xbtrue - Unique.<br>xbFalse - Not unique. - \param iOverLay xbTrue - Overlay if file already exists.<br>xbFalse - Don't overlay. - \param vpTag Output from method Pointer to vptag pointer. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::CreateTag( const xbString &sName, const xbString &sKey, - const xbString &, xbInt16, xbInt16 iUnique, xbInt16 iOverLay, void **vpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag *npTag = ndxTag; - *vpTag = ndxTag; - - try{ - //xbString sMsg; - SetFileName( sName ); - - if( FileExists() && !iOverLay ) - return XB_FILE_EXISTS; - - if( FileIsOpen()){ - if(( iRc = xbTruncate(0)) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npCurNode = NULL; - npTag->sKeyExpression.Set( "" ); - - if( npTag->cpKeyBuf ){ - free( npTag->cpKeyBuf ); - npTag->cpKeyBuf = NULL; - } - if( npTag->cpKeyBuf2 ){ - free( npTag->cpKeyBuf2 ); - npTag->cpKeyBuf2 = NULL; - } - } - if(( iRc = xbFopen( "w+b", dbf->GetShareMode())) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - //set up the key expression - npTag->exp = new xbExp( dbf->GetXbasePtr()); - if(( iRc = npTag->exp->ParseExpression( dbf, sKey )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - switch( npTag->exp->GetReturnType()){ - case XB_EXP_CHAR: - npTag->cKeyType = 'C'; - npTag->iKeyType = 0; - npTag->iKeyLen = npTag->exp->GetResultLen(); - break; - - case XB_EXP_NUMERIC: - npTag->cKeyType = 'F'; - npTag->iKeyType = 1; - npTag->iKeyLen = 8; - break; - - case XB_EXP_DATE: - npTag->cKeyType = 'D'; - npTag->iKeyType = 1; - npTag->iKeyLen = 8; - break; - - default: - iErrorStop = 140; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - npTag->iUnique = iUnique; - npTag->ulRootBlock = 1L; - //npTag->ulTotalBlocks = 2l; - npTag->ulTotalBlocks = 2L; - npTag->sKeyExpression = sKey; - - GetFileNamePart( npTag->sTagName ); - - if( npTag->iKeyLen > 100 ){ - iErrorStop = 150; - throw iRc; - } - - npTag->iKeyItemLen = npTag->iKeyLen + 8; - while(( npTag->iKeyItemLen % 4 )!= 0 ) npTag->iKeyItemLen++; - - npTag->iKeysPerBlock = (xbInt16) (GetBlockSize() - 8 ) / npTag->iKeyItemLen; - ndxTag->cpKeyBuf = (char *) malloc( (size_t) ndxTag->iKeyLen ); - ndxTag->cpKeyBuf2 = (char *) malloc( (size_t) ndxTag->iKeyLen ); - - if(( iRc = WriteHeadBlock(0)) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - - //write out block binary zeroes - char buf[512]; - memset( buf, 0x00, 512 ); - if(( iRc = xbFwrite( buf, 1, 512 )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::CreateTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Delete a key. -/*! - This routine deletes a key from a supplied node. - \param vpTag Tag to delete key on. - \param npNode Node to delete key on. - \param iSlotNo Slot number of key to delete. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::DeleteFromNode( void *vpTag, xbIxNode * npNode, xbInt16 iSlotNo ) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - - xbInt32 lKeyCnt = GetKeyCount( npNode ); - xbInt16 iLen = (lKeyCnt - iSlotNo - 1) * npTag->iKeyItemLen; - if( !IsLeaf( vpTag, npNode )) - iLen += 4; - - if( iLen > 0 ){ - char *pTrg = npNode->cpBlockData; - pTrg += (4 + (npTag->iKeyItemLen * (iSlotNo)) ); //lTrgPos; - char *pSrc = pTrg; - pSrc += npTag->iKeyItemLen; - memmove( pTrg, pSrc, (size_t) iLen ); - } - - // set the new number of keys - ePutUInt32( npNode->cpBlockData, (xbUInt32) lKeyCnt - 1 ); - - // write out the block - if(( iRc = WriteBlock( npNode->ulBlockNo, GetBlockSize(), npNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::DeleteFromNode() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return XB_NO_ERROR; -} - -/***********************************************************************/ -//! @brief Delete a key. -/*! - This routine deletes a key. It assumes the key to delete - is the current key in the node chain. - - \param vpTag Tag to delete key on. - - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::DeleteKey( void *vpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - // save copy of node chain to reset to after delete completed - xbIxNode *npSaveNodeChain = npTag->npNodeChain; - npTag->npNodeChain = NULL; - xbIxNode * npSaveCurNode = npTag->npCurNode; - - try{ - - xbString sMsg; - - if(( iRc = xbIxNdx::KeySetPosDel( npTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // Delete key needs to handle two scenarios - // 1 - if the delete is on the only key of a leaf node, then traverse up the tree, trimming as needed - // 2 - if the last key on a node is deleted, and the key value is not the same as the prev key value - // go up the tree looking for an interior node needing updated key value - - xbInt32 lOrigKeyCnt = GetKeyCount( npTag->npCurNode ); - if(( iRc = DeleteFromNode( npTag, npTag->npCurNode, npTag->npCurNode->iCurKeyNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - if( lOrigKeyCnt == 1 ){ - // scenario 1 - xbBool bDone = xbFalse; - xbBool bIsLeaf = xbFalse; - xbInt32 lKeyCnt; - npTag->npCurNode = npTag->npCurNode->npPrev; - - while( npTag->npCurNode && !bDone ){ - lKeyCnt = GetKeyCount( npTag->npCurNode ); - bIsLeaf = IsLeaf( npTag, npTag->npCurNode ); - if( lKeyCnt > 0 ){ - if(( iRc = DeleteFromNode( npTag, npTag->npCurNode, npTag->npCurNode->iCurKeyNo )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - if( (bIsLeaf && lKeyCnt > 1) || (!bIsLeaf && lKeyCnt > 0) ) - bDone = xbTrue; - else - npTag->npCurNode = npTag->npCurNode->npPrev; - } - } else if( npTag->npCurNode->iCurKeyNo == (xbUInt32) lOrigKeyCnt - 1 ){ - - // scenario 2 - // if last two keys identical, then nothing to do, else go up looking for a key to change - if( memcmp( GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), - GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo-1, npTag->iKeyItemLen ), - (size_t) npTag->iKeyLen )){ - - xbIxNode *pNode = npTag->npCurNode->npPrev; - char *pSrc = GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo-1, npTag->iKeyItemLen ); - - while( pNode && pNode->ulBlockNo != npTag->ulRootBlock && pNode->iCurKeyNo == (xbUInt32) GetKeyCount( pNode ) ) - pNode = pNode->npPrev; - if( pNode ){ - if( pNode->iCurKeyNo < (xbUInt32) GetKeyCount( pNode )){ - char *pTrg = pNode->cpBlockData; - pTrg += 12 + (pNode->iCurKeyNo * (xbUInt32) npTag->iKeyItemLen); - for( xbInt16 i = 0; i < npTag->iKeyLen; i++ ) - *pTrg++ = *pSrc++; - - // write out the block - if(( iRc = WriteBlock( pNode->ulBlockNo, GetBlockSize(), pNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - } - } - } - - // restore node chain to pre delete status (which should be post add status) - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npNodeChain = npSaveNodeChain; - npTag->npCurNode = npSaveCurNode; - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::DeleteKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( npSaveNodeChain ){ - npTag->npNodeChain = npSaveNodeChain; - npSaveNodeChain = FreeNodeChain( npSaveNodeChain ); - npTag->npCurNode = npSaveCurNode; - } - } - return iRc; -} - - -/***********************************************************************/ -//! @brief Delete tag. -/*! - In the case of an ndx tag, it deletes the ndx file as it contains - only one tag. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::DeleteTag( void * ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - //xbNdxTag * npTag; - //vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - - // if open, close it - if( FileIsOpen()){ - if(( iRc = Close()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - // delete file - if(( iRc = xbRemove()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::DeleteTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -#ifdef XB_DEBUG_SUPPORT - -//! @brief Dump a block for a given tag. -/*! - Dump blocks for given tag for debugging purposes. - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \param vpTag - Not required for single tag NDX files. - \returns void -*/ - -xbInt16 xbIxNdx::DumpTagBlocks( xbInt16 iOpt, void * ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbUInt32 lNoOfKeys; - char *p; - xbString s; - xbBool bIsLeaf = false; - - try{ - if( !FileIsOpen()){ - iRc = XB_NOT_OPEN; - iErrorStop = 100; - throw iRc; - } - - xbUInt32 ulStartBlock; - xbUInt32 ulEndBlock; - ulStartBlock = 1; - ulEndBlock = ndxTag->ulTotalBlocks; - - for( xbUInt32 lBlk = ulStartBlock; lBlk < ulEndBlock; lBlk++ ){ - - memset( cNodeBuf, 0x00, XB_NDX_BLOCK_SIZE ); - if(( iRc = ReadBlock( lBlk, XB_NDX_BLOCK_SIZE, cNodeBuf )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - p = cNodeBuf; - lNoOfKeys = eGetUInt32( p ); - - if( eGetUInt32( p + 4 ) > 0 ){ - bIsLeaf = false; - s.Sprintf( "Node # %ld - Interior Node - Key Type [%c] Key Count [%ld]", lBlk, ndxTag->cKeyType, lNoOfKeys ); - } else { - bIsLeaf = true; - s.Sprintf( "Node # %ld - Leaf Node - Key Type [%c] Key count [%ld]", lBlk, ndxTag->cKeyType, lNoOfKeys ); - } - xbase->WriteLogMessage( s, iOpt ); - xbase->WriteLogMessage( "Key Child Dbf Rec Key", iOpt ); - p += 4; - xbUInt32 ulLeftBranch; - xbUInt32 ulRecNo; - xbString sKey; - xbDouble d; - - xbUInt32 l; - for( l = 0; l < lNoOfKeys; l++ ){ - ulLeftBranch = eGetUInt32( p ); - p+= 4; - ulRecNo = eGetUInt32( p ); - p+= 4; - if( ndxTag->cKeyType == 'C' ){ - sKey.Assign( p, 1, (xbUInt32) ndxTag->iKeyLen ); - } else if( ndxTag->cKeyType == 'D' ){ - xbInt32 lDate = (xbInt32) eGetDouble( p ); - xbDate dt( lDate ); - //xbString s2; - //dt.JulToDate8( lDate, s2 ); - sKey.Sprintf( "%ld - %s", lDate, dt.Str()); - } else { - d = eGetDouble( p ); - sKey.Sprintf( "%f", d ); - } - p+= (ndxTag->iKeyItemLen-8); - - s.Sprintf( "%3d %9d %9d %s", l+1, ulLeftBranch, ulRecNo, sKey.Str() ); - xbase->WriteLogMessage( s, iOpt ); - } - if( !bIsLeaf ){ - ulLeftBranch = eGetUInt32( p ); - s.Sprintf( "%3d %9d", l+1, ulLeftBranch ); - xbase->WriteLogMessage( s, iOpt ); - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::DumpTagBlocks() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Dump index file header. -/*! - Dump a index file header for debugging purposes. - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::DumpHeader( xbInt16 iOpt, xbInt16 ){ - xbString s; - xbInt16 iRc; - - if(( iRc = ReadHeadBlock( 1 )) != XB_NO_ERROR ) - return iRc; - - s.Sprintf( "Index Header Node for %s", GetFileName().Str()); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "--------------------------------" ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "Root block = %ld", ndxTag->ulRootBlock ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "Total blocks = %ld", ndxTag->ulTotalBlocks ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "Key types = %c,%d", ndxTag->cKeyType, ndxTag->iKeyType ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "Key Length = %d", ndxTag->iKeyLen ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "Keys Per Block = %d", ndxTag->iKeysPerBlock ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "Key Item Len = %ld", ndxTag->iKeyItemLen ); - xbase->WriteLogMessage( s, iOpt); - s.Sprintf( "Serial No = %d", ndxTag->cSerNo ); - xbase->WriteLogMessage( s, iOpt); - s.Sprintf( "Unique = %d", ndxTag->iUnique ); - xbase->WriteLogMessage( s, iOpt ); - s.Sprintf( "KeyExpression = %s", ndxTag->sKeyExpression.Str() ); - xbase->WriteLogMessage( s, iOpt ); - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Dump the index for a tag. -/*! - Stub. - \returns XB_NO_ERROR -*/ -xbInt16 xbIxNdx::DumpIxForTag( void *, xbInt16 ) -{ - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Dump the index node chain. -/*! - Dump the index node chain for debugging purposes. - \param vpTag Tag of node chain to dump. - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \returns void -*/ -void xbIxNdx::DumpIxNodeChain( void *vpTag, xbInt16 iOpt ) const -{ - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - xbString s( "Dump Node Chain" ); - xbase->WriteLogMessage( s, iOpt ); - - if( npTag->npNodeChain ){ - xbIxNode *n = npTag->npNodeChain; - xbInt16 iCtr = 0; - char cLeaf; - s.Sprintf( "Cnt\tThis Prev Next CurKeyNo BlockNo NoOfKeys Type" ); - xbase->WriteLogMessage( s, iOpt ); - while( n ){ - IsLeaf( vpTag, n ) ? cLeaf = 'L' : cLeaf = 'I'; - s.Sprintf( "%d\t%08x %08x %08x %08d %08d %08d %c", - iCtr++, n, n->npPrev, n->npNext, n->iCurKeyNo, - n->ulBlockNo, eGetUInt32( n->cpBlockData ), cLeaf ); - xbase->WriteLogMessage( s, iOpt ); - n = n->npNext; - } - } else { - s = "Empty Node Chain"; - xbase->WriteLogMessage( s, iOpt ); - } -} -/***********************************************************************/ -//! @brief Dump node. -/*! - Dump a node for debugging purposes. - \param vpTag Tag of node chain to dump. - \param pNode Node to dump. - \param iOpt Output message destination<br> - 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \returns XB_INVALID_OBJECT<br>XB_NO_ERROR -*/ - -xbInt16 xbIxNdx::DumpNode( void *vpTag, xbIxNode *pNode, xbInt16 iOpt ) const -{ - xbString s; - xbString sKey; - xbUInt32 lLeftBranch; - xbUInt32 lRecNo; - xbDouble d; - - if( !pNode ) - return XB_INVALID_OBJECT; - - xbIx::DumpNode( vpTag, pNode, iOpt ); - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - xbUInt32 lNoOfKeys = eGetUInt32( pNode->cpBlockData ); - xbBool bIsLeaf = IsLeaf( vpTag, pNode ); - - if( bIsLeaf ) - xbase->WriteLogMessage( "Leaf node", iOpt ); - else - xbase->WriteLogMessage( "Interior node", iOpt ); - - s.Sprintf( "Key type = [%c] No Of Keys =[%d] Prev =[%x] Next =[%x]", npTag->cKeyType, lNoOfKeys, pNode->npPrev, pNode->npNext ); - xbase->WriteLogMessage( s, iOpt ); - - char *p = pNode->cpBlockData; - p += 4; - - xbUInt32 l; - for( l = 0; l < lNoOfKeys; l++ ){ - - lLeftBranch = eGetUInt32( p ); - p+= 4; - lRecNo = eGetUInt32( p ); - p+= 4; - - if( npTag->cKeyType == 'C' ){ - sKey.Assign( p, 1, (xbUInt32) npTag->iKeyLen ); - } else if( npTag->cKeyType == 'D' ){ - xbInt32 lDate = (xbInt32) eGetDouble( p ); - xbDate dt( lDate ); - sKey.Sprintf( "%ld - %s", lDate, dt.Str()); - } else { - d = eGetDouble( p ); - sKey.Sprintf( "%f", d ); - } - p+= (npTag->iKeyItemLen-8); - s.Sprintf( "%3d %9d %9d %s", l+1, lLeftBranch, lRecNo, sKey.Str() ); - xbase->WriteLogMessage( s, iOpt ); - } - if( !bIsLeaf ){ - lLeftBranch = eGetUInt32( p ); - s.Sprintf( "%3d %9d", l+1, lLeftBranch ); - xbase->WriteLogMessage( s.Str(), iOpt ); - } - return XB_NO_ERROR; -} -#endif -/***********************************************************************/ -//! @brief Find key -/*! - \param vpTag Pointer to tag to search. - \param vpKey Void pointer to key data to search on. - \param lSearchKeyLen Length of key to search for. - \param iRetrieveSw xbTrue - Retrieve the record if key found.<br> - xbFalse - Don't retrieve record, check for key existence only. - \returns XB_NO_ERROR - Key found.<br> - XB_NOT_FOUND - Key not found.<br> - <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::FindKey( void *vpTag, const void *vpKey, xbInt32 lSearchKeyLen, - xbInt16 iRetrieveSw ){ - - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbString sMsg; - // xbInt16 iFindSts; - try{ - // clean up any previous table updates before moving on - if( iRetrieveSw ){ - if( dbf->GetDbfStatus() == XB_UPDATED ){ - if( dbf->GetAutoCommit() == 1 ){ - if(( iRc = dbf->Commit()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } else { - if(( iRc = dbf->Abort()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - } - } - - xbUInt32 ulNoOfKeys; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - char cKeyType = npTag->cKeyType; - - if( npTag->npNodeChain ){ - - // determine if the index has been updated since the last time it was used - time_t tFileTs; - if(( iRc = GetFileMtime( tFileTs )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if( npTag->tNodeChainTs < tFileTs ){ - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npCurNode = NULL; - if(( iRc = ReadHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if(( iRc = GetBlock( npTag, (npTag->ulRootBlock ), 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - } else { - // pop up the chain looking for appropriate starting point - xbBool bDone = false; - xbIxNode * TempIxNode; - while( npTag->npCurNode && !bDone && npTag->npCurNode->ulBlockNo != npTag->ulRootBlock ){ // not root node - iRc = CompareKey( cKeyType, vpKey, GetKeyData( npTag->npCurNode, 0, npTag->iKeyItemLen ), (size_t) lSearchKeyLen ); - if( iRc <= 0 ){ - TempIxNode = npTag->npCurNode; - npTag->npCurNode = npTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } else { - // get the number of keys on the block and compare the key to the rightmost key - xbUInt32 ulKeyCtr = eGetUInt32( npTag->npCurNode->cpBlockData ) - 1; - iRc = CompareKey( cKeyType, vpKey, GetKeyData( npTag->npCurNode, ulKeyCtr, npTag->iKeyItemLen), (size_t) lSearchKeyLen ); - - if( iRc > 0 ){ - TempIxNode = npTag->npCurNode; - npTag->npCurNode = npTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } else { - bDone = true; - } - } - } - } - } else { - if(( iRc = GetBlock( npTag, (npTag->ulRootBlock ), 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - - - // if cur node is the base node and no keys on this node, then the index is empty - if( npTag->ulRootBlock == npTag->npCurNode->ulBlockNo ){ - ulNoOfKeys = eGetUInt32( npTag->npCurNode->cpBlockData ); - if( ulNoOfKeys == 0 && IsLeaf( npTag, npTag->npCurNode )){ - // iRc = XB_EMPTY; - - iRc = XB_NOT_FOUND; - return iRc; - } - } - - // should be in the appropriate position in the node chain to continue the search from here - // run down through the interior nodes - xbInt16 iSearchRc = 0; - xbUInt32 ulKeyPtr = 0; - - while( !IsLeaf( npTag, npTag->npCurNode ) ){ - - // get the number of keys on the block and compare the key to the rightmost key - ulNoOfKeys = eGetUInt32( npTag->npCurNode->cpBlockData ); - if( ulNoOfKeys == 0 ) // interior nodes can have zero keys, just a link to the next lower node - npTag->npCurNode->iCurKeyNo = 0; - else - { - iRc = CompareKey( cKeyType, vpKey, GetKeyData( npTag->npCurNode, ulNoOfKeys - 1, npTag->iKeyItemLen), (size_t) lSearchKeyLen ); - if( iRc > 0 ){ - npTag->npCurNode->iCurKeyNo = ulNoOfKeys; - } else { - npTag->npCurNode->iCurKeyNo = (xbUInt32) BSearchBlock( cKeyType, npTag->npCurNode, - (xbInt32) npTag->iKeyItemLen, vpKey, (xbInt32) lSearchKeyLen, iSearchRc ); - } - } - - if(( iRc = GetKeyPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - - if(( iRc = GetBlock( npTag, ulKeyPtr, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - - // should be on a the correct leaf node, it may or may not contain the actual key - ulNoOfKeys = eGetUInt32( npTag->npCurNode->cpBlockData ); - xbInt16 iCompRc = 0; - - if( ulNoOfKeys == 0 ){ - iRc = XB_NOT_FOUND; - return iRc; - } else { - - iRc = BSearchBlock( cKeyType, npTag->npCurNode, npTag->iKeyItemLen, vpKey, lSearchKeyLen, iCompRc ); - - // iCompRc - // 0 found - // < 0 eof encountered, search key > last key in file - // > 0 not found, positioned to next key - - - // std::cout << "xbIxNdx::FindKey -Rc = " << iRc << " CompRc = " << iCompRc << " NoOfKeys = " << ulNoOfKeys << " blk no = " << npTag->npCurNode->ulBlockNo << "\n"; - - if( iCompRc >= 0 ){ - npTag->npCurNode->iCurKeyNo = (xbUInt32) iRc; - if( iRetrieveSw ){ - xbUInt32 ulKey = npTag->npCurNode->iCurKeyNo; - if( ulKey >= ulNoOfKeys ) // if position past end of keys, need to go back one and position to last key - ulKey--; - - if(( iRc = GetDbfPtr( vpTag, ulKey, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - } - } - } - - if( iCompRc == 0 ) - return XB_NO_ERROR; - else if( iCompRc > 0 ) - return XB_NOT_FOUND; - else - return XB_EOF; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::FindKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Find key for current record -/*! - This routine is called when updating a key. - - \param vpTag Pointer to tag to search. - XB_NOT_FOUND Key not found.<br> - <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::FindKeyForCurRec( void * vpTag ) -{ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - if(( iRc = CreateKey( vpTag, 0 )) < XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // find key - iRc = FindKey( vpTag, npTag->cpKeyBuf, npTag->iKeyLen, 0 ); - if( iRc == XB_NOT_FOUND || iRc == XB_EMPTY || iRc == XB_EOF ) - return iRc; - - if( iRc != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - // if keys are unique, and the recrd number matches, then we are good - if( GetUnique() ) - return XB_NO_ERROR; - - // get here if key found and not unique, need to move forward looking for correct rec no - xbUInt32 ulDbfRecNo = dbf->GetCurRecNo(); - xbBool bKeysMatch = true; // keys match? - xbBool bCurRecsMatch = false; // cur recod number matches? - xbUInt32 ulIxRecNo = 0; - char cKeyType = GetKeyType( vpTag ); - - if(( iRc = GetDbfPtr( vpTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulIxRecNo )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if( ulIxRecNo == ulDbfRecNo ) - bCurRecsMatch = true; - - xbInt16 iCompRc; - while( !bCurRecsMatch && bKeysMatch ){ - - if(( iRc = GetNextKey( vpTag, 0 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - // do compare key here - iCompRc = CompareKey( cKeyType, npTag->cpKeyBuf, GetKeyData( npTag->npCurNode, 0, npTag->iKeyItemLen ), (size_t) npTag->iKeyLen ); - if( iCompRc != 0 ) - bKeysMatch = false; - else{ - if(( iRc = GetDbfPtr( vpTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulIxRecNo )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if( ulIxRecNo == ulDbfRecNo ) - bCurRecsMatch = true; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::FindKeyForCurRec() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return XB_NO_ERROR; -} - -/***********************************************************************/ -//! @brief Get dbf record number for given key number. -/*! - \param vpTag Tag to retrieve dbf rec number on. - \param iKeyNo Key number for retrieval - \param np Pointer to node - \param ulDbfPtr- Output dbf record number - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::GetDbfPtr( void *vpTag, xbInt16 iKeyNo, xbIxNode *np, xbUInt32 &ulDbfPtr ) const { - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - #ifdef XB_DEBUG_SUPPORT - // turn this off in production mode for better performance - xbUInt32 ulNoOfKeys = eGetUInt32 ( np->cpBlockData ); - if( iKeyNo < 0 || iKeyNo > (xbInt16) --ulNoOfKeys ){ - iErrorStop = 100; - throw XB_INVALID_KEYNO; - } - #endif - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - char *p = ( np->cpBlockData); - p += (8 + (iKeyNo * npTag->iKeyItemLen)); - ulDbfPtr = eGetUInt32 ( p ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::GetDbfPtr() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Get the first key for the given tag. -/*! - \param vpTag Tag to retrieve first key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::GetFirstKey( void *vpTag, xbInt16 iRetrieveSw ){ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - // clear out any history - if( npTag->npNodeChain ){ - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npCurNode = NULL; - } - if(( iRc = ReadHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // lRootBlock is now available - if(( iRc = GetBlock( npTag, npTag->ulRootBlock, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // if no keys on this node, and it's a leaf node then the index is empty - xbUInt32 ulKeyPtr = eGetUInt32( npTag->npCurNode->cpBlockData ); - if( ulKeyPtr == 0 && IsLeaf( npTag, npTag->npCurNode )){ - iRc = XB_EMPTY; - return iRc; - } - while( !IsLeaf( npTag, npTag->npCurNode )) // go down the chain looking for a leaf node - { - if(( iRc = GetKeyPtr( npTag, 0, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if(( iRc = GetBlock( npTag, ulKeyPtr, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } - if( iRetrieveSw ){ - if(( iRc = GetDbfPtr( npTag, 0, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - } - catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::GetFirstKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Get the key expression for the given tag. -/*! - \param vpTag Tag to retrieve expression from. - \returns Key expression. -*/ - -xbString &xbIxNdx::GetKeyExpression( const void * vpTag ) const{ - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - return npTag->sKeyExpression; -} - - -/***********************************************************************/ -//! @brief Get the key filter for the given tag. -/*! - NDX index files do not support filters. This returns NULL. - \returns NULL. -*/ - -xbString &xbIxNdx::GetKeyFilter( const void * ) const{ - return sNullString; -} -/***********************************************************************/ -//! @brief Get the key length for the given tag. -/*! - \param vpTag Tag to retrieve key length for. - \returns Length of key. -*/ -xbInt32 xbIxNdx::GetKeyLen( const void * vpTag ) const{ - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - return npTag->iKeyLen; -} -/***********************************************************************/ -//! @brief Get child node number for given key number. -/*! - \param vpTag Tag to retrieve dbf rec number on. - \param iKeyNo Key number for retrieval - \param np Pointer to node - \param ulKeyPtr Output node number - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::GetKeyPtr( void *vpTag, xbInt16 iKeyNo, xbIxNode *np, xbUInt32 &ulKeyPtr ) const { - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - try{ - #ifdef XB_DEBUG_SUPPORT - // turn this off in production mode for better performance - xbUInt32 ulNoOfKeys = eGetUInt32 ( np->cpBlockData ); - if( iKeyNo < 0 || iKeyNo > (xbInt16) ulNoOfKeys ){ - iErrorStop = 100; - throw XB_INVALID_KEYNO; - } - #endif - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - char *p = ( np->cpBlockData); - p += (4 + (iKeyNo * npTag->iKeyItemLen)); - ulKeyPtr = eGetUInt32 ( p ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::GetKeyPtr() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Returns key update status. -/*! - \param vpTag Tag to check status on. - \returns XB_UPD_KEY Key updated.<br> - XB_DEL_KEY Key deleted.<br> - XB_ADD_KEY Key added.<br> - 0 No key updates - -*/ -xbInt16 xbIxNdx::GetKeySts( void *vpTag ) const{ - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - return npTag->iKeySts; -} -/***********************************************************************/ -//! @brief Get character key type for given tag. -/*! - \param vpTag Tag to retrieve key type for. - \returns Char key type. -*/ - -char xbIxNdx::GetKeyType( const void * vpTag ) const{ - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - return npTag->cKeyType; -} - -/***********************************************************************/ -//! @brief Get numeric key type for given tag. -/*! - \param vpTag Tag to retrieve first key for. - \returns Numeric key type. -*/ -xbInt16 xbIxNdx::GetKeyTypeN( const void * vpTag ) const{ - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - return npTag->iKeyType; -} -/***********************************************************************/ -//! @brief Get the last key for the given tag. -/*! - \param vpTag Tag to retrieve last key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::GetLastKey( void *vpTag, xbInt16 iRetrieveSw ){ - return GetLastKey( 0, vpTag, iRetrieveSw ); -// return GetLastKey( 0, vpTag, 1 ); - -} -/***********************************************************************/ -//! @brief Get the last key for the given tag and starting node. -/*! - \param ulNodeNo Starting node - \param vpTag Tag to retrieve last key on. - \param iRetrieveSw xbTrue - Retrieve the record if key found.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::GetLastKey( xbUInt32 ulNodeNo, void *vpTag, xbInt16 iRetrieveSw ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulKeyPtr = 0; - xbUInt32 ulNoOfKeys = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - // clear out any history - if( npTag->npNodeChain ){ - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npCurNode = NULL; - } - if( ulNodeNo == 0 ){ - if(( iRc = ReadHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // lRootBlock is now available - if(( iRc = GetBlock( npTag, npTag->ulRootBlock, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } else { - if(( iRc = GetBlock( npTag, ulNodeNo, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - // if no keys on this node, then the index is empty - ulNoOfKeys = eGetUInt32( npTag->npCurNode->cpBlockData ); - if( ulNoOfKeys == 0 && IsLeaf( npTag, npTag->npCurNode )){ - iRc = XB_EMPTY; - return iRc; - } - npTag->npCurNode->iCurKeyNo = ulNoOfKeys; - while( !IsLeaf( npTag, npTag->npCurNode ) ){ // go down the chain looking for a leaf node - npTag->npCurNode->iCurKeyNo = eGetUInt32( npTag->npCurNode->cpBlockData ); - if(( iRc = GetKeyPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if(( iRc = GetBlock( npTag, ulKeyPtr, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - ulNoOfKeys = eGetUInt32( npTag->npCurNode->cpBlockData ); - npTag->npCurNode->iCurKeyNo = ulNoOfKeys; - } - // get here on a leaf node, it has one fewer iCurKeyNo - npTag->npCurNode->iCurKeyNo--; - if( iRetrieveSw ){ - ulNoOfKeys = eGetUInt32( npTag->npCurNode->cpBlockData ); - if(( iRc = GetDbfPtr( npTag, ulNoOfKeys - 1, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::GetLastKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Get the last key for a block number. -/*! - \param vpTag Tag to retrieve first key on. - \param ulBlockNo Block number for key retrieval. - \param cpBuf output buffer for key placement - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::GetLastKeyForBlockNo( void *vpTag, xbUInt32 ulBlockNo, char *cpBuf ){ - - // returns the last key for a given block number - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - xbIxNode * npSaveNodeChain = npTag->npNodeChain; - xbIxNode * npSaveCurNode = npTag->npCurNode; - npTag->npNodeChain = NULL; - - if(( iRc = GetLastKey( ulBlockNo, npTag, 0 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // set the key - memcpy( cpBuf, GetKeyData( npTag->npCurNode, GetKeyCount( npTag->npCurNode ) - 1, npTag->iKeyItemLen ), (size_t) npTag->iKeyLen ); - - // free memory - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npNodeChain = npSaveNodeChain; - npTag->npCurNode = npSaveCurNode; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::GetLastKeyForBlockNo() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc ) ); - } - return iRc; -} -/***********************************************************************/ -//! @brief Get the next key for the given tag. -/*! - \param vpTag Tag to retrieve next key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::GetNextKey( void * vpTag, xbInt16 iRetrieveSw ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - if( !npTag->npNodeChain ) - return GetFirstKey( vpTag, iRetrieveSw ); - - // more keys on this node? if yes, get the next one to the right - xbUInt32 ulKeyPtr; - if((eGetUInt32( npTag->npCurNode->cpBlockData ) -1) > npTag->npCurNode->iCurKeyNo ){ - npTag->npCurNode->iCurKeyNo++; - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if( iRetrieveSw ){ - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } else { - return iRc; - } - } else { - return iRc; - } - } - // if at end of head node, then eof - if( npTag->npCurNode->ulBlockNo == npTag->ulRootBlock ) - return XB_EOF; - - // This logic assumes that interior nodes have n+1 left node no's where n is he the number of keys in the node - xbIxNode * TempIxNode = npTag->npCurNode; - npTag->npCurNode = npTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - - while( npTag->npCurNode->iCurKeyNo >= eGetUInt32( npTag->npCurNode->cpBlockData ) && - (npTag->npCurNode->ulBlockNo != npTag->ulRootBlock )){ - TempIxNode = npTag->npCurNode; - npTag->npCurNode = npTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } - - // head node and at end of head node, then eof - if( npTag->npCurNode->ulBlockNo == npTag->ulRootBlock && - npTag->npCurNode->iCurKeyNo == eGetUInt32( npTag->npCurNode->cpBlockData )) - return XB_EOF; - - // move one to the right - npTag->npCurNode->iCurKeyNo++; - - if(( iRc = GetKeyPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - if(( iRc = GetBlock( npTag, ulKeyPtr, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - while( !IsLeaf( npTag, npTag->npCurNode )) // go down the chain looking for a leaf node - { - if(( iRc = GetKeyPtr( npTag, 0, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if(( iRc = GetBlock( npTag, ulKeyPtr, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - if( iRetrieveSw ){ - if(( iRc = GetDbfPtr( npTag, 0, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - } - catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::GetNextKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Get the previous key for the given tag. -/*! - \param vpTag Tag to retrieve previous key on. - \param iRetrieveSw xbTrue - Retrieve the record on success.<br> - xbFalse - Don't retrieve record. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::GetPrevKey( void * vpTag, xbInt16 iRetrieveSw ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - // This method assumes last index call landed on a valid key. - // If last call resulted in an error, this method will returns XB_BOF - - try{ - if( !npTag->npNodeChain ) - return GetLastKey( 0, vpTag, iRetrieveSw ); - - xbUInt32 ulKeyPtr; - if( npTag->npCurNode->iCurKeyNo > 0 ){ - npTag->npCurNode->iCurKeyNo--; - - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if( iRetrieveSw ){ - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } else { - return iRc; - } - } - } - - // next two lines might have been an issue - if( npTag->npCurNode->ulBlockNo == npTag->ulRootBlock && GetKeyCount( npTag->npCurNode ) == 0 && IsLeaf( npTag, npTag->npCurNode )) - return XB_EMPTY; - - if( npTag->npCurNode->ulBlockNo == npTag->ulRootBlock ) - return XB_BOF; - - // This logic assumes that interior nodes have n+1 left node no's where n is he the number of keys in the node - xbIxNode * TempIxNode = npTag->npCurNode; - npTag->npCurNode = npTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - - while( npTag->npCurNode->iCurKeyNo == 0 && - (npTag->npCurNode->ulBlockNo != npTag->ulRootBlock )){ - TempIxNode = npTag->npCurNode; - npTag->npCurNode = npTag->npCurNode->npPrev; - TempIxNode = FreeNodeChain( TempIxNode ); - } - - // head node and at end of head node, then bof - if( npTag->npCurNode->ulBlockNo == npTag->ulRootBlock && - npTag->npCurNode->iCurKeyNo == 0 ) - return XB_BOF; - - // move one to the left - npTag->npCurNode->iCurKeyNo--; - - if(( iRc = GetKeyPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - if(( iRc = GetBlock( npTag, ulKeyPtr, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - while( !IsLeaf( npTag, npTag->npCurNode )){ // go down the chain looking for a leaf node - npTag->npCurNode->iCurKeyNo = eGetUInt32( npTag->npCurNode->cpBlockData ); - if(( iRc = GetKeyPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if(( iRc = GetBlock( npTag, ulKeyPtr, 1, (xbUInt32) npTag->iKeyItemLen )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - - npTag->npCurNode->iCurKeyNo = eGetUInt32( npTag->npCurNode->cpBlockData ) - 1; - if( iRetrieveSw ){ - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if(( iRc = dbf->GetRecord( ulKeyPtr )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - } - } - - catch( xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::GetPrevKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Get the sort order for given tag. -/*! - Ndx indices only support ascending keys. - \returns 0 -*/ -xbBool xbIxNdx::GetSortOrder( void * ) const{ - return 0; -} -/***********************************************************************/ -//! @brief Get tag for tag number. -/*! - \returns Pointer to ndx tag. -*/ -void * xbIxNdx::GetTag( xbInt16 ) const{ - return ndxTag; -} -/***********************************************************************/ -//! @brief Get tag for tag name. -/*! - \returns Pointer to ndx tag. -*/ -void * xbIxNdx::GetTag( xbString & ) const{ - return ndxTag; -} - -/***********************************************************************/ -//! @brief Get tag count. -/*! - NDX index files contain one tag. - \returns 1 -*/ - -xbInt16 xbIxNdx::GetTagCount() const{ - return 1; -} -/***********************************************************************/ -//! @brief Get tag name. -/*! - \returns Tag name. -*/ -xbString &xbIxNdx::GetTagName( void * ) const { -// char * xbIxNdx::GetTagName( void * ) const { - - return ndxTag->sTagName; - -} -/***********************************************************************/ -//! @brief Get tag name. -/*! - \returns Tag name. -*/ -const char * xbIxNdx::GetTagName( void *, xbInt16 ) const { - return ndxTag->sTagName; -} - -/***********************************************************************/ -//! @brief Get the unique setting for given tag. -/*! - \param vpTag Tag to unique setting on. - \returns xbTrue - Unique index.<br> xbFalse - Not unique index. -*/ -xbBool xbIxNdx::GetUnique( void * vpTag ) const{ - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - return npTag->iUnique; -} - -/***********************************************************************/ -//! @brief Insert key into interior node. -/*! - Insert key into non-full interior node.<br> - Assumes valid inputs - - \param vpTag Tag in play. - \param npNode Node for insertion. - \param iSlotNo Slot number to insert key. - \param ulPtr Pointer number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::InsertNodeI( void *vpTag, xbIxNode *npNode, xbInt16 iSlotNo, xbUInt32 ulPtr ){ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char *pTrg; - xbInt16 iSrcPos; - char *pLastKey = NULL; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - // update number of keys on the node - xbInt32 lKeyCnt = GetKeyCount( npNode ); - iSrcPos = 12 + (iSlotNo * npTag->iKeyItemLen); - - char *pSrc = npNode->cpBlockData; - pSrc += iSrcPos; - - // if not appending to the end of the node, make some room, move things to the right - if( iSlotNo < lKeyCnt ) { - xbInt16 iCopyLen = ((lKeyCnt - iSlotNo) * npTag->iKeyItemLen) - 4; - pTrg = pSrc; - pTrg += npTag->iKeyItemLen; - memmove( pTrg, pSrc, (size_t) iCopyLen ); - } - - // get the right most key for the left part of the split node - xbUInt32 ulKeyPtr2; - if(( iRc = GetKeyPtr( vpTag, npNode->iCurKeyNo, npNode, ulKeyPtr2 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // get the new right key value for the freshly split node - pLastKey = (char *) malloc((size_t) ndxTag->iKeyLen); - if(( iRc = GetLastKeyForBlockNo( vpTag, ulKeyPtr2, pLastKey )) != XB_NO_ERROR ){ - iRc = 110; - throw iRc; - } - // write the key value - pTrg = pSrc; - char *pTrg2 = pSrc; - pSrc = pLastKey; - for( xbInt16 i = 0; i < npTag->iKeyLen; i++ ) - *pTrg++ = *pSrc++; - - pTrg2 += (npTag->iKeyItemLen - 8); - ePutUInt32( pTrg2, ulPtr ); - ePutInt32( npNode->cpBlockData, ++lKeyCnt ); - - // write out the updated block to disk - if(( iRc = WriteBlock( npNode->ulBlockNo, GetBlockSize(), npNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - if( pLastKey ) - free( pLastKey ); - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::InsertNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( pLastKey ) - free( pLastKey ); - } - return iRc; -} -/***********************************************************************/ -//! @brief Insert key into leaf node. -/*! - Insert key into non-full leaf node.<br> - Assumes valid inputs - - \param vpTag Tag in play. - \param npNode Node for insertion. - \param iSlotNo Slot number to insert key. - \param ulPtr Pointer number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::InsertNodeL( void *vpTag, xbIxNode *npNode, xbInt16 iSlotNo, - char * cpKeyBuf, xbUInt32 ulPtr ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char *pSrc; - char *pTrg; - char *pKeyPos; - xbString sMsg; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - try{ - xbInt32 lKeyCnt = GetKeyCount( npNode ); - xbInt16 iKeyPos = 4 + iSlotNo * npTag->iKeyItemLen; - pKeyPos = npNode->cpBlockData; - pKeyPos += iKeyPos; - - // if not appending to end, make space, move things right - if( iSlotNo < lKeyCnt ) { - xbInt16 iCopyLen = (lKeyCnt - iSlotNo) * npTag->iKeyItemLen; - pTrg = pKeyPos; - pTrg += npTag->iKeyItemLen; - memmove( pTrg, pKeyPos, (size_t) iCopyLen ); - } - // if leaf, write rec number - pTrg = pKeyPos; - memset( pTrg, 0x00, 4 ); - pTrg += 4; - ePutUInt32( pTrg, ulPtr ); - pTrg += 4; - - // write the key value - pSrc = cpKeyBuf; - for( xbInt16 i = 0; i < npTag->iKeyLen; i++ ) - *pTrg++ = *pSrc++; - - // update number of keys on the node - ePutInt32( npNode->cpBlockData, ++lKeyCnt ); - - // write out the updated block to disk - if(( iRc = WriteBlock( npNode->ulBlockNo, GetBlockSize(), npNode->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::InsertNodeL() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Determine node leaf status -/*! - \param npNode Node to examine. - \returns xbTrue - Leaf node.<br> xbFalse - Interior node. -*/ -xbBool xbIxNdx::IsLeaf( void *, xbIxNode *npNode ) const { - xbUInt32 ulBlock = eGetUInt32 ( npNode->cpBlockData+4 ); - if( ulBlock > 0 ) // if the second four bytes are a number, it's an interior node - return false; - else - return true; -} -/***********************************************************************/ -//! @brief Determine if key exists. -/*! - This method assumes the key has already been built and is in either - cpKeyBuf or dKey. - - \param vpTag - Pointer to tag. - \returns xbTrue - Key exists.<br> xbFalse - Key does not exist. -*/ -xbInt16 xbIxNdx::KeyExists( void * vpTag ){ - - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - xbInt16 iRc = FindKey( vpTag, npTag->cpKeyBuf, npTag->iKeyLen, 0 ); - if( iRc == 0 ) - return 1; - else - return 0; -} - -/***********************************************************************/ -//! @brief Set position for key add. -/*! - This routine is called by the AddKey() method and is used to position - the node chain to the position the new key should be added to the index. - - \param npTag Pointer to npTag. - \param ulAddRecNo Record number to add. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::KeySetPosAdd( xbNdxTag *npTag, xbUInt32 ulAddRecNo ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - - iRc = FindKey( npTag, npTag->cpKeyBuf, npTag->iKeyLen, 0 ); - if( iRc == XB_NOT_FOUND || iRc == XB_EMPTY ) - return XB_NO_ERROR; // good position - - else if( iRc != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - // get here if key was found, get the right most instance of any non unique key for append, find correct spot for update - if( GetUnique() == 0 ){ - xbUInt32 ulCurRecNo; - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulCurRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - xbBool bKeysMatch = xbTrue; - while( bKeysMatch && ulAddRecNo > ulCurRecNo && iRc == XB_NO_ERROR ){ - if(( iRc = GetNextKey( npTag, 0 )) == XB_NO_ERROR ){ - if( memcmp( GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), npTag->cpKeyBuf, (size_t) npTag->iKeyLen )) - bKeysMatch = xbFalse; - else{ - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulCurRecNo )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - } - } - } - if( iRc == XB_EOF ){ // eof condition - if(( iRc = GetLastKey( 0, npTag, 0 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - npTag->npCurNode->iCurKeyNo++; - return XB_NO_ERROR; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::KeySetPos() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Set position for key add. -/*! - This routine is called by the DeleteKey() method and is used to position - the node chain to the position the old key should be deleted from the index. - - \param npTag Pointer to npTag. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::KeySetPosDel( xbNdxTag *npTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbString sMsg; - - try{ - iRc = FindKey( NULL, npTag->cpKeyBuf2, npTag->iKeyLen, 0 ); - if( iRc == XB_NOT_FOUND || iRc == XB_EMPTY ) - return XB_NO_ERROR; // good position - else if( iRc != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - xbUInt32 ulIxRecNo; - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulIxRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if( ulIxRecNo == dbf->GetCurRecNo()) - return XB_NO_ERROR; - if( GetUnique() == 1 ){ - iErrorStop = 120; - iRc = XB_NOT_FOUND; - throw iRc; - } - xbBool bFound = xbFalse; - xbBool bKeysMatch = xbTrue; - while( bKeysMatch && !bFound && iRc == XB_NO_ERROR ){ - if(( iRc = GetNextKey( npTag, 0 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - if( memcmp( GetKeyData( npTag->npCurNode, npTag->npCurNode->iCurKeyNo, npTag->iKeyItemLen ), npTag->cpKeyBuf2, (size_t) npTag->iKeyLen )){ - bKeysMatch = xbFalse; - } else { - if(( iRc = GetDbfPtr( npTag, npTag->npCurNode->iCurKeyNo, npTag->npCurNode, ulIxRecNo )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - if( ulIxRecNo == dbf->GetCurRecNo()) - bFound = xbTrue; - } - } - if( bFound ) - return XB_NO_ERROR; - else - return XB_NOT_FOUND; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::KeySetPosDel() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Returns key filter status. -/*! - \param vpTag Tag to check status on. - \returns xbtrue - Key was updated.<br>xbFalse - Key not updated. - - Always true for NDX style indices. -*/ -//inline xbBool xbIxNdx::KeyFiltered( void *vpTag ) const{ -// return xbTrue; -//} - -/***********************************************************************/ -//! @brief Read head block of index file. -/*! - \param iOpt 0 - Read in entire block - 1 - Read in only dynamic section of block - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbIxNdx::ReadHeadBlock( xbInt16 iOpt = 0 ) { - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - try{ - if( !FileIsOpen()){ - iRc = XB_NOT_OPEN; - iErrorStop = 100; - throw iRc; - } - xbInt16 iLen; - iOpt == 0 ? iLen = 512 : iLen = 21; - - if(( iRc = ReadBlock( (xbUInt32) 0, (size_t) iLen, cNodeBuf )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - char *p = cNodeBuf; - ndxTag->ulRootBlock = eGetUInt32( p ); p+=4; - ndxTag->ulTotalBlocks = eGetUInt32( p ); p+=5; - if( iOpt == 0 ){ - ndxTag->cKeyType = *p; p+=3; - ndxTag->iKeyLen = eGetInt16( p ); p+=2; - ndxTag->iKeysPerBlock = eGetInt16( p ); p+=2; - ndxTag->iKeyType = eGetInt16( p ); p+=2; - ndxTag->iKeyItemLen = eGetInt16( p ); p+=2; - ndxTag->cSerNo = *p; p+=3; - ndxTag->iUnique = *p; p++; - ndxTag->sKeyExpression.Set( p ); - - if( ndxTag->exp ) - delete ndxTag->exp; - - ndxTag->exp = new xbExp( xbase, dbf ); - if(( iRc = ndxTag->exp->ParseExpression( ndxTag->sKeyExpression.Str() )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - if( ndxTag->cpKeyBuf ) - free( ndxTag->cpKeyBuf ); - if( ndxTag->cpKeyBuf2 ) - free( ndxTag->cpKeyBuf2 ); - - ndxTag->cpKeyBuf = (char *) malloc( (size_t) ndxTag->iKeyLen ); - ndxTag->cpKeyBuf2 = (char *) malloc( (size_t) ndxTag->iKeyLen ); - - if( ndxTag->sTagName == "" ) - GetFileNamePart( ndxTag->sTagName ); - - } else { - p+= 11; - ndxTag->cSerNo = *p; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::ReadHeadBlock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Reindex a tag. -/*! - \param vpTag Pointer to tag pointer. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::Reindex( void **vpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag *npTag = ndxTag; - - try{ - xbInt16 iUnique = GetUnique( *vpTag ); - - npTag->npNodeChain = FreeNodeChain( npTag->npNodeChain ); - npTag->npCurNode = NULL; - npTag->ulRootBlock = 1L; - npTag->ulTotalBlocks = 2L; - - if(( iRc = xbTruncate( 1024 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - if(( iRc = WriteHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - char buf[512]; - memset( buf, 0x00, 512 ); - - if(( iRc = WriteBlock( 1, 0, buf )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - xbUInt32 ulRecCnt = 0; - if(( iRc = dbf->GetRecordCnt( ulRecCnt )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - - for( xbUInt32 l = 1; l <= ulRecCnt; l++ ){ - if(( iRc = dbf->GetRecord( l )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - - if(( iRc = CreateKey( npTag, 1 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - if( iUnique ){ - // iRc = CheckForDupKey( vpTag2 ); - iRc = CheckForDupKey( npTag ); - if( iRc != 0 ){ - if( iRc < 0 ){ - iErrorStop = 160; - throw iRc; - } - return XB_KEY_NOT_UNIQUE; - } - } - - if(( iRc = AddKey( npTag, l )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - } - *vpTag = npTag; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::Reindex() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - this->DeleteTag( NULL ); // Don't leave the index in an incomplete state - } - return iRc; -} -/***********************************************************************/ -//! @brief Set current tag. -/*! - For ndx indices, there is only one tag. - \returns XB_NO_ERROR. -*/ -xbInt16 xbIxNdx::SetCurTag( xbInt16 ) { - xbIx::SetCurTag( ndxTag ); - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Set current tag. -/*! - For ndx indices, there is only one tag. - \returns XB_NO_ERROR. -*/ -xbInt16 xbIxNdx::SetCurTag( xbString & ) { - xbIx::SetCurTag( ndxTag ); - dbf->SetCurTag( "NDX", this, GetTag(0) ); - return XB_NO_ERROR; -} - -/***********************************************************************/ -//! @brief Split an interior node -/*! - - This routine splits an interior node into two nodes, divided by dSplitFactor.<br> - This behaves differently than V7 Dbase. V7 does not balance the nodes.<br> - For V7, if adding a key to the end of a node, it will create a right node - with only one key, and the left node is still full.<br><br> - - Possible performance improvement options.<br> - Two modes when splitting:<br> - a) Split nodes in the middle - good for random access applications<br> - b) Split off right node with only one key - good for applications with - expectation of ascending keys added moving forward.<br> - - This routine first inserts the key into the left node in the appropriate location - then splits the node based on the split factor setting. - - \param vpTag Tag in play. - \param npLeft Left node to split. - \param npRight Right node to split. - \param iSlotNo Slot number for split. - \param ulPtr Pointer number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::SplitNodeI( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, xbInt16 iSlotNo, xbUInt32 ulPtr ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbNdxTag * npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - xbDouble dSplitFactor = .5; // split the nodes 50/50 - xbString sMsg; - - try{ - xbInt32 lKeyCnt = GetKeyCount( npLeft ); - xbInt32 lNewLeftKeyCnt = (xbInt32) ((lKeyCnt + 1) * dSplitFactor) + 1; - xbInt32 lNewRightKeyCnt = lKeyCnt - lNewLeftKeyCnt; - xbInt16 iSrcPos; - xbInt16 iCopyLen; - char *pSrc; - char *pTrg; - - // insert the key into the left node - if(( iRc = InsertNodeI( vpTag, npLeft, iSlotNo, ulPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // move the right half of the left node to the right node - iSrcPos = ((lNewLeftKeyCnt + 1) * npTag->iKeyItemLen) + 4; - iCopyLen = (lNewRightKeyCnt * npTag->iKeyItemLen) + 4; - pSrc = npLeft->cpBlockData; - pSrc += iSrcPos; - pTrg = npRight->cpBlockData; - pTrg += 4; - memmove( pTrg, pSrc, (size_t) iCopyLen ); - - // write the new key counts into the nodes - pTrg = npLeft->cpBlockData; - ePutInt32( pTrg, lNewLeftKeyCnt ); - pTrg = npRight->cpBlockData; - ePutInt32( pTrg, lNewRightKeyCnt ); - - // write the new key counts into the nodes - pTrg = npLeft->cpBlockData; - ePutInt32( pTrg, lNewLeftKeyCnt ); - pTrg = npRight->cpBlockData; - ePutInt32( pTrg, lNewRightKeyCnt ); - - // write out the block - if(( iRc = WriteBlock( npLeft->ulBlockNo, GetBlockSize(), npLeft->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // write out the block - if(( iRc = WriteBlock( npRight->ulBlockNo, GetBlockSize(), npRight->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::SplitNodeI() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Split a leaf node. -/*! - This routine splits an index leaf into two nodes, divided by dSplitFactor.<br> - This behaves differently than V7 Dbase. V7 does not balance the nodes.<br> - For V7, if adding a key to the end of a node, it will create a right node - with only one key, and the left node is still full.<br><br> - - Possible performance improvement options.<br> - Two modes when splitting:<br> - a) Split nodes in the middle - good for random access applications<br> - b) Split off right node with only one key - good for applications with - expectation of ascending keys added moving forward.<br> - - This routine first inserts the key into the left node in the appropriate location - then splits the node based on the split factor setting. - - \param vpTag Tag in play. - \param npLeft Left node to split. - \param npRight Right node to split. - \param iSlotNo Slot number for split. - \param ulPtr Pointer number to insert. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::SplitNodeL( void *vpTag, xbIxNode * npLeft, xbIxNode *npRight, - xbInt16 iSlotNo, char * cpKeyBuf, xbUInt32 ulPtr ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbDouble dSplitFactor = .5; - xbNdxTag *npTag; - vpTag ? npTag = (xbNdxTag *) vpTag : npTag = ndxTag; - - xbString sMsg; - try{ - xbInt32 lKeyCnt = GetKeyCount( npLeft ); - xbInt32 lNewLeftKeyCnt = (xbInt32) ((lKeyCnt + 1) * dSplitFactor) + 1; - xbInt32 lNewRightKeyCnt = lKeyCnt + 1 - lNewLeftKeyCnt; - - // xbInt16 iSrcPos; - xbInt16 iLen; - char *pSrc = npLeft->cpBlockData; - char *pTrg; - - if(( iRc = InsertNodeL( vpTag, npLeft, iSlotNo, cpKeyBuf, ulPtr )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - - // move right half off of left node to the right node - pSrc = npLeft->cpBlockData; - pSrc += ((lNewLeftKeyCnt * npTag->iKeyItemLen)+4); - pTrg = npRight->cpBlockData; - pTrg += 4; - iLen = lNewRightKeyCnt * npTag->iKeyItemLen; - memmove( pTrg, pSrc, (size_t) iLen ); - - // write the new key counts into the nodes - pTrg = npLeft->cpBlockData; - ePutInt32( pTrg, lNewLeftKeyCnt ); - pTrg = npRight->cpBlockData; - ePutInt32( pTrg, lNewRightKeyCnt ); - - // write out the left block - if(( iRc = WriteBlock( npLeft->ulBlockNo, GetBlockSize(), npLeft->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - // write out the right block - if(( iRc = WriteBlock( npRight->ulBlockNo, GetBlockSize(), npRight->cpBlockData )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::SplitNodeL() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief UpdateTagKey -/*! - This routine updates a key or a given tag. - The file header is considered to be the first 2048 bytes in the file. - - \param cAction A - Add a key.<br> - D - Delete a key.<br> - R - Revise a key.<br> - \param vpTg - Pointer to tag.<br> - \param ulRecNo - Record number association with the action.<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbIxNdx::UpdateTagKey( char cAction, void *vpTag, xbUInt32 ulRecNo ){ - - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - // ..xbNdxTag *npTag = (xbMdxTag *) vpTag; - - try{ - // save off any needed fileds for updating - // xbUInt32 ulTagSizeSave = mpTag->ulTagSize; - //xbUInt32 ulLeftChildSave = mpTag->ulLeftChild; - //xbUInt32 ulRightChildSave = mpTag->ulRightChild; - - - if( cAction == 'D' || cAction == 'R' ){ -// std::cout << "UpdateTagKey delete\n"; - if(( iRc = DeleteKey( vpTag )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - } - - if( cAction == 'A' || cAction == 'R' ){ - if(( iRc = AddKey( vpTag, ulRecNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::UpdateTagKey() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -//! @brief Write head block. -/*! - Commit the index head node to disk. - \param iOpt 0 - Entire header.<br> - 1 - Update root block, number of blocks and seq number.<br> - 2 - Update sequence number only<br> - \returns <a href="xbretcod_8h.html"> -*/ - -xbInt16 xbIxNdx::WriteHeadBlock( xbInt16 iOpt ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - if( iOpt == 2 ){ - - // increment the serial number - if( ndxTag->cSerNo >= 0 && ndxTag->cSerNo < 127 ) - ndxTag->cSerNo++; - else - ndxTag->cSerNo = 0; - - if(( iRc = xbFseek( 20, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = xbFputc( ndxTag->cSerNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } else if( iOpt == 1 ){ - xbRewind(); - char buf[8]; - ePutUInt32( &buf[0], ndxTag->ulRootBlock ); - ePutUInt32( &buf[4], ndxTag->ulTotalBlocks ); - if(( iRc = xbFwrite( buf, 8, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - return WriteHeadBlock( 2 ); - - } else if ( iOpt == 0 ){ - - char buf[512]; - memset( buf, 0x00, 512 ); - ePutUInt32( &buf[0], ndxTag->ulRootBlock ); - ePutUInt32( &buf[4], ndxTag->ulTotalBlocks ); - buf[9] = ndxTag->cKeyType; - buf[11] = 0x1B; - ePutInt16( &buf[12], ndxTag->iKeyLen ); - ePutInt16( &buf[14], ndxTag->iKeysPerBlock ); - ePutInt16( &buf[16], ndxTag->iKeyType ); - ePutInt16( &buf[18], ndxTag->iKeyItemLen ); - if( ndxTag-> iUnique ) buf[23] = 0x01; - - for( xbUInt32 i = 0; i < ndxTag->sKeyExpression.Len(); i++ ) - buf[i+24] = ndxTag->sKeyExpression.GetCharacter(i+1); - - xbRewind(); - if(( iRc = xbFwrite( buf, 512, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - } else { - iRc = XB_INVALID_OPTION; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxNdx::WriteHeadBlock() Exception Caught. Error Stop = [%d] iRc = [%d] option = [%d] ser=[%d]", iErrorStop, iRc, iOpt, ndxTag->cSerNo ); - xbase->WriteLogMessage( sMsg ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -} /* namespace */ -#endif /* XB_NDX_SUPPORT */ - - - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixtdx.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbixtdx.cpp deleted file mode 100755 index 4137725..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbixtdx.cpp +++ /dev/null @@ -1,661 +0,0 @@ -/* xbixtdx.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 temporary index logic - -*/ - -#include "xbase.h" - - - -#ifdef XB_TDX_SUPPORT - - -namespace xb{ - -/************************************************************************/ -xbIxTdx::xbIxTdx( xbDbf *dbf ) : xbIxMdx( dbf ) { -//xbIxMdx::xbIxMdx( xbDbf *dbf ) : xbIx( dbf ){ - -// std::cout << "xbIxTdx::Constructor()\n"; - - // Init(); not needed, called in xbMdx - - -} - -/************************************************************************/ -xbIxTdx::~xbIxTdx() { - -// std::cout << "xbIxTdx::Destructor()\n"; - -} - -/***********************************************************************/ -xbInt16 xbIxTdx::Close(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - -std::cout << "xbIxTdx::Close\n"; - - try{ - if(( iRc = xbIxMdx::Close()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = xbRemove()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxTdx::Close() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Create new tag. -/*! - This routine creates a new tag. When complete, sets the cur tag pointer to - the newly created tag. - - - \param sName Tag Name, including .MDX suffix - \param sKey Key Expression - \param sFilter Filter expression. - \param iDescending - \param iUnique xbtrue - Unique.<br>xbFalse - Not unique. - \param iOverLay xbTrue - Overlay if file already exists.<br>xbFalse - Don't overlay. - \param vpTag Output from method Pointer to vptag pointer. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbIxTdx::CreateTag( const xbString &sName, const xbString &sKey, const xbString &sFilter, xbInt16 iDescending, xbInt16 iUnique, xbInt16 iOverlay, void **vpTag ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbMdxTag *tte = NULL; - - std::cout << "xbIxTdx::CreateTag()\n"; - - - // std::cout << "CreateTag() name=[" << sName.Str() << "] key=[" << sKey.Str() << "] sFilter=[" << sFilter.Str() << "]\n"; - // std::cout << "TagUseCnt = " << iTagUseCnt << std::endl; - - - try{ - // verify room for new tag - if( !( iTagUseCnt < 47 )){ - iErrorStop = 100; - iRc = XB_LIMIT_REACHED; - throw iRc; - } - - // verify valid tag name - xbString sWorker = sName; - sWorker.Trim(); - if( sWorker.Len() > 10 ){ - iErrorStop = 110; - iRc = XB_INVALID_TAG; - throw iRc; - } - - // verify tag not already defined - if( iTagUseCnt > 0 ){ - if( GetTag( sWorker )){ - iErrorStop = 120; - iRc = XB_INVALID_TAG; - throw iRc; - } - } - - // allocate a tag structure here - if(( tte = (xbMdxTag *) calloc( 1, (size_t) sizeof( xbMdxTag ))) == NULL ){ - iErrorStop = 130; - iRc = XB_NO_MEMORY; - throw iRc; - } - *vpTag = tte; - tte->sTagName = new xbString( sWorker ); - - //set up the key expression - sWorker = sFilter; - sWorker.Trim(); - if( sWorker.Len() > 0 ){ - if( sWorker.Len() == 0 || sWorker.Len() > 220 ){ - iRc = XB_INVALID_TAG; - iErrorStop = 140; - throw iRc; - } - tte->sFiltExp = new xbString( sWorker ); - tte->filter = new xbExp( dbf->GetXbasePtr()); - if(( iRc = tte->filter->ParseExpression( dbf, sWorker )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - // tte->filter->DumpTree( 1 ); - - if((tte->filter->GetReturnType()) != 'L' ){ - iRc = XB_INVALID_TAG; - iErrorStop = 160; - throw iRc; - } - tte->cHasFilter = 0x01; - } - - //set up the key expression - sWorker = sKey; - sWorker.Trim(); - if( sWorker.Len() == 0 || sWorker.Len() > 100 ){ - iRc = XB_INVALID_TAG; - iErrorStop = 170; - throw iRc; - } - tte->sKeyExp = new xbString( sWorker ); - tte->exp = new xbExp( dbf->GetXbasePtr()); - if(( iRc = tte->exp->ParseExpression( dbf, sWorker )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - - xbDate d; - d.Sysdate(); - if( iTagUseCnt == 0 ){ - // first tag, new mdx file - // create the file name - - // create temp file - xbString sIxFileName; - if(( iRc = CreateUniqueFileName( GetTempDirectory(), "TDX", sIxFileName )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - - // copy the file name to the class variable - this->SetFileName( sIxFileName ); - if( FileExists() && !iOverlay ){ - iErrorStop = 200; - iRc = XB_FILE_EXISTS; - throw iRc; - } - - // first tag, need to create the file - if(( iRc = xbFopen( "w+b", dbf->GetShareMode())) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - cVersion = 2; - cCreateYY = (char) d.YearOf() - 1900; - cCreateMM = (char) d.MonthOf(); - cCreateDD = (char) d.DayOf( XB_FMT_MONTH ); - - GetFileNamePart( sFileName ); - sFileName.ToUpperCase(); - - SetBlockSize( (xbUInt32) dbf->GetCreateMdxBlockSize()); - iBlockFactor = GetBlockSize() / 512; - - cProdIxFlag = 0; // MDX is 1 - cTagEntryCnt = 48; - iTagLen = 32; - ulPageCnt = 4; - ulFirstFreePage = 0; - ulNoOfBlockAvail = 0; - cNextTag = 1; - c1B = 0x1B; - cUpdateYY = cCreateYY; - cUpdateMM = cCreateMM; - cUpdateDD = cCreateDD; - - if(( iRc = WriteHeadBlock( 0 )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw iRc; - } - } - - // populate the tag table entry structure - tte->ulTagHdrPageNo = ulPageCnt; - ulPageCnt += (xbUInt32) iBlockFactor; - tte->sTagName->strncpy( tte->cTagName, 10 ); - - // cKeyFmt is always 0x10; - // tested 2+ZIPCD CITY+STATE or just standalone field - always 0x10 - tte->cKeyFmt = 0x10; // = CalcTagKeyFmt( *tte->exp ); - - switch( tte->exp->GetReturnType()){ - case XB_EXP_CHAR: - tte->cKeyType = 'C'; - tte->iKeyLen = tte->exp->GetResultLen(); - tte->iSecKeyType = 0; - break; - - case XB_EXP_NUMERIC: - tte->cKeyType = 'N'; - tte->iKeyLen = 12; - tte->iSecKeyType = 0; - break; - - case XB_EXP_DATE: - tte->cKeyType = 'D'; - tte->iKeyLen = 8; - tte->iSecKeyType = 1; - break; - - default: - iErrorStop = 200; - iRc = XB_INVALID_INDEX; - throw iRc; - } - - tte->cpKeyBuf = (char *) malloc( (size_t) tte->iKeyLen + 1 ); - tte->cpKeyBuf2 = (char *) malloc( (size_t) tte->iKeyLen + 1 ); - -// if( 0 ){ -// printf( "ulTagHdrPageNo=[%d] cTagName=[%-11s], cLeftChild=[%d] cRightChild=[%d] cParent=[%d] cKeyType=[%c]\n\n", -// tte->ulTagHdrPageNo, tte->cTagName, tte->cLeftChild, tte->cRightChild, tte->cParent, tte->cKeyType ); -// } - - // write the new tte entry here - char tteBuf[21]; - memset( tteBuf, 0x00, 21 ); - - ePutUInt32( &tteBuf[0], tte->ulTagHdrPageNo ); - for( xbUInt32 l = 0; l < tte->sTagName->Len() && l < 10; l++ ){ - tteBuf[l+4] = tte->sTagName->GetCharacter(l+1); - } - tteBuf[15] = tte->cKeyFmt; - tteBuf[19] = 0x02; // appears to always be a 0x02 - tteBuf[20] = tte->cKeyType; - - if(( iRc = xbFseek( (iTagUseCnt * 32) + 544, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 230; - throw iRc; - } - if(( iRc = xbFwrite( tteBuf, 21, 1 )) != XB_NO_ERROR ){ - iErrorStop = 240; - throw iRc; - } - - - // Begin Tag Header - tte->ulRootPage = ulPageCnt; - tte->ulTagSize = (xbUInt32) iBlockFactor; - ulPageCnt += 2; - tte->cKeyFmt2 = 0x10; - if( iDescending ) - tte->cKeyFmt2 += 0x08; - if( iUnique ){ - tte->cKeyFmt2 += 0x40; - tte->cUnique = 0x01; - } - - tte->cTag11 = 0x1B; // always 0x1b ? - tte->cSerialNo = 0x01; // version incremented with each tag update - tte->ulLeftChild = tte->ulRootPage; - tte->ulRightChild = tte->ulRootPage; - - tte->cTagYY = (char) d.YearOf() - 1900; - tte->cTagMM = (char) d.MonthOf(); - tte->cTagDD = (char) d.DayOf( XB_FMT_MONTH ); - - 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 ); -// printf( "iSecKeyType=[%d] iKeyItemLen=[%d] cUnique=[%d] \n", tte->iSecKeyType, tte->iKeyItemLen, tte->cUnique ); - - char *pBuf; - if(( pBuf = (char *) calloc( 1, (size_t) GetBlockSize())) == NULL ){ - iErrorStop = 230; - iRc = XB_NO_MEMORY; - throw iRc; - } - char *wPtr; - wPtr = pBuf; - ePutUInt32( wPtr, tte->ulRootPage ); - - wPtr += 4; - ePutUInt32( wPtr, tte->ulTagSize ); - - wPtr += 4; - *wPtr = tte->cKeyFmt2; - - wPtr++; - *wPtr = tte->cKeyType2; - - wPtr += 2; - *wPtr = tte->cTag11; - - wPtr += 1; - ePutInt16( wPtr, tte->iKeyLen ); - - wPtr += 2; - ePutInt16( wPtr, tte->iKeysPerBlock ); - - wPtr += 2; - ePutInt16( wPtr, tte->iSecKeyType ); - - wPtr += 2; - ePutInt16( wPtr, tte->iKeyItemLen ); - - wPtr += 2; - *wPtr = tte->cSerialNo; - - wPtr += 3; - *wPtr = tte->cUnique; - - wPtr++; - for( xbUInt32 l = 0; l < tte->sKeyExp->Len(); l++ ) - *wPtr++ = tte->sKeyExp->GetCharacter(l+1); - - wPtr = pBuf; - - tte->cHasKeys = 0x00; - pBuf[246] = tte->cHasKeys; - - wPtr += 248; - ePutUInt32( wPtr, tte->ulLeftChild ); - wPtr += 4; - ePutUInt32( wPtr, tte->ulRightChild ); - - pBuf[257] = tte->cTagYY; - pBuf[258] = tte->cTagMM; - pBuf[259] = tte->cTagDD; - pBuf[480] = tte->cKeyFmt3; - - if( sFilter.Len() > 0 ){ - pBuf[245] = tte->cHasFilter; - wPtr = pBuf; - wPtr += 762; - for( xbUInt32 l = 0; l < sFilter.Len(); l++ ) - *wPtr++ = sFilter.GetCharacter(l+1); - } - - if(( iRc = xbFseek( tte->ulTagHdrPageNo * 512, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 250; - throw iRc; - } - - if(( iRc = xbFwrite( pBuf, GetBlockSize(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 260; - throw iRc; - } - - memset( pBuf, 0x00, GetBlockSize() ); - if(( iRc = xbFwrite( pBuf, GetBlockSize(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 270; - throw iRc; - } - - iTagUseCnt++; - cNextTag++; - - - if(( iRc = WriteHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 280; - throw iRc; - } - - // add the new entry to the end of the list of tags - if( mdxTagTbl == NULL ){ - mdxTagTbl = tte; - } else { - xbMdxTag *tteL = mdxTagTbl; - while( tteL->next ) - tteL = tteL->next; - tteL->next = tte; - } - - /* update the btree pointers */ - CalcBtreePointers(); - char bBuf[3]; - xbMdxTag *tteWork = mdxTagTbl; - - if(( iRc = xbFseek( 560, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 290; - throw iRc; - } - while( tteWork ){ - bBuf[0] = tteWork->cLeftChild; - bBuf[1] = tteWork->cRightChild; - bBuf[2] = tteWork->cParent; - - if(( iRc = xbFwrite( bBuf, 3, 1 )) != XB_NO_ERROR ){ - iErrorStop = 300; - throw iRc; - } - if( tteWork->next ){ - if(( iRc = xbFseek( 29, SEEK_CUR )) != XB_NO_ERROR ){ - iErrorStop = 310; - throw iRc; - } - } - tteWork = tteWork->next; - } - free( pBuf ); - - } - - catch (xbInt16 iRc ){ - if( tte ){ - if( tte->cpKeyBuf ) - free( tte->cpKeyBuf ); - if( tte->cpKeyBuf2 ) - free( tte->cpKeyBuf2 ); - if( tte->exp ) - delete tte->exp; - if( tte->filter ) - delete tte->filter; - if( tte->sKeyExp ) - delete tte->sKeyExp; - if( tte->sFiltExp ) - delete tte->sFiltExp; - if( tte->sTagName ) - delete tte->sTagName; - free( tte ); - } - xbString sMsg; - sMsg.Sprintf( "xbIxTdx::CreateTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - return iRc; -}; - -/***********************************************************************/ -//! @brief Delete a given tag -/*! - \param vpTag Input tag ptr for tag to be deleted<br> - \returns <a href="xbretcod_8h.html">Return Codes</a><br> - 1 = Deleted entire MDX file, only had one tag - -*/ - -xbInt16 xbIxTdx::DeleteTag( void *vpTag ){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbMdxTag * mpTag = (xbMdxTag *) vpTag; - xbIxNode *n = NULL; - xbBool bLoneTag = xbFalse; - - try{ - - if( !vpTag ){ - iErrorStop = 100; - iRc = XB_INVALID_TAG; - throw iRc; - } - - // char cSaveHasFilter = mpTag->cHasFilter; - // char cSaveKeyFmt3 = mpTag->cKeyFmt3; - // xbString sSaveKey = mpTag->sKeyExp->Str(); - - if( iTagUseCnt == 1 ){ - // std::cout << "xbIxTdx::DeleteTag - one tag found, delete the mdx file\n"; - - // close the mdx file - if(( iRc = xbIxMdx::Close()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - - // delete the file - xbRemove(); - - // init variables - needed? - // Init(); - // iRc > 0 defines this as the only tag in an MDX file, MDX file deleted. - // signals to the calling process to drop the MDX file from the - // list of updateable indices. - bLoneTag = xbTrue; - - } else { - - // harvest tag nodes - - if(( iRc = HarvestTagNodes( mpTag, xbTrue )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - // remove an entry from tag table - // which tag is this? - xbInt16 iTagNo = 0; - xbMdxTag *mp = mdxTagTbl; - xbMdxTag *mpPrev = NULL; - while( mp && mp->ulTagHdrPageNo != mpTag->ulTagHdrPageNo ){ - iTagNo++; - mpPrev = mp; - mp = mp->next; - } - - // remove it from the linked list of tags - if( !mpPrev ){ - mdxTagTbl = mp->next; - } else { - mpPrev->next = mp->next; - } - if( mp ){ - if( mp->cpKeyBuf ) free( mp->cpKeyBuf ); - if( mp->cpKeyBuf2 ) free( mp->cpKeyBuf2 ); - if( mp->exp ) delete mp->exp; - if( mp->filter ) delete mp->filter; - if( mp->sKeyExp ) delete mp->sKeyExp; - if( mp->sFiltExp ) delete mp->sFiltExp; - if( mp->sTagName ) delete mp->sTagName; - free( mp ); - } - xbInt32 iTarg = iTagNo * 32; - xbInt32 iSrc = iTarg + 32; - xbInt32 iLen = (iTagUseCnt - iTagNo) * 32; - - if(( iRc = xbFseek( 544, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - char Buf[1536]; // 47 tags + 1 in case tag #47 is deleted - memset( Buf, 0x00, 1536 ); - if(( iRc = xbFread( Buf, 1504, 1 )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - char *pTrg = Buf; - pTrg += iTarg; - char *pSrc = Buf; - pSrc += iSrc; - for( xbInt32 i = 0; i < iLen; i++ ) - *pTrg++ = *pSrc++; - - if(( iRc = xbFseek( 544, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - if(( iRc = xbFwrite( Buf, 1504, 1 )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - - iTagUseCnt--; - if(( iRc = WriteHeadBlock( 1 )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw iRc; - } - - // update the btree pointers - CalcBtreePointers(); - char bBuf[3]; - xbMdxTag *tteWork = mdxTagTbl; - - if(( iRc = xbFseek( 560, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - while( tteWork ){ - bBuf[0] = tteWork->cLeftChild; - bBuf[1] = tteWork->cRightChild; - bBuf[2] = tteWork->cParent; - - if(( iRc = xbFwrite( bBuf, 3, 1 )) != XB_NO_ERROR ){ - iErrorStop = 320; - throw iRc; - } - if( tteWork->next ){ - if(( iRc = xbFseek( 29, SEEK_CUR )) != XB_NO_ERROR ){ - iErrorStop = 330; - throw iRc; - } - } - tteWork = tteWork->next; - } - } - - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbIxTdx::DeleteTag() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - if( n ) - free( n ); - } - if( bLoneTag && !iRc ) - return 1; - else - return iRc; -} - -/************************************************************************/ - - - -/************************************************************************/ -} /* namespace */ -#endif /* XB_TDX_SUPPORT */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xblog.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xblog.cpp deleted file mode 100755 index 9443006..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xblog.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* xblog.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 - -*/ - - -#include "xbase.h" -//#include <time.h> - -#ifdef XB_LOGGING_SUPPORT - -namespace xb{ - -/******************************************************************************/ -//! @brief Constructor. -xbLog::xbLog() : xbFile( NULL ){ - - - // std::cout << "xbLog::xbLog(1) Directory = [" << GetLogDirectory() << "]\n"; - // std::cout << "xbLog::xbLog(1) Name = [" << GetLogFileName() << "]\n"; - - SetDirectory( GetLogDirectory()); - SetFileName ( GetLogFileName()); - - bLoggingStatus = xbFalse; - lLogSize = 100000; - - #ifdef XB_LOCKING_SUPPORT - iShareMode = XB_MULTI_USER; - #else - iShareMode = XB_SINGLE_USER; - #endif -} -/******************************************************************************/ -//! @brief Constructor. -/*! - \param sLogFileName - Log file name. -*/ -xbLog::xbLog( const xbString & sLogFileName ) : xbFile( NULL ){ - if( sLogFileName.GetPathSeparator()) - SetFqFileName( sLogFileName ); // file name includes a path - else - SetFileName( sLogFileName ); // no file path - - bLoggingStatus = xbFalse; - lLogSize = 100000; - - #ifdef XB_LOCKING_SUPPORT - iShareMode = XB_MULTI_USER; - #else - iShareMode = XB_SINGLE_USER; - #endif - -} -/******************************************************************************/ -//! @brief Deconstructor. -xbLog::~xbLog(){ - xbFclose(); -} -/******************************************************************************/ -//! @brief Get the current log status -/*! - \returns xbTrue - Logging turned on.<br>xbFalse - Logging turned off. -*/ -xbBool xbLog::LogGetStatus(){ - return bLoggingStatus; -} -/******************************************************************************/ -//! @brief Close the logfile. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbLog::LogClose(){ - return xbFclose(); -} -/******************************************************************************/ -//! @brief Set maximum log file size. -/*! - \param lSize - New maximum log file size. - \returns void -*/ -void xbLog::LogSetLogSize( size_t lSize ){ - lLogSize = lSize; -} -/******************************************************************************/ -//! @brief Set log status. -/*! - \param bStatus xbTrue - Turn logging on.<br>xbFalse - Turn logging off. - \returns void -*/ -void xbLog::LogSetStatus( xbBool bStatus ){ - if( bLoggingStatus && !bStatus ) - LogClose(); - bLoggingStatus = bStatus; -} -/******************************************************************************/ -//! @brief Open the logfile. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbLog::LogOpen(){ - xbInt16 rc; - -// std::cout << "*****\nxbLog::LogOpen(1) GetLogDirectory = " << GetLogDirectory() << "\n"; -// std::cout << "xbLog::LogOpen(1) GetLogFileName = " << GetLogFileName() << "\n"; -// std::cout << "xbLog::GetFqFileName(1) = " << GetFqFileName() << "\n\n"; - - // 4.1.3 added next two lines for dynamic log file name changing - SetDirectory( GetLogDirectory()); - SetFileName ( GetLogFileName()); - -// std::cout << "*****\nxbLog::LogOpen(2) GetLogDirectory = " << GetLogDirectory() << "\n"; -// std::cout << "xbLog::LogOpen(2) GetLogFileName = " << GetLogFileName() << "\n"; -// std::cout << "xbLog::GetFqFileName(2) = " << GetFqFileName() << "\n\n"; - - if(( rc = xbFopen( "a", iShareMode )) != XB_NO_ERROR ) - return rc; - xbFTurnOffFileBuffering(); - return XB_NO_ERROR; -} -/******************************************************************************/ -//! @brief Write a logfile message. -/*! - \param sLogEntryData - Message to write to the logfile. - \param iOutputOption 0 - Write to logfile.<br> - 1 - Write to stdout.<br> - 2 - Write to both logfile and stdout. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbLog::LogWrite( const xbString &sLogEntryData, xbInt16 iOutputOption ){ - - if( bLoggingStatus == xbFalse ){ // logging turned off - return XB_NO_ERROR; - } - xbInt16 rc = 0; - if( iOutputOption != 1 && !FileIsOpen() ){ - if(( rc = LogOpen()) != XB_NO_ERROR ){ - fprintf( stderr, "Error - cant write to logfile\n" ); - return rc; - } - } - if( iOutputOption != 1 && lLogSize < xbFtell()){ - xbFputs( "Swapping to next log file" ); - xbFclose(); - xbString sBackupName; - sBackupName.Sprintf( "%s.bak", GetFqFileName().Str()); - if( FileExists( sBackupName )) - xbRemove( sBackupName ); - - xbRename( GetFqFileName(), sBackupName ); - xbFopen( "a", iShareMode ); - } - xbString sTimeStamp; - xbString sFled; // formatted log entry data - - if( iOutputOption != 1 ){ - #ifdef HAVE__LOCALTIME64_S_F - __time64_t timer; - struct tm tb; - _time64( &timer ); - _localtime64_s( &tb, &timer ); - tb.tm_year += 1900; - tb.tm_mon++; - sTimeStamp.Sprintf( "%4d-%02d-%02d %02d:%02d:%02d", tb.tm_year, tb.tm_mon, tb.tm_mday, tb.tm_hour, tb.tm_min, tb.tm_sec ); - #else - time_t timer; - struct tm *tb; - timer = time( NULL ); - tb = localtime( &timer ); - tb->tm_year += 1900; - tb->tm_mon++; - sTimeStamp.Sprintf( "%4d-%02d-%02d %02d:%02d:%02d", tb->tm_year, tb->tm_mon, tb->tm_mday, tb->tm_hour, tb->tm_min, tb->tm_sec ); - #endif - sFled.Sprintf( "%s - %s\n", sTimeStamp.Str(), sLogEntryData.Str() ); - } - - switch( iOutputOption ){ - case 0: - xbFputs( sFled ); - break; - case 1: - std::cout << sLogEntryData << std::endl; - break; - case 2: - xbFputs( sFled ); - std::cout << sLogEntryData << std::endl; - break; - } - return XB_NO_ERROR; -} -/******************************************************************************/ -//! @brief Write bytes to logfile. -/*! - \param ulByteCnt - Number of bytes to write to logfile. - \param p - Pointer to data to write to logfile. - \returns XB_NO_ERROR -*/ - -xbInt16 xbLog::LogWriteBytes( xbUInt32 ulByteCnt, const char *p ){ - - if( bLoggingStatus == xbFalse ) // logging turned off - return XB_NO_ERROR; - const char *p2 = p; - xbFputc( '[' ); - for( xbUInt32 l = 0; l < ulByteCnt; l++ ) - xbFputc( *p2++ ); - xbFputc( ']' ); - return XB_NO_ERROR; -} -/******************************************************************************/ -} // namespace -#endif // XB_LOGGING_ON - - - - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo.cpp deleted file mode 100755 index 406a77d..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* xbmemo.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 memo class -*/ - -#include "xbase.h" - -#ifdef XB_MEMO_SUPPORT - -namespace xb{ - -/***********************************************************************/ -//! @brief Class Constructor. -/*! - \param dbf Pointer to dbf construct. - \param sFileName Memo file name. -*/ - -xbMemo::xbMemo( xbDbf * dbf, xbString const &sFileName ) : xbFile( dbf->GetXbasePtr() ) { - this->dbf = dbf; /* pointer to the associated dbf class instance */ - // xbase = dbf->GetXbasePtr(); /* pointer to the engine */ - SetDirectory( dbf->GetDirectory()); - SetFileName( sFileName ); - mbb = NULL; - #ifdef XB_LOCKING_SUPPORT - bFileLocked = xbFalse; - #endif -} -/***********************************************************************/ -//! @brief Class Destructor. -xbMemo::~xbMemo(){ - if( mbb ) - free( mbb ); -} -/***********************************************************************/ -//! @brief Calculate the last data block number. -/*! - \param ulLastDataBlock Output - Last used block number in the file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemo::CalcLastDataBlock( xbUInt32 & ulLastDataBlock ){ - - xbInt16 iRc = XB_NO_ERROR; - if(( iRc = xbFseek( 0, SEEK_END )) != XB_NO_ERROR ) - return iRc; - - ulLastDataBlock = (xbUInt32) xbFtell() / (xbUInt32) GetBlockSize(); - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Close the memo file. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemo::CloseMemoFile(){ - - if( mbb ){ - free( mbb ); - mbb = NULL; - } - return xbFclose(); -} - - -/***********************************************************************/ -//! @brief Get memo file type. -/*! - \returns 3 - Version 3 memo file.<br> - 4 - Version 4 memo file. -*/ -xbInt16 xbMemo::GetMemoFileType(){ - return iMemoFileType; -} - -/***********************************************************************/ -//! @brief Get next block available from file header. -/*! - \param ulBlockNo Output - Next block number for appending data to memo file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemo::GetHdrNextBlock( xbUInt32 & ulBlockNo ){ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - if(( iRc = ReadDbtHeader( 0 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - ulBlockNo = ulHdrNextBlock; - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbmemo::GetNextAvailableBlock() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -#ifdef XB_LOCKING_SUPPORT -//! @brief Lock memo file -/*! - - \param iLockFunction XB_LOCK<br>XB_UNLOCK - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemo::LockMemo( xbInt16 iLockFunction ){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - if( iLockFunction == XB_LOCK ){ - - if( bFileLocked ) // already locked - return XB_NO_ERROR; - - if( dbf->GetLockFlavor() == LK_DBASE ){ - iRc = xbLock( XB_LOCK, LK4026531838, 1 ); - if( iRc != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ) - return iRc; - else { - iErrorStop = 100; - throw iRc; - } - } else { - bFileLocked = xbTrue; - } - } - } else if( iLockFunction == XB_UNLOCK ){ - - if( !bFileLocked ) // already unlocked - return XB_NO_ERROR; - - if( dbf->GetLockFlavor() == LK_DBASE ){ - iRc = xbLock( XB_UNLOCK, LK4026531838, 1 ); - if( iRc != XB_NO_ERROR ){ - if( iRc == XB_LOCK_FAILED ) - return iRc; - else { - iErrorStop = 110; - throw iRc; - } - } else { - bFileLocked = xbFalse; - } - } - } else { - iErrorStop = 120; - iRc = XB_INVALID_OPTION; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbmemo::LockMemoFile() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -//! @brief Get memo file lock status. -/*! - \returns xbTrue - Memo file is locked.<br> - xbFalse - Memo file is not locked. -*/ -xbBool xbMemo::GetMemoLocked() const { - return bFileLocked; -} -#endif - -/***********************************************************************/ -//! @brief Update Next Node number in file header -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemo::UpdateHeadNextNode(){ - - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - try{ - char buf[4]; - ePutUInt32( buf, ulHdrNextBlock ); - if(( iRc = xbFseek( 0, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc = xbFwrite( &buf, 4, 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbmemo::UpdateHeadeNextNode() Exception Caught. Error Stop = [%d] iRc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -} /* namespace */ -#endif /* XB_MEMO_SUPPORT */ - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo3.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo3.cpp deleted file mode 100755 index 767e9d2..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo3.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* xbmemo3.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 class is used for support dBASE V3 memo files - -*/ - -#include "xbase.h" - -#ifdef XB_MEMO_SUPPORT -#ifdef XB_DBF3_SUPPORT - -namespace xb{ - -/***********************************************************************/ -//! @brief Class Constructor. -/*! - \param dbf Pointer to dbf instance. - \param sFileName Memo file name. -*/ -xbMemoDbt3::xbMemoDbt3( xbDbf * dbf, xbString const & sFileName ) : xbMemo( dbf, sFileName ){ - iMemoFileType = 3; - SetBlockSize( 512 ); -} - -/***********************************************************************/ -//! @brief Class Deconstructor. -xbMemoDbt3::~xbMemoDbt3(){} - -/***********************************************************************/ -//! @brief Abort. -/*! - Abort any pending updates to the memo file. - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt3::Abort(){ - return XB_NO_ERROR; -}/***********************************************************************/ -//! @brief Commit changes to memo file. -/*! - \returns XB_NO_ERROR. -*/ -xbInt16 xbMemoDbt3::Commit(){ - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Create memo file. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt3::CreateMemoFile(){ - - xbInt16 rc = XB_NO_ERROR; - char cBuf[4]; - if(( rc = xbFopen( "w+b", dbf->GetShareMode())) != XB_NO_ERROR ) - return rc; - ulHdrNextBlock = 1L; - ePutUInt32( cBuf, ulHdrNextBlock ); - if(( rc = xbFwrite( cBuf, 4, 1 ))!= XB_NO_ERROR ){ - xbFclose(); - return rc; - } - for(int i = 0; i < 12; i++ ) - xbFputc( 0x00 ); - xbFputc( 0x03 ); - for(int i = 0; i < 495; i++ ) - xbFputc( 0x00 ); - if(( mbb = (void *) malloc( 512 )) == NULL ){ - xbFclose(); - return XB_NO_MEMORY; - } - return XB_NO_ERROR; -} -/***********************************************************************/ -#ifdef XB_DEBUG_SUPPORT -//! @brief Dump memo file header. -/*! - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt3::DumpMemoFreeChain() { - std::cout << "Xbase version 3 file - no free block chain" << std::endl; - return XB_NO_ERROR; -} -#endif // XB_DEBUG_SUPPORT - -//! @brief Dump memo file header. -/*! - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt3::DumpMemoHeader(){ - xbInt16 rc = XB_NO_ERROR; - xbUInt64 stFileSize; - if(( rc = ReadDbtHeader( 1 )) != XB_NO_ERROR ) - return rc; - GetFileSize( stFileSize ); - std::cout << "Version 3 Memo Header Info" << std::endl; - std::cout << "Memo File Name = " << GetFqFileName() << std::endl; - std::cout << "Next Available Block = " << ulHdrNextBlock << std::endl; - std::cout << "Memo File Version = " << (xbInt16) cVersion << " ("; - BitDump( cVersion ); - std::cout << ")" << std::endl; - std::cout << "Block Size = " << GetBlockSize() << std::endl; - std::cout << "File Size = " << stFileSize << std::endl; - std::cout << "Block Count = " << stFileSize / GetBlockSize() << std::endl; - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Get a memo field for a given field number. -/*! - \param iFieldNo Field number to retrieve data for. - \param sMemoData Output - string containing memo field data. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt3::GetMemoField( xbInt16 iFieldNo, xbString & sMemoData ){ - - xbInt16 iErrorStop = 0; - xbInt16 rc = XB_NO_ERROR; - xbUInt32 ulScnt; - char *sp, *spp; - xbUInt32 ulBlockNo; - xbBool bDone = xbFalse; - sMemoData = ""; - try{ - - if(( rc = dbf->GetULongField( iFieldNo, ulBlockNo )) < XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - - if( ulBlockNo == 0L ){ - sMemoData = ""; - return XB_NO_ERROR; - } - spp = NULL; - - while( !bDone ){ - if(( rc = ReadBlock( ulBlockNo++, GetBlockSize(), mbb )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - ulScnt = 0; - sp = (char *) mbb; - while( ulScnt < 512 && !bDone ){ - if( *sp == 0x1a && *spp == 0x1a ) - bDone = xbTrue; - else{ - ulScnt++; spp = sp; sp++; - } - } - sMemoData.Append( (char *) mbb, ulScnt ); - } - sMemoData.ZapTrailingChar( 0x1a ); - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt3::GetMemoField() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Get a memo field length for a given field number. -/*! - \param iFieldNo Field number to retrieve data for. - \param ulFieldLen Output - length of memo field data. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemoDbt3::GetMemoFieldLen( xbInt16 iFieldNo, xbUInt32 & ulFieldLen ){ - - xbInt16 iErrorStop = 0; - xbInt16 rc = XB_NO_ERROR; - xbInt16 iScnt; - char *sp, *spp; - xbUInt32 ulBlockNo; - xbInt16 iNotDone; - try{ - if(( rc = dbf->GetULongField( iFieldNo, ulBlockNo )) < XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - if( ulBlockNo == 0 ){ - ulFieldLen = 0; - return XB_NO_ERROR; - } - ulFieldLen = 0L; - spp = NULL; - iNotDone = 1; - while( iNotDone ){ - if(( rc = ReadBlock( ulBlockNo++, GetBlockSize(), mbb )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - iScnt = 0; - sp = (char *) mbb; - while( iScnt < 512 && iNotDone ){ - if( *sp == 0x1a && *spp == 0x1a ) - iNotDone = 0; - else{ - ulFieldLen++; iScnt++; spp = sp; sp++; - } - } - } - if( ulFieldLen > 0 ) ulFieldLen--; - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt3::GetMemoFieldLen() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Open memo file. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt3::OpenMemoFile() { - xbInt16 rc = XB_NO_ERROR; - if(( rc = xbFopen( dbf->GetOpenMode(), dbf->GetShareMode())) != XB_NO_ERROR ) - return rc; - if(( mbb = (void *) malloc( 512 )) == NULL ){ - xbFclose(); - return XB_NO_MEMORY; - } - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Pack memo file. -/*! - This routine frees up any unused blocks in the file resulting from field updates. - Version 3 memo files do not reclaim unused space (Version 4 files do). - This routine cleans up the unused space. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemoDbt3::PackMemo( void (*memoStatusFunc ) ( xbUInt32 ulItemNum, xbUInt32 ulNumItems )) -{ - xbInt16 iRc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char * cBlock = NULL; - - #ifdef XB_LOCKING_SUPPORT - xbBool bTableLocked = xbFalse; - xbBool bMemoLocked = xbFalse; - #endif - - try{ - - #ifdef XB_LOCKING_SUPPORT - if( dbf->GetAutoLock() && !dbf->GetTableLocked() ){ - if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } else { - bTableLocked = xbTrue; - } - if(( iRc = LockMemo( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } else { - bMemoLocked = xbTrue; - } - } - #endif - - // create temp file - xbString sTempMemoName; - //if(( iRc = CreateUniqueFileName( GetDirectory(), "dbt", sTempMemoName )) != XB_NO_ERROR ){ - if(( iRc = CreateUniqueFileName( GetTempDirectory(), "DBT", sTempMemoName )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - xbMemoDbt3 *pMemo = new xbMemoDbt3( dbf, sTempMemoName ); - if(( iRc = pMemo->CreateMemoFile()) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - // for dbase III, block size is always 512, don't need to reset it - // for each record in dbf - xbUInt32 ulRecCnt; - if(( iRc = dbf->GetRecordCnt( ulRecCnt )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - xbInt32 lFldCnt = dbf->GetFieldCnt(); - char cFldType; - xbString sMemoFldData; - - for( xbUInt32 ulI = 1; ulI <= ulRecCnt; ulI++ ){ - - if(( iRc = dbf->GetRecord( ulI )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - if( (void *) memoStatusFunc ) - (*memoStatusFunc) ( ulI, ulRecCnt ); - - // for each memo field - for( xbInt32 lFc = 0; lFc < lFldCnt; lFc++ ){ - if(( iRc = dbf->GetFieldType( lFc, cFldType )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - - - if( cFldType == 'M' ){ - // copy it to work field - if(( iRc = dbf->GetMemoField( lFc, sMemoFldData )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - // write it to new field - if(( iRc = pMemo->UpdateMemoField( lFc, sMemoFldData )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - } - } - } - - //copy target back to source - xbUInt32 ulBlkSize = GetBlockSize(); - xbUInt64 ullFileSize; - if(( iRc = pMemo->GetFileSize( ullFileSize )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - // file size should be evenly divisible by block size - xbUInt32 ulBlkCnt; - - if( ullFileSize % ulBlkSize ){ - iErrorStop = 200; - throw iRc; - } else { - ulBlkCnt = (xbUInt32) (ullFileSize / ulBlkSize); - } - if(( iRc = xbTruncate( 0 )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - - if(( cBlock = (char *) malloc( (size_t) ulBlkSize )) == NULL ){ - iErrorStop = 220; - throw iRc; - } - - // can't rename files in a multiuser, cross platform environment, causes issues - // copy work table back to source table - for( xbUInt32 ulBc = 0; ulBc < ulBlkCnt; ulBc++ ){ - if(( iRc = pMemo->ReadBlock( ulBc, ulBlkSize, cBlock )) != XB_NO_ERROR ){ - iErrorStop = 230; - throw iRc; - } - if(( iRc = WriteBlock( ulBc, ulBlkSize, cBlock )) != XB_NO_ERROR ){ - iErrorStop = 240; - throw iRc; - } - } - - //close and delete target - if(( iRc = pMemo->xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 250; - throw iRc; - } - - if(( iRc = pMemo->xbRemove()) != XB_NO_ERROR ){ - iErrorStop = 260; - throw iRc; - } - free( cBlock ); - delete pMemo; - } - catch (xbInt16 iRc ){ - free( cBlock ); - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt3::PackMemo() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - - #ifdef XB_LOCKING_SUPPORT - if( bTableLocked ) - dbf->LockTable( XB_UNLOCK ); - if( bMemoLocked ) - LockMemo( XB_UNLOCK ); - #endif - return iRc; -} - -/***********************************************************************/ -//! @brief Read dbt header file. -/*! - \param iOption 0 --> read only first four bytes<br> - 1 --> read the entire thing - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt3::ReadDbtHeader( xbInt16 iOption ){ - char *p; - char MemoBlock[20]; - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulReadSize; - - try{ - if( !FileIsOpen() ){ - iErrorStop = 100; - rc = XB_NOT_OPEN; - throw rc; - } - if( iOption == 0 ) - ulReadSize = 4; - else{ - xbUInt64 stFileSize = 0; - if(( rc = GetFileSize( stFileSize )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - if( stFileSize < 4 ){ - iErrorStop = 120; - rc = XB_INVALID_BLOCK_NO; - throw rc; - } - else if( stFileSize > 20 ) - ulReadSize = 130; - else - ulReadSize = 4; - } - if( xbFseek( 0, SEEK_SET )){ - iErrorStop = 140; - rc = XB_SEEK_ERROR; - throw rc; - } - if(( xbFread( &MemoBlock, ulReadSize, 1 )) != XB_NO_ERROR ){ - iErrorStop = 150; - rc = XB_READ_ERROR; - throw rc; - } - p = MemoBlock; - ulHdrNextBlock = eGetUInt32( p ); - - if( iOption == 0) - return XB_NO_ERROR; - - if( ulReadSize >= 20 ){ - p+=16; - cVersion = *p; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt3::ReadDbtHeader() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Update header name. -/*! - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt3::UpdateHeaderName(){ - return XB_NO_ERROR; -} -/***********************************************************************/ -//! @brief Update a memo field for a given field number. -/*! - \param iFieldNo Field number to update data for. - \param sMemoData Data to update memo field data with. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt3::UpdateMemoField( xbInt16 iFieldNo, const xbString & sMemoData ) { - - xbInt16 iErrorStop = 0; - xbInt16 rc = XB_NO_ERROR; - try{ - if( sMemoData == "" ){ - if(( rc = dbf->PutField( iFieldNo, "" )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - } else { - xbUInt32 ulDataLen = sMemoData.Len() + 2; - xbUInt32 ulBlocksNeeded = (ulDataLen / 512) + 1; - xbUInt32 ulLastDataBlock; - if(( rc = CalcLastDataBlock( ulLastDataBlock )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - if(( rc = xbFseek( ((xbInt64) ulLastDataBlock * 512), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - if(( rc = xbFwrite( sMemoData.Str(), sMemoData.Len(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw rc; - } - if(( rc = xbFputc( 0x1a, 2 )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw rc; - } - if(( rc = xbFputc( 0x00, (xbInt32) ( ulBlocksNeeded * 512 ) - (xbInt32) ulDataLen )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw rc; - } - if(( rc = dbf->PutULongField( iFieldNo, ulLastDataBlock )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw rc; - } - ulHdrNextBlock = ulLastDataBlock + ulBlocksNeeded; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ){ - iErrorStop = 170; - throw rc; - } - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt3::UpdateMemoField() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} - -/***********************************************************************/ -//! @brief Empty the memo file. -/*! - This routine clears everything out of the file. It does not address the - block pointers on the dbf file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemoDbt3::Zap(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - char cBuf[4]; - - try{ - ulHdrNextBlock = 1L; - ePutUInt32( cBuf, ulHdrNextBlock ); - - if(( iRc != xbFseek( 0, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc != xbFwrite( cBuf, 4, 1 ))!= XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if(( iRc != xbTruncate( 512 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt3::Zap() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/***********************************************************************/ -} /* namespace */ -#endif /* XB_DBF3_SUPPORT */ -#endif /* XB_MEMO_SUPPORT */ diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo4.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo4.cpp deleted file mode 100755 index 9770806..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbmemo4.cpp +++ /dev/null @@ -1,1336 +0,0 @@ -/* xbmemo4.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 class is used for support dBASE V4 memo files - -*/ - -#include "xbase.h" - -#ifdef XB_MEMO_SUPPORT -#ifdef XB_DBF4_SUPPORT - -namespace xb{ - -/***********************************************************************/ -//! @brief Class Constructor. -/*! - \param dbf Pointer to dbf instance. - \param sFileName Memo file name. -*/ -xbMemoDbt4::xbMemoDbt4( xbDbf * dbf, xbString const & sFileName ) : xbMemo( dbf, sFileName ){ - iMemoFileType = 4; - SetBlockSize( dbf->GetCreateMemoBlockSize() ); -} - -/***********************************************************************/ -//! @brief Class Deconstructor. -xbMemoDbt4::~xbMemoDbt4(){} - -/***********************************************************************/ -//! @brief Abort. -/*! - Abort any pending updates to the memo file. - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt4::Abort(){ - - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulBlockNo; - - try{ - xbUInt32 ulNodeCnt = llNewBlocks.GetNodeCnt(); - for( xbUInt32 l = 0; l < ulNodeCnt; l++ ){ - if(( rc = llNewBlocks.RemoveFromFront( ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - if(( rc = FreeMemoBlockChain( ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - } - llOldBlocks.Clear(); - } - - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::Abort() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} - -/***********************************************************************/ -//! @brief Commit changes to memo file. -/*! - Commit any pending updates to the memo file. - \returns XB_NO_ERROR. -*/ -xbInt16 xbMemoDbt4::Commit(){ - - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulBlockNo; - - try{ - xbUInt32 ulNodeCnt = llOldBlocks.GetNodeCnt(); - for( xbUInt32 l = 0; l < ulNodeCnt; l++ ){ - if(( rc = llOldBlocks.RemoveFromFront( ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - if(( rc = FreeMemoBlockChain( ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - } - llNewBlocks.Clear(); - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::Commit() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Create memo file. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::CreateMemoFile(){ - - xbInt16 iErrorStop = 0; - xbInt16 rc = XB_NO_ERROR; - char cBuf[4]; - - try{ - if(( rc = xbFopen( "w+b", dbf->GetShareMode() )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - - ulHdrNextBlock = 1L; - ePutUInt32( cBuf, ulHdrNextBlock ); - if(( rc = xbFwrite( cBuf, 4, 1 ))!= XB_NO_ERROR ){ - iErrorStop = 110; - xbFclose(); - throw rc; - } - for(int i = 0; i < 4; i++ ) - xbFputc( 0x00 ); - GetFileNamePart( sDbfFileNameWoExt ); - sDbfFileNameWoExt.PadRight( ' ', 8 ); // need at least eight bytes of name - sDbfFileNameWoExt = sDbfFileNameWoExt.Mid( 1, 8 ); // need no more than eight bytes of name - for( int i = 1; i < 9; i++ ) - xbFputc( sDbfFileNameWoExt[i] ); - - for(int i = 0; i < 4; i++ ) - xbFputc( 0x00 ); - - ePutInt16( cBuf, GetBlockSize()); - if(( rc = xbFwrite( cBuf, 2, 1 ))!= XB_NO_ERROR ){ - iErrorStop = 120; - xbFclose(); - throw rc; - } - for( xbUInt32 i = 0; i < (GetBlockSize() - 22); i++ ) - xbFputc( 0x00 ); - if(( mbb = (void *) malloc( GetBlockSize())) == NULL ){ - rc = XB_NO_MEMORY; - iErrorStop = 130; - return XB_NO_MEMORY; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::CreateMemoFile() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - xbFclose(); - } - return rc; -} -/***********************************************************************/ -#ifdef XB_DEBUG_SUPPORT -//! @brief Dump memo file header. -/*! - \returns XB_NO_ERROR -*/ - -xbInt16 xbMemoDbt4::DumpMemoFreeChain() -{ - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulCurBlock, ulLastDataBlock; - - try{ - if(( rc = ReadDbtHeader(1)) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - if(( rc = CalcLastDataBlock( ulLastDataBlock )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - - ulCurBlock = ulHdrNextBlock; - std::cout << "**********************************" << std::endl; - std::cout << "Head Node Next Block = " << ulCurBlock << std::endl;; - std::cout << "Total blocks in file = " << ulLastDataBlock << std::endl; - - while( ulCurBlock < ulLastDataBlock ){ - if(( rc = ReadBlockHeader( ulCurBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - std::cout << "**********************************" << std::endl; - std::cout << "This Free Block = [" << ulCurBlock << "] contains [" << ulFreeBlockCnt << "] block(s)" << std::endl; - std::cout << "Next Free Block = [" << ulNextFreeBlock << "]" << std::endl; - ulCurBlock = ulNextFreeBlock; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::UpdateMemoField() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return XB_NO_ERROR; -} - -//! @brief Dump memo internals. -/*! - \returns XB_NO_ERROR -*/ - -xbInt16 xbMemoDbt4::DumpMemoInternals() { - - xbLinkListNode<xbUInt32> *llPtr; - xbInt16 iNodeCnt; - - llPtr = llOldBlocks.GetHeadNode(); - iNodeCnt = llOldBlocks.GetNodeCnt(); - - std::cout << "Link List Old Blocks - " << iNodeCnt << " nodes" << std::endl; - for( xbInt16 i = 0; i < iNodeCnt; i++ ){ - std::cout << llPtr->GetKey() << ","; - llPtr = llPtr->GetNextNode(); - } - std::cout << std::endl; - - llPtr = llNewBlocks.GetHeadNode(); - iNodeCnt = llNewBlocks.GetNodeCnt(); - std::cout << "Link List New Blocks - " << iNodeCnt << " nodes" << std::endl; - for( xbInt16 i = 0; i < iNodeCnt; i++ ){ - std::cout << llPtr->GetKey() << ","; - llPtr = llPtr->GetNextNode(); - } - std::cout << std::endl; - - return XB_NO_ERROR; -} -#endif // XB_DEBUG_SUPPORT - -/***********************************************************************/ -//! @brief Dump memo file header. -/*! - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt4::DumpMemoHeader(){ - - xbInt16 rc = XB_NO_ERROR; - xbUInt32 ulLastDataBlock; - CalcLastDataBlock( ulLastDataBlock ); - - if(( rc = ReadDbtHeader( 1 )) != XB_NO_ERROR ) - return rc; - std::cout << "Version 4 Memo Header Info" << std::endl; - std::cout << "Memo File Name = " << GetFqFileName() << std::endl; - std::cout << "Hdr Next Avail Block = " << ulHdrNextBlock << std::endl; - std::cout << "Block Size = " << GetBlockSize() << std::endl; - std::cout << "Dbf File Name wo Ext = " << sDbfFileNameWoExt.Str() << std::endl; - std::cout << "Last Data Block = " << ulLastDataBlock << std::endl; - return rc; -} - -/************************************************************************/ -//! @brief Find an empty set of blocks in the free block chain -/*! - This routine searches thruugh the free node chain in a dbase IV type - memo file searching for a place to grab some free blocks for reuse - - \param ulBlocksNeeded The size to look in the chain for. - \param ulLastDataBlock is the last data block in the file, enter 0 - for the routine to calculate it. - \param ulLocation The location it finds. - \param ulPreviousNode Block number of the node immediately previous to this node in the chain.<br> - 0 if header node - \param bFound Output xbFalse - Spot not found in chain.<br> - xbTrue - Spot found in chain. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemoDbt4::FindBlockSetInChain( xbUInt32 ulBlocksNeeded, - xbUInt32 &ulLastDataBlock, xbUInt32 &ulLocation, xbUInt32 &ulPrevNode, xbBool &bFound ){ - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulCurNode; - - try{ - ulPrevNode = 0L; - if( ulLastDataBlock == 0 ){ - /* Determine last good data block */ - if(( rc = CalcLastDataBlock( ulLastDataBlock )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - } - if( ulHdrNextBlock < ulLastDataBlock ){ - ulCurNode = ulHdrNextBlock; - - if(( rc = ReadBlockHeader( ulHdrNextBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - while( ulBlocksNeeded > ulFreeBlockCnt && ulNextFreeBlock < ulLastDataBlock ){ - ulPrevNode = ulCurNode; - ulCurNode = ulNextFreeBlock; - if(( rc = ReadBlockHeader( ulNextFreeBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - } - if( ulBlocksNeeded <= ulFreeBlockCnt ){ - ulLocation = ulCurNode; - // PreviousNode = lPrevNode; - bFound = xbTrue; - } else { // no data found and at end of chain - ulPrevNode = ulCurNode; - bFound = xbFalse; - } - } else { - bFound = xbFalse; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::FindBlockSetInChain() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Free a block. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::FreeMemoBlockChain( xbUInt32 ulBlockNo ){ - xbUInt32 ulLastDataBlock; - return FreeMemoBlockChain( ulBlockNo, ulLastDataBlock ); -} - -/***********************************************************************/ -//! @brief Free a block. -/*! - \param ulBlockNo The block number being deleted. - \param ulLastDataBlock Output - Last free block number,prior to this block. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemoDbt4::FreeMemoBlockChain( xbUInt32 ulBlockNo, xbUInt32 &ulLastDataBlock ) -{ - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulNoOfFreedBlocks; - xbUInt32 ulLastFreeBlock = 0; - xbUInt32 ulLastFreeBlockCnt = 0; - xbUInt32 ulSaveNextFreeBlock; - - // iFieldNo - The field no m\bing deleted - // iBlockNo - The block number being deleted - // iNoOfFreeBlocks - The number of blocks being freed with this delete - // iLastDataBlock - The next block number to allocate if more blocks needed - // iHdrNextBlock - The head pointer in the main header block - // iNextFreeBlock - The block that is immediately following the current free block to be added - // iLastFreeBlock - Last free block number,prior to this block - // iLastFreeBlockCnt - Last free block number of blocks - - try{ - - if( ulBlockNo <= 0 ){ - iErrorStop = 100; - rc =XB_INVALID_BLOCK_NO; - throw rc; - } - - /* Load the first block */ - if(( rc = ReadBlockHeader( ulBlockNo, 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - - if( (ulFieldLen) % GetBlockSize() ) - ulNoOfFreedBlocks = ((ulFieldLen) / GetBlockSize()) + 1L; - else - ulNoOfFreedBlocks = (ulFieldLen) / GetBlockSize(); - - /* Determine last good data block */ - if(( rc = CalcLastDataBlock( ulLastDataBlock )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - - if(( rc = ReadDbtHeader( 0 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw rc; - } - - // Not an empty node chain, position to correct location in chain - ulNextFreeBlock = ulHdrNextBlock; - while( ulBlockNo > ulNextFreeBlock && ulBlockNo < ulLastDataBlock ){ - ulLastFreeBlock = ulNextFreeBlock; - - if(( rc = ReadBlockHeader( ulNextFreeBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 140; - return rc; - } - ulLastFreeBlockCnt = ulFreeBlockCnt; - } - - // One of two outcomes at this point - // A) This block is combined with the next free block chain, and points to the free chain after the next free block - // B) This block is not combined with the next free block chain, and points to the next block - // (which could be the last block - - // should next block should be concatonated onto the end of this set? - ulSaveNextFreeBlock = ulNextFreeBlock; - if(( ulBlockNo + ulNoOfFreedBlocks ) == ulNextFreeBlock && ulNextFreeBlock < ulLastDataBlock ){ - if(( rc = ReadBlockHeader( ulNextFreeBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw rc; - } - ulNoOfFreedBlocks += ulFreeBlockCnt; - ulSaveNextFreeBlock = ulNextFreeBlock; - } - - // if this is the first set of free blocks - if( ulLastFreeBlock == 0 ){ - // 1 - write out the current block - // 2 - update header block - // 3 - write header block - // 4 - update data field - - ePutUInt32( (char *) mbb, ulSaveNextFreeBlock ); - ePutUInt32( (char *) mbb+4, ulNoOfFreedBlocks ); - if(( rc = WriteBlock( ulBlockNo, 8, mbb )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw rc; - } - - ulHdrNextBlock = ulBlockNo; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ){ - iErrorStop = 170; - throw rc; - } - return XB_NO_ERROR; - } - - /* determine if this block set should be added to the previous set */ - if(( ulLastFreeBlockCnt + ulLastFreeBlock ) == ulBlockNo ){ - if(( rc = ReadBlockHeader( ulLastFreeBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw rc; - } - ulFreeBlockCnt += ulNoOfFreedBlocks; - - ePutUInt32( (char *) mbb, ulSaveNextFreeBlock ); - ePutUInt32( (char *) mbb+4, ulFreeBlockCnt ); - if(( rc = WriteBlock( ulLastFreeBlock, 8, mbb )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw rc; - } - return XB_NO_ERROR; - } - - /* insert into the chain */ - /* 1 - set the next bucket on the current node */ - /* 2 - write this node */ - /* 3 - go to the previous node */ - /* 4 - insert this nodes id into the previous node set */ - /* 5 - write previous node */ - - ePutUInt32( (char *) mbb, ulSaveNextFreeBlock ); - ePutUInt32( (char *) mbb+4, ulNoOfFreedBlocks ); - if(( rc = WriteBlock( ulBlockNo, 8, mbb )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw rc; - } - - if(( rc = ReadBlockHeader( ulLastFreeBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw rc; - } - - ePutUInt32( (char *) mbb, ulBlockNo ); - if(( rc = WriteBlock( ulLastFreeBlock, 8, mbb )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw rc; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::DeleteMemoField() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/************************************************************************/ -//! @brief Get a set of blocks from the free block chain. -/*! - This routine grabs a set of blocks out of the free block chain. - - \param ulBlocksNeeded The number of blocks requested. - \param ulLocation - \param ulPrevNode - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - - -xbInt16 xbMemoDbt4::GetBlockSetFromChain( xbUInt32 ulBlocksNeeded, - xbUInt32 ulLocation, xbUInt32 ulPrevNode ) -{ - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - xbUInt32 ulNextFreeBlock2; - xbUInt32 ulNewFreeBlocks; - xbUInt32 ulSaveNextFreeBlock; - - try{ - if(( rc = ReadBlockHeader( ulLocation, 2 )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - - if( ulBlocksNeeded == ulFreeBlockCnt ){ // grab this whole set of blocks - if( ulPrevNode == 0 ){ // first in the chain - ulHdrNextBlock = ulNextFreeBlock; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - } - else // remove out of the middle or end - { - ulNextFreeBlock2 = ulNextFreeBlock; - if(( rc = ReadBlockHeader( ulPrevNode, 2 )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - ulNextFreeBlock = ulNextFreeBlock2; - if(( rc = WriteBlockHeader( ulPrevNode, 2 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw rc; - } - } - } else { // only take a portion of this set - if( ulPrevNode == 0 ){ // first in the set - ulHdrNextBlock = ulLocation + ulBlocksNeeded; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ){ - iErrorStop = 140; - throw rc; - } - ulFreeBlockCnt -= ulBlocksNeeded; - if(( rc = WriteBlockHeader( ulHdrNextBlock, 2 )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw rc; - } - } - else { // remove out of the middle or end - ulNewFreeBlocks = ulFreeBlockCnt - ulBlocksNeeded; - ulSaveNextFreeBlock = ulNextFreeBlock; - ulNextFreeBlock2 = ulLocation + ulBlocksNeeded; - - if(( rc = ReadBlockHeader( ulPrevNode, 2 )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw rc; - } - ulNextFreeBlock = ulNextFreeBlock2; - if(( rc = WriteBlockHeader( ulPrevNode, 2 )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw rc; - } - ulFreeBlockCnt = ulNewFreeBlocks; - ulNextFreeBlock = ulSaveNextFreeBlock; - if(( rc = WriteBlockHeader( ulNextFreeBlock2, 2 )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw rc; - } - } - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::GetBlockSetFromChain() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Get a memo field for a given field number. -/*! - \param iFieldNo Field number to retrieve data for. - \param sMemoData Output - string containing memo field data. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::GetMemoField( xbInt16 iFieldNo, xbString & sMemoData ){ - - xbUInt32 ulBlockNo; - xbUInt32 ulMemoFieldLen; - xbUInt32 ulMemoFieldDataLen; - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char *p = NULL; - - try{ - if(( rc = GetMemoFieldLen( iFieldNo, ulMemoFieldLen, ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - - if( ulBlockNo == 0L || ulMemoFieldLen == 0L ) - sMemoData = ""; - else{ - ulMemoFieldDataLen = ulMemoFieldLen - 8; - - if(( p = (char *)calloc(1, ulMemoFieldDataLen+1)) == NULL ){ - iErrorStop = 110; - rc = XB_NO_MEMORY; - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::GetMemoField() lBlockNo = %ld Data Len = [%ld]", ulBlockNo, ulMemoFieldDataLen + 1 ); - xbase->WriteLogMessage( sMsg.Str() ); - throw rc; - } - - // go to the first block of the memo field, skip past the first 8 bytes - if(( xbFseek( ( ulBlockNo * GetBlockSize() + 8 ), SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 120; - rc = XB_SEEK_ERROR; - throw rc; - } - - // read the memo file data into buffer pointed to by "p" - if(( rc = xbFread( p, ulMemoFieldDataLen, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - rc = XB_READ_ERROR; - throw rc; - } - // null terminate the string - char *p2; - p2 = p + ulMemoFieldDataLen; - *p2 = 0x00; - - // save it to the string - sMemoData.Set( p, ulMemoFieldDataLen + 1 ); - free( p ); - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::GetMemoField() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - if( p ) - free( p ); - } - return rc; -} - -/***********************************************************************/ -//! @brief Get a memo field length for a given field number. -/*! - \param iFieldNo Field number to retrieve data for. - \param ulMemoFieldLen Output - length of memo field data. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemoDbt4::GetMemoFieldLen( xbInt16 iFieldNo, xbUInt32 &ulMemoFieldLen ){ - xbUInt32 ulBlockNo; - return GetMemoFieldLen( iFieldNo, ulMemoFieldLen, ulBlockNo ); -} - -/***********************************************************************/ -//! @brief Get a memo field length for a given field number. -/*! - \param iFieldNo Field number to retrieve data for. - \param ulMemoFieldLen Output - length of memo field data. - \param ulBlockNo Output - Starting block number. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::GetMemoFieldLen( xbInt16 iFieldNo, xbUInt32 &ulMemoFieldLen, xbUInt32 &ulBlockNo ){ - - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - char cFieldType; - - try{ - - if(( rc = dbf->GetFieldType( iFieldNo, cFieldType )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - if( cFieldType != 'M' ){ - iErrorStop = 110; - rc = XB_INVALID_MEMO_FIELD; - throw rc; - } - if(( rc = dbf->GetULongField( iFieldNo, ulBlockNo )) < XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - if( ulBlockNo < 1 ){ - ulMemoFieldLen = 0; - return XB_NO_ERROR; - } - if(( rc = ReadBlockHeader( ulBlockNo, 1 )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw rc; - } - ulMemoFieldLen = ulFieldLen; - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::GetMemoFieldLen() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Open memo file. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::OpenMemoFile() { - - xbInt16 iErrorStop = 0; - xbInt16 rc = XB_NO_ERROR; - - try{ - if(( rc = xbFopen( dbf->GetOpenMode(), dbf->GetShareMode())) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - if(( rc = ReadDbtHeader( 1 )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - if(( mbb = (void *) malloc( GetBlockSize())) == NULL ){ - xbFclose(); - iErrorStop = 120; - rc = XB_NO_MEMORY; - throw rc; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::OpenMemoFile() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Pack memo file. -/*! - This routine frees up any unused blocks in the file resulting from field updates. - Version 3 memo files do not reclaim unused space (Version 4 files do). - This routine cleans up the unused space. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::PackMemo( void (*memoStatusFunc ) ( xbUInt32 ulItemNum, xbUInt32 ulNumItems )){ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - char * cBlock = NULL; - - #ifdef XB_LOCKING_SUPPORT - xbBool bTableLocked = xbFalse; - xbBool bMemoLocked = xbFalse; - #endif - - try{ - #ifdef XB_LOCKING_SUPPORT - if( dbf->GetAutoLock() && !dbf->GetTableLocked() ){ - if(( iRc = dbf->LockTable( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } else { - bTableLocked = xbTrue; - } - if(( iRc = LockMemo( XB_LOCK )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } else { - bMemoLocked = xbTrue; - } - } - #endif - - // create temp file - xbString sTempMemoName; - //if(( iRc = CreateUniqueFileName( GetDirectory(), "dbt", sTempMemoName )) != XB_NO_ERROR ){ - if(( iRc = CreateUniqueFileName( GetTempDirectory(), "DBT", sTempMemoName )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - - xbMemoDbt4 *pMemo = new xbMemoDbt4( dbf, sTempMemoName ); - if(( iRc = pMemo->CreateMemoFile()) != XB_NO_ERROR ){ - iErrorStop = 130; - throw iRc; - } - // for dbase III, block size is always 512, don't need to reset it - // for each record in dbf - xbUInt32 ulRecCnt; - if(( iRc = dbf->GetRecordCnt( ulRecCnt)) != XB_NO_ERROR ){ - iErrorStop = 140; - throw iRc; - } - xbInt32 lFldCnt = dbf->GetFieldCnt(); - char cFldType; - xbString sMemoFldData; - - for( xbUInt32 ulI = 1; ulI <= ulRecCnt; ulI++ ){ - if(( iRc = dbf->GetRecord( ulI )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw iRc; - } - - if( (void *) memoStatusFunc) - (*memoStatusFunc)(ulI, ulRecCnt ); - - // for each memo field - for( xbInt32 lFc = 0; lFc < lFldCnt; lFc++ ){ - if(( iRc = dbf->GetFieldType( lFc, cFldType )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - if( cFldType == 'M' ){ - // copy it to work field - if(( iRc = dbf->GetMemoField( lFc, sMemoFldData )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw iRc; - } - // write it to new field - if(( iRc = pMemo->UpdateMemoField( lFc, sMemoFldData )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw iRc; - } - } - } - } - - //copy target back to source - xbUInt32 ulBlkSize = GetBlockSize(); - xbUInt64 ullFileSize; - if(( iRc = pMemo->GetFileSize( ullFileSize )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw iRc; - } - // file size should be evenly divisible by block size - xbUInt32 ulBlkCnt; - - if( ullFileSize % ulBlkSize ){ - iErrorStop = 200; - throw iRc; - } else { - ulBlkCnt = (xbUInt32) (ullFileSize / ulBlkSize); - } - if(( iRc = xbTruncate( 0 )) != XB_NO_ERROR ){ - iErrorStop = 210; - throw iRc; - } - - if(( cBlock = (char *) malloc( ulBlkSize )) == NULL ){ - iErrorStop = 220; - throw iRc; - } - - // can't rename files in a multiuser, cross platform environment, causes issues - // copy work table back to source table - - for( xbUInt32 ulBc = 0; ulBc < ulBlkCnt; ulBc++ ){ - if(( iRc = pMemo->ReadBlock( ulBc, ulBlkSize, cBlock )) != XB_NO_ERROR ){ - iErrorStop = 230; - throw iRc; - } - if(( iRc = WriteBlock( ulBc, ulBlkSize, cBlock )) != XB_NO_ERROR ){ - iErrorStop = 240; - throw iRc; - } - } - - if(( xbFseek( 8, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 250; - iRc = XB_SEEK_ERROR; - throw iRc; - } - - for( int i = 1; i < 9; i++ ) - xbFputc( sDbfFileNameWoExt[i] ); - - //close and delete target - if(( iRc = pMemo->xbFclose()) != XB_NO_ERROR ){ - iErrorStop = 260; - throw iRc; - } - if(( iRc = pMemo->xbRemove()) != XB_NO_ERROR ){ - iErrorStop = 270; - throw iRc; - } - free( cBlock ); - delete pMemo; - - } - catch (xbInt16 iRc ){ - free( cBlock ); - - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::PackMemo() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - #ifdef XB_LOCKING_SUPPORT - if( bTableLocked ) - dbf->LockTable( XB_UNLOCK ); - if( bMemoLocked ) - LockMemo( XB_UNLOCK ); - #endif - return iRc; -} -/***********************************************************************/ -//! @brief Read block header. -/*! - \param ulBlockNo Block to read - \param iOption 1 - Read fields option 1 - 2 - Read fields option 2 - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::ReadBlockHeader( xbUInt32 ulBlockNo, xbInt16 iOption ) { - - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - - if(( rc = ReadBlock( ulBlockNo, 8, mbb )) != XB_NO_ERROR ){ - iErrorStop = 100; - rc = XB_READ_ERROR; - } - if( iOption == 1 ){ - iField1 = eGetInt16((char *) mbb ); - iStartPos = eGetInt16((char *) mbb+2); - ulFieldLen = eGetUInt32((char *) mbb+4); - } - else if( iOption == 2 ){ - ulNextFreeBlock = eGetUInt32((char *) mbb ); - ulFreeBlockCnt = eGetUInt32((char *) mbb+4 ); - } - else{ - iErrorStop = 110; - rc = XB_INVALID_OPTION; - throw rc; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::ReadBlockHeader() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Read dbt header file. -/*! - \param iOption 0 --> read only first four bytes<br> - 1 --> read the entire thing - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::ReadDbtHeader( xbInt16 iOption ) { - - xbInt16 iErrorStop = 0; - xbInt16 rc = XB_NO_ERROR; - xbInt16 iReadLen = 0; - char *p; - char MemoBlock[22]; - - try{ - if( !FileIsOpen() ){ - iErrorStop = 100; - rc = XB_NOT_OPEN; - throw rc; - } - if( xbFseek( 0, SEEK_SET )){ - iErrorStop = 110; - rc = XB_SEEK_ERROR; - throw rc; - } - if( iOption ) - iReadLen = 22; - else - iReadLen = 4; - - if(( xbFread( &MemoBlock, (size_t) iReadLen, 1 )) != XB_NO_ERROR ){ - iErrorStop = 120; - rc = XB_READ_ERROR; - throw rc; - } - - p = MemoBlock; - ulHdrNextBlock = eGetUInt32( p ); - if( iOption == 0) - return XB_NO_ERROR; - - p += 8; - sDbfFileNameWoExt = ""; - for( int i = 0; i < 8; i++ ) - sDbfFileNameWoExt += *p++; - - p += 4; - SetBlockSize( (xbUInt32) eGetInt16( p )); - - cVersion = MemoBlock[16]; - - } - catch (xbInt16 rc ){ - - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::ReadDbtHeader() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} - -/***********************************************************************/ -#ifdef XB_DEBUG_SUPPORT -//! @brief Read free block information from header. -/*! - This routing pulls any reusable block information for file header. - Not used with version 3 memo files - stub. - - \param ulBlockNo - \param ulNextBlock - \param ulFreeBlockCnt - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt4::ReadFreeBlockHeader( xbUInt32 ulBlockNo, xbUInt32 &ulNextBlock, xbUInt32 &ulFreeBlockCount ){ - - xbInt16 rc = XB_NO_ERROR; - rc = ReadBlockHeader( ulBlockNo, 2 ); - ulNextBlock = ulNextFreeBlock; - ulFreeBlockCount = ulFreeBlockCnt; - return rc; -} -#endif -/***********************************************************************/ -//! @brief Update header name. -/*! - \returns XB_NO_ERROR -*/ -xbInt16 xbMemoDbt4::UpdateHeaderName() { - - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - GetFileNamePart( sDbfFileNameWoExt ); - sDbfFileNameWoExt.PadRight( ' ', 8 ); // need at least eight bytes of name - sDbfFileNameWoExt = sDbfFileNameWoExt.Mid( 1, 8 ); // need no more than eight bytes of name - - try{ - if(( rc = xbFseek( 8, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - - for( int i = 1; i < 9; i++ ){ - if(( rc = xbFputc( sDbfFileNameWoExt[i] )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::UpdateHeaderName() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Update a memo field length for a given field number. -/*! - \param iFieldNo Field number to update data for. - \param sMemoData Data to update memo field data with. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::UpdateMemoField( xbInt16 iFieldNo, const xbString & sMemoData ) { - - xbInt16 iErrorStop = 0; - xbInt16 rc = XB_NO_ERROR; - xbUInt32 ulBlockNo; - - try{ - - if(( rc = dbf->GetULongField( iFieldNo, ulBlockNo )) < XB_NO_ERROR ){ - iErrorStop = 100; - throw rc; - } - - if( sMemoData == "" ){ - if( ulBlockNo == 0 ){ - /* if nothing to do, return */ - return XB_NO_ERROR; - } else { - - // if this is in the new blocks link list already, then this is not the first update for this memo field - // this would be second or third update on the field since the original change and not commited - // Since it won't be needed in either a Commmit() or Abort(), can be freed immediately - if( llNewBlocks.SearchFor( ulBlockNo ) > 0 ){ - if(( rc = FreeMemoBlockChain( ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 110; - throw rc; - } - if(( llNewBlocks.RemoveByVal( ulBlockNo )) < XB_NO_ERROR ){ - iErrorStop = 120; - throw rc; - } - } else { - // first revision, save what it was in case of Abort() command - if(( llOldBlocks.InsertAtFront( ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 130; - throw rc; - } - } - if(( rc = dbf->PutField( iFieldNo, "" )) != XB_NO_ERROR ){ - iErrorStop = 140; - throw rc; - } - } - } else { - // free up the old space - xbUInt32 ulLastDataBlock = 0L; - - if( ulBlockNo > 0 ){ - if( llNewBlocks.SearchFor( ulBlockNo ) > 0 ){ - - if(( rc = FreeMemoBlockChain( ulBlockNo, ulLastDataBlock )) != XB_NO_ERROR ){ - iErrorStop = 150; - throw rc; - } - } else { - // first revision, save what it was in case of Abort() command - if(( rc = llOldBlocks.InsertAtFront( ulBlockNo )) != XB_NO_ERROR ){ - iErrorStop = 160; - throw rc; - } - } - } - // should next line be unsigned 32 bit int? - xbUInt32 ulTotalLen = 8 + sMemoData.Len(); - xbUInt32 ulBlocksNeeded; - if( ulTotalLen % GetBlockSize()) - ulBlocksNeeded = ulTotalLen / GetBlockSize() + 1; - else - ulBlocksNeeded = ulTotalLen / GetBlockSize(); - - xbBool bUsedBlockFound; - xbUInt32 ulHeadBlock; - xbUInt32 ulPrevNode; - if(( rc = FindBlockSetInChain( ulBlocksNeeded, ulLastDataBlock, ulHeadBlock, ulPrevNode, bUsedBlockFound )) != XB_NO_ERROR ){ - iErrorStop = 170; - throw rc; - } - iField1 = -1; - iStartPos = 8; - ulFieldLen = sMemoData.Len() + 8; - - if( bUsedBlockFound ){ - - if(( rc = GetBlockSetFromChain( ulBlocksNeeded, ulHeadBlock, ulPrevNode )) != XB_NO_ERROR ){ - iErrorStop = 180; - throw rc; - } - - if(( rc = WriteBlockHeader( ulHeadBlock, 1 )) != XB_NO_ERROR ){ - iErrorStop = 190; - throw rc; - } - - if(( rc = xbFwrite( sMemoData.Str(), sMemoData.Len(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 200; - throw rc; - } - } else { // append to the end - - if(( rc = WriteBlockHeader( ulLastDataBlock, 1 )) != XB_NO_ERROR ){ - iErrorStop = 220; - throw rc; - } - - if(( rc = xbFwrite( sMemoData.Str(), sMemoData.Len(), 1 )) != XB_NO_ERROR ){ - iErrorStop = 230; - throw rc; - } - - if(( rc = xbFputc( 0x00, (xbInt32)((ulBlocksNeeded * GetBlockSize()) - (sMemoData.Len() + 8)))) != XB_NO_ERROR ){ - iErrorStop = 240; - throw rc; - } - - if( ulLastDataBlock == ulHdrNextBlock ){ // this is first node to be added to the node chain - ulHdrNextBlock += ulBlocksNeeded; - ulHeadBlock = ulLastDataBlock; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ){ - iErrorStop = 250; - throw rc; - } - - } else { // adding memo data to the end of the file, but chain exists - - ulNextFreeBlock = ulLastDataBlock + ulBlocksNeeded; - ulHeadBlock = ulLastDataBlock; - if(( rc = WriteBlockHeader( ulPrevNode, 2 )) != XB_NO_ERROR ){ - iErrorStop = 260; - throw rc; - } - } - } - - if(( rc = llNewBlocks.InsertAtFront( ulHeadBlock )) != XB_NO_ERROR ){ // In case of Abort(), this block needs to be freed - iErrorStop = 270; - throw rc; - } - if(( rc = dbf->PutLongField( iFieldNo, (xbInt32) ulHeadBlock )) != XB_NO_ERROR ){ - iErrorStop = 280; - throw rc; - } - } - } - - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::UpdateMemoField() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Write block header. -/*! - \param ulBlockNo Block to read - \param iOption 1 - Read fields option 1 - 2 - Read fields option 2 - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbMemoDbt4::WriteBlockHeader( xbUInt32 ulBlockNo, xbInt16 iOption ) { - - xbInt16 rc = XB_NO_ERROR; - xbInt16 iErrorStop = 0; - - try{ - if( iOption == 1 ){ - ePutInt16 ((char *) mbb, iField1 ); - ePutInt16 ((char *) mbb+2, iStartPos ); - ePutUInt32((char *) mbb+4, ulFieldLen ); - } - else if( iOption == 2 ){ - ePutUInt32((char *) mbb, ulNextFreeBlock ); - ePutUInt32((char *) mbb+4, ulFreeBlockCnt ); - } - else{ - iErrorStop = 100; - rc = XB_INVALID_OPTION; - throw rc; - } - - if(( rc = WriteBlock( ulBlockNo, 8, mbb )) != XB_NO_ERROR ){ - iErrorStop = 110; - rc = XB_READ_ERROR; - } - } - catch (xbInt16 rc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::WriteHeader() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, rc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( rc )); - } - return rc; -} -/***********************************************************************/ -//! @brief Empty the memo file. -/*! - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbMemoDbt4::Zap(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - char cBuf[4]; - try{ - ulHdrNextBlock = 1L; - ePutUInt32( cBuf, ulHdrNextBlock ); - - if(( iRc != xbFseek( 0, SEEK_SET )) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - if(( iRc != xbFwrite( cBuf, 4, 1 ))!= XB_NO_ERROR ){ - iErrorStop = 110; - throw iRc; - } - if(( iRc != xbTruncate( GetBlockSize())) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - } - - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbMemoDbt4::Zap() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); - xbase->WriteLogMessage( sMsg.Str() ); - xbase->WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -}/***********************************************************************/ -} /* namespace */ -#endif /* XB_DBF4_SUPPORT */ -#endif /* XB_MEMO_SUPPORT */ - diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbssv.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbssv.cpp deleted file mode 100755 index 532f942..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbssv.cpp +++ /dev/null @@ -1,658 +0,0 @@ -/* xbssv.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 - -*/ - -#include "xbase.h" - -namespace xb{ - -const xbErrorMessage xbErrorMessages[] = { - { XB_NO_ERROR, "No Error" }, - { XB_NO_MEMORY, "No Memory" }, - { XB_INVALID_OPTION, "Invalid Option" }, - { XB_INVALID_PARAMETER, "Invalid Parameter" }, - { 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" }, - { XB_FILE_NOT_FOUND, "File not found" }, - { XB_FILE_TYPE_NOT_SUPPORTED, "Not an Xbase type database" }, - { XB_RENAME_ERROR, "Unable to rename file" }, - { XB_INVALID_OBJECT, "Invalid Object" }, - { XB_NOT_OPEN, "Database not open" }, - { XB_NOT_FOUND, "Not Found" }, - { XB_OPEN_ERROR, "Open Error" }, - { XB_CLOSE_ERROR, "Close Error" }, - { XB_SEEK_ERROR, "Seek Error" }, - { XB_READ_ERROR, "Read Error" }, - { XB_WRITE_ERROR, "Error writing to disk drive" }, - { XB_EOF, "End Of File" }, - { XB_BOF, "Beginning Of File" }, - { XB_INVALID_BLOCK_SIZE, "Invalid Block Size" }, - { XB_INVALID_BLOCK_NO, "Invalid Block Number" }, - { XB_INVALID_RECORD, "Invalid Record Number" }, - { XB_DELETE_FAILED, "Delete Failed" }, - { 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" }, - { XB_INVALID_FIELD_NAME, "Invalid Field Name" }, - { XB_INVALID_MEMO_FIELD, "Not a Memo field" }, - { XB_INVALID_FIELD, "Invalid Field" }, - { XB_INVALID_FIELD_LEN, "Invalid Field Length" }, - { XB_INVALID_DATE, "Invalid Date" }, - { XB_INVALID_LOCK_OPTION, "Invalid Lock Option" }, - { XB_LOCK_FAILED, "Lock Failed" }, - { XB_TABLE_NOT_LOCKED, "Table Not Locked" }, - { XB_PARSE_ERROR, "Parse Error" }, - { XB_INVALID_FUNCTION, "Invalid or Undefined Function" }, - { XB_INVALID_PARM, "Invalid Parm" }, - { XB_INCONSISTENT_PARM_LENS, "Inconsistent parm lengths" }, - { XB_INCOMPATIBLE_OPERANDS, "Incompatible operands" }, - { XB_UNBALANCED_PARENS, "Unbalanced Parens" }, - { XB_UNBALANCED_QUOTES, "Unbalanced Quotes" }, - { XB_INVALID_EXPRESSION, "Invalid expression" }, - { XB_INVALID_KEYNO, "Invalid Key Number" }, - { XB_INVALID_INDEX, "Index File Error" }, - { XB_INVALID_TAG, "Invalid index tag" }, - { XB_SYNTAX_ERROR, "Invalid SQL Syntax" }, - { XB_MAX_ERROR_NO, "End of Error List" } -}; -// see also xbretcod.h - -xbInt16 xbSsv::iEndianType = 0; -xbString xbSsv::sDefaultDateFormat = "MM/DD/YY"; - -xbInt16 xbSsv::iDefaultFileVersion = 4; -xbString xbSsv::sNullString = ""; -xbBool xbSsv::bDefaultAutoCommit = xbTrue; - -xbString xbSsv::sDataDirectory = PROJECT_DATA_DIR; -xbString xbSsv::sTempDirectory = PROJECT_TEMP_DIR; - -#ifdef XB_LOGGING_SUPPORT -xbString xbSsv::sLogDirectory = PROJECT_LOG_DIR; -xbString xbSsv::sLogFileName = PROJECT_DFLT_LOGFILE; -#endif // XB_LOGGING_SUPPORT - -#ifdef XB_LOCKING_SUPPORT -xbInt32 xbSsv::lDefaultLockWait = 100; -xbInt16 xbSsv::iDefaultLockRetries = 3; -xbBool xbSsv::bDefaultAutoLock = xbTrue; -xbInt16 xbSsv::iDefaultLockFlavor = 1; -xbBool xbSsv::bMultiUser = xbTrue; -#else -xbBool xbSsv::bMultiUser = xbFalse; -#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 // 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 // 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. -xbSsv::xbSsv(){} -/*************************************************************************/ -void xbSsv::BitDump( unsigned char c ) const { - for( int i = 7; i >= 0; i-- ) - std::cout << (BitSet( c, i ) ? 1 : 0); -} -void xbSsv::BitDump( char c ) const { - BitDump( (unsigned char) c ); -} -/*************************************************************************/ -//! @brief Check a bit in a one byte field and see if it is set. -/*! - \param c One byte char field to examine. - \param iBitNo which bit to examine. - \returns xbTrue Bit is set<br> - xbFalse Bit is not set -*/ -xbBool xbSsv::BitSet( unsigned char c, xbInt16 iBitNo ) const { - return c & 1 << iBitNo; -} -/*************************************************************************/ -//! @brief Display error message on console for a given error number. -/*! - \param iErrorCode Error number to reference -*/ -void xbSsv::DisplayError( xbInt16 iErrorCode ) const { - std::cout << (const char *) GetErrorMessage( iErrorCode ) << std::endl; -} -/*************************************************************************/ -//! @brief Get the default auto commit setting. -/*! - - When auto commit is enabled, the library will automatically post any updates - when moving off an updated record or closing files. - If auto commit is disabled, the application program will need to explicitly - update the tables using using dbf->Put() and dbf->AppendRecord(). - - \returns xbTrue if auto commit is turned on<br> - xbFalse is auto commit is turned off -*/ - -xbBool xbSsv::GetDefaultAutoCommit() const { - return bDefaultAutoCommit; -} -/*************************************************************************/ -//! @brief Get the current data directory. -/*! - \returns xbString containing the current data directory - where the database files are stored. -*/ - -xbString &xbSsv::GetDataDirectory() const { - return sDataDirectory; -} -/*************************************************************************/ -//! @brief Get the default date format. -/*! - \returns xbString containing the default date format. -*/ - -xbString & xbSsv::GetDefaultDateFormat() const { - return sDefaultDateFormat; -} -/*************************************************************************/ -//! @brief Get the Endian type. -/*! - \returns B - Big endian<br> - L - Little endian<br> -*/ -xbInt16 xbSsv::GetEndianType() const { - return iEndianType; -} -/*************************************************************************/ -//! @brief Get an error message. -/*! - \param iErrorCode ErrorCode is the error number of description to be returned. - \returns Returns a pointer to a string containing a text description for the error code. -*/ - -const char * xbSsv::GetErrorMessage( xbInt16 iErrorCode ) const{ - - if( iErrorCode > 0 || iErrorCode <= XB_MAX_ERROR_NO ) - return ""; - - xbBool bFound = xbFalse; - xbInt16 iCtr = 0; - while( !bFound ){ - if( xbErrorMessages[iCtr].iErrorNo == XB_MAX_ERROR_NO ) - return "Unknown Error"; - if( xbErrorMessages[iCtr].iErrorNo == iErrorCode ) - return xbErrorMessages[iCtr].sErrorText; - iCtr++; - } - return ""; -} -/*************************************************************************/ -//! @brief Get home directory. -/*! - \param sHomeDirOut - Output home directory for current user. -*/ - -void xbSsv::GetHomeDir( xbString &sHomeDirOut ){ - - #ifdef HAVE_GETENV_S_F - - char sPath[MAX_PATH]; - size_t lSize; - - sHomeDirOut = ""; - memset( sPath, 0x00, MAX_PATH ); - - getenv_s( &lSize, NULL, 0, "HOMEDRIVE" ); - if( lSize > 0 ){ - getenv_s( &lSize, sPath, lSize, "HOMEDRIVE" ); - sHomeDirOut = sPath; - memset( sPath, 0x00, MAX_PATH ); - } - - getenv_s( &lSize, NULL, 0, "HOMEPATH" ); - if( lSize > 0 ){ - getenv_s( &lSize, sPath, lSize, "HOMEPATH" ); - sHomeDirOut += sPath; - } - if( sHomeDirOut == "" ) - sHomeDirOut = "C:\xbase64"; - - #elif defined(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. -/*! - \param sDataDirectory Set the data directory. -*/ - -void xbSsv::SetDataDirectory( const xbString &sDataDirectory ){ - this->sDataDirectory = sDataDirectory; - - #ifdef WIN32 - this->sDataDirectory.SwapChars( '/', '\\' ); - #else - this->sDataDirectory.SwapChars( '\\', '/' ); - #endif - -} - -/*************************************************************************/ -//! @brief Set the default date format. -/*! - \param sDefaultDateFormat Set the default date format. -*/ - -void xbSsv::SetDefaultDateFormat( const xbString &sDefaultDateFormat ) { - this->sDefaultDateFormat = sDefaultDateFormat; -} - -/*************************************************************************/ -//! @brief Set the default auto commit. -/*! - - Disabling auto commit requires the application execute explicit updates - using dbf->Put() and dbf->AppendRecord(). With auto commit on, the library - posts updates automatically when moving off the current record or closing - a file. - - \param bDefaultAutoCommit xbTrue - Enable default auto commit.<br> - xbFalse - Disable default auto commit.<br> -*/ - -void xbSsv::SetDefaultAutoCommit( xbBool bDefaultAutoCommit ) { - this->bDefaultAutoCommit = bDefaultAutoCommit; -} -/*************************************************************************/ -//! @brief Set the endian type -/*! - This routine determines the Endian-ness at run time instead of - compile time as some processers (ie; Sparc,ARM) can be switched either way. - This routine is called automatically by the library at startup and does not - need to be called in an application program. - -*/ - -void xbSsv::SetEndianType() { - xbInt16 e = 1; - iEndianType = *(char *) &e; - if( iEndianType ) - iEndianType = 'L'; - else - iEndianType = 'B'; - return; -} - -/*************************************************************************/ -//! @brief Set the temp directory. -/*! - \param sTempDirectory Set the data direcroty. -*/ - -void xbSsv::SetTempDirectory( const xbString &sTempDirectory ){ - this->sTempDirectory = sTempDirectory; - - #ifdef WIN32 - this->sTempDirectory.SwapChars( '/', '\\' ); - #else - this->sTempDirectory.SwapChars( '\\', '/' ); - #endif - -} - -/*************************************************************************/ -//! @brief Get the OS dependent path separator. -/*! - \returns Returns '\' for windows environment, otherwise returns '/'. -*/ - -char xbSsv::GetPathSeparator() const { - #ifdef WIN32 - return '\\'; - #else - return '/'; - #endif -} - -/*************************************************************************/ -//! @brief Get the current temp directory. -/*! - \returns xbString containing the current data directory - where the database files are stored. -*/ - -xbString &xbSsv::GetTempDirectory() const { - return sTempDirectory; -} - -/*************************************************************************/ -#ifdef XB_LOGGING_SUPPORT - -//! @brief Get the default log file name. -/*! - \returns Returns the log file name. -*/ - -xbString & xbSsv::GetLogFileName() const { - return sLogFileName; -} - -/*************************************************************************/ -//! @brief Get the default log directory. -/*! - \returns Returns the log directory. -*/ - - -xbString & xbSsv::GetLogDirectory() const { - return sLogDirectory; -} -/*************************************************************************/ -//! @brief Set the default log directory name. -/*! - \param sLogDirectory Name of desired log directory. - -*/ - -void xbSsv::SetLogDirectory( const xbString &sLogDirectoryIn ){ - - this->sLogDirectory = sLogDirectoryIn; - #ifdef WIN32 - this->sLogDirectory.SwapChars( '/', '\\' ); - #else - this->sLogDirectory.SwapChars( '\\', '/' ); - #endif - -} - -//! @brief Set the log file name. -/*! - \param sLogFileName - Log File Name. - \return void -*/ - -void xbSsv::SetLogFileName( const xbString & sLogFileName ){ - - this->sLogFileName = sLogFileName; -} - - -#else - -xbString & xbSsv::GetLogFileName() const { - return sNullString; -} - - -xbString & xbSsv::GetLogDirectory() const { - -std::cout << "xbSsv::GetLogDirectory() returning null\n"; - - return sNullString; -} - -void xbSsv::SetLogDirectory( const xbString &sLogDirectory ){ - return; -} - -void xbSsv::SetLogFileName( const xbString & sLogFileName ){ - return; -} - -#endif - -/*************************************************************************/ - -#ifdef XB_LOCKING_SUPPORT - -//! @brief Get the default lock retries. -/*! - This is the number of lock attempts the libary will make before returning - failure if the file can not be locked. - \returns Default lock retry count. -*/ -xbInt16 xbSsv::GetDefaultLockRetries() const { - return iDefaultLockRetries; -} - -//! @brief Set the default lock retries. -/*! - \param iDefaultLockRetries - Number of lock attempts before returning failure. -*/ -void xbSsv::SetDefaultLockRetries( xbInt16 iDefaultLockRetries ) { - this->iDefaultLockRetries = iDefaultLockRetries; -} - -//! @brief Get the default auto lock setting. -/*! - When auto locking is turned on, the library automatically locks and unlocks - files and indices as needed in a multi user environment. - \returns Number of lock attempt settings. -*/ -xbBool xbSsv::GetDefaultAutoLock() const { - return bDefaultAutoLock; -} - - -//! @brief Set the default auto lock setting. -/*! - When auto locking is turned on, the library automatically locks and unlocks - files and indices as needed in a multi user environment. Locking is not required - in single a single user environment. - - \param bDefaultAutoLock xbTrue - Turn autolocking on<br> - xbFalse - Turn autolocking off<br> -*/ -void xbSsv::SetDefaultAutoLock( xbBool bDefaultAutoLock ) { - this->bDefaultAutoLock = bDefaultAutoLock; -} - -//! @brief Enable default auto locking. -/*! - When auto locking is turned on, the library automatically locks and unlocks - files and indices as needed in a multi user environment. -*/ -void xbSsv::EnableDefaultAutoLock() { - this->bDefaultAutoLock = xbTrue; -} - -//! @brief Disable defalt auto locking. -/*! - When auto locking is turned off, the library does not automatically lock - and unlock files and indices as needed in a multi user environment. - Locking is not needed in a single user environment. - -*/ -void xbSsv::DisableDefaultAutoLock() { - this->bDefaultAutoLock = xbFalse; -} -/***************************************************************************/ -//! @brief Get default lock flavor -/*! - Currently one flavor. This routine is part of the structure to support - future additional locking scenarios for Clipper and Foxpro. - \returns 1 -*/ -xbInt16 xbSsv::GetDefaultLockFlavor() const { - return iDefaultLockFlavor; -} - -/***************************************************************************/ -//! @brief Set default lock flavor -/*! - Currently one flavor. This routine is part of the structure to support - future additional locking scenarios for Clipper and Foxpro. -*/ -void xbSsv::SetDefaultLockFlavor( xbInt16 iDefaultLockFlavor ) { - this->iDefaultLockFlavor = iDefaultLockFlavor; -} - -/***************************************************************************/ -//! @brief Set default lock wait -/*! - \param lLockWait Set default lock wait in milliseconds. -*/ -void xbSsv::SetDefaultLockWait( xbInt32 lLockWait ) { - this->lDefaultLockWait = lLockWait; -} - -/***************************************************************************/ -//! @brief Get default lock wait -/*! - \returns Lock wait time in milliseconds. - -*/ -xbInt32 xbSsv::GetDefaultLockWait() const { - return lDefaultLockWait; -} -#endif - -/***************************************************************************/ -//! @brief Get the multi user setting. -/*! - \returns xbTrue - Multi user mode turned on.<br> - xbFalse - Multi user mode turned off.<br> -*/ -xbBool xbSsv::GetMultiUser() const { - return bMultiUser; -} - -//! @brief Get the multi user setting. -/*! - \param bMultiUser xbTrue - Turn on Multi user mode.<br> - xbFalse - Turn off Multi user mode.<br> -*/ -void xbSsv::SetMultiUser( xbBool bMultiUser ) { - this->bMultiUser = bMultiUser; -} - - - -/************************************************************************/ -#ifdef XB_MDX_SUPPORT -//! @brief Get the mdx file block size used when creating a memo file. -/*! - \returns system default setting for MDX block size. -*/ -xbInt16 xbSsv::GetCreateMdxBlockSize() const { - return iCreateMdxBlockSize; -} - -/************************************************************************/ -//! @brief Create mdx block size. -/*! - This routine sets the mdx file block size at the system level. This value is - used when the mdx index file is initially created so if you want to change it, - this must be called before creating the table. - - \param iBlockSize - Block size, must be evenly divisible by 512 and <= 16384 - \returns XB_INVALID_BLOCK_SIZE<br>XB_NO_ERROR -*/ - -xbInt16 xbSsv::SetCreateMdxBlockSize( xbInt16 iBlockSize ){ - - if( iBlockSize < 512 || iBlockSize > 16384 || iBlockSize % 512 ) - return XB_INVALID_BLOCK_SIZE; - else - iCreateMdxBlockSize = iBlockSize; - - return XB_NO_ERROR; -} -#endif - -/************************************************************************/ -#if defined (XB_NDX_SUPPORT) || defined (XB_MDX_SUPPORT) -//! @brief Get Unique Key Opt -/*! - This routine returns the Unique Key Processing Option which is one of: - XB_HALT_ON_DUPKEY - XB_EMULATE_DBASE -*/ - -xbInt16 xbSsv::GetUniqueKeyOpt() const { - return iUniqueKeyOpt; -} - -//! @brief Set Unique Key Opt -/*! @brief Set Unique Key Opt - This routine Sets the Unique Key Processing Option which is one of: - XB_HALT_ON_DUPKEY - XB_EMULATE_DBASE -*/ -xbInt16 xbSsv::SetUniqueKeyOpt( xbInt16 iOpt ){ - if( iOpt == XB_HALT_ON_DUPKEY || iOpt == XB_EMULATE_DBASE ){ - iUniqueKeyOpt = iOpt; - return XB_NO_ERROR; - } else { - return XB_INVALID_OPTION; - } -} -#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 -/************************************************************************/ - - - - -} /* namespace */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbstring.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbstring.cpp deleted file mode 100755 index 89cefb6..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbstring.cpp +++ /dev/null @@ -1,2000 +0,0 @@ -/* xbstring.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014,2021,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 - -*/ - -//#ifdef __GNU LesserG__ -// #pragma implementation "xbstring.h" -//#endif - -#include "xbase.h" - - -namespace xb{ - -XBDLLEXPORT const char * xbString::NullString = ""; -XBDLLEXPORT char xbString::cJunkBuf; - -/************************************************************************/ -//! @brief Destructor - -xbString::~xbString(){ - if (data != NULL) - free(data); - -} - -/************************************************************************/ -//! @brief Constructor -/*! - \param ulSize - Allocation size. The allocation size is normally handled internally - by the class, but it can be set in this constructor. -*/ -xbString::xbString(xbUInt32 ulSize) { - data = (char *)calloc(1, ulSize); - this->size = ulSize; -// memset( data, 0x00, ulSize ); - redundant, initialized by calloc -} -/************************************************************************/ -//! @brief Constructor -/*! - \param c - Initialize string to c. -*/ -xbString::xbString(char c) { - data = (char *)calloc(1, 2); - data[0] = c; - data[1] = 0; - size = 2; -} -/************************************************************************/ -//! @brief Constructor -/*! - \param s - Initialize string to s. -*/ -xbString::xbString( const char *s ) { - - if( s == NULL ){ - size = 0; - data = NULL; - } else { - size = (xbUInt32) (strlen(s) + 1 ); - data = (char *) calloc( 1, size ); - xb_strcpy( data, s ); - } - // ctor(s); -} -/************************************************************************/ -//! @brief Constructor -/*! - \param d - Initiailize string to d. -*/ -xbString::xbString( xbDouble d ) { - data = NULL; - size = 0; - Sprintf("%f", d); -} -/************************************************************************/ -//! @brief Constructor -/*! - \param s Initialize string to s. - \param ulMaxLen Maximum length of string. Truncate any characters greater than ulMaxLen. -*/ -xbString::xbString( const char *s, xbUInt32 ulMaxLen ) { - xbUInt32 sSize = (xbUInt32) strlen( s ); - if( sSize < ulMaxLen ) - size = sSize; - else - size = ulMaxLen; - data = (char *)calloc(1, size+1); - for( xbUInt32 i = 0; i < size; i++ ) - data[i] = s[i]; - data[size] = '\0'; - size++; // account for null trailing byte - return; -} -/************************************************************************/ -//! @brief Constructor -/*! - \param s Initialize string to s. -*/ -xbString::xbString( const xbString &s ) { - ctor(s.Str()); -} - -/************************************************************************/ -//! @brief Operator const char * -/*! - \returns Pointer to string data. -*/ -xbString::operator const char *() const { - return data ? data : NullString; -} - -/************************************************************************/ -//! @brief Set operator = -/*! - \param s - Set the string to the string on the right of the equal sign. -*/ -xbString &xbString::operator=( const xbString &s ) { - return Set(s); -} -/************************************************************************/ -//! @brief Set operator = -/*! - \param s - Set the string to the string on the right of the equal sign. -*/ -xbString &xbString::operator=( const char *s ) { - return Set(s); -} - -/************************************************************************/ -//! @brief Stream insertion operator << -/*! - std::cout << MyString << std::endl; - - \param os Output stream - \param s String to send to output stream -*/ -std::ostream& operator<< ( std::ostream& os, const xbString & s ) { - return os << s.Str(); -} -/************************************************************************/ -//! @brief Append operator += -/*! - \param s - Append s to the string. -*/ -xbString &xbString::operator+=( const xbString &s ) { - - if (s.IsNull()) - return (*this); - - xbUInt32 Len = s.Len(); - xbUInt32 oldLen = this->Len(); - xbUInt32 newLen = Len + oldLen; - - data = (char *)realloc(data, newLen+1); - if( !data ) - return (*this); - - if(oldLen == 0) - data[0] = 0; - - char *t = data; - t+= oldLen; - for( xbUInt32 i = 0; i < Len; i++ ) - *t++ = s.GetCharacter(i+1); - - data[newLen] = '\0'; - size == 0 ? size += (Len + 1) : size += Len; - - return (*this); -} -/************************************************************************/ -//! @brief Append operator += -/*! - \param s - Append s to the string. -*/ -xbString &xbString::operator+=( const char *s ) { - - if (s == NULL) - return (*this); - xbUInt32 Len = (xbUInt32) strlen(s); - xbUInt32 oldLen = this->Len(); - xbUInt32 newLen = Len + oldLen; - data = (char *)realloc(data, newLen+1); - if(oldLen == 0) - data[0] = 0; - for( xbUInt32 i = 0; i < Len; i++ ) - data[i+oldLen] = s[i]; - data[newLen] = '\0'; - // size += Len; - size == 0 ? size+= (Len + 1) : size += Len; - return (*this); -} -/************************************************************************/ -//! @brief Append operator += -/*! - \param c - Append c to the string. -*/ -xbString &xbString::operator+=( char c ) { - xbUInt32 Len = 1; - xbUInt32 oldLen = this->Len(); - data = (char *)realloc(data, oldLen+Len+1); - data[oldLen] = c; - data[oldLen+1] = 0; - // size++; - size == 0 ? size += 2 : size++; - return (*this); -} -/************************************************************************/ -//! @brief Append operator -= -/*! - Append s to the right of this string, right trimming both strings. - \param s - Append s to the right of the string value. -*/ -xbString &xbString::operator-=( const xbString &s ) { - - Rtrim(); - if (s.IsNull()) - return (*this); - xbUInt32 Len = s.Len(); - xbUInt32 oldLen = this->Len(); - xbUInt32 newLen = Len + oldLen; - - data = (char *)realloc(data, newLen+1); - if(oldLen == 0) - data[0] = 0; - - for( xbUInt32 i = 0; i < Len; i++ ) - data[i+oldLen] = s.GetCharacter(i+1); - - data[newLen] = '\0'; - //size += Len; - size == 0 ? size += (Len+1) : size += Len; - Rtrim(); - return (*this); -} -/************************************************************************/ -//! @brief Append operator -= -/*! - Append s to the right of this string, right trimming both strings. - \param s - Append s to the right of the string value. -*/ -xbString &xbString::operator-=(const char *s) { - - Rtrim(); - if (s == NULL) - return (*this); - xbUInt32 Len = (xbUInt32) strlen(s); - xbUInt32 oldLen = this->Len(); - xbUInt32 newLen = Len + oldLen; - - data = (char *)realloc(data, newLen+1); - - if(oldLen == 0) - data[0] = 0; - - for( xbUInt32 i = 0; i < Len; i++ ) - data[i+oldLen] = s[i]; - data[newLen] = '\0'; - - //size += Len; - size == 0 ? size += (Len+1) : size += Len; - - Rtrim(); - return (*this); -} -/************************************************************************/ -//! @brief Append operator -= -/*! - Append c to the right of this string, trimming right space on this string first. - \param c - Append s to the right of the string value. -*/ -xbString &xbString::operator-=(const char c) { - Rtrim(); - xbUInt32 oldSize = size; - - // size += 1; - size == 0 ? size += 2 : size += 1; - - data = (char *)realloc( data, size ); - if( oldSize == 0 ) data[0] = 0; - data[size-2] = c; - data[size-1] = 0; - Trim(); - return (*this); -} -/************************************************************************/ -//! @brief Concatonate operator - -/*! - Concatonate left string with right string returning reference to new string. - Both strings are trimmed. - - \param s1 Right string operator. -*/ -xbString xbString::operator-(const xbString &s1) { - xbString tmp( data ); - tmp -= s1; - return tmp; -} -/************************************************************************/ -//! @brief Concatonate operator + -/*! - Concatonate left string with right string returning reference to new string. - - \param s1 Right string operator. -*/ -xbString xbString::operator+( const char *s1) { - xbString tmp( data ); - tmp += s1; - return tmp; -} -/************************************************************************/ -//! @brief Concatonate operator + -/*! - Concatonate left string with right string returning reference to new string. - - \param s1 Right string operator. -*/ -xbString xbString::operator+( const xbString &s1) { - xbString tmp( data ); - tmp += s1; - return tmp; -} -/************************************************************************/ -//! @brief Concatonate operator + -/*! - Concatonate left string with right string returning reference to new string. - - \param c Right string operator. -*/ - -xbString xbString::operator+( const char c) { - xbString tmp( data ); - tmp += c; - return tmp; -} -/************************************************************************/ -//! @brief operator [] -/*! - \param n - Offset into the string of the byte to retrieve. - \returns c - The character to return from the offset within the [] brackets. -*/ -char &xbString::operator[]( xbUInt32 n ) const { - if( n > 0 && n <= size ) - return data[n-1]; - else - return cJunkBuf; -} -/************************************************************************/ -//! @brief operator [] -/*! - \param n - Offset into the string of the byte to retrieve. - \returns c - The character to return from the offset within the [] brackets. -*/ -char &xbString::operator[]( xbInt32 n ) const { - if( n > 0 && n <= (xbInt32) size ) - return data[n-1]; - else - return cJunkBuf; -} -/************************************************************************/ -//! @brief operator == -/*! - \param s String to compare - \returns xbTrue - Strings match.<br> - zbFalse - Strings don't match.<br> - -*/ -xbBool xbString::operator==( const xbString &s ) const { - - if( data == NULL || data[0] == 0 ) { - if( s.data == NULL || s.data[0] == 0 ) - return true; - return false; - } else { - if( s.data == NULL || s.data[0] == 0 ) - return false; - return( strcmp(data,s.data) == 0 ? xbTrue : xbFalse ); - } -} -/************************************************************************/ -//! @brief operator == -/*! - \param s String to compare - \returns xbTrue - Strings match.<br> - zbFalse - Strings don't match.<br> -*/ -xbBool xbString::operator==( const char *s ) const { - - if (s == NULL) { - if ( data == NULL) - return true; - return false; - } - if ((s[0] == 0) && data == NULL) - return true; - if ( data == NULL) - return false; - return( strcmp( data, s) == 0 ? xbTrue : xbFalse ); -} -/************************************************************************/ -//! @brief operator != -/*! - \param s String to compare - \returns xbTrue - Strings don't match.<br> - xbFalse - Strings match.<br> -*/ -xbBool xbString::operator!=( const xbString &s ) const { - if( data == NULL || data[0] == 0 ) { - if( s.data == NULL || s.data[0] == 0 ) - return xbFalse; // NULL != NULL - return xbTrue; // NULL != !NULL - } else { - if( s.data == NULL || s.data[0] == 0 ) - return xbTrue; // !NULL != NULL - return( strcmp( data, s.data ) != 0 ? xbTrue : xbFalse ); // !NULL != !NULL - } -} -/************************************************************************/ -//! @brief operator != -/*! - \param s String to compare - \returns xbTrue - Strings don't match.<br> - zbFalse - Strings match.<br> -*/ -xbBool xbString::operator!=( const char *s ) const { - if( s == NULL || s[0] == 0 ) { - if( data == NULL || data[0] == 0 ) - return xbFalse; // NULL != NULL - return xbTrue; // NULL != !NULL - } else { - if( s == NULL || s[0] == 0 ) - return xbTrue; // !NULL != NULL - return( strcmp( data, s ) != 0 ? xbTrue : xbFalse ); // !NULL != !NULL - } -} -/************************************************************************/ -//! @brief operator < -/*! - \param s String to compare - \returns xbTrue - Left string is less than the right string.<br> - zbFalse - Left string is not less than the right string.<br> -*/ -xbBool xbString::operator< ( const xbString &s ) const { - - if( data == NULL || data[0] == 0 ) { - if( s.data == NULL || s.data[0] == 0 ) - return false; - return true; - } else { - if( s.data == NULL || s.data[0] == 0 ) - return false; - return ( strcmp(data, s.data) < 0 ? xbTrue : xbFalse ); - } -} -/************************************************************************/ -//! @brief operator > -/*! - \param s String to compare - \returns xbTrue - Left string is greater than the right string.<br> - zbFalse - Left string is not greater than the right string.<br> -*/ -xbBool xbString::operator> ( const xbString &s ) const { - if( data == NULL || data[0] == 0 ) { - if( s.data == NULL || s.data[0] == 0 ) - return false; - return false; - } else { - if( s.data == NULL || s.data[0] == 0 ) - return true; - return( strcmp(data,s.data) > 0 ? xbTrue : xbFalse ); - } -} -/************************************************************************/ -//! @brief operator <= -/*! - \param s String to compare - \returns xbTrue - Left string is less than or equal to the right string.<br> - zbFalse - Left string is not less than or equal to the right string.<br> -*/ -xbBool xbString::operator<=( const xbString &s ) const { - if( data == NULL || data[0] == 0 ) { - if( s.data == NULL || s.data[0] == 0 ) - return true; - return true; - } else { - if( s.data == NULL || s.data[0] == 0 ) - return false; - return( strcmp(data,s.data) <= 0 ? xbTrue : xbFalse ); - } -} -/************************************************************************/ -//! @brief operator >= -/*! - \param s String to compare - \returns xbTrue - Left string is greater than or equal to the right string.<br> - zbFalse - Left string is not greater than or equal to the right string.<br> -*/ -xbBool xbString::operator>=( const xbString &s ) const { - if( data == NULL || data[0] == 0 ) { - if( s.data == NULL || s.data[0] == 0 ) - return true; - return false; - } else { - if( s.data == NULL || s.data[0] == 0 ) - return true; - return( strcmp(data, s.data) >= 0 ? xbTrue : xbFalse ); - } -} - -/************************************************************************/ -//! @brief Add a prefixing back slash to specified characters in the string. -/*! - \param c Character to prefix with a backslash. - \returns Reference to this string. -*/ -xbString &xbString::AddBackSlash( char c ) { - - xbUInt32 lCnt = CountChar( c ); - if( lCnt == 0 ) - return *this; - char *p; - if(( p = (char *)calloc( 1, size + lCnt )) == NULL ) - return *this; - - char *p2 = p; - for( xbUInt32 lS = 0; lS < size; lS++ ){ - if( data[lS] == c ) - *p2++ = '\\'; - *p2++ = data[lS]; - } - if( data ) - free( data ); - data = p; - - // size += lCnt; - size == 0 ? size += (lCnt+1) : size += lCnt; - - return *this; -} -/************************************************************************/ -//! @brief Append data to string. -/*! - \param s String data to append. - \returns Reference to this string. -*/ -xbString &xbString::Append( const xbString &s ) { - *this += s; - return *this; -} - -/************************************************************************/ -//! @brief Append data to string. -/*! - \param s String data to append. - \returns Reference to this string. -*/ -xbString &xbString::Append( const char *s ) { - *this += s; - return *this; -} -/************************************************************************/ -//! @brief Append data to string. -/*! - \param c String data to append. - \returns Reference to this string. -*/ -xbString &xbString::Append( char c ) { - *this += c; - return *this; -} -/************************************************************************/ -//! @brief Append data to string. -/*! - \param s String data to append. - \param ulByteCount Maximum number of bytes to append. - \returns Reference to this string. -*/ -xbString &xbString::Append( const char *s, xbUInt32 ulByteCount ) { - - if ( s == NULL || !*s || ulByteCount == 0) - return (*this); - - xbUInt32 ulOrigLen = this->Len(); - - // s might not be null byte at the end, can't use strlen - // xbUInt32 ulAddLen = strlen( s ); - xbUInt32 ulAddLen = 0; - const char *p = s; - - while( ulAddLen < ulByteCount && *p ){ - p++; - ulAddLen++; - } - - if( ulAddLen > ulByteCount ) - ulAddLen = ulByteCount; - - size = ulOrigLen + ulAddLen + 1; - data = (char *) realloc( data, size ); - - for( xbUInt32 i = 0; i < ulAddLen; i++ ) - data[i+ulOrigLen] = s[i]; - - data[size-1] = 0x00; - return (*this); -} - -/************************************************************************/ -//! @brief Assign portion of string. -/*! - \param sStr - Source string for copy operation. sStr needs to be a Null terminated string. - \param ulStartPos - Starting position within source string. - \param ulCopyLen - Length of data to copy. - \returns Reference to this string. -*/ -xbString &xbString::Assign(const char * sStr, xbUInt32 ulStartPos, xbUInt32 ulCopyLen){ - if(data){ - free(data); - data = 0; - size = 0; - } - xbUInt32 lLen = (xbUInt32) strlen( sStr ); - if( ulStartPos > lLen ){ - size = 0; - return( *this ); - } - if((( ulCopyLen - 1) + ulStartPos ) > lLen ) - ulCopyLen = lLen - ulStartPos + 1; - data = (char *)calloc(1, ulCopyLen + 1); - - //size = ulCopyLen + 1; - size == 0 ? size += (ulCopyLen+1) : size += ulCopyLen; - - for( xbUInt32 i = 0; i < ulCopyLen; i++ ) - data[i] = sStr[i + ulStartPos - ((xbUInt32) 1)]; - data[ulCopyLen] = '\0'; - return (*this); -} -/************************************************************************/ -//! @brief Assign portion of string. -/*! - \param sStr - Source string for copy operation. sStr needs to be a Null terminated string. - \param ulStartPos - Starting position within source string. - \returns Reference to this string. -*/ -xbString &xbString::Assign(const char * sStr, xbUInt32 ulStartPos){ - if(data){ - free(data); - data = 0; - size = 0; - } - xbUInt32 ulSrcLen = (xbUInt32) strlen( sStr ); - if( ulStartPos > ulSrcLen ){ - size = 0; - return( *this ); - } - xbUInt32 ulCopyLen; - ulCopyLen = ulSrcLen - ulStartPos + 1; - data = (char *)calloc(1, ulCopyLen + 1); - - size = ulCopyLen + 1; - - for( xbUInt32 i = 0; i < ulCopyLen; i++ ) - data[i] = sStr[i + ulStartPos - ((xbUInt32) 1)]; - data[ulCopyLen] = '\0'; - return (*this); -} - -/************************************************************************/ -//! @brief Assign portion of string. -/*! - \param sStr - Source string for copy operation. sStr needs to be a Null terminated string. - \param ulStartPos - Starting position within source string. - \param ulCopyLen - Length of data to copy. - \returns Reference to this string. -*/ -xbString &xbString::Assign(const xbString& sStr, xbUInt32 ulStartPos, xbUInt32 ulCopyLen){ - if(data){ - free(data); - data = 0; - size = 0; - } - xbUInt32 ulSrcLen = sStr.Len(); - if( ulStartPos > ulSrcLen ){ - size = 0; - return( *this ); - } - if((( ulCopyLen - 1) + ulStartPos ) > ulSrcLen ) - ulCopyLen = ulSrcLen - ulStartPos + 1; - data = (char *)calloc(1, ulCopyLen + 1); - size = ulCopyLen + 1; - for( xbUInt32 i = 0; i < ulCopyLen; i++ ) - data[i] = sStr[i + ulStartPos]; - data[ulCopyLen] = '\0'; - return (*this); -} -/************************************************************************/ -//! @brief Assign portion of string. -/*! - \param sStr - Source string for copy operation. sStr needs to be a Null terminated string. - \param ulStartPos - Starting position within source string. - \returns Reference to this string. -*/ -xbString &xbString::Assign(const xbString& sStr, xbUInt32 ulStartPos){ - if(data){ - free(data); - data = 0; - size = 0; - } - xbUInt32 ulSrcLen = sStr.Len(); - if( ulStartPos > ulSrcLen ){ - size = 0; - return( *this ); - } - xbUInt32 ulCopyLen; - ulCopyLen = ulSrcLen - ulStartPos + 1; - data = (char *)calloc(1, ulCopyLen + 1); - size = ulCopyLen; - for( xbUInt32 i = 0; i < ulCopyLen; i++ ) - data[i] = sStr[i + ulStartPos]; - data[ulCopyLen] = '\0'; - size++; - return (*this); -} -/************************************************************************/ -//! @brief Copy a string -/*! - \returns xbString. -*/ -xbString xbString::Copy() const { - return( *this ); -} -/************************************************************************/ -//! @brief Count the number of characters in the string. -/*! - \param c Character to count. - \param iOpt 0 - Count the number of characters.<br> - 1 - Count the number of characters not between single or double quotes. - \returns The number of characters. -*/ -xbUInt32 xbString::CountChar( char c, xbInt16 iOpt ) const { - if( iOpt == 0 ) - return CountChar( c ); - else{ - xbBool bSingleQuote = xbFalse; - xbBool bDoubleQuote = xbFalse; - char cPrevChar = 0x00; - xbUInt32 i,j; - for( i = 0, j = 0; i < size; i++ ){ - if( bSingleQuote && data[i] == '\'' && cPrevChar != '\\' ){ - bSingleQuote = xbFalse; - } - else if( bDoubleQuote && data[i] == '"' && cPrevChar != '\\' ){ - bDoubleQuote = xbFalse; - } - else if( data[i] == '\'' && cPrevChar != '\\' && !bDoubleQuote ){ - bSingleQuote = xbTrue; - } - else if( data[i] == '"' && cPrevChar != '\\' && !bSingleQuote ){ - bDoubleQuote = xbTrue; - } - else if( !bDoubleQuote && !bSingleQuote && data[i] == c ){ - j++; - } - cPrevChar = data[i]; - } - return j; - } -} -/************************************************************************/ -//! @brief Count the number of characters in the string. -/*! - \param c Character to count. - \returns The number of characters. -*/ -xbUInt32 xbString::CountChar( char c ) const { - xbUInt32 i,j; - for( i = 0,j = 0; i < size; i++ ) - if( data[i] == c ) - j++; - return j; -} -/************************************************************************/ -void xbString::ctor( const char *s ) { - - // this routine assumes it was called by one of the constructors. - - if (s == NULL) { - data = NULL; - size = 0; - return; - } - - size = (xbUInt32) (strlen(s) + 1); - data = (char *) calloc( 1, size); - - xb_strcpy(data, s); -} -/************************************************************************/ -//! @brief Convert hex character to string. -/*! - This routine converts a four byte string in the format of 0x00 to a one byte char value. - The first four bytes of the string must be in the format 0x00. - Anything past the first four bytes is disregarded. - - \param cOut Output character. - \returns XB_INVALID_PARM on error<br> - XB_NO_ERROR on success. -*/ -xbInt16 xbString::CvtHexChar( char &cOut ){ - - int j, k; - char c; - - if( Len() < 4 || data[0] != '0' || (data[1]!='X' && data[1]!='x' )) - return XB_INVALID_PARM; - - c = (char) toupper( data[2] ); - j = ( c > '9' ? c - 'A' + 10 : c - '0' ); - c = (char)toupper( data[3] ); - k = ( c > '9' ? c - 'A' + 10 : c - '0' ); - j = ( j << 4 ) + k; - - cOut = ( char ) j; - return XB_NO_ERROR; -} -/************************************************************************/ -//! @brief Convert string of hex characters to string. -/*! - - This routine converts a string of four byte format of 0x00 to a string of one byte chars. - - \param sOut Output string of converted characters. - \returns XB_INVALID_PARM on error<br> - XB_NO_ERROR on success. -*/ -xbInt16 xbString::CvtHexString( xbString &sOut ){ - char c; - xbString ws; - ws = data; - sOut = ""; - xbInt16 iRc; - while( ws.Len()){ - if(( iRc= ws.CvtHexChar( c )) != XB_NO_ERROR ) - return iRc; - sOut += c; - ws.Ltrunc( 4 ); - } - return XB_NO_ERROR; -} -/************************************************************************/ -//! @brief Convert string to xbUInt64 number -/*! - \param ullOut - output unsigned long long. - \returns XB_NO_ERROR -*/ -xbInt16 xbString::CvtULongLong( xbUInt64 &ullOut ){ - - // version 1 - fast, but no data checking - ullOut = 0; - char *s = data; - int i = 0; - while( *s ){ - ullOut *= 10; - ullOut += (xbUInt64) *s - '0'; - s++; - i++; - } - return XB_NO_ERROR; -} -/************************************************************************/ -//! @brief Convert string to xbInt64 number -/*! - \param llOut - output long long. - \returns XB_NO_ERROR -*/ -xbInt16 xbString::CvtLongLong( xbInt64 &llOut ){ - - // version 1 - fast, but no data checking - llOut = 0; - char *s = data; - int i = 0; - while( *s ){ - llOut *= 10; - llOut += (xbInt64) *s - '0'; - s++; - i++; - } - return XB_NO_ERROR; -} - -/************************************************************************/ -#ifdef XB_DEBUG_SUPPORT -void xbString::Dump( const char * title, xbInt16 iHexOption ) const { - fprintf(stdout, "%s StringSize[%d] DataLen=[%d] data=[%s]\n", title, size, Len(), data ); - if( iHexOption ){ - std::cout << "Hex values" << std::endl; - for( xbUInt32 i = 0; i < strlen( data ); i++ ) - printf( " %x", data[i] ); - std::cout << std::endl; - } -} -void xbString::Dump( const char * title ) const { - Dump( title, 0 ); -} - -void xbString::DumpHex( const char * title ) const { - Dump( title, 1 ); -} -#endif - -/************************************************************************/ -//! @brief Extract an element out of a delimited string. -/*! - \param sSrc Source string. - \param cDelim Delimiter. - \param lSkipCnt Number of delimiters to skip. - \param iOpt 0 - ignore single and double quotes.<br> - 1 - ignore delimiters between single or double quotes. - \returns Reference to string extracted from element. -*/ -xbString &xbString::ExtractElement( xbString &sSrc, char cDelim, xbUInt32 lSkipCnt, xbInt16 iOpt ) -{ - return ExtractElement( sSrc.Str(), cDelim, lSkipCnt, iOpt ); -} - -/************************************************************************/ -//! @brief Extract an element out of a delimited string. -/*! - \param pSrc Source string. - \param cDelim Delimiter. - \param lSkipCnt Number of delimiters to skip. - \param iOpt 0 - ignore single and double quotes.<br> - 1 - ignore delimiters between single or double quotes. - \returns Reference to string extracted from element. -*/ -xbString &xbString::ExtractElement( const char *pSrc, char cDelim, xbUInt32 lSkipCnt, xbInt16 iOpt ) -{ - /* opt values - 0 - ignore single and double quotes - 1 - ignore delimiters between single or double quotes - */ - - xbUInt32 lLen; - xbUInt32 lCurCnt = 0; - xbBool bInSingleQuotes = xbFalse; - xbBool bInDoubleQuotes = xbFalse; - char cPrevChar = 0x00; - const char *s = pSrc; - const char *pAnchor; - - /* skip past skipcnt delimiters */ - while( *s && lCurCnt < (lSkipCnt-1) ){ - if( iOpt == 0 ){ - if( *s == cDelim ) - lCurCnt++; - } else { - if( *s == cDelim && !bInSingleQuotes && !bInDoubleQuotes ){ - lCurCnt++; - } else if( *s == '\'' && !bInDoubleQuotes && cPrevChar != '\\' ){ - if( bInSingleQuotes == xbTrue ) - bInSingleQuotes = xbFalse; - else - bInSingleQuotes = xbTrue; - } else if( *s == '"' && !bInSingleQuotes && cPrevChar != '\\' ){ - if( bInDoubleQuotes == xbTrue ) - bInDoubleQuotes = xbFalse; - else - bInDoubleQuotes = xbTrue; - } - } - cPrevChar = *s; - s++; - } - - /* at the beginning of the field */ - pAnchor = s; - xbBool bDone = xbFalse; - while( *s && !bDone ){ - if( iOpt == 0 ){ - if( *s == cDelim ) - bDone = xbTrue; - } else { - if( *s == cDelim && !bInSingleQuotes && !bInDoubleQuotes ){ - bDone = xbTrue; - } else if( *s == '\'' && !bInDoubleQuotes && cPrevChar != '\\' ){ - if( bInSingleQuotes == xbTrue ) - bInSingleQuotes = xbFalse; - else - bInSingleQuotes = xbTrue; - } else if( *s == '"' && !bInSingleQuotes && cPrevChar != '\\' ){ - if( bInDoubleQuotes == xbTrue ) - bInDoubleQuotes = xbFalse; - else - bInDoubleQuotes = xbTrue; - } - } - cPrevChar = *s; - s++; - } - - // if at end of string, go back one and drop the delimiter - if( *s ) s--; - - lLen = (xbUInt32)(s - pAnchor); - - /* copy data */ - data = (char *) realloc( data, lLen+1 ); - memcpy( data, pAnchor, lLen ); - data[lLen] = 0; - this->size = lLen+1; - return *this; -} - -/************************************************************************/ -//! @brief Get a character by position -/*! - \param n - Position in string to extract. First position is 1 (not 0). - \returns Character from position n, or null. -*/ -char xbString::GetCharacter( xbUInt32 n ) const { - if( n > 0 && n <= size ) - return data[n-1]; - else - return 0x00; -} -/************************************************************************/ -//! @brief Get the position of the last occurrence of a given character. -/*! - \param c - Character to search for. - \returns Last position of character in the string. -*/ -xbUInt32 xbString::GetLastPos(char c) const { - - if (data == NULL) - return 0; - - char *p = data; - xbUInt32 iPos = 0; - xbUInt32 hPos = 0; - while( *p && iPos++ < ( size - 1 )){ - if( *p == c ) - hPos = iPos; - p++; - } - if( hPos ) - return hPos; - else - return 0; -} -/************************************************************************/ -//! @brief Get the position of the last occurrence of a given string. -/*! - \param s - String to search for. - \returns Last position of character in the string. -*/ -xbUInt32 xbString::GetLastPos(const char* s) const{ - - if (data == NULL) - return 0; - - char *p = data; - char *saveP = NULL; - while( p ){ - p = strstr( p, s); - if( p ){ - saveP = p; - p++; - } - } - if (saveP == NULL) - return 0; - return (xbUInt32)(saveP - data) + 1; -} -/************************************************************************/ -//! @brief Get the path separator out of the string. -/*! - This method assumes the string is a valid path name. - If it is, it returns either / or \. - \returns Char value containing either / or \ depending on OS. -*/ -char xbString::GetPathSeparator() const { - - if (data == NULL) - return 0x00; - char *p = data; - while( *p ){ - if( *p == '\\' || *p == '/' ) - return *p; - else - p++; - } - return 0x00; -} - -/************************************************************************/ -//! @brief Retrieve the size of the string buffer. -/*! - \returns Size of string buffer including the null terminating byte. -*/ -xbUInt32 xbString::GetSize() const { - return size; -} - -/************************************************************************/ -//! @brief Determine if the string has any alpha characters -/*! - \returns xbTrue - String contains one or more aloha characters.<br> - xbFalse - String contains no alpha characters. -*/ -xbBool xbString::HasAlphaChars() const { - for( xbUInt32 i = 0; i < size; i++ ) - if( isalpha( data[i] )) - return xbTrue; - return xbFalse; -} - - -/************************************************************************/ -//! @brief Determine if string is empty -/*! - \returns xbTrue if string is empty.<br> - xbFalse if string is not empty. -*/ -xbBool xbString::IsEmpty() const { - if( data == NULL ) - return true; - if( data[0] == 0 ) - return xbTrue; - return xbFalse; -} - -/************************************************************************/ -//! @brief Determine if string is NULL -/*! - \returns xbTrue if string is NULL.<br> - xbFalse if string is not NULL. -*/ -xbBool xbString::IsNull() const { - return( data == NULL ); -} - - -/************************************************************************/ -//! @brief Retain left part of string, drop rightmost characters. -/*! - \param ulLen New string length, truncate rightmost excess. - \returns Reference to string. -*/ -xbString &xbString::Left( xbUInt32 ulLen ) { - return Mid( 1, ulLen ); -} - -/************************************************************************/ -//! @brief Retrieve length of current string. -/*! - \returns String length, excluding the terminating null byte. -*/ -// return length of string -xbUInt32 xbString::Len() const { - return( data ? (xbUInt32) strlen(data) : 0 ); -} - -/************************************************************************/ -//! @brief Left trim white space from string. -/*! - \returns Reference to this string. -*/ -xbString &xbString::Ltrim(){ - - if( !data ) - return *this; - - char *p = data; - if( !*p || (*p && *p != ' ') ) - return *this; /* nothing to do */ - - xbUInt32 s = 0; - while( *p && *p == ' ' ){ - p++; - s++; - size--; - } - - xbUInt32 i; - for( i = 0; i < size; i++ ) - data[i] = data[i+s]; - data[i] = 0x00; - data = (char *) realloc( data, size ); - - return *this; - -} - -/************************************************************************/ -//! @brief Left truncate string -/*! - \param ulCnt Number of bytes to remove from the left. - \returns Reference to this string. -*/ -xbString &xbString::Ltrunc( xbUInt32 ulCnt ){ - if( ulCnt >= size ){ - if( size > 0 ){ - free( data ); - data = NULL; - size = 0; - } - return *this; - } - - char * ndata; - char * p; - ndata = (char *) calloc( 1, size - ulCnt ); - p = data; - p += ulCnt; - xb_strcpy( ndata, p ); - free( data ); - data = ndata; - size = size - ulCnt; - return *this; -} - -/************************************************************************/ -//! @brief Extract portion of data from string -/*! - \param ulStartPos Starting position - \param ulTargLen Length - \returns Reference to string -*/ -xbString &xbString::Mid( xbUInt32 ulStartPos, xbUInt32 ulTargLen ){ - - // this is a 1 based routine - if( ulStartPos == 0 ) - return *this; - - if( data == NULL ) - return( *this ); - if( data[0] == 0 ) - return( *this ); - if( ulStartPos > Len() ) - return( *this ); -/* - // Resize( ulTargLen + 1 ); - char *pTarg = data; - char *pSrc = data + ulStartPos - 1; - for( xbUInt32 l = 0; l < ulTargLen; l++ ) - *pTarg++ = *pSrc++; - *pTarg = 0x00; - // Resize( ulTargLen + 1 ); - */ - - char * newData = (char *) calloc( 1, ulTargLen + 1 ); - char *pTarg = newData; - char *pSrc = data + ulStartPos - 1; - for( xbUInt32 l = 0; l < ulTargLen; l++ ) - *pTarg++ = *pSrc++; - *pTarg = 0x00; - - free( data ); - data = newData; - size = ulTargLen + 1; - - return *this; -} - -/************************************************************************/ -//! @brief Left pad string -/*! - \param c Padding character. - \param ulNewLen New string length. - \returns Reference to this string. -*/ -xbString &xbString::PadLeft( char c, xbUInt32 ulNewLen ){ - - xbUInt32 srcLen; - if( data ) - srcLen = (xbUInt32) strlen( data ); - else - srcLen = 0; - - if( srcLen >= ulNewLen ) - return *this; - - char * newData = (char *) calloc( 1, ulNewLen + 1 ); - xbUInt32 i; - for( i = 0; i < ulNewLen - srcLen; i++ ) - newData[i] = c; - - char *targ = &newData[i]; - xb_strcpy( targ, data ); - free( data ); - data = newData; - size = ulNewLen + 1; - return *this; -} - -/************************************************************************/ -//! @brief Right pad string -/*! - \param c Padding character. - \param ulNewLen New string length. - \returns Reference to this string. -*/ -xbString &xbString::PadRight( char c, xbUInt32 ulNewLen ){ - xbUInt32 srcLen = (xbUInt32) strlen( data ); - if( srcLen >= ulNewLen ) - return *this; - data = (char *) realloc( data, ulNewLen + 1 ); - xbUInt32 i; - for( i = srcLen; i < ulNewLen; i++ ) - data[i] = c; - data[i] = 0x00; - size = ulNewLen + 1; - return *this; -} - -/************************************************************************/ -//! @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 { - - if (data == NULL) - return 0; - char *p = data; - xbUInt32 iPos = 0; - int iFound = 0; - while( *p && !iFound && iPos < ( size - 1 )){ - if( *p == c ) - iFound = 1; - else { - iPos++; - p++; - } - } - if( iFound ) - return iPos + 1; - else - return 0; -} - -/************************************************************************/ -//! @brief Determine position of a given substring -/*! - \param s Substring - \returns Position within string. Returns 0 if not found. -*/ -xbUInt32 xbString::Pos(const char* s) const{ - - if (data == NULL) - return 0; - - char *p = strstr(data, s); - if ( p == NULL) - return 0; - - return (xbUInt32)(p - data + 1); -} - -/************************************************************************/ -//! @brief Insert character into string -/*! - \param ulPos Insertion position. - \param c Character to insert. - \returns Reference to this string. -*/ -xbString &xbString::PutAt(xbUInt32 ulPos, char c){ - if((ulPos-1) > Len() ) - return *this; - data[ulPos-1] = c; - return *this; -} - -/************************************************************************/ -//! @brief Remove portion of string. -/*! - \param ulStartPos Starting position for removal operation. - \param ulDelSize Size of deletion. - \returns Reference to string. -*/ -xbString &xbString::Remove(xbUInt32 ulStartPos, xbUInt32 ulDelSize ) { - if( data == NULL ) - return( *this ); - if( data[0] == 0 ) - return( *this ); - xbUInt32 srcLen = Len(); - - if( ulStartPos > srcLen || ulStartPos < 1 || ulDelSize < 1 ) - return( *this ); - - if(( ulStartPos + ulDelSize - 1) >= size ){ - data[ulStartPos-1] = 0x00; - size = ulStartPos; - return( *this ); - } - - char *t; - char *s; - t = data + (ulStartPos - 1); - s = t + ulDelSize; - size -= ulDelSize; - while( *s ) - *t++ = *s++; - *t = 0x00; - return( *this ); -} - -/************************************************************************/ -//! @brief Replace a value within a string with another value -/*! - \param sReplace - Character string to replace. - \param sReplaceWith - Character string to replace with - \param iOption - 0 = All occurrences, 1 = first occurrence - \returns Reference to this string. -*/ - -//the new size includes the null termination byte -xbString &xbString::Replace( const char *sReplace, const char *sReplaceWith, xbInt16 iOption ){ - - xbBool bDone = xbFalse; - xbUInt32 ulPos; - 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 { - - 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++ ) - *t++ = *s++; - - // copy part2 - s = sReplaceWith; - for( xbUInt32 ul = 0; ul < ulReplaceWithLen; ul++ ) - *t++ = *s++; - - // copy part3 - 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; - size = ulNewLen; - } - } - return *this; -} - -/************************************************************************/ -//! @brief Resize a string -/*! - \param ulSize - New string size, including null termination byte. - \returns Reference to this string. -*/ -//the new size includes the null termination byte -xbString &xbString::Resize(xbUInt32 ulSize) { - -// data = (char *) realloc( data, ulSize ); - - -// original - data = (char *) realloc( data, ulSize ); - - if( ulSize > 0 ) - data[ulSize-1] = 0; - this->size = ulSize; - return *this; -} -/************************************************************************/ -//! @brief Right trim the string. -/*! - This routine removes any trailing white space on the string. - - \returns Reference to string. -*/ -xbString &xbString::Rtrim(){ - - xbUInt32 l = Len(); - if( l == 0 ) - return *this; - - xbUInt32 ulOrigSize = size; - l--; - - for(;;) { - if( data[l] != ' ' ) - break; - data[l] = 0; - size--; - if( l == 0 ) - break; - l--; - } - - if( ulOrigSize != size ) - data = (char * ) realloc( data, size ); - return *this; -} - -/************************************************************************/ -//! @brief Set the value of the string. -/*! - - Note: This routine fails if you try to set the string to itself or some part of itself. - - \param s Value to set the string. - \returns Reference to string. - -*/ -xbString &xbString::Set( const char *s ) { - - if(data != NULL){ - free(data); - data = NULL; - } - if( s == NULL || !*s ) { - if( data ) - free( data ); - data = NULL; - size = 0; - } else { - //data = (char *)calloc(1, strlen(s) + 1 ); - data = (char *) realloc( data, strlen(s) + 1 ); - xb_strcpy(data, s); - size = (xbUInt32) (strlen(data) + 1); - } - return (*this); -} -/************************************************************************/ -//! @brief Set the value of the string. -/*! - \param s Value to set the string. - \returns Reference to string. -*/ -xbString &xbString::Set( const xbString &s ) { - -// if( s.Str() == NULL || s.Len() == 0 ){ - - if( s.Str() == NULL ){ - if( data ) free( data ); - data = NULL; - size = 0; - } else { - xbUInt32 ulLen = s.Len(); - char *p = (char *) calloc( 1, ulLen + 1 ); - xb_strcpy( p, s.Str()); - size = ulLen + 1; - if( data ) free( data ); - data = p; - } - return (*this ); -} - -/************************************************************************/ -//! @brief Set the value of the string. -/*! - - Note: This routine fails if you try to set the string to itself or some part of itself. - - \param s Value to set the string. - \param ulSize Maximum size of resultant string. - \returns Reference to string. -*/ - -xbString &xbString::Set(const char *s, xbUInt32 ulSize) { - - if( data != NULL ) - free( data ); - - if(s == NULL) { - data = NULL; - size = 0; - return (*this); - } - - data = (char *) calloc( 1, ulSize+1 ); - char *pTarget = data; - for( xbUInt32 i = 0; i < ulSize; i++ ){ - *pTarget = *s; - pTarget++; - s++; - } - this->size = ulSize + 1; - return *this; -} - - -/************************************************************************/ -//! @brief Set the string to long integer numeric value. -/*! - \param lNum Value to set the string - \returns Reference to this string. -*/ -xbString &xbString::SetNum(xbInt32 lNum) { - Sprintf("%ld", lNum); - return *this; -} - -/************************************************************************/ -//! @brief Printf routine for formatting a string. -/*! - See documentation on the standard C printf function for how to use this. - - MyString.Sprintf( "a number %d some text %s", 100, "test text data" ); - - \param sFormat A format specifier - \returns Reference to a formatted string -*/ -xbString &xbString::Sprintf( const char *sFormat, ...) { - - xbInt32 iRc; - va_list ap; - char *t; - -#ifdef HAVE__VSNPRINTF_S_F - - va_start( ap, sFormat ); - size = (xbUInt32) _vsnprintf_s( NULL, 0, sFormat, ap ) + 1; - va_end( ap ); - - t = (char *) malloc( size ); - if( !t ){ - size = 0; - return( *this ); - } - - va_start( ap, sFormat ); - iRc = _vsnprintf_s( t, size, sFormat, ap ); - va_end( ap ); - -#else -#ifdef HAVE_VSPRINTF_S_F - - va_start( ap, sFormat ); - // size = (xbUInt32) vsprintf_s( NULL, 0, sFormat, ap ) + 1; - size = (xbUInt32) _vscprintf( sFormat, ap ) + 1; - va_end( ap ); - - t = (char *) malloc( size ); - if( !t ){ - size = 0; - return( *this ); - } - - va_start( ap, sFormat ); - iRc = vsprintf_s( t, size, sFormat, ap ); - va_end( ap ); - -#else -#ifdef HAVE_VSNPRINTF_F - - va_start( ap, sFormat ); - size = (xbUInt32) vsnprintf( NULL, 0, sFormat, ap) + 1; - va_end( ap ); - - t = (char *) calloc( 1, size ); - if( !t ){ - size = 0; - return( *this ); - } - va_start( ap, sFormat ); - iRc = vsnprintf( t, size, sFormat, ap ); - va_end( ap ); - -# else -# error "Fatal error building [xbstring.cpp] - You have neither _vsnprintf_s nor vsnprintf_s." -# endif -#endif -#endif - - if( iRc < 0 ){ - if( data ) - free( data ); - data = NULL; - size = 0; - } else { - if( data ) - free( data ); - data = t; - } - return( *this ); -} - -/************************************************************************/ -//! @brief Return string data -/*! - \returns char * to string data or NULL if string is empty -*/ -const char *xbString::Str() const { - return data ? data : NullString; -} - -/************************************************************************/ -//! @brief Copy all or part of string to character array -/*! - \param cDest pointer to destination buffer. - \param n Number of bytest to copy. It is the responsibility of the application - to verify the buffer is large enough to hold the string contents. - \returns char * to result - -*/ -char *xbString::strncpy( char * cDest, xbUInt32 n ) const { - xbUInt32 i; - xbUInt32 ulLen; - n > (size-1) ? ulLen = size-1 : ulLen = n; - memset( cDest, 0x00, ulLen ); - for( i = 0; i < ulLen; i++ ) - cDest[i] = data[i]; -// cDest[i] = 0x00; - return cDest; -} -/************************************************************************/ -//! @brief Swap characters -/*! - \param cFrom character to replace. - \param cTo character to replace with. - \returns Reference to this string. -*/ -xbString &xbString::SwapChars( char cFrom, char cTo ){ - xbUInt32 i; - for( i = 0; i < size; i++ ) - if( data[i] == cFrom ) - data[i] = cTo; - return *this; -} - - -/************************************************************************/ -//! @brief Replace all upper case charaters with lower case characters -/*! - \returns Reference to this string. -*/ -xbString &xbString::ToLowerCase(){ - xbUInt32 Len = this->Len(); - for (xbUInt32 i=0; i<Len; i++) - data[i] = (char)tolower(data[i]); - return *this; -} - -/************************************************************************/ -//! @brief Replace all lower case charaters with lower case characters -/*! - \returns Reference to this string. -*/ -xbString &xbString::ToUpperCase(){ - xbUInt32 Len = this->Len(); - for (xbUInt32 i=0;i<Len;i++) - data[i] = (char)toupper(data[i]); - return *this; -} -/************************************************************************/ -//! @brief Trim all leading and trailing white space from string. -/*! - \returns Reference to string. -*/ -xbString &xbString::Trim(){ - Rtrim(); - Ltrim(); - return *this; -} - -/************************************************************************/ -//! @brief Private function used for reallocateing memory -/*! - This function is designed to be a drop in replacement for the realloc - function call. -*/ -/* -char * xbString::xb_realloc( char * pIn, xbUInt32 iLen ){ - - if( iLen == 0 ){ - if( pIn ){ - free( pIn ); - return NULL; - } - } - - char *pNew = (char *) calloc( 1, (size_t) iLen ); - if( !pNew ) return NULL; - char *s = pIn; - char *t = pNew; - xbUInt32 iCnt = 0; - while( *s && iCnt++ < iLen ) - *t++ = *s++; - return pNew; -} -*/ -/************************************************************************/ -//! @brief Private function used for copying a string -/*! - For performance reasons, this is an internal function that does no - memory checking and assumes a valid buffer area is available to be copied. - - This function is marked as private because of the above reason and - is used by "stronger" calling functions. - - \param sTarget Target destination of copied string - \param sSource Source string to copy - \returns Reference to string. -*/ - -char * xbString::xb_strcpy( char *sTarget, const char *sSource ){ - - char *temp = sTarget; - while( *sSource != '\0') - *sTarget++ = *sSource++; - *sTarget= '\0'; - return temp; -} - -/************************************************************************/ -//! @brief Check for valid logical field data -/*! - Valid logical data is one 'T', 'F', 'N' or 'Y'.<br> - - \returns xbTrue if the data is valid logical data.<br> - xbFalse if not valid logical data. -*/ - -xbBool xbString::ValidLogicalValue() const { - if( Len() == 1 ) - if( data[0] == 'T' || data[0] == 'F' || data[0] == 'Y' || data[0] == 'N' || data[0] == '?' ) - return xbTrue; - return xbFalse; -} -/************************************************************************/ -//! @brief This function returns true if the data is valid numeric data -/*! - \returns xbTrue if valid numeric data.<br> - xbFalse if not valid numeric daata. -*/ - -xbBool xbString::ValidNumericValue() const { - const char *p; - p = data; - while( *p ){ - if( *p != '+' && *p != '-' && *p != '.' && *p != '0' && *p != '1' && - *p != '2' && *p != '3' && *p != '4' && *p != '5' && *p != '6' && - *p != '7' && *p != '8' && *p != '9' ) - return xbFalse; - else - p++; - } - return xbTrue; -} - - -/************************************************************************/ -//! @brief Remove every instance of a character from a string. -/*! - \param c character to remove from string. - \returns Reference to this stirng.void -*/ - -xbString &xbString::ZapChar( char c ){ - - if( data == NULL ) - return *this; - if( data[0] == 0 ) - return *this; - - char *s; - char *t; - - s = data; - t = data; - while( *s ){ - if( *s == c ){ - s++; - size--; - } else { - *t++ = *s++; - } - } - *t = 0x00; - - data = (char *) realloc( data, size ); - return *this; -} - -/************************************************************************/ -//! @brief Remove leading character from a string. -/*! - \param c character to remove from beginning of string. - \returns Reference to this string. -*/ -xbString &xbString::ZapLeadingChar( char c ){ - /* left truncate all of character c */ - xbUInt32 iLen = 0; - char *p; - p = data; - while( *p && *p == c ){ - iLen++; - p++; - } - if( iLen ) - Ltrunc( iLen ); - return *this; -} - -/************************************************************************/ -//! @brief Remove trailing character from a string. -/*! - \param c character to remove from ending of string. - \returns Reference to this string. -*/ -xbString &xbString::ZapTrailingChar( char c ){ - - xbUInt32 l = Len(); - if( l == 0 ) - return *this; - xbUInt32 ulOrigSize = size; - l--; - for(;;) { - if( data[l] != c ) - break; - data[l] = 0; - size--; - if( l == 0 ) - break; - l--; - } - if( ulOrigSize != size ) - data = (char *) realloc( data, size ); - return *this; -} - -} /* namespace */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbtag.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbtag.cpp deleted file mode 100755 index 621d44b..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbtag.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* xbtag.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 - -*/ - -#include "xbase.h" - -#ifdef XB_INDEX_SUPPORT - - -namespace xb{ - -/************************************************************************/ -//! @brief Constructor -/*! - \param pIx Pointer to index file instance. - \param vpTag Pointer to tag structure within file instance. - \param sType NDX or MDX - \param sTagName Name of tag. - \param sExpression Tag key definition. - \param sFilter MDX only - tag qualification expression. - \param bUnique xbTrue - Index is unique.<br>xbFalse - Index is not unique. - \param bSort MDX only<br>xbTrue - Descending.<br>xbFalse - Ascending. -*/ - -xbTag::xbTag( xbIx *pIx, void *vpTag, xbString &sType, xbString &sTagName, xbString &sExpression, xbString &sFilter, -xbBool bUnique, xbBool bSort ) -{ - this->pIx = pIx; - this->vpTag = vpTag; - this->sType = sType; - this->sTagName = sTagName; - this->sExpression = sExpression; - this->sFilter = sFilter; - this->bUnique = bUnique; - this->bSort = bSort; -} - - -/************************************************************************/ -//! @brief Get tag key expression. -/*! - \returns Tag key expression. -*/ -const xbString &xbTag::GetExpression() const { - return sExpression; -} -/************************************************************************/ -//! @brief Get tag filter expression. -/*! - \returns Tag filter expression (mdx only). -*/ - -const xbString &xbTag::GetFilter() const { - return sFilter; -} -/************************************************************************/ -//! @brief Get index file pointer. -/*! - \returns Pointer to index file instance. -*/ -xbIx *xbTag::GetIx() const { - return pIx; -} -/************************************************************************/ -//! @brief Get tag ascending setting. -/*! - \returns Tag sort setting - MDX only.<br>xbTrue - Descending.<br>xbFalse - Ascending. -*/ -xbBool xbTag::GetSort() const { - return bSort; -} -/************************************************************************/ -//! @brief Get tag name. -/*! - \returns Tag name. -*/ - -const xbString &xbTag::GetTagName() const { - return sTagName; -} -/************************************************************************/ -//! @brief Get tag type. -/*! - \returns Tag type. -*/ -const xbString &xbTag::GetType() const { - return sType; -} - -/************************************************************************/ -//! @brief Get tag unique setting. -/*! - \returns Tag unique setting.<br>xbTrue - Unique.<br>xbFalse - Not unique. -*/ - -xbBool xbTag::GetUnique() const { - return bUnique; -} -/************************************************************************/ -//! @brief Get tag pointer for tag within index file. -/*! - \returns Pointer to tag within index file instance. -*/ -void *xbTag::GetVpTag() const { - return vpTag; -} -/************************************************************************/ -} /* namespace */ -#endif /* XB_INDEX_SUPPORT */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbtblmgr.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbtblmgr.cpp deleted file mode 100755 index 53b6dd9..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbtblmgr.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* xbtblmgr.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 - -*/ - -#include "xbase.h" - -//#ifdef HAVE_STRING_H -//#include <string.h> -//#endif - -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 ); - } - } -} - -/*************************************************************************/ -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 - - - 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( sFqTblName.Len() == 0 ){ - iErrorStop = 100; - iRc = XB_INVALID_TABLE_NAME; - throw iRc; - } - - 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; - 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->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; - t = TblList; - - while(t && (strcmp( t->psTblAlias->Str(), sAlias.Str()) < 0 )){ - s = t; - t = t->pNext; - } - - if( t && (strcmp( t->psTblAlias->Str(), sAlias.Str()) == 0 )){ - iErrorStop = 120; - delete i->psFqTblName; - delete i->psTblName; - delete i->psTblAlias; - free( i ); - iRc = XB_DUP_TABLE_OR_ALIAS; - throw iRc; - } - i->pNext = t; - if (s == NULL) - TblList = i; - else - s->pNext = i; - } - catch (xbInt16 iRc ){ - if( iErrorStop != 120 ){ - xbString sMsg; - sMsg.Sprintf( "xbTblMgr::AddTblToTblList() Exception Caught. Error Stop = [%d] iRc = [%d] Tbl Name = [%s] Alias = [%s]", iErrorStop, iRc, sTblName.Str(), sTblAlias.Str() ); - std::cout << sMsg << std::endl; - } - } - if( iRc == XB_NO_ERROR ) - iOpenTableCount++; - return iRc; -} - -/*************************************************************************/ -xbInt16 xbTblMgr::DisplayTableList() const { - xbInt16 iTblCnt = 0; - xbTblList * l = TblList; - std::cout << "-- Open Table List --" << std::endl; - if( l == NULL ) - std::cout << "Table list is empty" << std::endl; - else{ - while( l ){ - iTblCnt++; - std::cout << iTblCnt << " FqFileName=[" << l->psFqTblName->Str() << "] TableName=[" << l->psTblName->Str() << "] Alias=[" << l->psTblAlias->Str() << "]" << std::endl; - l = l->pNext; - } - } - return iTblCnt; -} -/*************************************************************************/ -/* Get pointer to named dbf. - Looks up an open DBF file by Name. - - returns A pointer to the xbDbf class instance if found or NULL if not found. - - // looks for a match as an alias first, if not found as an alias, looks at the name - -*/ - -xbDbf *xbTblMgr::GetDbfPtr(const xbString& sTblAlias) const { - - - xbTblList *t; - t = TblList; - xbString s; - xbUInt32 ui = sTblAlias.Pos( ".DBF" ); - if( ui > 0 ) - s.Assign( sTblAlias.Str(), 1, ui - 1 ); - else - s.Set( sTblAlias ); - - while( t ){ - 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->psFqTblName->Str()) - return t->pDbf; - t = t->pNext; - } - return NULL; -} -/*************************************************************************/ -/* Get pointer to named dbf. - Looks up an open DBF file by Name. - - returns pointer to the xbDbf class instance if found or NULL if not found. -*/ - -xbDbf *xbTblMgr::GetDbfPtr(xbInt16 iItemNo ) const { - - xbTblList *t; - t = TblList; - xbInt16 iCnt = 1; - - if( iItemNo < 1 || iItemNo > iOpenTableCount ) - return NULL; - - while( t && iCnt < iItemNo ){ - t = t->pNext; - iCnt++; - } - if( t ) - return t->pDbf; - else - return NULL; -} -/*************************************************************************/ -xbInt16 xbTblMgr::GetOpenTableCount() const { - return iOpenTableCount; -} -/*************************************************************************/ -xbTblList * xbTblMgr::GetTblListEntry( xbDbf *pTbl ){ - - xbTblList * i = TblList; - while( i ){ - if( i->pDbf == pTbl ) - return i; - i = i->pNext; - } - return NULL; -} -/*************************************************************************/ -xbInt16 xbTblMgr::RemoveTblFromTblList( const xbString & sTblAlias ) { - xbTblList *i, *s; - - i = TblList; - s = NULL; - - while( i ){ - - if( strcmp( i->psTblAlias->Str(), sTblAlias.Str()) == 0 ) { - if(s) - s->pNext = i->pNext; - else - TblList = i->pNext; - - delete i->psFqTblName; - delete i->psTblName; - delete i->psTblAlias; - free( i ); - iOpenTableCount--; - return XB_NO_ERROR; - } else { - s = i; - i = i->pNext; - } - } - return XB_NOT_FOUND; -} -/*************************************************************************/ -xbInt16 xbTblMgr::RemoveTblFromTblList( xbDbf *pTbl ) { - xbTblList *i, *s; - - i = TblList; - s = NULL; - - while( i ){ - - if( i->pDbf == pTbl ) { - if(s) - s->pNext = i->pNext; - else - TblList = i->pNext; - - delete i->psFqTblName; - delete i->psTblName; - delete i->psTblAlias; - free( i ); - iOpenTableCount--; - return XB_NO_ERROR; - } else { - s = i; - i = i->pNext; - } - } - return XB_NOT_FOUND; -} -/*************************************************************************/ -} /* namespace */ diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbuda.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbuda.cpp deleted file mode 100755 index 5db7aec..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbuda.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* xbuda.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 uda (user data area) methods - -*/ - -#include "xbase.h" - - -// might need to change thisto XB_EXPRESSION_SUPPORT -#ifdef XB_EXPRESSION_SUPPORT - - -namespace xb{ - -/************************************************************************/ -xbUda::xbUda() { - llOrd. SetDupKeys( xbFalse ); -} -/************************************************************************/ -xbUda::~xbUda() {} -/************************************************************************/ -void xbUda::Clear() { - llOrd.Clear(); -} -/************************************************************************/ -xbInt16 xbUda::GetTokenCnt() const { - return llOrd.GetNodeCnt(); -} -/************************************************************************/ - -xbInt16 xbUda::GetTokenForKey( const xbString &sKey, xbString &sToken ) { - return llOrd.GetDataForKey( sKey, sToken ); -} - -/************************************************************************/ -xbInt16 xbUda::AddTokenForKey( const xbString &sKey, const xbString &sToken ) { - return llOrd.InsertKey( sKey, sToken ); -} -/************************************************************************/ - -xbInt16 xbUda::UpdTokenForKey( const xbString &sKey, const xbString &sData ) { - return llOrd.UpdateForKey( sKey, sData ); -} - -/************************************************************************/ -xbInt16 xbUda::DelTokenForKey( const xbString &sKey ) { - return llOrd.RemoveKey( sKey ); //, sToken ); -} - - -/************************************************************************/ - -void xbUda::DumpUda() const{ - - xbLinkListNode<xbString> *lln = llOrd.GetHeadNode(); - - xbInt32 l = 0; - while( lln ){ - std::cout << ++l << " Key=[" << lln->GetKey() << "] Data=[" << lln->GetData() << "]" << std::endl; - lln = lln->GetNextNode(); - } -} - -/************************************************************************/ -} /* namespace */ -#endif /* XB_EXPRESSION_SUPPORT */
\ No newline at end of file diff --git a/1Tdata/xbase/xbase64-4.1.4/src/core/xbxbase.cpp b/1Tdata/xbase/xbase64-4.1.4/src/core/xbxbase.cpp deleted file mode 100755 index 7267f98..0000000 --- a/1Tdata/xbase/xbase64-4.1.4/src/core/xbxbase.cpp +++ /dev/null @@ -1,803 +0,0 @@ -/* xbxbase.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 - -*/ - -#include "xbase.h" - -namespace xb{ - -/*************************************************************************/ -//! @brief Class Constructor. -xbXBase::xbXBase() { - SetEndianType(); - - xbFile f( this ); - f.SetHomeFolders(); - xbDate d( (xbUInt16) 1); // initialize xbDate static variables - #ifdef XB_LOGGING_SUPPORT - xLog = new xbLog(); - #endif -} -/*************************************************************************/ -//! @brief Class Deconstructor. -xbXBase::~xbXBase(){ - CloseAllTables(); - #ifdef XB_LOGGING_SUPPORT - delete xLog; - #endif -} -/*************************************************************************/ -//! @brief Close all tables / files. -/*! - This closes everything and deletes references to the associated xbDbf objects. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::CloseAllTables(){ - - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - xbInt16 iOpenTableCnt = GetOpenTableCount(); - try{ - xbDbf *d; - for( xbInt16 i = 0; i < iOpenTableCnt; i++ ){ - d = (xbDbf *) GetDbfPtr( 1 ); - if( d ){ - if(( iRc = d->Close()) != XB_NO_ERROR ){ - iErrorStop = 100; - throw iRc; - } - delete d; - } else { - iRc = XB_INVALID_OBJECT; - iErrorStop = 110; - throw iRc; - } - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbxbase::CloseAllTables() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); - WriteLogMessage( sMsg.Str() ); - WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} - -/************************************************************************/ -//! @brief Fully qualified file name from a directory, filename and extension. -/*! - Given a directory, file name and file extension as inputs, create a fully qualified file name. - - \param sDirIn Directory - \param sFileIn File Name - \param sExtIn File Extension - \param sFqnOut A fully qualifed unique file name as output - \returns XB_INVALIED_PARAMETER or XB_NO_ERROR -*/ -xbInt16 xbXBase::CreateFqn( const xbString &sDirIn, const xbString &sNameIn, const xbString &sExtIn, xbString &sFqnOut ){ - - if( sNameIn == "" || sExtIn == "" ) - return XB_INVALID_PARAMETER; - - sFqnOut = sDirIn; - #ifdef WIN32 - sFqnOut.SwapChars( '/', '\\' ); - if( sFqnOut[sFqnOut.Len()] != '\\' ) - sFqnOut += '\\'; - #else - sFqnOut.SwapChars( '\\', '/' ); - if( sFqnOut[sFqnOut.Len()] != '/' ) - sFqnOut += '/'; - #endif - sFqnOut += sNameIn; - if( sExtIn != "" ){ - sFqnOut += '.'; - sFqnOut += sExtIn; - } - return XB_NO_ERROR; -} - -/*************************************************************************/ -//! @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. -/*! - \returns Returns the fully qualified log file name. -*/ -const xbString & xbXBase::GetLogFqFileName() const { - return xLog->GetFqFileName(); -} - -//! @brief Get the log file name. -/*! - \returns Returns the log file name. -*/ -/* -const xbString & xbXBase::GetLogFileName() const { - return xLog->GetFileName(); -} -*/ - -//! @brief Get the log directory. -/*! - \returns Returns the log directory. -*/ -/* -const xbString & xbXBase::GetLogDirectory() const { - return GetLogDirectory(); -} -*/ -//! @brief Get the log directory. -/*! - \returns xbTrue - Logging enabled.<br>xbFalse - Logging disables. -*/ -xbBool xbXBase::GetLogStatus() const { - return xLog->LogGetStatus(); -} - -//! @brief Set the log file name. -/*! - \param sLogFileName - Log File Name. - \return void -*/ -/* -void xbXBase::SetLogFileName( const xbString & sLogFileName ){ - - xLog->SetFileName( sLogFileName ); -} -*/ -//! @brief Set the log directory. -/*! - \param sLogDirectory - Log File Directory. - \return void -*/ -/* -void xbXBase::SetLogDirectory( const xbString & sLogDirectory ){ - xLog->SetDirectory( sLogDirectory ); -} -*/ - - -//! @brief Set the logfile size. -/*! - \param lSize - Log File Size. - \return void -*/ -void xbXBase::SetLogSize( size_t lSize ) { - xLog->LogSetLogSize( lSize ); -} - -//! @brief Get the logfile size. -/*! - \return log file size -*/ -size_t xbXBase::GetLogSize() const { - return xLog->LogGetLogSize(); -} - - -//! @brief Write message to logfile. -/*! - \param sLogMessage - Message to write. - \param iOpt 0 = stdout<br> - 1 = Syslog<br> - 2 = Both<br> - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbXBase::WriteLogMessage( const xbString & sLogMessage, xbInt16 iOpt ){ - return xLog->LogWrite( sLogMessage, iOpt ); -} - -//! @brief Write message to logfile. -/*! - \param lCnt - Number of bytes to write. - \param p - Pointer to bytes to write to log file. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ -xbInt16 xbXBase::WriteLogBytes( xbUInt32 lCnt, const char *p ){ - return xLog->LogWriteBytes( lCnt, p ); -} - -//! @brief Enable message logging. -void xbXBase::EnableMsgLogging() { - xLog->LogSetStatus( xbTrue ); -} - -//! @brief Disable message logging. -void xbXBase::DisableMsgLogging() { - xLog->LogSetStatus( xbFalse ); -} - -//! @brief Flush log file updates to disk. -xbInt16 xbXBase::FlushLog() { - return xLog->xbFflush(); -} -#else - -// if logging not compiled in, these stubs are called with no effect -const xbString & xbXBase::GetLogFqFileName() const { - return sNullString; -} -/* -const xbString & xbXBase::GetLogFileName() const { - return sNullString; -} -const xbString & xbXBase::GetLogDirectory() const { - return sNullString; -} -*/ -/* -void xbXBase::SetLogFileName( const xbString & sLogFileName ){ - return; -} -void xbXBase::SetLogDirectory( const xbString & sLogDirectory ){ - return; -} -*/ -xbBool xbXBase::GetLogStatus() const { - return xbFalse; -} -xbInt16 xbXBase::WriteLogMessage( const xbString & sLogMessage, xbInt16 ){ - return XB_NO_ERROR; -} -xbInt16 xbXBase::WriteLogBytes( xbUInt32 lCnt, const char *p ){ - return XB_NO_ERROR; -} -void xbXBase::EnableMsgLogging() { - return; -} -void xbXBase::DisableMsgLogging() { - return; -} -xbInt16 xbXBase::FlushLog() { - return XB_NO_ERROR; -} -void xbXBase::SetLogSize( size_t lSize ) { - return; -} - -#endif // XB_LOGGING_SUPPORT - -/*************************************************************************/ -#ifdef XB_FUNCTION_SUPPORT - -//! @brief Get information regarding expression functions. -/*! - \param sExpLine An expression beginning with function name. - \param cReturnType Output - return type of function. - \param iCalc Used to calculate the function return value is<br> - 1 = use value specified in lReturnLenVal<br> - 2 = use length of operand specified in col 4<br> - 3 = use valued of numeric operand specified in col 4<br> - 4 = length of parm 1 * numeric value parm<br> - 5 = larger length of parm 2 or length of parm 3<br> - 6 = if two or more parms, use numeric value from second parm, otherwise use col4 value - \param lReturnLenVal Used in combination with iReturnLenCalc. - \returns <a href="xbretcod_8h.html">Return Codes</a> -*/ - -xbInt16 xbXBase::GetFunctionInfo( const xbString &sExpLine, char &cReturnType, xbInt16 &iCalc, xbInt32 &lReturnLenVal ) const{ - - xbUInt32 iLen; - const char *s; - if( sExpLine.Len() == 0 ) - return XB_INVALID_FUNCTION; - - s = sExpLine; - iLen = 0; - while( *s && *s != '(' && *s != ' ' ) { s++; iLen++; } - xbString sFunction( sExpLine, iLen ); - cReturnType = 0x00; - char cFunc1 = sFunction[1]; - - if( cFunc1 < 'L' ){ - // std::cout << "less than L\n"; - if( cFunc1 < 'D' ){ - // std::cout << "less than D\n"; - if( sFunction == "ABS" ){ - // { "ABS", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "ALLTRIM" ){ - // { "ALLTRIM", 'C', 2, 1 }, - cReturnType = 'C'; - iCalc = 2; - lReturnLenVal = 1; - } else if( sFunction == "ASC" ){ - // { "ASC", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "AT" ){ - // { "AT", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "CDOW" ){ - // { "CDOW", 'C', 1, 9 }, - cReturnType = 'C'; - iCalc = 1; - lReturnLenVal = 9; - } else if( sFunction == "CHR" ){ - // { "CHR", 'C', 1, 1 }, - cReturnType = 'C'; - iCalc = 1; - lReturnLenVal = 1; - } else if( sFunction == "CMONTH" ){ - // { "CMONTH", 'C', 1, 9 }, - cReturnType = 'C'; - iCalc = 1; - lReturnLenVal = 9; - } else if( sFunction == "CTOD" ){ - // { "CTOD", 'D', 1, 8 }, - cReturnType = 'D'; - iCalc = 1; - lReturnLenVal = 8; - } - } else { - // std::cout << ">= D\n"; - if( sFunction == "DATE" ){ - // { "DATE", 'D', 1, 8 }, - cReturnType = 'D'; - iCalc = 1; - lReturnLenVal = 8; - } else if( sFunction == "DAY" ){ - // { "DAY", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "DEL" ){ - // { "DEL", 'C', 1, 1 }, - cReturnType = 'C'; - iCalc = 1; - lReturnLenVal = 1; - } else if( sFunction == "DELETED" ){ - // { "DELETED", 'L', 1, 1 }, - cReturnType = 'L'; - iCalc = 1; - lReturnLenVal = 1; - } else if( sFunction == "DESCEND" ){ - // { "DESCEND", '1', 2, 1 }, - cReturnType = '1'; - iCalc = 2; - lReturnLenVal = 1; - } else if( sFunction == "DOW" ){ - // { "DOW", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "DTOC" ){ - // { "DTOC", 'C', 1, 8 }, - cReturnType = 'C'; - iCalc = 1; - lReturnLenVal = 8; - } else if( sFunction == "DTOS" ){ - // { "DTOS", 'C', 1, 8 }, - cReturnType = 'C'; - iCalc = 1; - lReturnLenVal = 8; - } else if( sFunction == "EXP" ){ - // { "EXP", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "IIF" ){ - // { "IIF", 'C', 5, 0 }, - cReturnType = 'C'; - iCalc = 5; - lReturnLenVal = 0; - } else if( sFunction == "INT" ){ - // { "INT", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "ISALPHA" ){ - // { "ISALPHA", 'L', 1, 1 }, - cReturnType = 'L'; - iCalc = 1; - lReturnLenVal = 1; - } else if( sFunction == "ISLOWER" ){ - // { "ISLOWER", 'L', 1, 1 }, - cReturnType = 'L'; - iCalc = 1; - lReturnLenVal = 1; - } else if( sFunction == "ISUPPER" ){ - // { "ISUPPER", 'L', 1, 1 }, - cReturnType = 'L'; - iCalc = 1; - lReturnLenVal = 1; - } - } - } else { - // std::cout << ">= L\n"; - if( cFunc1 < 'R' ) { - // std::cout << " < R\n"; - if( sFunction == "LEFT" ){ - // { "LEFT", 'C', 3, 2 }, - cReturnType = 'C'; - iCalc = 3; - lReturnLenVal = 2; - } else if( sFunction == "LEN" ){ - // { "LEN", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 3; - } else if( sFunction == "LOG" ){ - // { "LOG", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "LOWER" ){ - // { "LOWER", 'C', 2, 1 }, - cReturnType = 'C'; - iCalc = 2; - lReturnLenVal = 1; - } else if( sFunction == "LTRIM" ){ - // { "LTRIM", 'C', 2, 1 }, - cReturnType = 'C'; - iCalc = 2; - lReturnLenVal = 1; - } else if( sFunction == "MAX" ){ - // { "MAX", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "MIN" ){ - // { "MIN", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "MONTH" ){ - // { "MONTH", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } - } else if( cFunc1 == 'R' ){ - // std::cout << "==R\n"; - if( sFunction == "RECNO" ){ - // { "RECNO", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "RECCOUNT" ){ - // { "RECCOUNT", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "REPLICATE" ){ - // { "REPLICATE", 'C', 4, 0 }, - cReturnType = 'C'; - iCalc = 4; - lReturnLenVal = 0; - } else if( sFunction == "RIGHT" ){ - // { "RIGHT", 'C', 3, 2 }, - cReturnType = 'C'; - iCalc = 3; - lReturnLenVal = 2; - } else if( sFunction == "RTRIM" ){ - // { "RTRIM", 'C', 2, 1 }, - cReturnType = 'C'; - iCalc = 2; - lReturnLenVal = 1; - } - } else if( cFunc1 == 'S' ){ - // std::cout << "==S\n"; - if( sFunction == "SPACE" ){ - // { "SPACE", 'C', 3, 1 }, - cReturnType = 'C'; - iCalc = 3; - lReturnLenVal = 1; - } else if( sFunction == "SQRT" ){ - // { "SQRT", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } else if( sFunction == "STOD" ){ - // { "STOD", 'D', 1, 8 }, - cReturnType = 'D'; - iCalc = 1; - lReturnLenVal = 8; - } else if( sFunction == "STR" ){ - // { "STR", 'C', 6, 10 }, - cReturnType = 'C'; - iCalc = 6; - lReturnLenVal = 10; - } else if( sFunction == "STRZERO" ){ - // { "STRZERO", 'C', 3, 2 }, - cReturnType = 'C'; - iCalc = 3; - lReturnLenVal = 2; - } else if( sFunction == "SUBSTR" ){ - // { "SUBSTR", 'C', 3, 3 }, - cReturnType = 'C'; - iCalc = 3; - lReturnLenVal = 3; - } - } else { - // std::cout << ">S\n"; - if( sFunction == "TRIM" ){ - // { "TRIM", 'C', 2, 1 }, - cReturnType = 'C'; - iCalc = 2; - lReturnLenVal = 1; - } else if( sFunction == "UPPER" ){ - // { "UPPER", 'C', 2, 1 }, - cReturnType = 'C'; - iCalc = 2; - lReturnLenVal = 1; - } else if( sFunction == "VAL" ){ - // { "VAL", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 3; - } else if( sFunction == "YEAR" ){ - // { "YEAR", 'N', 1, 4 }, - cReturnType = 'N'; - iCalc = 1; - lReturnLenVal = 4; - } - } - } - if( cReturnType == 0x00 ) - return XB_INVALID_FUNCTION; - else - return XB_NO_ERROR; -} -#endif -/*************************************************************************/ -//! @brief Cross platform sleep function. -/*! - \param lMillisecs Milliseconds to sleep. -*/ -void xbXBase::xbSleep( xbInt32 lMillisecs ){ - #ifdef WIN32 - Sleep( (xbUInt32) lMillisecs ); - #else - usleep( (xbInt64) lMillisecs * 1000 ); - #endif - -} -/***********************************************************************/ -//! @brief Cross memcmp function. -/*! - \param s1 Left operand to compare. - \param s2 Right operand to compare. - \param n Number of bytes to compare. - \returns 1 s1 > s2<br> - 0 s1 == s2<br> - -1 s1 < s2 -*/ -xbInt16 xbXBase::xbMemcmp( const unsigned char *s1, const unsigned char *s2, size_t n ){ - // The standard memcmp function was found not to behave the same across all platforms - for( size_t i = 0; i < n; i++ ){ - if( s1[i] > s2[i] ) - return 1; - else if( s1[i] < s2[i] ) - return -1; - } - return 0; -} - -/***********************************************************************/ -//! @brief Open highest qualified class available for dbf file. -/*! - This routine opens the highest available version of the dbf file. - Defaults to XB_READ_WRITE and XB_MULTI_USER mode. - \returns param dbf - Output pointer to dbf file opened or null if error -*/ -xbDbf* xbXBase::Open( const xbString &sTableName, xbInt16 &iRc ){ - return Open( sTableName, "", XB_READ_WRITE, XB_MULTI_USER, 0, iRc ); -} -/***********************************************************************/ -//! @brief Open highest qualified class available for dbf file. -/*! - This routine can open various versions of the dbf file dependent on the iVersion field - - \param sTableName - Table name to open. - \param sAlias - Optional alias name. - \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 - 3 - Version three dbf - \param iRc - Return code from open request - \returns param dbf - Output pointer to dbf file opened or null if error -*/ - - -xbDbf* xbXBase::Open( const xbString &sTableName, const xbString &sAlias, xbInt16 iOpenMode, - xbInt16 iShareMode, xbInt16 iRequestVersion, xbInt16 &iRc ){ - - xbInt16 iErrorStop = 0; - xbDbf * pDbf = 0; - iRc = 0; - xbString sFqFileName; - - try{ - - if( sTableName.Len() == 0 ){ - iErrorStop = 100; - iRc = XB_FILE_NOT_FOUND; - throw iRc; - } - xbFile *f = new xbFile(this); - f->SetFileName( sTableName ); - if(( iRc = f->FileExists( f->GetFqFileName())) != xbTrue ){ - iErrorStop = 110; - iRc = XB_FILE_NOT_FOUND; - throw iRc; - } - unsigned char cFileTypeByte; - if(( iRc = f->GetXbaseFileTypeByte( f->GetFqFileName(), cFileTypeByte )) != XB_NO_ERROR ){ - iErrorStop = 120; - throw iRc; - } - xbInt16 iTblVsn = f->DetermineXbaseTableVersion( cFileTypeByte ); - f->xbFclose(); - sFqFileName.Set( f->GetFqFileName() ); - delete f; - - if( iTblVsn == 4 && ( iRequestVersion == 0 || iRequestVersion == 4 )){ - #ifdef XB_DBF4_SUPPORT - pDbf = new xbDbf4( this ); - iRc = pDbf->Open( sFqFileName, sAlias, iOpenMode, iShareMode ); - #else - // std::cout << "Dbase IV file support not build into library. See XB_DBF4_SUPPORT" << std::endl; - iErrorStop = 130; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - #endif - } - else if( iTblVsn == 3 && ( iRequestVersion == 0 || iRequestVersion == 3 )){ - - #ifdef XB_DBF3_SUPPORT - pDbf = new xbDbf3( this ); - iRc = pDbf->Open( sFqFileName, sAlias, iOpenMode, iShareMode ); - #else - //std::cout << "Dbase III file support not build into library. See XB_DBF3_SUPPORT" << std::endl; - iErrorStop = 140; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - #endif - - } else { - iErrorStop = 150; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - } - - if( iRc != XB_NO_ERROR ){ - iErrorStop = 160; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbxbase::Open() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); - WriteLogMessage( sMsg.Str() ); - WriteLogMessage( GetErrorMessage( iRc )); - } - return pDbf; -} - -xbInt16 xbXBase::OpenHighestVersion( const xbString &sTableName, const xbString &sAlias, - xbDbf **dbf ) -{ - xbInt16 iRc = 0; - xbInt16 iErrorStop = 0; - - try{ - xbFile f(this); - if( sTableName.Len() == 0 ){ - iErrorStop = 100; - iRc = XB_FILE_NOT_FOUND; - throw iRc; - } - f.SetFileName( sTableName ); - if(( iRc = f.FileExists( f.GetFqFileName() )) != xbTrue ){ - iErrorStop = 110; - iRc = XB_FILE_NOT_FOUND; - throw iRc; - } - - unsigned char cFileTypeByte; - if(( iRc = f.GetXbaseFileTypeByte( f.GetFqFileName(), cFileTypeByte )) != XB_NO_ERROR ){ - iErrorStop = 120; - return iRc; - } - if( f.DetermineXbaseTableVersion( cFileTypeByte ) == 4 ){ - #ifdef XB_DBF4_SUPPORT - xbDbf *pwDbf = new xbDbf4( this ); - pwDbf->Open( f.GetFqFileName(), sAlias ); - *dbf = pwDbf; - pwDbf = 0; - #else - // std::cout << "Dbase IV file support not build into library. See XB_DBF4_SUPPORT" << std::endl; - iErrorStop = 130; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - #endif - - } else if( f.DetermineXbaseTableVersion( cFileTypeByte ) == 3 ){ - #ifdef XB_DBF3_SUPPORT - *dbf = new xbDbf3( this ); - #else - //std::cout << "Dbase III file support not build into library. See XB_DBF3_SUPPORT" << std::endl; - iErrorStop = 140; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - #endif - - } else { - iErrorStop = 150; - iRc = XB_FILE_TYPE_NOT_SUPPORTED; - throw iRc; - } - } - catch (xbInt16 iRc ){ - xbString sMsg; - sMsg.Sprintf( "xbxbase::OpenHighestVersion() Exception Caught. Error Stop = [%d] rc = [%d]", iErrorStop, iRc ); - WriteLogMessage( sMsg.Str() ); - WriteLogMessage( GetErrorMessage( iRc )); - } - return iRc; -} -/***********************************************************************/ -} /* namespace */ |