unit CollPArray; (***************************************************************************** * Copyright 2003 by Matthew Greet * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library 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 Lesser General Public License for more * details. (http://opensource.org/licenses/lgpl-license.php) * * See http://www.warmachine.u-net.com/delphi_collections for updates and downloads. * * $Version: v1.0.3 $ * $Revision: 1.2.1.2 $ * $Log: D:\QVCS Repositories\Delphi Collections\CollPArray.qbt $ * * Collection implementations based on TList. * * Revision 1.2.1.2 by: Matthew Greet Rev date: 12/06/04 20:08:30 * Capacity property. * * Revision 1.2.1.1 by: Matthew Greet Rev date: 14/02/04 17:46:10 * v1.0 branch. * * Revision 1.2 by: Matthew Greet Rev date: 28/04/03 15:07:14 * Correctly handles nil items. * * Revision 1.1 by: Matthew Greet Rev date: 06/04/03 10:43:16 * Added TPArrayMap and TExposedPArrayList. * * Revision 1.0 by: Matthew Greet Rev date: 01/03/03 10:50:02 * Initial revision. * * FPC compatibility fixes by: UltraStar Deluxe Team * * $Endlog$ *****************************************************************************) {$IFDEF FPC} {$MODE Delphi}{$H+} {$ENDIF} interface uses Classes, Collections; type TPArrayBag = class(TAbstractBag) private FList: TList; protected function TrueAdd(const Item: ICollectable): Boolean; override; procedure TrueClear; override; function TrueRemove(const Item: ICollectable): ICollectable; override; function TrueRemoveAll(const Item: ICollectable): ICollection; override; public constructor Create(NaturalItemsOnly: Boolean); override; destructor Destroy; override; function GetCapacity: Integer; override; procedure SetCapacity(Value: Integer); override; function GetIterator: IIterator; override; function GetSize: Integer; override; function TrueContains(const Item: ICollectable): Boolean; override; end; TPArraySet = class(TAbstractSet) private FList: TList; protected function GetPosition(const Item: ICollectable): TCollectionPosition; override; procedure TrueAdd2(Position: TCollectionPosition; const Item: ICollectable); override; procedure TrueClear; override; function TrueGet(Position: TCollectionPosition): ICollectable; override; procedure TrueRemove2(Position: TCollectionPosition); override; public constructor Create(NaturalItemsOnly: Boolean); override; destructor Destroy; override; function GetCapacity: Integer; override; procedure SetCapacity(Value: Integer); override; function GetIterator: IIterator; override; function GetSize: Integer; override; end; TPArrayList = class(TAbstractList) private FList: TList; protected function TrueGetItem(Index: Integer): ICollectable; override; procedure TrueSetItem(Index: Integer; const Item: ICollectable); override; procedure TrueAppend(const Item: ICollectable); override; procedure TrueClear; override; function TrueDelete(Index: Integer): ICollectable; override; procedure TrueInsert(Index: Integer; const Item: ICollectable); override; public constructor Create(NaturalItemsOnly: Boolean); override; destructor Destroy; override; function GetCapacity: Integer; override; procedure SetCapacity(Value: Integer); override; function GetIterator: IIterator; override; function GetSize: Integer; override; end; TPArrayMap = class(TAbstractMap) private FList: TList; protected function GetAssociationIterator: IMapIterator; override; function GetKeyPosition(const Key: ICollectable): TCollectionPosition; override; procedure TrueClear; override; function TrueGet(Position: TCollectionPosition): IAssociation; override; function TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation; override; function TrueRemove2(Position: TCollectionPosition): IAssociation; override; public constructor Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); override; destructor Destroy; override; function GetCapacity: Integer; override; procedure SetCapacity(Value: Integer); override; function GetSize: Integer; override; end; // Same as TPArrayList but raises method visibilities so items can be manually // appended or inserted without resetting sort flag. TExposedPArrayList = class(TPArrayList) public procedure TrueAppend(const Item: ICollectable); override; procedure TrueInsert(Index: Integer; const Item: ICollectable); override; end; implementation type TPArrayIterator = class(TAbstractIterator) private FList: TList; FIndex: Integer; protected constructor Create(List: TList; AllowRemove: Boolean); function TrueFirst: ICollectable; override; function TrueNext: ICollectable; override; procedure TrueRemove; override; end; TPArrayAssociationIterator = class(TAbstractAssociationIterator) private FList: TList; FIndex: Integer; protected constructor Create(List: TList; AllowRemove: Boolean); function TrueFirst: IAssociation; override; function TrueNext: IAssociation; override; procedure TrueRemove; override; end; TPArrayPosition = class(TCollectionPosition) private FIndex: Integer; public constructor Create(Found: Boolean; Index: Integer); property Index: Integer read FIndex; end; constructor TPArrayBag.Create(NaturalItemsOnly: Boolean); begin inherited Create(NaturalItemsOnly); FList := TList.Create; end; destructor TPArrayBag.Destroy; begin FList.Free; inherited Destroy; end; function TPArrayBag.TrueAdd(const Item: ICollectable): Boolean; begin FList.Add(Pointer(Item)); Result := true; // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item <> nil then Item._AddRef; end; procedure TPArrayBag.TrueClear; var Item: ICollectable; I: Integer; begin // Delete all interface references for I := 0 to FList.Count - 1 do begin Item := ICollectable(FList[I]); FList[I] := nil; // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item <> nil then Item._Release; end; FList.Clear; end; function TPArrayBag.TrueContains(const Item: ICollectable): Boolean; var I: Integer; Success: Boolean; begin // Sequential search I := 0; Success := false; while (I < FList.Count) and not Success do begin Success := Comparator.Equals(Item, ICollectable(FList[I])); Inc(I); end; Result := Success; end; function TPArrayBag.TrueRemove(const Item: ICollectable): ICollectable; var Item2: ICollectable; I: Integer; Found: Boolean; begin // Sequential search I := 0; Found := false; Result := nil; while (I < FList.Count) and not Found do begin Item2 := ICollectable(FList[I]); if Comparator.Equals(Item, Item2) then begin Found := true; Result := Item2; FList.Delete(I); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item2 <> nil then Item2._Release; end else Inc(I); end; end; function TPArrayBag.TrueRemoveAll(const Item: ICollectable): ICollection; var ResultCollection: TPArrayBag; Item2: ICollectable; I: Integer; begin // Sequential search I := 0; ResultCollection := TPArrayBag.Create; while I < FList.Count do begin Item2 := ICollectable(FList[I]); if Comparator.Equals(Item, Item2) then begin ResultCollection.Add(Item2); FList.Delete(I); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item <> nil then Item._Release; end else Inc(I); end; Result := ResultCollection; end; function TPArrayBag.GetCapacity: Integer; begin Result := FList.Capacity; end; procedure TPArrayBag.SetCapacity(Value: Integer); begin FList.Capacity := Value; end; function TPArrayBag.GetIterator: IIterator; begin Result := TPArrayIterator.Create(FList, true); end; function TPArrayBag.GetSize: Integer; begin Result := FList.Count; end; constructor TPArraySet.Create(NaturalItemsOnly: Boolean); begin inherited Create(NaturalItemsOnly); FList := TList.Create; end; destructor TPArraySet.Destroy; begin FList.Free; inherited Destroy; end; function TPArraySet.GetPosition(const Item: ICollectable): TCollectionPosition; var I: Integer; Success: Boolean; begin // Sequential search I := 0; Success := false; while (I < FList.Count) do begin Success := Comparator.Equals(Item, ICollectable(FList[I])); if Success then break; Inc(I); end; Result := TPArrayPosition.Create(Success, I); end; procedure TPArraySet.TrueAdd2(Position: TCollectionPosition; const Item: ICollectable); begin FList.Add(Pointer(Item)); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually Item._AddRef; end; procedure TPArraySet.TrueClear; var Item: ICollectable; I: Integer; begin // Delete all interface references for I := 0 to FList.Count - 1 do begin Item := ICollectable(FList[I]); FList[I] := nil; // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually Item._Release; end; FList.Clear; end; function TPArraySet.TrueGet(Position: TCollectionPosition): ICollectable; begin Result := ICollectable(FList.Items[TPArrayPosition(Position).Index]); end; procedure TPArraySet.TrueRemove2(Position: TCollectionPosition); var Item: ICollectable; begin Item := ICollectable(FList[TPArrayPosition(Position).Index]); FList.Delete(TPArrayPosition(Position).Index); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually Item._Release; end; function TPArraySet.GetCapacity: Integer; begin Result := FList.Capacity; end; procedure TPArraySet.SetCapacity(Value: Integer); begin FList.Capacity := Value; end; function TPArraySet.GetIterator: IIterator; begin Result := TPArrayIterator.Create(FList, true); end; function TPArraySet.GetSize: Integer; begin Result := FList.Count; end; constructor TPArrayList.Create(NaturalItemsOnly: Boolean); begin inherited Create(NaturalItemsOnly); FList := TList.Create; end; destructor TPArrayList.Destroy; begin FList.Free; inherited Destroy; end; function TPArrayList.TrueGetItem(Index: Integer): ICollectable; begin Result := ICollectable(FList.Items[Index]); end; procedure TPArrayList.TrueSetItem(Index: Integer; const Item: ICollectable); var OldItem: ICollectable; begin OldItem := ICollectable(FList[Index]); FList[Index] := Pointer(Item); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item <> nil then Item._AddRef; if OldItem <> nil then OldItem._Release; end; procedure TPArrayList.TrueAppend(const Item: ICollectable); begin FList.Add(Pointer(Item)); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item <> nil then Item._AddRef; end; procedure TPArrayList.TrueClear; var Item: ICollectable; I: Integer; begin // Delete all interface references for I := 0 to FList.Count - 1 do begin Item := ICollectable(FList[I]); FList[I] := nil; // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item <> nil then Item._Release; end; FList.Clear; end; function TPArrayList.TrueDelete(Index: Integer): ICollectable; begin Result := ICollectable(FList[Index]); FList.Delete(Index); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Result <> nil then Result._Release; end; procedure TPArrayList.TrueInsert(Index: Integer; const Item: ICollectable); begin FList.Insert(Index, Pointer(Item)); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually if Item <> nil then Item._AddRef; end; function TPArrayList.GetCapacity: Integer; begin Result := FList.Capacity; end; procedure TPArrayList.SetCapacity(Value: Integer); begin FList.Capacity := Value; end; function TPArrayList.GetIterator: IIterator; begin Result := TPArrayIterator.Create(FList, true); end; function TPArrayList.GetSize: Integer; begin Result := FList.Count; end; constructor TPArrayMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); begin inherited Create(NaturalItemsOnly, NaturalKeysOnly); FList := TList.Create; end; destructor TPArrayMap.Destroy; begin FList.Free; inherited Destroy; end; function TPArrayMap.GetAssociationIterator: IMapIterator; begin Result := TPArrayAssociationIterator.Create(FList, true); end; function TPArrayMap.GetKeyPosition(const Key: ICollectable): TCollectionPosition; var I: Integer; Success: Boolean; begin // Sequential search I := 0; Success := false; while (I < FList.Count) do begin Success := KeyComparator.Equals(Key, IAssociation(FList[I]).GetKey); if Success then break; Inc(I); end; Result := TPArrayPosition.Create(Success, I); end; procedure TPArrayMap.TrueClear; var Association: IAssociation; I: Integer; begin // Delete all interface references for I := 0 to FList.Count - 1 do begin Association := IAssociation(FList[I]); FList[I] := nil; // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually Association._Release; end; FList.Clear; end; function TPArrayMap.TrueGet(Position: TCollectionPosition): IAssociation; begin Result := IAssociation(FList.Items[TPArrayPosition(Position).Index]); end; function TPArrayMap.TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation; var OldAssociation: IAssociation; Index: Integer; begin if Position.Found then begin Index := (Position as TPArrayPosition).Index; OldAssociation := IAssociation(FList[Index]); FList[Index] := Pointer(Association); end else begin OldAssociation := nil; FList.Add(Pointer(Association)); end; Result := OldAssociation; // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually Association._AddRef; if OldAssociation <> nil then OldAssociation._Release; end; function TPArrayMap.TrueRemove2(Position: TCollectionPosition): IAssociation; var OldAssociation: IAssociation; begin OldAssociation := IAssociation(FList[TPArrayPosition(Position).Index]); FList.Delete(TPArrayPosition(Position).Index); Result := OldAssociation; // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually OldAssociation._Release; end; function TPArrayMap.GetCapacity: Integer; begin Result := FList.Capacity; end; procedure TPArrayMap.SetCapacity(Value: Integer); begin FList.Capacity := Value; end; function TPArrayMap.GetSize: Integer; begin Result := FList.Count; end; procedure TExposedPArrayList.TrueAppend(const Item: ICollectable); begin inherited TrueAppend(Item); end; procedure TExposedPArrayList.TrueInsert(Index: Integer; const Item: ICollectable); begin inherited TrueInsert(Index, Item); end; { TPArrayIterator } constructor TPArrayIterator.Create(List: TList; AllowRemove: Boolean); begin inherited Create(AllowRemove); FList := List; FIndex := -1; end; function TPArrayIterator.TrueFirst: ICollectable; begin FIndex := 0; if FIndex < FList.Count then Result := ICollectable(FList[FIndex]) else Result := nil; end; function TPArrayIterator.TrueNext: ICollectable; begin Inc(FIndex); if FIndex < FList.Count then Result := ICollectable(FList[FIndex]) else Result := nil; end; procedure TPArrayIterator.TrueRemove; var Item: ICollectable; begin Item := ICollectable(FList[FIndex]); FList.Delete(FIndex); Dec(FIndex); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually Item._Release; end; { TPArrayAssociationIterator } constructor TPArrayAssociationIterator.Create(List: TList; AllowRemove: Boolean); begin inherited Create(AllowRemove); FList := List; FIndex := -1; end; function TPArrayAssociationIterator.TrueFirst: IAssociation; begin FIndex := 0; if FIndex < FList.Count then Result := IAssociation(FList[FIndex]) else Result := nil; end; function TPArrayAssociationIterator.TrueNext: IAssociation; begin Inc(FIndex); if FIndex < FList.Count then Result := IAssociation(FList[FIndex]) else Result := nil; end; procedure TPArrayAssociationIterator.TrueRemove; var Association: IAssociation; begin Association := IAssociation(FList[FIndex]); FList.Delete(FIndex); Dec(FIndex); // Storing interface reference as a pointer does not update reference // count automatically, so this must be done manually Association._Release; end; { TPArrayPosition } constructor TPArrayPosition.Create(Found: Boolean; Index: Integer); begin inherited Create(Found); FIndex := Index; end; end.