⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbmmembinarystreamformat.pas

📁 内存表控件 kbmMemTable
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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 + -