123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- //******************************************************************************
- //*** COMMON DELPHI FUNCTIONS ***
- //*** ***
- //*** (c) Beppe Grimaldi, Massimo Magnano 11-11-2004. ***
- //*** ***
- //*** ***
- //******************************************************************************
- // File : MGList.pas REV. 1.6 (13-09-2006)
- //
- // Description : Implementation of an Optimazed and Polimorphic List.
- //
- //******************************************************************************
- unit MGList;
- interface
- Type
- PDataExt = ^TDataExt;
- TDataExt = record
- Data :Pointer;
- Prev :PDataExt;
- Next :PDataExt;
- end;
- //I Tag sono necessari xche' Non posso leggere le variabili che stanno nello Stack
- //quindi devo passare le variabile necessarie alle funzioni locali così
- TLocalCompareFunction = function (Tag :Integer; ptData1, ptData2 :Pointer) :Boolean;
- TLocalWalkFunction = procedure (Tag :Integer; ptData :Pointer);
- TObjCompareFunction = function (Tag :Integer; ptData1, ptData2 :Pointer) :Boolean of object;
- PObjCompareFunction = ^TObjCompareFunction;
- TObjWalkFunction = procedure (Tag :Integer; ptData :Pointer) of object;
- TMGList = class
- protected
- rListInit,
- rListEnd,
- rCurrent :PDataExt;
- rCount :Integer;
- function Get(Index: Integer): Pointer;
- function InternalDelete(Item :PDataExt) :PDataExt; overload;
- function InternalFind(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=nil) :PDataExt; virtual;
- function PutInRightPosition(newElem :PDataExt; ATag :Integer; CompareFunction : TLocalCompareFunction=nil) :Integer; overload; virtual;
- function PutInRightPosition(newElem :PDataExt; ATag :Integer; CompareFunction : TObjCompareFunction) :Integer; overload; virtual;
- function allocData :Pointer; virtual;
- procedure deallocData(pData :Pointer); virtual;
- function RefreshOK(pData :Pointer) : Boolean; virtual;
- public
- constructor Create; virtual;
- destructor Destroy; override;
- function Find(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=nil): Integer; overload;
- function Find(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction): Integer; overload;
- function Find(const Args: array of Variant): Pointer; overload; virtual;
- function ExtFind(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=nil): Pointer; overload;
- function ExtFind(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction): Pointer; overload;
- procedure Walk(ATag :Integer; WalkFunction : TLocalWalkFunction); overload;
- procedure Walk(ATag :Integer; WalkFunction : TObjWalkFunction); overload;
- procedure WalkAndRefresh(ATag :Integer; WalkFunction : TLocalWalkFunction); overload;
- procedure WalkAndRefresh(ATag :Integer; WalkFunction : TObjWalkFunction); overload;
- function Add :Pointer; overload;
- function Insert(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=nil) :Integer; overload;
- function Insert(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction) :Integer; overload;
- function Delete(Index :Integer) :Boolean; overload;
- function Delete(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=Nil) :Boolean; overload;
- function Delete(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction) :Boolean; overload;
- procedure Exchange(pData1, pData2 :Pointer); overload; virtual;
- procedure Clear;
- procedure Refresh;
- function FindFirst: Pointer; virtual;
- function FindNext : Pointer; virtual;
- function GetCurrent : Pointer; virtual;
- function GetData(DataPointer :Pointer; DataName :String) :Variant; virtual;
- function DeleteCurrent :Boolean;
- procedure FindClose; virtual;
- property Count :Integer read rCount;
- property Items [Index :Integer] :Pointer read Get;
- end;
- TMGListClass = class of TMGList;
- TMGObjectWithCreate = class(TObject)
- public
- constructor Create(dummy :Boolean); virtual;
- end;
- TObjectWCClass = class of TMGObjectWithCreate;
- TMGObject_List = class(TMGList)
- protected
- function allocData :Pointer; override;
- procedure deallocData(pData :Pointer); override;
- function GetObjectClass :TObjectWCClass; virtual; abstract;
- end;
- TMGList_List = class(TMGList)
- protected
- function allocData :Pointer; override;
- procedure deallocData(pData :Pointer); override;
- function GetObjectClass :TMGListClass; virtual; abstract;
- end;
- implementation
- Type
- TLocalToObjData_Compare = record
- Tag :Integer;
- Func :TObjCompareFunction;
- end;
- PLocalToObjData_Compare = ^TLocalToObjData_Compare;
- TLocalToObjData_Walk = record
- Tag :Integer;
- Func :TObjWalkFunction;
- end;
- PLocalToObjData_Walk = ^TLocalToObjData_Walk;
- function _localToObj_Compare(xTag :Integer; ptData1, ptData2 :Pointer) :Boolean;
- begin
- Result := PLocalToObjData_Compare(xTag).Func(
- PLocalToObjData_Compare(xTag).Tag,
- ptData1, ptData2);
- end;
- procedure _localToObj_Walk(xTag :Integer; ptData :Pointer);
- begin
- PLocalToObjData_Walk(xTag).Func(PLocalToObjData_Walk(xTag).Tag, ptData);
- end;
- function AllocData_Compare(Tag :Integer; Func :TObjCompareFunction) :PLocalToObjData_Compare;
- begin
- GetMem(Result, sizeOf(TLocalToObjData_Compare));
- Result^.Tag :=Tag;
- Result^.Func :=Func;
- end;
- function AllocData_Walk(Tag :Integer; Func :TObjWalkFunction) :PLocalToObjData_Walk;
- begin
- GetMem(Result, sizeOf(TLocalToObjData_Walk));
- Result^.Tag :=Tag;
- Result^.Func :=Func;
- end;
- function CompByData(xTag :Integer; ptData1, ptData2 :Pointer) :Boolean;
- begin
- Result := (ptData1 = ptData2);
- end;
- // =============================================================================
- constructor TMGList.Create;
- begin
- rCount := 0;
- rListInit := Nil;
- rListEnd := Nil;
- rCurrent := Nil;
- end;
- destructor TMGList.Destroy;
- begin
- Clear;
- end;
- function TMGList.allocData :Pointer;
- begin
- Result :=Nil;
- end;
- procedure TMGList.deallocData(pData :Pointer);
- begin
- end;
- function TMGList.RefreshOK(pData :Pointer) : Boolean;
- begin
- Result :=True;
- end;
- procedure TMGList.Clear;
- var
- pIndex :PDataExt;
- begin
- while (rListInit <> Nil) do
- begin
- pIndex := rListInit;
- rListInit := rListInit^.Next;
- deallocData(pIndex^.Data);
- Dispose(pIndex);
- end;
- rListInit := Nil;
- rListEnd := Nil;
- rCount := 0;
- end;
- procedure TMGList.Refresh;
- var
- pIndex :PDataExt;
- begin
- pIndex := rListInit;
- while (pIndex <> Nil) do
- begin
- if RefreshOK(pIndex^.Data)
- then pIndex := pIndex^.Next
- else begin
- if (pIndex^.Next = Nil) // se è l'ultimo elemento..
- then rListEnd := pIndex^.Prev;
- pIndex := InternalDelete(pIndex);
- end;
- end;
- end;
- function TMGList.FindFirst: Pointer;
- begin
- if (rCurrent=Nil)
- then begin
- rCurrent :=rListInit;
- Result :=GetCurrent;
- end
- else Result :=Nil;
- end;
- function TMGList.FindNext : Pointer;
- begin
- if (rCurrent<>Nil)
- then begin
- rCurrent :=rCurrent^.Next;
- Result :=GetCurrent;
- end
- else Result :=Nil;
- end;
- function TMGList.GetCurrent : Pointer;
- begin
- if (rCurrent=Nil)
- then Result :=Nil
- else Result :=rCurrent^.Data;
- end;
- function TMGList.GetData(DataPointer :Pointer; DataName :String) :Variant;
- begin
- Result :=Variant(Integer(DataPointer));
- end;
- function TMGList.DeleteCurrent :Boolean;
- begin
- Result := False;
- if (rCurrent <> Nil) then
- begin
- rCurrent := InternalDelete(rCurrent);
- Result := True;
- end;
- end;
- procedure TMGList.FindClose;
- begin
- rCurrent :=Nil;
- end;
- function TMGList.Get(Index: Integer): Pointer;
- var
- I :Integer;
- pIndex :PDataExt;
- begin
- Result := Nil;
- if ((Index >= 0) and (Index < rCount)) then
- begin
- pIndex := rListInit;
- for i:=0 to Index-1 do
- pIndex := pIndex^.Next;
- Result := pIndex^.Data;
- end;
- end;
- function TMGList.Find(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=nil): Integer;
- var
- i :Integer;
- Found :Boolean;
- pIndex :PDataExt;
- begin
- if not(Assigned(CompareFunction))
- then CompareFunction :=CompByData;
- Result := -1;
- i := 0;
- Found := False;
- pIndex := rListInit;
- while ((i < rCount) and not Found) do
- if CompareFunction(ATag, pData, pIndex^.Data)
- then begin
- Result := i;
- Found := True;
- end
- else begin
- Inc(i);
- pIndex := pIndex^.Next;
- end;
- end;
- function TMGList.Find(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction): Integer;
- Var
- auxPointer :PLocalToObjData_Compare;
- begin
- auxPointer :=AllocData_Compare(ATag, CompareFunction);
- Result := Find(pData, Integer(auxPointer), _LocalToObj_Compare);
- FreeMem(auxPointer);
- end;
- function TMGList.Find(const Args: array of Variant): Pointer;
- begin
- Result :=Nil;
- end;
- function TMGList.ExtFind(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=nil): Pointer;
- var
- Found :Boolean;
- pIndex :PDataExt;
- begin
- if not(Assigned(CompareFunction))
- then CompareFunction :=CompByData;
- Result := Nil;
- Found := False;
- pIndex := rListInit;
- while ((pIndex <> Nil) and not Found) do
- if CompareFunction(ATag, pData, pIndex^.Data)
- then begin
- Result := pIndex^.Data;
- Found := True;
- end
- else pIndex := pIndex^.Next;
- end;
- function TMGList.ExtFind(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction): Pointer;
- Var
- auxPointer :PLocalToObjData_Compare;
- begin
- auxPointer :=AllocData_Compare(ATag, CompareFunction);
- Result := ExtFind(pData, Integer(auxPointer), _LocalToObj_Compare);
- FreeMem(auxPointer);
- end;
- procedure TMGList.Walk(ATag :Integer; WalkFunction : TLocalWalkFunction);
- var
- pIndex :PDataExt;
- begin
- pIndex := rListInit;
- while (pIndex <> Nil) do
- begin
- WalkFunction(ATag, pIndex^.Data);
- pIndex := pIndex^.Next;
- end;
- end;
- procedure TMGList.Walk(ATag :Integer; WalkFunction : TObjWalkFunction);
- Var
- auxPointer :PLocalToObjData_Walk;
- begin
- auxPointer :=AllocData_Walk(ATag, WalkFunction);
- Walk(Integer(auxPointer), _LocalToObj_Walk);
- FreeMem(auxPointer);
- end;
- procedure TMGList.WalkAndRefresh(ATag :Integer; WalkFunction : TLocalWalkFunction);
- var
- pIndex :PDataExt;
- begin
- pIndex := rListInit;
- while (pIndex <> Nil) do
- begin
- if RefreshOk(pIndex^.Data)
- then begin
- WalkFunction(ATag, pIndex^.Data);
- pIndex := pIndex^.Next;
- end
- else begin
- if (pIndex^.Next = Nil) // se è l'ultimo elemento..
- then rListEnd := pIndex^.Prev;
- pIndex := InternalDelete(pIndex);
- end;
- end;
- end;
- procedure TMGList.WalkAndRefresh(ATag :Integer; WalkFunction : TObjWalkFunction);
- Var
- auxPointer :PLocalToObjData_Walk;
- begin
- auxPointer :=AllocData_Walk(ATag, WalkFunction);
- WalkAndRefresh(Integer(auxPointer), _LocalToObj_Walk);
- FreeMem(auxPointer);
- end;
- function TMGList.Add :Pointer;
- var
- newElem :PDataExt;
- begin
- new(newElem);
- fillchar(newElem^, sizeof(TDataExt), 0);
- newElem^.Data := allocData;
- if (rListEnd = Nil)
- then begin
- rListInit := newElem;
- rListEnd := newElem;
- end
- else begin
- rListEnd^.Next := newElem;
- newElem^.Prev := rListEnd;
- rListEnd := newElem;
- end;
- Inc(rCount);
- Result := newElem^.Data;
- end;
- function TMGList.PutInRightPosition(newElem :PDataExt; ATag :Integer; CompareFunction : TLocalCompareFunction) :Integer;
- var
- Found :Boolean;
- pIndex :PDataExt;
- begin
- if not(Assigned(CompareFunction))
- then CompareFunction :=CompByData;
- Result := 0;
- if (rListInit = Nil)
- then begin
- rListInit := newElem;
- rListEnd := newElem;
- end
- else begin
- Found := False;
- pIndex := rListInit;
- repeat
- if CompareFunction(ATag, newElem^.Data, pIndex^.Data)
- then begin
- // uso 'newElem^.Prev' per conservare il puntatore al record precedente..
- newElem^.Prev := pIndex;
- pIndex := pIndex^.Next;
- end
- else Found := True;
- Inc(Result);
- until ((pIndex = Nil) or Found);
- if (newElem^.Prev = Nil) // inserisco in prima posizione..
- then rListInit := newElem
- else newElem^.Prev^.Next := newElem;
- newElem^.Next := pIndex;
- if (pIndex <> Nil)
- then pIndex^.Prev := newElem
- else rListEnd := newElem; // inserisco in ultima posizione..
- end;
- end;
- function TMGList.PutInRightPosition(newElem :PDataExt; ATag :Integer; CompareFunction : TObjCompareFunction) :Integer;
- Var
- auxPointer :PLocalToObjData_Compare;
- begin
- auxPointer :=AllocData_Compare(ATag, CompareFunction);
- Result := PutInRightPosition(newElem, Integer(auxPointer), _LocalToObj_Compare);
- FreeMem(auxPointer);
- end;
- function TMGList.Insert(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=Nil) :Integer;
- var
- newElem :PDataExt;
-
- begin
- if not(Assigned(CompareFunction))
- then CompareFunction :=CompByData;
- new(newElem);
- fillchar(newElem^, sizeof(TDataExt), 0);
- newElem^.Data :=pData;
- Result := PutInRightPosition(pData, ATag, CompareFunction);
- Inc(rCount);
- end;
- function TMGList.Insert(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction) :Integer;
- Var
- auxPointer :PLocalToObjData_Compare;
- begin
- auxPointer :=AllocData_Compare(ATag, CompareFunction);
- Result := Insert(pData, Integer(auxPointer), _LocalToObj_Compare);
- FreeMem(auxPointer);
- end;
- function TMGList.Delete(Index :Integer) :Boolean;
- var
- i :Integer;
- pIndex :PDataExt;
- begin
- Result := False;
- if ((Index >= 0) and (Index < rCount)) then
- begin
- pIndex := rListInit;
- for i:=0 to Index-1 do
- pIndex := pIndex^.Next;
- if (pIndex = Nil)
- then InternalDelete(rListEnd)
- else InternalDelete(pIndex);
- Result := True;
- end;
- end;
- function TMGList.Delete(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=Nil) :Boolean;
- Var
- toDel :PDataExt;
- begin
- if not(Assigned(CompareFunction))
- then CompareFunction :=CompByData;
- toDel := InternalFind(pData, ATag, CompareFunction);
- Result := (toDel<>Nil);
- if Result
- then InternalDelete(toDel);
- end;
- function TMGList.Delete(pData :Pointer; ATag :Integer; CompareFunction : TObjCompareFunction) :Boolean;
- Var
- auxPointer :PLocalToObjData_Compare;
- begin
- auxPointer :=AllocData_Compare(ATag, CompareFunction);
- Result := Delete(pData, Integer(auxPointer), _LocalToObj_Compare);
- FreeMem(auxPointer);
- end;
- procedure TMGList.Exchange(pData1, pData2 :Pointer);
- var
- pIndex,
- pIndexData1,
- pIndexData2 :PDataExt;
- xData :Pointer;
- begin
- pIndex := rListInit;
- pIndexData1 :=Nil;
- pIndexData2 :=Nil;
- while ((pIndex <> Nil) and ((pIndexData1=Nil) or (pIndexData2=Nil))) do
- begin
- if (pIndex^.Data=pData1)
- then pIndexData1 :=pIndex
- else if (pIndex^.Data=pData2)
- then pIndexData2 :=pIndex;
- pIndex := pIndex^.Next;
- end;
- if ((pIndexData1<>Nil) and (pIndexData2<>Nil)) then
- begin
- xData := pIndexData1^.Data;
- pIndexData1^.Data := pIndexData2^.Data;
- pIndexData2^.Data := xData;
- end;
- end;
- function TMGList.InternalDelete(Item :PDataExt) :PDataExt;
- var
- P :PDataExt;
- begin
- Result := Nil;
- P := PDataExt(Item);
- if (P <> Nil) then
- begin
- if (P^.Prev <> Nil)
- then P^.Prev^.Next := P^.Next
- else rListInit := P^.Next;
- if (P^.Next <> Nil)
- then P^.Next^.Prev := P^.Prev
- else rListEnd := P^.Prev; // sto cancellando l'ultimo elemento..
- Result := P^.Prev;
- deallocData(P^.Data);
- Dispose(P);
- Dec(rCount);
- end;
- end;
- function TMGList.InternalFind(pData :Pointer; ATag :Integer; CompareFunction : TLocalCompareFunction=nil) :PDataExt;
- var
- Found :Boolean;
- pIndex :PDataExt;
- begin
- if not(Assigned(CompareFunction))
- then CompareFunction :=CompByData;
- Result := Nil;
- Found := False;
- pIndex := rListInit;
- while ((pIndex <> Nil) and not Found) do
- if CompareFunction(ATag, pData, pIndex^.Data)
- then begin
- Result := pIndex;
- Found := True;
- end
- else pIndex := pIndex^.Next;
- end;
- //==============================================================================
- // TMGObject_List = class(TMGList)
- constructor TMGObjectWithCreate.Create(dummy :Boolean);
- begin
- inherited Create;
- end;
- function TMGObject_List.allocData :Pointer;
- begin
- Result :=GetObjectClass.Create(true); //Why Tobject.Create is not virtual???
- end;
- procedure TMGObject_List.deallocData(pData :Pointer);
- begin
- TObject(pData).Free;
- end;
- //==============================================================================
- // TMGList_List = class(TMGList)
- function TMGList_List.allocData :Pointer;
- begin
- Result :=GetObjectClass.Create;
- end;
- procedure TMGList_List.deallocData(pData :Pointer);
- begin
- TMGList(pData).Free;
- end;
- end.
|