📄 kbmmembinarystreamformat.pas
字号:
ftTime,ftDateTime: Writer.WriteFloat(Fields[i].AsFloat);
else
Writer.WriteString(Fields[i].AsString);
end;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY}
{$IFNDEF BINARY_FILE_230_COMPATIBILITY}
end;
{$ENDIF}
{$ENDIF}
{$ENDIF}
end;
end;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY} // New for v. 2.24.
// Only write newest version (current data).
if not (sfSaveDeltas in sfDeltas) then break;
// Prepare writing next older version of record.
FOverrideActiveRecordBuffer:=FOverrideActiveRecordBuffer^.PrevRecordVersion;
NewestVersion:=false;
end;
Writer.WriteListEnd;
{$ENDIF}
{$ENDIF}
// Increment save count.
inc(FSaveCount);
end;
Writer.WriteListEnd;
end;
end;
procedure TkbmCustomBinaryStreamFormat.BeforeLoad(ADataset:TkbmCustomMemTable);
begin
inherited;
StreamSize:=WorkStream.Size;
ProgressCnt:=0;
Reader:=TReader.Create(WorkStream,FBuffSize);
Reader.ReadSignature;
InitIndexDef:=false;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
if Reader.NextValue = vaList then // A hack since vaList only exists in >= v. 2.xx.
FileVersion := 100
else
FileVersion:=Reader.ReadInteger;
{$ELSE}
FileVersion:=0;
{$ENDIF}
end;
procedure TkbmCustomBinaryStreamFormat.AfterLoad(ADataset:TkbmCustomMemTable);
begin
Reader.Free;
with TkbmProtCustomMemTable(ADataset) do
begin
// Now create indexes as defined.
if InitIndexDef then CreateIndexes;
FOverrideActiveRecordBuffer:=nil;
end;
inherited;
end;
procedure TkbmCustomBinaryStreamFormat.LoadDef(ADataset:TkbmCustomMemTable);
var
i:integer;
FName,KName,TName,DName,EMask,DExpr:string;
FSize,DSize:integer;
REQ,RO:boolean;
FT:TFieldType;
FK:TFieldKind;
InitTableDef:boolean;
ld:boolean;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
ioptions:TIndexOptions;
FFields:string;
{$ENDIF}
begin
if (StreamSize = 0) then exit;
ld:=sfLoadDef in sfDef;
with TkbmProtCustomMemTable(ADataset) do
begin
// Read all definitions if any saved.
InitTableDef:=false;
InitIndexDef:=false;
try
Reader.ReadListBegin;
while not(Reader.EndofList) do
begin
// Clear previous setup if not cleared yet.
if not InitTableDef then
begin
if ld then
begin
Close;
FieldDefs.clear;
DeleteTable;
end;
InitTableDef:=true;
end;
// read field definition.
FName := Reader.ReadString;
TName := Reader.ReadString;
FSize := Reader.ReadInteger;
DName := Reader.ReadString;
EMask := Reader.ReadString;
DSize := Reader.ReadInteger;
REQ := Reader.ReadBoolean;
RO := Reader.ReadBoolean;
if FileVersion>=250 then KName:=Reader.ReadString
else KName:=FieldKindNames[0]; // fkData
if FileVersion>=251 then DExpr:=Reader.ReadString
else DExpr:='';
// Find fieldtype from fieldtypename.
for i:=0 to ord(High(FieldTypeNames)) do
if FieldTypeNames[TFieldType(i)]=TName then break;
FT:=TFieldType(i);
if not (FT in kbmSupportedFieldTypes) then
raise EMemTableError.Create(Format(kbmUnknownFieldErr1,[TName]));
// Find fieldkind from fieldkindname.
FK:=fkData;
for i:=0 to ord(High(FieldKindNames)) do
if FieldKindNames[i]=KName then
begin
FK:=TFieldKind(i);
break;
end;
if ld then
begin
// Add field definition.
FieldDefs.Add(FName,FT,FSize,REQ);
// Setup other properties.
i:=FieldDefs.IndexOf(FName);
with FieldDefs.Items[i].CreateField(ADataset) do
begin
FieldKind:=FK;
DisplayLabel:=DName;
EditMask:=EMask;
ReadOnly:=RO;
DisplayWidth:=DSize;
{$IFDEF LEVEL4}
DefaultExpression:=DExpr;
{$ENDIF}
end;
end;
end;
Reader.ReadListEnd;
// Indexes introduced in file version 2.00
if FileVersion>=200 then
begin
// Read all index definitions if any saved.
Reader.ReadListBegin;
while not(Reader.EndofList) do
begin
// Clear previous setup if not cleared yet.
if not InitIndexDef then
begin
if ld then
begin
DestroyIndexes;
FIndexDefs.Clear;
end;
InitIndexDef:=true;
end;
// read index definition.
FName := Reader.ReadString;
FFields := Reader.ReadString;
DName := Reader.ReadString;
ioptions:=[];
if Reader.ReadBoolean then ioptions:=ioptions+[ixDescending];
if Reader.ReadBoolean then ioptions:=ioptions+[ixCaseInSensitive];
{$IFNDEF LEVEL3}
if Reader.ReadBoolean then ioptions:=ioptions+[ixNonMaintained];
{$ELSE}
Reader.ReadBoolean; // Skip ixNonMaintained info since not supported for D3/BCB3.
{$ENDIF}
if Reader.ReadBoolean then ioptions:=ioptions+[ixUnique];
// Add field definition.
if ld then
begin
{$IFNDEF LEVEL3}
with IndexDefs.AddIndexDef do
begin
Name:=FName;
Fields:=FFields;
Options:=ioptions;
DisplayName:=DName;
end;
{$ELSE}
IndexDefs.Add(FName,FFields,ioptions);
{$ENDIF}
end;
end;
Reader.ReadListEnd;
end;
finally
if InitTableDef then Open;
end;
end;
if not ld then InitIndexDef:=false;
end;
procedure TkbmCustomBinaryStreamFormat.LoadData(ADataset:TkbmCustomMemTable);
var
i:integer;
nf:integer;
Accept:boolean;
bNull:boolean;
Date:double;
NewestVersion:boolean;
pRec:PkbmRecord;
ApproxRecs:integer;
begin
if (StreamSize = 0) then exit;
with TkbmProtCustomMemTable(ADataset),TkbmProtCommon(ADataset.Common) do
begin
SetTempState(dsinsert);
try
ResetAutoInc;
// Try to determine approx how many records in stream + add some slack.
if RecordSize>0 then
begin
ApproxRecs:=StreamSize div FDataRecordSize;
ApproxRecs:=ApproxRecs + (ApproxRecs div 50) + RecordCount;
end
else
ApproxRecs:=0;
// Read all records.
FLoadCount:=0;
FLoadedCompletely:=true;
if ApproxRecs>0 then FRecords.Capacity:=ApproxRecs; // For speed reason try to preallocate room for all records.
nf:=Fieldcount;
Reader.ReadListBegin;
while not(Reader.EndofList) do
begin
// Show progress.
inc(ProgressCnt);
ProgressCnt:=ProgressCnt mod 100;
if (ProgressCnt=0) then
Progress(trunc((WorkStream.Position / StreamSize) * 100),mtpcLoad);
if (FLoadLimit>0) and (FLoadCount>=FLoadLimit) then
begin
FLoadedCompletely:=false;
break;
end;
pRec:=_InternalAllocRecord;
FOverrideActiveRecordBuffer:=pRec;
NewestVersion:=true;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY} // New for v. 2.24.
// Loop for all versions of record if versioning is used (2.30 and forth).
if FileVersion>=230 then Reader.ReadListBegin;
while true do
begin
if FileVersion>=230 then FOverrideActiveRecordBuffer^.UpdateStatus:=TUpdateStatus(Reader.ReadInteger);
{$ENDIF}
{$ENDIF}
// Read fields for current record version.
for i:=0 to nf-1 do
begin
//2.50i if Fields[i].FieldKind<>fkData then continue;
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY}
{$IFNDEF BINARY_FILE_230_COMPATIBILITY} // New for v. 2.49.
// Check if null values saved in binary file.
if (FileVersion>=249) then
bNull:=Reader.ReadBoolean
else
{$ENDIF}
{$ENDIF}
{$ENDIF}
bNull:=false;
// Check if null field.
if bNull then
Fields[i].Clear
else
begin
// Not null, load data.
case Fields[i].DataType of
ftBoolean : Fields[i].AsBoolean := Reader.ReadBoolean;
{$IFNDEF LEVEL3}
ftLargeInt: Fields[i].AsFloat := Reader.ReadFloat;
{$ENDIF}
ftSmallInt,
ftInteger,
ftWord : Fields[i].AsInteger := Reader.ReadInteger;
ftAutoInc : with Fields[i] do begin
AsInteger:=Reader.ReadInteger;
if FAutoIncMax<AsInteger then
FAutoIncMax:=AsInteger;
end;
ftFloat : Fields[i].AsFloat := Reader.ReadFloat;
ftBCD,
ftCurrency : Fields[i].AsCurrency := Reader.ReadFloat;
ftDate,
ftTime,
ftDateTime : begin
Date:=Reader.ReadFloat;
if Date=0 then Fields[i].Clear
else Fields[i].AsFloat:=Date;
end;
else
Fields[i].AsString := Reader.ReadString;
end;
end;
if NewestVersion and Assigned(FOnLoadField) then OnLoadField(ADataset,i,Fields[i]);
{$IFNDEF BINARY_FILE_1XX_COMPATIBILITY}
{$IFNDEF BINARY_FILE_200_COMPATIBILITY} // New for v. 2.24.
end;
// Previous file versions didnt contain versions, so just break loop.
if FileVersion<230 then break;
// Prepare for reading next version if any. (introduced in v. 2.30)
if Reader.EndOfList then break;
// Prepare next version.
NewestVersion:=false;
FOverrideActiveRecordBuffer^.PrevRecordVersion:=_InternalAllocRecord;
FOverrideActiveRecordBuffer:=FOverrideActiveRecordBuffer^.PrevRecordVersion;
end;
if FileVersion>=230 then Reader.ReadListEnd;
{$ENDIF}
{$ENDIF}
Accept:=true;
if Assigned(OnLoadRecord) then OnLoadRecord(ADataset,Accept);
if Accept then
begin
pRec^.RecordID:=FRecordID;
inc(FRecordID);
pRec^.UniqueRecordID:=FUniqueRecordID;
inc(FUniqueRecordID);
pRec^.Flag:=kbmrfInTable;
FRecords.Add(pRec);
if pRec^.UpdateStatus=usDeleted then inc(FDeletedCount);
inc(FLoadCount);
end
else
_InternalFreeRecord(pRec,true,true);
end;
Reader.ReadListEnd;
finally
RestoreState(dsBrowse);
end;
end;
end;
// -----------------------------------------------------------------------------------
// Registration for Delphi 3 / C++ Builder 3
// -----------------------------------------------------------------------------------
{$ifdef LEVEL3}
procedure Register;
begin
RegisterComponents('kbmMemTable', [TkbmBinaryStreamFormat]);
end;
{$endif}
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -