{ /*************************************************************************** packagedefs.pas --------------- ***************************************************************************/ *************************************************************************** * * * This source is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This code is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * A copy of the GNU General Public License is available on the World * * Wide Web at . You can also * * obtain it by writing to the Free Software Foundation, * * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. * * * *************************************************************************** Author: Mattias Gaertner Abstract: Classes to associate objects/pointers with objects/pointers. } unit ObjectLists; {$mode objfpc}{$H+} interface uses Classes, SysUtils; type T2Pointer = record Item, Associated: Pointer; end; P2Pointer = ^T2Pointer; TObjectArray = class private FCapacity: Integer; FCount: Integer; FList: P2Pointer; protected function Get(Index: Integer): Pointer; procedure Put(Index: Integer; const AValue: Pointer); function GetObject(Index: Integer): Pointer; procedure PutObject(Index: Integer; const AValue: Pointer); procedure SetCapacity(const AValue: Integer); procedure SetCount(const AValue: Integer); procedure Grow; procedure Shrink; public destructor Destroy; override; function Add(Item: Pointer): Integer; function AddObject(Item, Associated: Pointer): Integer; procedure Clear; virtual; procedure Delete(Index: Integer); procedure Exchange(Index1, Index2: Integer); function First: Pointer; function IndexOf(Item: Pointer): Integer; procedure Insert(Index: Integer; Item: Pointer); procedure InsertObject(Index: Integer; Item, Associated: Pointer); function Last: Pointer; procedure Move(CurIndex, NewIndex: Integer); procedure Assign(SrcList: TList); function Remove(Item: Pointer): Integer; procedure Pack; property Capacity: Integer read FCapacity write SetCapacity; property Count: Integer read FCount write SetCount; property Items[Index: Integer]: Pointer read Get write Put; default; property Objects[Index: Integer]: Pointer read GetObject write PutObject; property List: P2Pointer read FList; end; implementation { TObjectArray } function TObjectArray.GetObject(Index: Integer): Pointer; begin Result:=FList[Index].Associated; end; procedure TObjectArray.PutObject(Index: Integer; const AValue: Pointer); begin FList[Index].Associated:=AValue; end; function TObjectArray.Get(Index: Integer): Pointer; begin Result:=FList[Index].Item; end; procedure TObjectArray.Put(Index: Integer; const AValue: Pointer); begin FList[Index].Item:=AValue; end; procedure TObjectArray.SetCapacity(const AValue: Integer); begin if FCapacity=AValue then exit; FCapacity:=AValue; ReallocMem(FList,SizeOf(T2Pointer)*FCapacity); if FCount>FCapacity then FCount:=FCapacity; end; procedure TObjectArray.SetCount(const AValue: Integer); begin if FCount=AValue then exit; FCount:=AValue; if FCount>FCapacity then SetCapacity(AValue); end; procedure TObjectArray.Grow; begin if FCapacity<5 then Capacity:=5 else Capacity:=Capacity*2; end; procedure TObjectArray.Shrink; begin Capacity:=Capacity div 2; end; destructor TObjectArray.Destroy; begin ReallocMem(FList,0); inherited Destroy; end; function TObjectArray.Add(Item: Pointer): Integer; begin Result:=AddObject(Item,nil); end; function TObjectArray.AddObject(Item, Associated: Pointer): Integer; begin if FCount=FCapacity then Grow; FList[FCount].Item:=Item; FList[FCount].Associated:=Associated; Result:=FCount; inc(FCount); end; procedure TObjectArray.Clear; begin FCount:=0; ReallocMem(FList,0); FCapacity:=0; end; procedure TObjectArray.Delete(Index: Integer); begin if FCount>Index+1 then System.Move(FList[Index+1],FList[Index],SizeOf(T2Pointer)*(FCount-Index-1)); dec(FCount); if FCapacity>FCount*4 then Shrink; end; procedure TObjectArray.Exchange(Index1, Index2: Integer); var SwapDummy: T2Pointer; begin if Index1=Index2 then exit; SwapDummy:=FList[Index1]; FList[Index1]:=FList[Index2]; FList[Index2]:=SwapDummy; end; function TObjectArray.First: Pointer; begin if FCount>0 then Result:=FList[0].Item else Result:=nil; end; function TObjectArray.IndexOf(Item: Pointer): Integer; begin Result:=FCount-1; while (Result>=0) and (FList[Result].Item<>Item) do dec(Result); end; procedure TObjectArray.Insert(Index: Integer; Item: Pointer); begin InsertObject(Index,Item,nil); end; procedure TObjectArray.InsertObject(Index: Integer; Item, Associated: Pointer); begin if FCount=FCapacity then Grow; if Index0 then Result:=FList[FCount-1].Item else Result:=nil; end; procedure TObjectArray.Move(CurIndex, NewIndex: Integer); var SwapDummy: T2Pointer; begin if CurIndex=NewIndex then exit; SwapDummy:=FList[CurIndex]; if CurIndex=0 then Delete(Result); end; procedure TObjectArray.Pack; var SrcID: Integer; DestID: Integer; begin SrcID:=0; DestID:=0; while SrcIDnil) then begin if SrcID<>DestID then FList[DestID]:=FList[SrcID]; inc(DestID); end; inc(SrcID); end; FCount:=DestID; end; end.