📄 kbmmembinarystreamformat.pas
字号:
unit kbmMemBinaryStreamFormat;
interface
{$include kbmMemTable.inc}
// =========================================================================
// Binary stream format for kbmMemTable v. 3.xx+
//
// Copyright 1999-2002 Kim Bo Madsen/Optical Services - Scandinavia
// All rights reserved.
//
// LICENSE AGREEMENT
// PLEASE NOTE THAT THE LICENSE AGREEMENT HAS CHANGED!!! 16. Feb. 2000
//
// You are allowed to use this component in any project for free.
// You are NOT allowed to claim that you have created this component or to
// copy its code into your own component and claim that it was your idea.
//
// -----------------------------------------------------------------------------------
// IM OFFERING THIS FOR FREE FOR YOUR CONVINIENCE, BUT
// YOU ARE REQUIRED TO SEND AN E-MAIL ABOUT WHAT PROJECT THIS COMPONENT (OR DERIVED VERSIONS)
// IS USED FOR !
// -----------------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------------
// PLEASE NOTE THE FOLLOWING ADDITION TO THE LICENSE AGREEMENT:
// If you choose to use this component for generating middleware libraries (with similar
// functionality as dbOvernet, Midas, Asta etc.), those libraries MUST be released as
// Open Source and Freeware!
// -----------------------------------------------------------------------------------
//
// You dont need to state my name in your software, although it would be
// appreciated if you do.
//
// If you find bugs or alter the component (f.ex. see suggested enhancements
// further down), please DONT just send the corrected/new code out on the internet,
// but instead send it to me, so I can put it into the official version. You will
// be acredited if you do so.
//
//
// DISCLAIMER
// By using this component or parts theirof you are accepting the full
// responsibility of the use. You are understanding that the author cant be
// made responsible in any way for any problems occuring using this component.
// You also recognize the author as the creator of this component and agrees
// not to claim otherwize!
//
// Please forward corrected versions (source code ONLY!), comments,
// and emails saying you are using it for this or that project to:
// kbm@optical.dk
//
// Latest version can be found at:
// http://www.onelist.com/community/memtable
//=============================================================================
// Remove the remark on the next lines if to keep binary file compatibility
// between different versions of TkbmMemTable.
//{$define BINARY_FILE_230_COMPATIBILITY}
//{$define BINARY_FILE_200_COMPATIBILITY}
//{$define BINARY_FILE_1XX_COMPATIBILITY}
//=============================================================================
// History.
// Per v. 3.00, the stream formats will each have their own history.
//
// 3.00a alpha
// Initial v. 3.00 binary stream format release based on the sources of v. 2.53b.
//
// 3.00b beta
// Fixed Floating point error in calculation of progress.
// Bug reported by Fred Schetterer (yahoogroups@shaw.ca)
//
// 3.00c beta
// Fixed bug not setting record flag to record being part of table.
// This would result in massive memory leaks.
//
// 3.00 Final
// Added BufferSize property (default 16384) which controls the internal
// read and write buffer size. Suggested by Ken Schafer (prez@write-brain.com)
uses
kbmMemTable,Classes,DB,
{$include kbmMemRes.inc}
SysUtils;
type
TkbmStreamFlagUsingIndex = (sfSaveUsingIndex);
TkbmStreamFlagUsingIndexs = set of TkbmStreamFlagUsingIndex;
TkbmCustomBinaryStreamFormat = class(TkbmCustomStreamFormat)
private
Writer:TWriter;
Reader:TReader;
FUsingIndex:TkbmStreamFlagUsingIndexs;
FBuffSize:LongInt;
FileVersion:integer;
InitIndexDef:boolean;
ProgressCnt:integer;
StreamSize:longint;
procedure SetBuffSize(ABuffSize:LongInt);
protected
function GetVersion:string; override;
procedure BeforeSave(ADataset:TkbmCustomMemTable); override;
procedure SaveDef(ADataset:TkbmCustomMemTable); override;
procedure SaveData(ADataset:TkbmCustomMemTable); override;
procedure AfterSave(ADataset:TkbmCustomMemTable); override;
procedure BeforeLoad(ADataset:TkbmCustomMemTable); override;
procedure LoadDef(ADataset:TkbmCustomMemTable); override;
procedure LoadData(ADataset:TkbmCustomMemTable); override;
procedure AfterLoad(ADataset:TkbmCustomMemTable); override;
property sfUsingIndex:TkbmStreamFlagUsingIndexs read FUsingIndex write FUsingIndex;
property BufferSize:LongInt read FBuffSize write SetBuffSize;
public
constructor Create(AOwner:TComponent); override;
end;
TkbmBinaryStreamFormat = class(TkbmCustomBinaryStreamFormat)
published
property Version;
property sfUsingIndex;
property sfData;
property sfCalculated;
property sfLookup;
property sfNonVisible;
property sfBlobs;
property sfDef;
property sfIndexDef;
property sfFiltered;
property sfIgnoreRange;
property sfIgnoreMasterDetail;
property sfDeltas;
property sfDontFilterDeltas;
property sfAppend;
property sfFieldKind;
property sfFromStart;
property OnBeforeLoad;
property OnAfterLoad;
property OnBeforeSave;
property OnAfterSave;
property OnCompress;
property OnDeCompress;
property BufferSize;
end;
{$ifdef LEVEL3}
procedure Register;
{$endif}
implementation
const
// Binary file magic word.
kbmBinaryMagic = '@@BINARY@@';
// Current file versions. V. 1.xx file versions are considered 100, 2.xx are considered 2xx etc.
kbmBinaryFileVersion = 251;
kbmDeltaVersion = 200;
type
TkbmProtCustomMemTable = class(TkbmCustomMemTable);
TkbmProtCommon = class(TkbmCommon);
function TkbmCustomBinaryStreamFormat.GetVersion:string;
begin
Result:='3.00';
end;
constructor TkbmCustomBinaryStreamFormat.Create(AOwner:TComponent);
begin
inherited;
FUsingIndex:=[sfSaveUsingIndex];
FBuffSize:=16384;
end;
procedure TkbmCustomBinaryStreamFormat.SetBuffSize(ABuffSize:LongInt);
begin
if ABuffSize<16384 then ABuffSize:=16384;
FBuffSize:=ABuffSize;
end;
procedure TkbmCustomBinaryStreamFormat.BeforeSave(ADataset:TkbmCustomMemTable);
begin
inherited;
Writer:=TWriter.Create(WorkStream,FBuffSize);
Writer.WriteSignature;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
Writer.WriteInteger(kbmBinaryFileVersion);
{$ENDIF}
end;
procedure TkbmCustomBinaryStreamFormat.AfterSave(ADataset:TkbmCustomMemTable);
begin
Writer.FlushBuffer;
Writer.Free;
Writer:=nil;
TkbmProtCustomMemTable(ADataset).FOverrideActiveRecordBuffer:=nil;
inherited;
end;
procedure TkbmCustomBinaryStreamFormat.SaveDef(ADataset:TkbmCustomMemTable);
var
i:integer;
nf:integer;
begin
// Write field definitions
with TkbmProtCustomMemTable(ADataset) do
begin
// Write fielddefinitions.
nf:=FieldCount;
Writer.WriteListBegin;
if (sfSaveDef in sfDef) then
begin
for i:=0 to nf-1 do
begin
if SaveFields[i]>=0 then
begin
Writer.WriteString(Fields[i].FieldName);
Writer.WriteString(FieldTypeNames[Fields[i].DataType]);
Writer.WriteInteger(Fields[i].Size);
Writer.WriteString(Fields[i].DisplayName);
Writer.WriteString(Fields[i].EditMask);
Writer.WriteInteger(Fields[i].DisplayWidth);
Writer.WriteBoolean(Fields[i].Required);
Writer.WriteBoolean(Fields[i].ReadOnly);
// New for 2.50i BinaryFileVersion 250
if sfSaveFieldKind in sfFieldKind then
Writer.WriteString(FieldKindNames[ord(Fields[i].FieldKind)])
else
Writer.WriteString(FieldKindNames[0]); //fkData.
// New for 2.50o2 BinaryFileVersion 251
{$IFDEF LEVEL4}
Writer.WriteString(Fields[i].DefaultExpression);
{$ELSE}
Writer.WriteString('');
{$ENDIF}
end;
end;
end;
Writer.WriteListEnd;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
// Save index definitions.
Writer.WriteListBegin;
if sfSaveIndexDef in sfIndexDef then
begin
for i:=0 to FIndexDefs.Count-1 do
with FIndexDefs.Items[i] do
begin
Writer.WriteString(Name);
Writer.WriteString(Fields);
{$IFNDEF LEVEL3}
Writer.WriteString(DisplayName);
{$ELSE}
Writer.WriteString(Name);
{$ENDIF}
Writer.WriteBoolean(ixDescending in Options);
Writer.WriteBoolean(ixCaseInSensitive in Options);
{$IFNDEF LEVEL3}
Writer.WriteBoolean(ixNonMaintained in Options);
{$ELSE}
Writer.WriteBoolean(false);
{$ENDIF}
Writer.WriteBoolean(ixUnique in Options);
end;
end;
Writer.WriteListEnd;
{$ENDIF}
end;
end;
procedure TkbmCustomBinaryStreamFormat.SaveData(ADataset:TkbmCustomMemTable);
var
i,j,cnt:integer;
nf:integer;
Accept:boolean;
NewestVersion:boolean;
pRec:PkbmRecord;
UsingIndex:boolean;
begin
with TkbmProtCustomMemTable(ADataset) do
begin
// Write fielddefinitions.
nf:=FieldCount;
// Write all records
FSaveCount:=0;
FSavedCompletely:=true;
Writer.WriteListBegin;
// Check if to write according to current index or not.
UsingIndex:=sfSaveUsingIndex in FUsingIndex;
if UsingIndex then
cnt:=FCurIndex.References.Count
else
cnt:=TkbmProtCommon(Common).FRecords.Count;
for j:=0 to cnt-1 do
begin
// Check if to save more.
if (FSaveLimit>0) and (FSaveCount>=FSaveLimit) then
begin
FSavedCompletely:=false;
break;
end;
// Check if to invoke progress event if any.
if (j mod 100)=0 then Progress(trunc((j/cnt)*100),mtpcSave);
// Setup which record to look at.
if UsingIndex then
FOverrideActiveRecordBuffer:=PkbmRecord(FCurIndex.References.Items[j])
else
FOverrideActiveRecordBuffer:=PkbmRecord(TkbmProtCommon(Common).FRecords.Items[j]);
if (FOverrideActiveRecordBuffer=nil) then continue;
// Calculate fields.
ClearCalcFields(PChar(FOverrideActiveRecordBuffer));
GetCalcFields(PChar(FOverrideActiveRecordBuffer));
// Check filter of record.
Accept:=FilterRecord(FOverrideActiveRecordBuffer,false);
if not Accept then continue;
// Check accept of saving this record.
Accept:=true;
if Assigned(OnSaveRecord) then OnSaveRecord(ADataset,Accept);
if not Accept then continue;
// Write current record.
NewestVersion:=true;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY}
// New for v. 2.24.
if (not (sfSaveData in sfData)) and (FOverrideActiveRecordBuffer^.UpdateStatus=usUnmodified) then continue;
// New for v. 2.30b
if (not (sfSaveDontFilterDeltas in sfDontFilterDeltas)) and (FOverrideActiveRecordBuffer^.UpdateStatus=usDeleted) then
begin
// Make sure record has not been inserted and deleted again.
pRec:=FOverrideActiveRecordBuffer^.PrevRecordVersion;
while pRec^.PrevRecordVersion<>nil do pRec:=pRec^.PrevRecordVersion;
if pRec^.UpdateStatus=usInserted then continue;
end;
// Write record versions in a list starting with Updatestatus.
Writer.WriteListBegin;
while FOverrideActiveRecordBuffer<>nil do
begin
Writer.WriteInteger(ord(FOverrideActiveRecordBuffer^.UpdateStatus));
{$ENDIF}
{$ENDIF}
for i:=0 to nf-1 do
begin
if SaveFields[i]>=0 then
begin
if NewestVersion and Assigned(FOnSaveField) then FOnSaveField(ADataset,i,Fields[i]);
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY}
{$IFNDEF BINARY_FILE_230_COMPATIBILITY}
Writer.WriteBoolean(Fields[i].IsNull);
if not Fields[i].IsNull then
begin
{$ENDIF}
{$ENDIF}
{$ENDIF}
case Fields[i].DataType of
ftBoolean : Writer.WriteBoolean(Fields[i].AsBoolean);
{$IFNDEF LEVEL3}
ftLargeInt: Writer.WriteFloat(Fields[i].AsFloat);
{$ENDIF}
ftSmallInt,
ftInteger,
ftWord,
ftAutoInc : Writer.WriteInteger(Fields[i].AsInteger);
ftFloat : Writer.WriteFloat(Fields[i].AsFloat);
ftBCD,
ftCurrency : Writer.WriteFloat(Fields[i].AsCurrency);
ftDate,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -