summaryrefslogtreecommitdiff
path: root/xbase64/xbmemo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbase64/xbmemo.cpp')
-rwxr-xr-xxbase64/xbmemo.cpp1173
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 */