📄 memo.cpp
字号:
if(( rc = ReadMemoBlock( BlockNo, Vswitch )) != 0 ) {#ifdef XB_LOCKING_ON if( LockOpt != -1 ) LockMemoFile( F_SETLK, F_UNLCK );#endif return rc; } tp = Buf; sp = (char *) mbb; if( IsType4Dbt() ) { sp+=8; Scnt = 8L; } else Scnt = 0L; Tcnt = 0L; while( Tcnt < len ) { *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( F_SETLK, F_UNLCK );#endif return XB_NO_ERROR;}/***********************************************************************///! Short description/*! \param FieldNo*/xbLong xbDbf::GetMemoFieldLen( const xbShort 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; sp = 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( void ) const{ xbShort i; for( i = 0; i < NoOfFields; i++ ) if( GetFieldType( i ) == 'M' ) return 1; return 0;}/***********************************************************************///! Short description/*! \param FieldNo*/xbShort xbDbf::DeleteMemoField( const xbShort FieldNo ){ xbLong SBlockNo, SNoOfBlocks = 0L, SNextBlock; xbLong LastFreeBlock, LastFreeBlockCnt, LastDataBlock; xbShort rc; NextFreeBlock = 0L; LastFreeBlockCnt = 0L; LastFreeBlock = 0L; SNextBlock = 0L; if( IsType3Dbt() ) /* type III */ { PutField( FieldNo, " " ); return XB_NO_ERROR; } /* Get Block Number */ if(( SBlockNo = GetLongField( FieldNo )) == 0 ) xb_error(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( const xbShort FieldNo, const 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( void ) const{ char buf[4]; memset( buf, 0x00, 4 ); xbase->PutLong( buf, MemoHeader.NextBlock ); if(( fseek( mfp, 0L, SEEK_SET )) != 0 ) xb_error(XB_SEEK_ERROR); if(( fwrite( &buf, 4, 1, mfp )) != 1 ) xb_error(XB_WRITE_ERROR); return XB_NO_ERROR;}/***********************************************************************///! Short description/*! \param StartBlock \param BlocksNeeded \param DataLen \param Buf*/xbShort xbDbf::PutMemoData( const xbLong StartBlock, const xbLong BlocksNeeded, const xbLong DataLen, const char *Buf ){ xbShort i, rc, Qctr, Tctr, wlen; xbLong CurBlock; char *tp; const char *sp; wlen = DataLen + 2; CurBlock = StartBlock; tp = (char *) mbb; sp = Buf; Qctr = 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 && Qctr < wlen ) { if( Qctr >= DataLen ) *tp++ = 0x1a; /* end of data marker */ else *tp++ = *sp++; Tctr++; Qctr++; } 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( const xbShort FieldNo, const xbLong DataLen, const char * Buf, const xbShort LockOpt ){ xbShort rc; xbLong TotalLen; xbLong BlocksNeeded, BlocksAvailable; #ifdef XB_LOCKING_ON if( LockOpt != -1 ) if(( rc = LockMemoFile( LockOpt, F_WRLCK )) != 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( F_SETLK, F_UNLCK ); #endif return rc; } } } else if((IsType3Dbt() || GetMemoFieldLen(FieldNo)==0L)) { if(( rc = AddMemoData( FieldNo, DataLen, Buf )) != XB_NO_ERROR ) { #ifdef XB_LOCKING_ON LockMemoFile( F_SETLK, F_UNLCK ); #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( F_SETLK, F_UNLCK ); #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( F_SETLK, F_UNLCK ); #endif return rc; } } else { if(( rc = DeleteMemoField( FieldNo )) != XB_NO_ERROR ) { #ifdef XB_LOCKING_ON LockMemoFile( F_SETLK, F_UNLCK ); #endif return rc; } if(( rc = AddMemoData( FieldNo, DataLen, Buf )) != XB_NO_ERROR ) { #ifdef XB_LOCKING_ON LockMemoFile( F_SETLK, F_UNLCK ); #endif return rc; } } } #ifdef XB_LOCKING_ON if( LockOpt != -1 ) if(( rc = LockMemoFile( F_SETLK, F_UNLCK )) != XB_NO_ERROR ) xb_error(XB_LOCK_FAILED); #endif return XB_NO_ERROR;}/***********************************************************************///! Short description/*! \param FieldNo*/xbShort xbDbf::MemoFieldExists( const xbShort FieldNo ) const{ if( GetLongField( FieldNo ) == 0L ) return 0; else return 1;}/***********************************************************************///! Short description/*!*/#ifdef XBASE_DEBUGvoid xbDbf::DumpMemoHeader( void ) const{ xbShort i; cout << "\n*********************************"; cout << "\nMemo header data..."; cout << "\nNext Block " << MemoHeader.NextBlock; if( IsType4Dbt() ) { cout << "\nFilename "; for( i = 0; i < 8; i++ ) cout << MemoHeader.FileName[i]; } cout << "\nBlocksize " << MemoHeader.BlockSize; return;}/***********************************************************************///! Short description/*!*/xbShort xbDbf::DumpMemoFreeChain( void ) { xbShort rc; xbLong CurBlock, LastDataBlock; if(( rc = GetDbtHeader(1)) != XB_NO_ERROR ) return rc; LastDataBlock = CalcLastDataBlock(); CurBlock = MemoHeader.NextBlock; cout << "\nTotal blocks in file = " << LastDataBlock; cout << "\nHead Next Block = " << CurBlock; while( CurBlock < LastDataBlock ) { if(( rc = ReadMemoBlock( CurBlock, 2 )) != XB_NO_ERROR ) return rc; cout << "\n**********************************"; cout << "\nThis Block = " << CurBlock; cout << "\nNext Block = " << NextFreeBlock; cout << "\nNo Of Blocks = " << FreeBlockCnt << "\n"; CurBlock = NextFreeBlock; } return XB_NO_ERROR;}/***********************************************************************///! Short description/*!*/void xbDbf::DumpMemoBlock( void ) const{ xbShort i; char *p; p = (char *) mbb; if( IsType3Dbt() ) { for( i = 0; i < 512; i++ ) cout << *p++; } else { cout << "\nField1 => " << mfield1; cout << "\nStart Pos => " << MStartPos; cout << "\nField Len => " << MFieldLen; cout << "\nBlock data => "; p += 8; for( i = 8; i < MemoHeader.BlockSize; i++ ) cout << *p++; } return;}#endif /* XBASE_DEBUG *//***********************************************************************/#endif /* MEMO_FIELD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -