📄 kbmmembinarystreamformat.pas
字号:
while not(Reader.EndofList) do
begin
// Clear previous setup if not cleared yet.
if not InitIndexDef then
begin
if ld and ldidx then
begin
ADataSet.DestroyIndexes;
ADataSet.IndexDefs.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 index definition.
if ld and ldidx then
begin
{$IFNDEF LEVEL3}
aIndexDef := ADataSet.IndexDefs.AddIndexDef;
aIndexDef.Name:=FName;
aIndexDef.Fields:=FFields;
aIndexDef.Options:=ioptions;
aIndexDef.DisplayName:=DName;
{$ELSE}
IndexDefs.Add(FName,FFields,ioptions);
{$ENDIF}
end;
end;
Reader.ReadListEnd;
end;
finally
if InitTableDef then ADataSet.Open;
end;
if not (ld and ldidx) then InitIndexDef:=false;
end;
procedure TkbmCustomBinaryStreamFormat.LoadData(ADataset:TkbmCustomMemTable);
procedure SkipField(AFieldType:TFieldType);
begin
case AFieldType of
ftBoolean : Reader.ReadBoolean;
{$IFNDEF LEVEL3}
ftLargeInt: Reader.ReadFloat;
ftWideString: Reader.ReadString;
{$ENDIF}
ftSmallInt,
ftInteger,
ftWord : Reader.ReadInteger;
ftAutoInc : Reader.ReadInteger;
ftFloat : Reader.ReadFloat;
ftBCD,
ftCurrency : Reader.ReadFloat;
ftDate,
ftTime,
ftDateTime : Reader.ReadFloat;
else
Reader.ReadString;
end;
end;
var
i,j:integer;
nf:integer;
Accept:boolean;
bNull:boolean;
Date:double;
NewestVersion:boolean;
pRec:PkbmRecord;
ApproxRecs:integer;
fc,fno:integer;
ftypes:array of TFieldType;
{$IFDEF DOTNET}
ARec,Rec:TKbmRecord;
{$ENDIF}
begin
if (StreamSize = 0) then exit;
ADataSet.__SetTempState(dsinsert);
try
ADataSet.ResetAutoInc;
// Try to determine approx how many records in stream + add some slack.
if ADataSet.RecordSize>0 then
begin
ApproxRecs:=StreamSize div ADataSet.Common.DataRecordSize;
ApproxRecs:=ApproxRecs + (ApproxRecs div 50) + ADataSet.RecordCount;
end
else
ApproxRecs:=0;
{$IFDEF LEVEL4}
nf:=length(LoadFields);
{$ELSE}
nf:=LoadFieldsCount;
{$ENDIF}
// Load datatypes from header.
fc:=0;
if sfLoadDataTypeHeader in sfDataTypeHeader then
begin
Reader.ReadListBegin;
fc:=Reader.ReadInteger;
SetLength(ftypes,fc);
for i:=0 to fc-1 do
ftypes[i]:=TFieldType(Reader.ReadInteger);
Reader.ReadListEnd;
end;
// Read all records.
ADataSet.LoadCount:=0;
ADataSet.LoadedCompletely:=true;
if ApproxRecs>0 then ADataSet.Common.Records.Capacity:=ApproxRecs; // For speed reason try to preallocate room for all records.
Reader.ReadListBegin;
while not(Reader.EndofList) do
begin
// Show progress.
inc(ProgressCnt);
ProgressCnt:=ProgressCnt mod 100;
if (ProgressCnt=0) then
ADataSet.Progress(trunc((WorkStream.Position / StreamSize) * 100),mtpcLoad);
if (ADataSet.LoadLimit>0) and (ADataSet.LoadCount>=ADataSet.LoadLimit) then
begin
ADataSet.LoadedCompletely:=false;
break;
end;
pRec:=ADataSet.Common._InternalAllocRecord;
ADataSet.OverrideActiveRecordBuffer:=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
{$IFDEF DOTNET}
ARec := TKbmRecord (Marshal.PtrToStructure(ADataSet.OverrideActiveRecordBuffer,TypeOf(TKbmRecord)));
if FileVersion>=230 then ARec.UpdateStatus:=TUpdateStatus(Reader.ReadInteger);
Marshal.StructureToPtr(ARec,ADataSet.OverrideActiveRecordBuffer,False);
{$ELSE}
if FileVersion>=230 then ADataSet.OverrideActiveRecordBuffer^.UpdateStatus:=TUpdateStatus(Reader.ReadInteger);
{$ENDIF}
{$ENDIF}
{$ENDIF}
// Read fields for current record version.
fno:=0;
for i:=0 to nf-1 do
begin
if LoadFields[i]<0 then
begin
// Check if to skip.
if fc>0 then SkipField(ftypes[fno]);
continue;
end;
j:=LoadFields[i];
//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
ADataSet.Fields[j].Clear
else
begin
// Not null, load data.
case ADataSet.Fields[j].DataType of
ftBoolean : ADataSet.Fields[j].AsBoolean := Reader.ReadBoolean;
{$IFNDEF LEVEL3}
ftLargeInt: ADataSet.Fields[j].AsFloat:=Reader.ReadFloat;
{$IFDEF DOTNET}
ftWideString: ADataSet.Fields[j].AsString:=Reader.ReadString;
{$ELSE}
ftWideString: ADataSet.Fields[j].Value:={$IFDEF LEVEL6}UTF8Decode(Reader.ReadString){$ELSE}Reader.ReadString{$ENDIF};
{$ENDIF}
{$ENDIF}
ftSmallInt,
ftInteger,
ftWord : ADataSet.Fields[j].AsInteger := Reader.ReadInteger;
ftAutoInc :begin
ADataSet.Fields[j].AsInteger:=Reader.ReadInteger;
if ADataSet.Common.AutoIncMax<ADataSet.Fields[j].AsInteger then
ADataSet.Common.AutoIncMax:=ADataSet.Fields[j].AsInteger;
end;
ftFloat : ADataSet.Fields[j].AsFloat := Reader.ReadFloat;
ftBCD,
ftCurrency : ADataSet.Fields[j].AsCurrency := Reader.ReadFloat;
ftDate,
ftTime,
ftDateTime : begin
Date:=Reader.ReadFloat;
if Date=0 then ADataSet.Fields[j].Clear
else ADataSet.Fields[j].AsFloat:=Date;
end;
else
ADataSet.Fields[j].AsString := Reader.ReadString;
end;
end;
if NewestVersion and Assigned(ADataSet.OnLoad) then ADataSet.OnLoadField(ADataset,i,ADataSet.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;
{$IFDEF DOTNET}
ARec := TKbmRecord (Marshal.PtrToStructure(ADataSet.OverrideActiveRecordBuffer,TypeOf(TKbmRecord) ));
ARec.PrevRecordVersion:=ADataSet.Common._InternalAllocRecord;
Marshal.StructureToPtr(ARec,ADataSet.OverrideActiveRecordBuffer,False);
ADataSet.OverrideActiveRecordBuffer:=ARec.PrevRecordVersion;
{$ELSE}
ADataSet.OverrideActiveRecordBuffer^.PrevRecordVersion:=ADataSet.Common._InternalAllocRecord;
ADataSet.OverrideActiveRecordBuffer:=ADataSet.OverrideActiveRecordBuffer^.PrevRecordVersion;
{$ENDIF}
end;
if FileVersion>=230 then Reader.ReadListEnd;
{$ENDIF}
{$ENDIF}
Accept:=true;
if Assigned(ADataSet.OnLoadRecord) then ADataSet.OnLoadRecord(ADataset,Accept);
if Accept then
begin
{$IFDEF DOTNET}
Rec:=TKbmRecord(Marshal.PtrToStructure(pRec,TypeOf(TKbmRecord)));
Rec.RecordID:=ADataSet.Common.RecordID;
ADataSet.Common.RecordID:=ADataSet.Common.RecordID+1;
Rec.UniqueRecordID:=ADataSet.Common.UniqueRecordID;
ADataSet.Common.UniqueRecordID:=ADataSet.Common.UniqueRecordID+1;
Rec.Flag:=kbmrfInTable;
if Rec.UpdateStatus=usDeleted then
ADataSet.Common.deletedCount:=ADataSet.Common.DeletedCount+1;
Marshal.StructureToPtr(Rec,pRec,False);
ADataSet.Common.Records.Add(pRec);
{$ELSE}
pRec^.RecordID:=ADataset.Common.RecordID;
ADataSet.Common.RecordID:=ADataSet.Common.RecordID+1;
pRec^.UniqueRecordID:=ADataSet.Common.UniqueRecordID;
ADataSet.Common.UniqueRecordID:=ADataSet.Common.UniqueRecordID+1;
pRec^.Flag:=kbmrfInTable;
ADataSet.Common.Records.Add(pRec);
if pRec^.UpdateStatus=usDeleted then
ADataSet.Common.deletedCount:=ADataSet.Common.DeletedCount+1;
{$ENDIF}
ADataSet.LoadCount:=ADataSet.LoadCount+1;
end
else
ADataSet.Common._InternalFreeRecord(pRec,true,true);
end;
Reader.ReadListEnd;
finally
ADataSet.__RestoreState(dsBrowse);
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 + -