diff options
Diffstat (limited to 'src/core/xbmemo3.cpp')
-rwxr-xr-x | src/core/xbmemo3.cpp | 575 |
1 files changed, 0 insertions, 575 deletions
diff --git a/src/core/xbmemo3.cpp b/src/core/xbmemo3.cpp deleted file mode 100755 index 60c1d53..0000000 --- a/src/core/xbmemo3.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/* xbmemo3.cpp - -XBase64 Software Library - -Copyright (c) 1997,2003,2014,2022 Gary A Kunkel - -The xb64 software library is covered under the terms of the GPL Version 3, 2007 license. - -Email Contact: - - XDB-devel@lists.sourceforge.net - XDB-users@lists.sourceforge.net - - 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 ){ - 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 */ |