diff options
Diffstat (limited to 'xbase64/xbmemo.cpp')
-rwxr-xr-x | xbase64/xbmemo.cpp | 1173 |
1 files changed, 0 insertions, 1173 deletions
diff --git a/xbase64/xbmemo.cpp b/xbase64/xbmemo.cpp deleted file mode 100755 index 75956dd..0000000 --- a/xbase64/xbmemo.cpp +++ /dev/null @@ -1,1173 +0,0 @@ -/* xbmemo.cpp - - Xbase64 project source code - - This file contains the basic Xbase64 routines for handling - dBASE III+ and dBASE IV style memo .dbt files - - - Copyright (C) 1997,2003 Gary A Kunkel - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - Contact: - - Email: - - xdb-devel@lists.sourceforge.net - xdb-users@lists.sourceforge.net - - - Regular Mail: - - XBase Support - 149C South Main St - Keller Texas, 76248 - USA -*/ - -#ifdef __WIN32__ -#include <xbase64/xbwincfg.h> -#else -#include <xbase64/xbconfig.h> -#endif - -#include <xbase64/xbase64.h> -#ifdef XB_MEMO_FIELDS - -#include <stdio.h> -//#include <xbase64/xbexcept.h> - -#ifdef HAVE_IO_H -#include <io.h> -#endif - - -/*! \file xbmemo.cpp -*/ - -/************************************************************************/ -//! Short description -/*! -*/ -xbLong xbDbf::CalcLastDataBlock() -{ - if( _fseek( mfp, 0, SEEK_END ) != 0 ) - return XB_SEEK_ERROR; - return ( _ftell( mfp ) / MemoHeader.BlockSize ); -} -/************************************************************************/ -//! Short description -/*! - \param BlocksNeeded - \param Location - \param PrevNode -*/ -xbShort xbDbf::GetBlockSetFromChain( xbLong BlocksNeeded, - xbLong Location, xbLong PrevNode ) - -/* this routine grabs a set of blocks out of the free block chain */ -{ - xbShort rc; - xbLong NextFreeBlock2, NewFreeBlocks, SaveNextFreeBlock; - - if(( rc = ReadMemoBlock( Location, 2 )) != XB_NO_ERROR ) - return rc; - - if( BlocksNeeded == FreeBlockCnt ){ /* grab this whole set of blocks */ - if( PrevNode == 0 ){ /* first in the chain */ - MemoHeader.NextBlock = NextFreeBlock; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ) - return rc; - } - else /* remove out of the middle or end */ - { - NextFreeBlock2 = NextFreeBlock; - if(( rc = ReadMemoBlock( PrevNode, 2 )) != XB_NO_ERROR ) - return rc; - NextFreeBlock = NextFreeBlock2; - if(( rc = WriteMemoBlock( PrevNode, 2 )) != XB_NO_ERROR ) - return rc; - } - } - - else /* only take a portion of this set */ - { - if( PrevNode == 0 ){ /* first in the set */ - MemoHeader.NextBlock = Location + BlocksNeeded; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ) - return rc; - FreeBlockCnt -= BlocksNeeded; - if(( rc = WriteMemoBlock( MemoHeader.NextBlock, 2 )) != XB_NO_ERROR ) - return rc; - } - else /* remove out of the middle or end */ - { - NewFreeBlocks = FreeBlockCnt - BlocksNeeded; - SaveNextFreeBlock = NextFreeBlock; - NextFreeBlock2= Location + BlocksNeeded; - if(( rc = ReadMemoBlock( PrevNode, 2 )) != XB_NO_ERROR ) - return rc; - NextFreeBlock = NextFreeBlock2; - if(( rc = WriteMemoBlock( PrevNode, 2 )) != XB_NO_ERROR ) - return rc; - FreeBlockCnt = NewFreeBlocks; - NextFreeBlock = SaveNextFreeBlock; - if(( rc = WriteMemoBlock( NextFreeBlock2, 2 )) != XB_NO_ERROR ) - return rc; - } - } - return 0; -} -/************************************************************************/ -//! Short description -/*! - \param BlocksNeeded - \param LastDataBlock - \param Location - \param PreviousNode -*/ -xbShort xbDbf::FindBlockSetInChain( xbLong BlocksNeeded, - xbLong LastDataBlock, xbLong &Location, xbLong &PreviousNode ) - -/* this routine searches thru the free node chain in a dbase IV type - memo file searching for a place to grab some free blocks for reuse - - LastDataBlock- is the last data block in the file, enter 0 - for the routine to calculate it. - BlocksNeeded - is the size to look in the chain for - Location - is the location it finds - PreviousNode - is the block number of the node imediately previous - to this node in the chain - 0 if header node - returns - 0 if no spot in chain found - 1 if spot in chain is found -*/ -{ - xbShort rc; - xbLong LDB, PrevNode, CurNode; - - if( LastDataBlock == 0 ) - LDB = CalcLastDataBlock(); - else - LDB = LastDataBlock; - - if( MemoHeader.NextBlock < LDB ){ - PrevNode = 0L; - CurNode = MemoHeader.NextBlock; - if(( rc = ReadMemoBlock( MemoHeader.NextBlock, 2 )) != XB_NO_ERROR ) - return rc; - while( BlocksNeeded > FreeBlockCnt && NextFreeBlock < LDB ){ - PrevNode = CurNode; - CurNode = NextFreeBlock; - if(( rc = ReadMemoBlock( NextFreeBlock, 2 )) != XB_NO_ERROR ) - return rc; - } - if( BlocksNeeded <= FreeBlockCnt ){ - Location = CurNode; - PreviousNode = PrevNode; - return 1; - } - else{ /* no data found and at end of chain */ - PreviousNode = CurNode; - return 0; - } - } - else{ - PreviousNode = 0; - return 0; - } -} -/************************************************************************/ -//! Short description -/*! - \param BlockSize -*/ -xbShort xbDbf::SetMemoBlockSize( xbShort BlockSize ) -{ - if(IsType3Dbt()) - return XB_NO_ERROR; // not applicable for type 3 - if( BlockSize % 512 != 0 ) - return XB_INVALID_BLOCK_SIZE; - - MemoHeader.BlockSize = BlockSize; - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param Option -*/ -xbShort xbDbf::GetDbtHeader( xbShort Option ) -{ - char *p; - xbShort i; - char MemoBlock[24]; - - /* Option = 0 --> read only first four bytes - 1 --> read the entire thing */ - - if( !mfp ) - return XB_NOT_OPEN; - - if( _fseek( mfp, 0, SEEK_SET )) - return XB_SEEK_ERROR; - - if(( fread( MemoBlock, 24, 1, mfp )) != 1 ) - return XB_READ_ERROR; - - p = MemoBlock; - MemoHeader.NextBlock = xbase->GetLong( p ); - if(IsType3Dbt() || Option == 0) - return XB_NO_ERROR; - - /* version IV stuff follows */ - p+=8; - for( i = 0; i < 8; i++, p++ ) - MemoHeader.FileName[i] = *p; - MemoHeader.Version = *p; - p+=4; - MemoHeader.BlockSize = xbase->GetShort( p ); - return XB_NO_ERROR; -} - -/***********************************************************************/ -xbShort xbDbf::OpenFPTFile() -{ - if (GetFileName().len() < 3) - return XB_INVALID_NAME; - - xbShort len = GetFileName().len() - 1; - xbString ext = GetFileName().mid(len-2, 3); - MemofileName = GetFileName().mid(0, len-2); - if (ext == "DBF") - MemofileName += "FPT"; - else - if (ext = "dbf") - MemofileName += "fpt"; - else - return XB_INVALID_NAME; - if ((mfp = fopen(MemofileName, "r+b" )) == NULL){ - // - // Try to open read only if can't open read/write - // - if ((mfp = fopen(MemofileName, "rb" )) == NULL) - return XB_OPEN_ERROR; - } - char header[8]; - if ((fread(header, 8, 1, mfp)) != 1) - return XB_READ_ERROR; - - char *p = header; - MemoHeader.NextBlock = xbase->GetHBFULong(p); - p += 6; - MemoHeader.BlockSize = xbase->GetHBFShort(p); - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! -*/ -xbShort xbDbf::OpenMemoFile() -{ - if (Version == (char)0xf5 || Version == (char)0x30) - return OpenFPTFile(); - - xbShort len, rc; - xbOffT Size, NewSize, l; - MemofileName = GetFileName(); - len = GetFileName().len() - 1; - if( MemofileName[len] == 'F' ) - MemofileName.putAt(len, 'T'); - else if( MemofileName[len] == 'f' ) - MemofileName.putAt(len, 't'); - else - return XB_INVALID_NAME; - - if(( mfp = fopen( MemofileName, "r+b" )) == NULL ){ - // - // Try to open read only if can't open read/write - // - if(( mfp = fopen( MemofileName, "rb" )) == NULL ) - return XB_OPEN_ERROR; - } -#ifdef XB_LOCKING_ON - setbuf( mfp, NULL ); -#endif - if(( rc = GetDbtHeader(1)) != 0 ){ - fclose( mfp ); - return rc; - } - - len = GetMemoBlockSize(); - if( len == 0 || ((len % 512) != 0 )){ - fclose( mfp ); - return XB_INVALID_BLOCK_SIZE; - } - - /* logic to verify file size is a multiple of block size */ - if(( rc = _fseek( mfp, 0, SEEK_END )) != 0 ){ - fclose( mfp ); - return XB_SEEK_ERROR; - } - - /* if the file is not a multiple of block size, fix it, append nulls */ - Size = _ftell( mfp ); - if(( Size % MemoHeader.BlockSize ) != 0 ){ - NewSize = ( Size / MemoHeader.BlockSize + 1) * MemoHeader.BlockSize; - for( l = Size; l < NewSize; l++ ) - fputc( 0x00, mfp ); - } - - if(( mbb = (void *) malloc(len)) == NULL ){ - fclose( mfp ); - return XB_NO_MEMORY; - } - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! -*/ -xbShort xbDbf::CreateMemoFile( void ) -{ - xbShort len,i; - char *sp; - char buf[4]; - - len = GetMemoBlockSize(); - if( len == 0 || len % 512 != 0 ) - return XB_INVALID_BLOCK_SIZE; - - if(( sp = (char*)strrchr(GetFileName(), PATH_SEPARATOR)) != NULL ) - sp++; - else - sp = MemoHeader.FileName; - - memset( MemoHeader.FileName, 0x00, 8 ); - - for( i = 0; i < 8 && *sp != '.'; i++ ) - MemoHeader.FileName[i] = *sp++; - - MemofileName = GetFileName(); - - len = GetFileName().len() - 1; - if( MemofileName[len] == 'F' ) - MemofileName.putAt(len, 'T'); - else if( MemofileName[len] == 'f' ) - MemofileName.putAt(len, 't'); - else - return XB_INVALID_NAME; - - /* Initialize the variables */ - MemoHeader.NextBlock = 1L; - - if(( mfp = fopen( MemofileName, "w+b" )) == NULL ) - return XB_OPEN_ERROR; -#ifdef XB_LOCKING_ON - setbuf( mfp, NULL ); -#endif - - if(( _fseek( mfp, 0, SEEK_SET )) != 0 ){ - fclose( mfp ); - return XB_SEEK_ERROR; - } - - memset( buf, 0x00, 4 ); - xbase->PutLong( buf, MemoHeader.NextBlock ); - if(( fwrite( &buf, 4, 1, mfp )) != 1 ){ - fclose( mfp ); - return XB_WRITE_ERROR; - } - - if( IsType3Dbt() ){ /* dBASE III+ */ - for( i = 0; i < 12; i++ ) fputc( 0x00, mfp ); - fputc( 0x03, mfp ); - for( i = 0; i < 495; i++ ) fputc( 0x00, mfp ); - } - else - { - for( i = 0; i < 4; i++ ) fputc( 0x00, mfp ); - fwrite( &MemoHeader.FileName, 8, 1, mfp ); - for( i = 0; i < 4; i++ ) fputc( 0x00, mfp ); - memset( buf, 0x00, 2 ); - xbase->PutShort( buf, MemoHeader.BlockSize ); - if(( fwrite( &buf, 2, 1, mfp )) != 1 ){ - fclose( mfp ); - return XB_WRITE_ERROR; - } - for( i = 22; i < MemoHeader.BlockSize; i++ ) fputc( 0x00, mfp ); - } - - if(( mbb = (void *) malloc( MemoHeader.BlockSize )) == NULL ){ - fclose( mfp ); - return XB_NO_MEMORY; - } - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param BlockNo - \param Option -*/ - -/* Option = 0 - 1st Block of a set of valid data blocks, load buckets */ -/* Option = 1 - subsequant block of data in a multi block set or db III*/ -/* Option = 2 - 1st block of a set of free blocks, load buckets */ -/* Option = 3 - read 8 bytes of a block, don't load any buckets */ -/* Option = 4 - read 8 bytes of a block, load data buckets */ - -xbShort xbDbf::ReadMemoBlock( xbLong BlockNo, xbShort Option ) -{ - size_t ReadSize; - CurMemoBlockNo = -1; - - if( BlockNo < 1L ) - return XB_INVALID_BLOCK_NO; - - if( _fseek( mfp,((xbOffT)BlockNo*MemoHeader.BlockSize), SEEK_SET )) - return XB_SEEK_ERROR; - - - if( Option == 0 || Option == 1 ) - ReadSize = MemoHeader.BlockSize; - else - ReadSize = 8L; - - if(fread( mbb, ReadSize, 1, mfp ) != 1 ) - return XB_READ_ERROR; - - if( Option == 0 || Option == 4){ // 1st block of a set of valid data blocks - mfield1 = xbase->GetShort( (char *) mbb ); - MStartPos = xbase->GetShort( (char *) mbb+2 ); - MFieldLen = xbase->GetLong ( (char *) mbb+4 ); - } - else if( Option == 2 ){ // 1st block of a set of free blocks - NextFreeBlock = xbase->GetLong( (char *) mbb ); - FreeBlockCnt = xbase->GetLong( (char *) mbb+4 ); - } - - if( Option == 0 || Option == 1 ) - CurMemoBlockNo = BlockNo; - - return XB_NO_ERROR; -} -/************************************************************************/ -//! Short description -/*! - \param BlockNo - \param Option -*/ -xbShort xbDbf::WriteMemoBlock( xbLong BlockNo, xbShort Option ) -{ -/* Option = 0 - 1st Block of a set of valid data blocks, set buckets */ -/* Option = 1 - subsequant block of data in a multi block set or db III */ -/* Option = 2 - 1st block of a set offree blocks, set buckets */ - - xbLong WriteSize; - - if( BlockNo < 1L ) - return XB_INVALID_BLOCK_NO; - - CurMemoBlockNo = -1; - - if( Option == 0 ){ - xbase->PutShort( (char *) mbb, mfield1 ); - xbase->PutShort( (char *) mbb+2, MStartPos ); - xbase->PutLong ( (char *) mbb+4, MFieldLen ); - WriteSize = MemoHeader.BlockSize; - } - else if( Option == 2 ){ - xbase->PutLong((char *) mbb, NextFreeBlock ); - xbase->PutLong((char *) mbb+4, FreeBlockCnt ); - WriteSize = 8L; - } - else - WriteSize = MemoHeader.BlockSize; - - if( _fseek( mfp,((xbOffT)BlockNo*MemoHeader.BlockSize), SEEK_SET )) - return XB_SEEK_ERROR; - - if(( fwrite( mbb, WriteSize, 1, mfp )) != 1 ) - return XB_WRITE_ERROR; - - if( Option == 0 || Option == 1 ) - CurMemoBlockNo = BlockNo; - - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo - \param len - \param Buf - \param LockOpt -*/ -xbShort xbDbf::GetFPTField(xbShort FieldNo, xbLong len, - char * Buf, xbShort LockOpt) { - - if (FieldNo < 0 || FieldNo > (NoOfFields - 1)) - return XB_INVALID_FIELDNO; - - if (GetFieldType(FieldNo) != 'M') - return XB_NOT_MEMO_FIELD; - -#ifdef XB_LOCKING_ON -// if( LockOpt != -1 ) -// if( LockMemoFile( XB_LOCK ) != XB_NO_ERROR ) -// return XB_LOCK_FAILED; -#endif - - xbLong BlockNo; - char buf[18]; - - if( Version == (char)0x30 ) { - memset( buf, 0x00, 18 ) ; - GetField( FieldNo, buf ); - BlockNo = xbase->GetLong((char*) buf); - } else { - BlockNo = GetLongField(FieldNo); - } - - if ( BlockNo == 0L ) - return 0L; - - // Seek to start_of_block + 4 - - -// FIXME LOCK - -#ifdef XB_LOCKING_ON -// try { -#endif - if (_fseek(mfp, ((xbOffT)BlockNo * MemoHeader.BlockSize + 4), SEEK_SET) != 0) - return XB_SEEK_ERROR; - char h[4]; - if ((fread(h, 4, 1, mfp)) != 1) - return XB_READ_ERROR; - - xbULong fLen = xbase->GetHBFULong(h); - - xbULong l = (fLen < (xbULong)len) ? fLen : len; - if ((fread(Buf, l, 1, mfp)) != 1) - return XB_READ_ERROR; - Buf[l]=0; -#ifdef XB_LOCKING_ON -// } -// catch (...) { -// if (LockOpt != -1) -// LockMemoFile( XB_UNLOCK ); -// throw; -// } -#endif - -#ifdef XB_LOCKING_ON -// if (LockOpt != -1) -// LockMemoFile( XB_UNLOCK ); -#endif - - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo - \param len - \param Buf - \param LockOpt -*/ -xbShort xbDbf::GetMemoField( xbShort FieldNo, xbLong len, - char * Buf, xbShort LockOpt ) -{ - if( Version == (char)0xf5 || Version == (char)0x30 ) - return GetFPTField(FieldNo, len, Buf, LockOpt); - - xbLong BlockNo, Tcnt, Scnt; - char *tp, *sp; /* target and source pointers */ - xbShort rc; - xbShort Vswitch; - xbLong MemoLen; - - if( FieldNo < 0 || FieldNo > ( NoOfFields - 1 )) - return XB_INVALID_FIELDNO; - - if( GetFieldType( FieldNo ) != 'M' ) - return XB_NOT_MEMO_FIELD; - -#ifdef XB_LOCKING_ON -// if( LockOpt != -1 ) -// if(( rc = LockMemoFile( LockOpt, XB_LOCK )) != XB_NO_ERROR ) -// return XB_LOCK_FAILED; -#endif - - if(( BlockNo = GetLongField( FieldNo )) == 0 ){ -#ifdef XB_LOCKING_ON -// if( LockOpt != -1 ) -// LockMemoFile( XB_UNLOCK ); -#endif - return XB_NO_MEMO_DATA; - } - - if( IsType3Dbt() ) - Vswitch = 1; - else - Vswitch = 0; - - if(( rc = ReadMemoBlock( BlockNo, Vswitch )) != 0 ){ -#ifdef XB_LOCKING_ON -// if( LockOpt != -1 ) -// LockMemoFile( XB_UNLOCK ); -#endif - return rc; - } - - tp = Buf; - sp = (char *) mbb; - - if( IsType4Dbt() ){ - sp+=8; - Scnt = 8L; - } - else - Scnt = 0L; - - Tcnt = 0L; - MemoLen = GetMemoFieldLen( FieldNo ); - while( Tcnt < len && Tcnt < MemoLen ){ - *tp++ = *sp++; - Scnt++; - Tcnt++; - if( Scnt >= MemoHeader.BlockSize ){ - BlockNo++; - if(( rc = ReadMemoBlock( BlockNo, 1 )) != 0 ) - return rc; - Scnt = 0; - sp = (char *) mbb; - } - } -#ifdef XB_LOCKING_ON - //if( LockOpt != -1 ) -// LockMemoFile( XB_LOCK ); -#endif - - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo -*/ -xbLong xbDbf::GetFPTFieldLen( xbShort FieldNo ) -{ - xbLong BlockNo; - if(( BlockNo = GetLongField(FieldNo)) == 0L ) - return 0L; - // Seek to start_of_block + 4 - if(_fseek(mfp, ((xbOffT)BlockNo * MemoHeader.BlockSize + 4), SEEK_SET) != 0) - return XB_SEEK_ERROR; - char h[4]; - if((fread(h, 4, 1, mfp)) != 1) - return XB_READ_ERROR; - - return xbase->GetHBFULong(h); -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo -*/ -xbLong xbDbf::GetMemoFieldLen( xbShort FieldNo ) { - if (Version == (char)0xf5 || Version == (char)0x30 ) - return GetFPTFieldLen(FieldNo); - - xbLong BlockNo, ByteCnt; - xbShort scnt, NotDone; - char *sp, *spp; - - if(( BlockNo = GetLongField( FieldNo )) == 0L ) - return 0L; - - if( IsType4Dbt()){ /* dBASE IV */ - if( BlockNo == CurMemoBlockNo && CurMemoBlockNo != -1 ) - return MFieldLen - MStartPos; - if( ReadMemoBlock( BlockNo, 0 ) != XB_NO_ERROR ) - return 0L; - return MFieldLen - MStartPos; - } else { /* version 0x03 dBASE III+ */ - ByteCnt = 0L; - spp = NULL; - NotDone = 1; - while( NotDone ){ - if( ReadMemoBlock( BlockNo++, 1 ) != XB_NO_ERROR ) - return 0L; - scnt = 0; - sp = (char *) mbb; - while( scnt < 512 && NotDone ){ - if( *sp == 0x1a && *spp == 0x1a ) - NotDone = 0; - else{ - ByteCnt++; scnt++; spp = sp; sp++; - } - } - } - if( ByteCnt > 0 ) ByteCnt--; - return ByteCnt; - } -} -/***********************************************************************/ -//! Short description -/*! -*/ -xbShort xbDbf::MemoFieldsPresent() const -{ - xbShort i; - for( i = 0; i < NoOfFields; i++ ) - if( GetFieldType( i ) == 'M' ) - return 1; - - return 0; -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo -*/ -xbShort xbDbf::DeleteMemoField( xbShort FieldNo ) -{ - xbLong SBlockNo, SNoOfBlocks, SNextBlock; - xbLong LastFreeBlock, LastFreeBlockCnt, LastDataBlock; - xbShort rc; - - NextFreeBlock = 0L; - LastFreeBlockCnt = 0L; - LastFreeBlock = 0L; - - if( IsType3Dbt() ){ /* type III */ - PutField( FieldNo, " " ); - return XB_NO_ERROR; - } - - /* Get Block Number */ - if(( SBlockNo = GetLongField( FieldNo )) == 0 ) - return XB_INVALID_BLOCK_NO; - - /* Load the first block */ - - if(( rc = ReadMemoBlock( SBlockNo, 4 )) != XB_NO_ERROR ) - return rc; - - if( (MFieldLen+2) % MemoHeader.BlockSize ) - SNoOfBlocks = (MFieldLen+2)/MemoHeader.BlockSize+1L; - else - SNoOfBlocks = (MFieldLen+2)/MemoHeader.BlockSize; - - /* Determine last good data block */ - LastDataBlock = CalcLastDataBlock(); - - /* position to correct location in chain */ - NextFreeBlock = MemoHeader.NextBlock; - while( SBlockNo > NextFreeBlock && SBlockNo < LastDataBlock ){ - LastFreeBlock = NextFreeBlock; - if(( rc = ReadMemoBlock( NextFreeBlock, 2 )) != XB_NO_ERROR ) - return rc; - LastFreeBlockCnt = FreeBlockCnt; - } - - - /* if next block should be concatonated onto the end of this set */ - - if((SBlockNo+SNoOfBlocks) == NextFreeBlock && NextFreeBlock < LastDataBlock ) - { - if(( rc = ReadMemoBlock( NextFreeBlock, 2 )) != XB_NO_ERROR ) - return XB_NO_ERROR; - SNoOfBlocks += FreeBlockCnt; - SNextBlock = NextFreeBlock; - } else if( LastFreeBlock == 0L ) - SNextBlock = MemoHeader.NextBlock; - else - SNextBlock = NextFreeBlock; - - /* if this is the first set of free blocks */ - if( LastFreeBlock == 0L ){ - /* 1 - write out the current block */ - /* 2 - update header block */ - /* 3 - write header block */ - /* 4 - update data field */ - - NextFreeBlock = SNextBlock; - FreeBlockCnt = SNoOfBlocks; - if(( rc = WriteMemoBlock( SBlockNo, 2 )) != XB_NO_ERROR ) - return rc; - - MemoHeader.NextBlock = SBlockNo; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ) - return rc; - PutField( FieldNo, " " ); - return XB_NO_ERROR; - } - -/* determine if this block set should be added to the previous set */ - - if(( LastFreeBlockCnt + LastFreeBlock ) == SBlockNo ){ - if(( rc = ReadMemoBlock( LastFreeBlock, 2 )) != XB_NO_ERROR ) - return rc; - NextFreeBlock = SNextBlock; - FreeBlockCnt += SNoOfBlocks; - if(( rc = WriteMemoBlock( LastFreeBlock, 2 )) != XB_NO_ERROR ) - return rc; - PutField( FieldNo, " " ); - 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 */ - - FreeBlockCnt = SNoOfBlocks; - if(( rc = WriteMemoBlock( SBlockNo, 2 )) != XB_NO_ERROR ) - return rc; - if(( rc = ReadMemoBlock( LastFreeBlock, 2 )) != XB_NO_ERROR ) - return rc; - NextFreeBlock = SBlockNo; - if(( rc = WriteMemoBlock( LastFreeBlock, 2 )) != XB_NO_ERROR ) - return rc; - PutField( FieldNo, " " ); - - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo - \param DataLen - \param Buf -*/ - -xbShort xbDbf::AddMemoData( xbShort FieldNo, xbLong DataLen, - const char * Buf ) -{ - xbShort rc; - xbLong BlocksNeeded, LastDataBlock; - xbLong PrevNode, HeadBlock; - xbLong TotalLen; /* total length of needed area for memo field */ - - TotalLen = DataLen+2; - LastDataBlock = CalcLastDataBlock(); - - if( IsType3Dbt() || /* always append to end */ - ( LastDataBlock == MemoHeader.NextBlock )){ /* no free space */ - if( TotalLen % MemoHeader.BlockSize ) - BlocksNeeded = TotalLen / MemoHeader.BlockSize + 1; - else - BlocksNeeded = TotalLen / MemoHeader.BlockSize; - - MemoHeader.NextBlock = LastDataBlock + BlocksNeeded; /* reset to eof */ - if(( rc = PutMemoData( LastDataBlock, BlocksNeeded, DataLen, Buf )) - != XB_NO_ERROR ) - return rc; - HeadBlock = LastDataBlock; - if(( rc = UpdateHeadNextNode()) != XB_NO_ERROR ) - return rc; - }else{ - TotalLen += 8; - if( TotalLen % MemoHeader.BlockSize ) - BlocksNeeded = TotalLen / MemoHeader.BlockSize + 1; - else - BlocksNeeded = TotalLen / MemoHeader.BlockSize; - - if(( rc = FindBlockSetInChain( BlocksNeeded, LastDataBlock, - HeadBlock, PrevNode )) == 1 ){ - if(( rc = GetBlockSetFromChain( BlocksNeeded, HeadBlock, PrevNode )) - != XB_NO_ERROR ) - return rc; - if(( rc = PutMemoData( HeadBlock, BlocksNeeded, DataLen, Buf )) - != XB_NO_ERROR ) - return rc; - } else { /* append to the end */ - /* if header block needed updated, already done by here */ - if(( rc = PutMemoData( LastDataBlock, BlocksNeeded, DataLen, Buf )) - != XB_NO_ERROR ) - return rc; - HeadBlock = LastDataBlock; - if(( rc = ReadMemoBlock( PrevNode, 2 )) != XB_NO_ERROR ) - return rc; - NextFreeBlock += BlocksNeeded; - if(( rc = WriteMemoBlock( PrevNode, 2 )) != XB_NO_ERROR ) - return rc; - } - } - PutLongField( FieldNo, HeadBlock ); - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! -*/ -xbShort xbDbf::UpdateHeadNextNode() const -{ - char buf[4]; - memset( buf, 0x00, 4 ); - xbase->PutLong( buf, MemoHeader.NextBlock ); - if(( _fseek( mfp, 0, SEEK_SET )) != 0 ) - return XB_SEEK_ERROR; - - if(( fwrite( &buf, 4, 1, mfp )) != 1 ) - return XB_WRITE_ERROR; - - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param StartBlock First block to write - \param BlocksNeeded Total number of blocks needed - \param DataLen Length of data to write - \param Buf Actual data -*/ -xbShort xbDbf::PutMemoData( xbLong StartBlock, xbLong BlocksNeeded, - xbLong DataLen, const char *Buf ) -{ - xbShort i, rc, Tctr; - xbShort BytesProcessed; // bytes processed so far - xbShort TotalLen; // total length of data - xbLong CurBlock; - char *tp; - const char *sp; - - TotalLen = DataLen + 2; - CurBlock = StartBlock; - memset( (char *) mbb, 0x00, MemoHeader.BlockSize ); - tp = (char *) mbb; - sp = Buf; - BytesProcessed = 0; /* total length processed */ - - - if( IsType3Dbt() ) - Tctr = 0; - else{ /* dBASE IV */ - tp += 8; - Tctr = 8; - } - - for( i = 0; i < BlocksNeeded; i++ ){ - while( Tctr < MemoHeader.BlockSize && BytesProcessed < TotalLen ){ - if( BytesProcessed >= DataLen ) - *tp++ = 0x1a; /* end of data marker */ - else - *tp++ = *sp++; /* copy data to memo block buffer */ - Tctr++; - BytesProcessed++; - } - - /* if incomplete block, finish it out with 0x00 */ - while( Tctr++ < MemoHeader.BlockSize ) - *tp++ = 0x00; - - if( i == 0 && IsType4Dbt() ){ - mfield1 = -1; - MStartPos = 8; - MFieldLen = DataLen + MStartPos; - if(( rc = WriteMemoBlock( CurBlock++, 0 )) != XB_NO_ERROR ) - return rc; - } else { - if(( rc = WriteMemoBlock( CurBlock++, 1 )) != XB_NO_ERROR ) - return rc; - } - Tctr = 0; - tp = (char *) mbb; - } - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo - \param DataLen - \param Buf - \param LockOpt -*/ -xbShort xbDbf::UpdateMemoData( xbShort FieldNo, xbLong DataLen, - const char * Buf, xbShort LockOpt ) -{ - xbShort rc; - xbLong TotalLen; - xbLong BlocksNeeded, BlocksAvailable; - - #ifdef XB_LOCKING_ON - if( LockOpt != -1 ) -// if(( rc = LockMemoFile( XB_LOCK )) != XB_NO_ERROR ) -// return XB_LOCK_FAILED; - #endif - - if( DataLen ){ - TotalLen = DataLen + 2; // add 2 eod 0x1a chars - if( IsType4Dbt()) TotalLen += 8; // leading fields for dbase iv - } - else - TotalLen = 0; - - if( DataLen == 0L ){ /* handle delete */ - if( MemoFieldExists( FieldNo )){ - if(( rc = DeleteMemoField( FieldNo )) != XB_NO_ERROR ){ - #ifdef XB_LOCKING_ON -// LockMemoFile( XB_UNLOCK ); - #endif - return rc; - } - } - } else if((IsType3Dbt() || GetMemoFieldLen(FieldNo)==0L)){ - if(( rc = AddMemoData( FieldNo, DataLen, Buf )) != XB_NO_ERROR ){ - #ifdef XB_LOCKING_ON -// LockMemoFile( XB_UNLOCK ); - #endif - return rc; - } - } else { /* version IV type files, reuse unused space */ - if( TotalLen % MemoHeader.BlockSize ) - BlocksNeeded = TotalLen / MemoHeader.BlockSize + 1; - else - BlocksNeeded = TotalLen / MemoHeader.BlockSize; - - if(( rc = ReadMemoBlock( GetLongField( FieldNo ), 4 )) != XB_NO_ERROR ){ - #ifdef XB_LOCKING_ON -// LockMemoFile( XB_UNLOCK ); - #endif - return rc; - } - - if( (MFieldLen+2) % MemoHeader.BlockSize ) - BlocksAvailable = (MFieldLen+2) / MemoHeader.BlockSize + 1; - else - BlocksAvailable = (MFieldLen+2) / MemoHeader.BlockSize; - - if( BlocksNeeded == BlocksAvailable ){ - if(( rc = PutMemoData( GetLongField( FieldNo ), BlocksNeeded, - DataLen, Buf )) != XB_NO_ERROR ){ - #ifdef XB_LOCKING_ON -// LockMemoFile( XB_UNLOCK ); - #endif - return rc; - } - } else { - if(( rc = DeleteMemoField( FieldNo )) != XB_NO_ERROR ){ - #ifdef XB_LOCKING_ON -// LockMemoFile( XB_UNLOCK ); - #endif - return rc; - } - if(( rc = AddMemoData( FieldNo, DataLen, Buf )) != XB_NO_ERROR ){ - #ifdef XB_LOCKING_ON -// LockMemoFile( XB_UNLOCK ); - #endif - return rc; - } - } - } - - - #ifdef XB_LOCKING_ON -// if( LockOpt != -1 ) -// if(( rc = LockMemoFile( XB_UNLOCK )) != XB_NO_ERROR ) -// return XB_LOCK_FAILED; - #endif - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! - \param FieldNo -*/ -xbShort xbDbf::MemoFieldExists( xbShort FieldNo ) const -{ - if( GetLongField( FieldNo ) == 0L ) - return 0; - else - return 1; -} -/***********************************************************************/ -//! Short description -/*! -*/ -#ifdef XBASE_DEBUG -void xbDbf::DumpMemoHeader() const -{ - xbShort i; - std::cout << "\n*********************************"; - std::cout << "\nMemo header data..."; - std::cout << "\nNext Block " << MemoHeader.NextBlock; - if( IsType4Dbt() ){ - std::cout << "\nFilename "; - for( i = 0; i < 8; i++ ) - std::cout << MemoHeader.FileName[i]; - } - std::cout << "\nBlocksize " << MemoHeader.BlockSize; - return; -} -/***********************************************************************/ -//! Short description -/*! -*/ -xbShort xbDbf::DumpMemoFreeChain() -{ - xbShort rc; - xbLong CurBlock, LastDataBlock; - - if(( rc = GetDbtHeader(1)) != XB_NO_ERROR ) - return rc; - LastDataBlock = CalcLastDataBlock(); - CurBlock = MemoHeader.NextBlock; - std::cout << "Total blocks in file = " << LastDataBlock << std::endl; - std::cout << "Head Next Block = " << CurBlock << std::endl;; - while( CurBlock < LastDataBlock ){ - if(( rc = ReadMemoBlock( CurBlock, 2 )) != XB_NO_ERROR ) - return rc; - std::cout << "**********************************" << std::endl; - std::cout << "This Block = " << CurBlock << std::endl; - std::cout << "Next Block = " << NextFreeBlock << std::endl; - std::cout << "No Of Blocks = " << FreeBlockCnt << std::endl; - CurBlock = NextFreeBlock; - } - return XB_NO_ERROR; -} -/***********************************************************************/ -//! Short description -/*! -*/ -void xbDbf::DumpMemoBlock() const -{ - xbShort i; - char *p; - p = (char *) mbb; - if( IsType3Dbt() ){ - for( i = 0; i < 512; i++ ) - std::cout << *p++; - } else { - std::cout << "\nField1 => " << mfield1; - std::cout << "\nStart Pos => " << MStartPos; - std::cout << "\nField Len => " << MFieldLen; - std::cout << "\nBlock data => "; - p += 8; - for( i = 8; i < MemoHeader.BlockSize; i++ ) - std::cout << *p++; - } - return; -} -#endif /* XBASE_DEBUG */ -#endif /* MEMO_FIELD */ |