aboutsummaryrefslogtreecommitdiffstats
path: root/unicode/src/lib
diff options
context:
space:
mode:
authortobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2009-03-14 21:18:50 +0000
committertobigun <tobigun@b956fd51-792f-4845-bead-9b4dfca2ff2c>2009-03-14 21:18:50 +0000
commita92d9807237a024106b67f045822679f7ee4df54 (patch)
tree5f2c2501be7da18d2b82216fe60e645d1a2caaac /unicode/src/lib
parentc61a339ad465ecb43897975538a77c3eb87110be (diff)
downloadusdx-a92d9807237a024106b67f045822679f7ee4df54.tar.gz
usdx-a92d9807237a024106b67f045822679f7ee4df54.tar.xz
usdx-a92d9807237a024106b67f045822679f7ee4df54.zip
merge with current trunk (just update)
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@1634 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to '')
-rw-r--r--unicode/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas2
-rw-r--r--unicode/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas2
-rw-r--r--unicode/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas3
-rw-r--r--unicode/src/lib/collections/CollArray.pas183
-rw-r--r--unicode/src/lib/collections/CollHash.pas1497
-rw-r--r--unicode/src/lib/collections/CollLibrary.pas131
-rw-r--r--unicode/src/lib/collections/CollList.pas270
-rw-r--r--unicode/src/lib/collections/CollPArray.pas689
-rw-r--r--unicode/src/lib/collections/CollWrappers.pas876
-rw-r--r--unicode/src/lib/collections/Collections.pas5318
-rw-r--r--unicode/src/lib/collections/readme.txt14
-rw-r--r--unicode/src/lib/ffmpeg/avcodec.pas317
-rw-r--r--unicode/src/lib/ffmpeg/avformat.pas217
-rw-r--r--unicode/src/lib/ffmpeg/avio.pas119
-rw-r--r--unicode/src/lib/ffmpeg/avutil.pas89
-rw-r--r--unicode/src/lib/ffmpeg/mathematics.pas27
-rw-r--r--unicode/src/lib/ffmpeg/opt.pas52
-rw-r--r--unicode/src/lib/ffmpeg/rational.pas52
-rw-r--r--unicode/src/lib/requirements.txt4
19 files changed, 9560 insertions, 302 deletions
diff --git a/unicode/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas b/unicode/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas
index 2dc99df5..d1231cdd 100644
--- a/unicode/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas
+++ b/unicode/src/lib/JEDI-SDL/OpenGL/Pas/gl.pas
@@ -131,7 +131,7 @@ const
{$IFDEF DARWIN}
GLLibName = '/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib';
{$ELSE}
- GLLibName = 'libGL.so';
+ GLLibName = 'libGL.so.1';
{$ENDIF}
{$ENDIF}
diff --git a/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas b/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas
index 29647d12..876270ff 100644
--- a/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas
+++ b/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glu.pas
@@ -140,7 +140,7 @@ const
{$IFDEF DARWIN}
GLuLibName = '/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib';
{$ELSE}
- GLuLibName = 'libGLU.so';
+ GLuLibName = 'libGLU.so.1';
{$ENDIF}
{$ENDIF}
diff --git a/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas b/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas
index f43a4e4c..9f36d2b5 100644
--- a/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas
+++ b/unicode/src/lib/JEDI-SDL/OpenGL/Pas/glx.pas
@@ -266,8 +266,7 @@ end;
function InitGLX: Boolean;
begin
- Result := InitGLXFromLibrary('libGL.so') or
- InitGLXFromLibrary('libGL.so.1') or
+ Result := InitGLXFromLibrary('libGL.so.1') or
InitGLXFromLibrary('libMesaGL.so') or
InitGLXFromLibrary('libMesaGL.so.3');
end;
diff --git a/unicode/src/lib/collections/CollArray.pas b/unicode/src/lib/collections/CollArray.pas
new file mode 100644
index 00000000..a10ba905
--- /dev/null
+++ b/unicode/src/lib/collections/CollArray.pas
@@ -0,0 +1,183 @@
+unit CollArray;
+
+(*****************************************************************************
+ * 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 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollArray.qbt $
+ *
+ * Colllection implementations based on arrays.
+ *
+ * Revision 1.2 by: Matthew Greet Rev date: 12/06/04 20:02:16
+ * Capacity property.
+ *
+ * Revision 1.1 by: Matthew Greet Rev date: 06/04/03 10:30:36
+ * Size property dropped.
+ * Unused abstract functions still implemented.
+ *
+ * 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
+ Collections;
+
+type
+ TArray = class(TAbstractList)
+ private
+ FArray: array of ICollectable;
+ protected
+ function TrueGetItem(Index: Integer): ICollectable; override;
+ procedure TrueSetItem(Index: Integer; const Value: 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;
+ constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean = false); override;
+ constructor Create(Size: Integer; NaturalItemsOnly: Boolean = false); overload; virtual;
+ constructor Create(const Collection: ICollection); override;
+ destructor Destroy; override;
+ function GetCapacity: Integer; override;
+ procedure SetCapacity(Value: Integer); override;
+ function GetFixedSize: Boolean; override;
+ function GetSize: Integer; override;
+ end;
+
+implementation
+
+constructor TArray.Create(NaturalItemsOnly: Boolean);
+begin
+ Create(0, NaturalItemsOnly);
+end;
+
+constructor TArray.Create(Size: Integer; NaturalItemsOnly: Boolean = false);
+begin
+ inherited Create(NaturalItemsOnly);
+ SetLength(FArray, Size);
+end;
+
+constructor TArray.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+ Item: ICollectable;
+ ItemError: TCollectionError;
+ I: Integer;
+begin
+ inherited Create(ItemArray, NaturalItemsOnly);
+ SetLength(FArray, Length(ItemArray));
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Item := ItemArray[I];
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ end
+ else
+ Items[I] := Item;
+ end;
+end;
+
+constructor TArray.Create(const Collection: ICollection);
+var
+ Iterator: IIterator;
+ I: Integer;
+begin
+ inherited Create(Collection);
+ SetLength(FArray, Collection.GetSize);
+ Iterator := Collection.GetIterator;
+ I := 0;
+ while not Iterator.EOF do
+ begin
+ Items[I] := Iterator.CurrentItem;
+ Inc(I);
+ Iterator.Next;
+ end;
+end;
+
+destructor TArray.Destroy;
+var
+ I: Integer;
+begin
+ // Delete interface references to all items
+ for I := Low(FArray) to High(FArray) do
+ begin
+ FArray[I] := nil;
+ end;
+ inherited Destroy;
+end;
+
+function TArray.TrueGetItem(Index: Integer): ICollectable;
+begin
+ Result := FArray[Index];
+end;
+
+procedure TArray.TrueSetItem(Index: Integer; const Value: ICollectable);
+begin
+ FArray[Index] := Value;
+end;
+
+procedure TArray.TrueAppend(const Item: ICollectable);
+begin
+ // Ignored as collection is fixed size
+end;
+
+procedure TArray.TrueClear;
+begin
+ // Ignored as collection is fixed size
+end;
+
+function TArray.TrueDelete(Index: Integer): ICollectable;
+begin
+ // Ignored as collection is fixed size
+end;
+
+procedure TArray.TrueInsert(Index: Integer; const Item: ICollectable);
+begin
+ // Ignored as collection is fixed size
+end;
+
+function TArray.GetCapacity: Integer;
+begin
+ Result := Size;
+end;
+
+procedure TArray.SetCapacity(Value: Integer);
+begin
+ // Ignored
+end;
+
+function TArray.GetFixedSize: Boolean;
+begin
+ Result := true;
+end;
+
+function TArray.GetSize: Integer;
+begin
+ Result := Length(FArray);
+end;
+
+end.
diff --git a/unicode/src/lib/collections/CollHash.pas b/unicode/src/lib/collections/CollHash.pas
new file mode 100644
index 00000000..796fc740
--- /dev/null
+++ b/unicode/src/lib/collections/CollHash.pas
@@ -0,0 +1,1497 @@
+unit CollHash;
+
+(*****************************************************************************
+ * 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.1.1.2 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollHash.qbt $
+ *
+ * Collection implementations based on hash tables.
+ *
+ * Revision 1.1.1.2 by: Matthew Greet Rev date: 12/06/04 20:04:30
+ * Capacity property.
+ *
+ * Revision 1.1.1.1 by: Matthew Greet Rev date: 24/10/03 16:48:16
+ * v1.0 branch.
+ *
+ * Revision 1.1 by: Matthew Greet Rev date: 06/04/03 10:40:16
+ * Added integer map and string map versions.
+ * THashSet uses its own implementation, not THashMap.
+ * DefaulMaxLoadFactor changed.
+ *
+ * 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, Math,
+ Collections;
+
+const
+ DefaultTableSize = 100;
+ MaxLoadFactorMin = 0.01; // Minimum allowed value for MaxLoadFactor property.
+ DefaultMaxLoadFactor = 5.0;
+
+type
+ THashMap = class(TAbstractMap)
+ private
+ FArray: TListArray;
+ FCapacity: Integer;
+ FMaxLoadFactor: Double;
+ FSize: Integer;
+ FTableSize: Integer;
+ protected
+ function GetAssociationIterator: IMapIterator; override;
+ procedure SetMaxLoadFactor(Value: Double); virtual;
+ procedure SetTableSize(Value: Integer); virtual;
+ procedure ChangeCapacity(Value: TListArray); virtual;
+ procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+ function GetHash(const Key: ICollectable): Integer; virtual;
+ function GetKeyPosition(const Key: ICollectable): TCollectionPosition; override;
+ procedure Rehash;
+ 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;
+ class function GetAlwaysNaturalKeys: Boolean; override;
+ function GetCapacity: Integer; override;
+ procedure SetCapacity(Value: Integer); override;
+ function GetNaturalKeyIID: TGUID; override;
+ function GetSize: Integer; override;
+ property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+ property TableSize: Integer read FTableSize write SetTableSize;
+ end;
+
+ THashSet = class(TAbstractSet)
+ private
+ FArray: TListArray;
+ FCapacity: Integer;
+ FMaxLoadFactor: Double;
+ FSize: Integer;
+ FTableSize: Integer;
+ protected
+ procedure SetMaxLoadFactor(Value: Double); virtual;
+ procedure SetTableSize(Value: Integer); virtual;
+ procedure ChangeCapacity(Value: TListArray); virtual;
+ procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+ function GetHash(const Item: ICollectable): Integer; virtual;
+ function GetPosition(const Item: ICollectable): TCollectionPosition; override;
+ procedure Rehash;
+ 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;
+ class function GetAlwaysNaturalItems: Boolean; override;
+ function GetCapacity: Integer; override;
+ procedure SetCapacity(Value: Integer); override;
+ function GetIterator: IIterator; override;
+ function GetNaturalItemIID: TGUID; override;
+ function GetSize: Integer; override;
+ property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+ property TableSize: Integer read FTableSize write SetTableSize;
+ end;
+
+ THashIntegerMap = class(TAbstractIntegerMap)
+ private
+ FArray: TListArray;
+ FCapacity: Integer;
+ FMaxLoadFactor: Double;
+ FSize: Integer;
+ FTableSize: Integer;
+ protected
+ function GetAssociationIterator: IIntegerMapIterator; override;
+ procedure SetMaxLoadFactor(Value: Double); virtual;
+ procedure SetTableSize(Value: Integer); virtual;
+ procedure ChangeCapacity(Value: TListArray); virtual;
+ procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+ function GetHash(const Key: Integer): Integer; virtual;
+ function GetKeyPosition(const Key: Integer): TCollectionPosition; override;
+ procedure Rehash;
+ procedure TrueClear; override;
+ function TrueGet(Position: TCollectionPosition): IIntegerAssociation; override;
+ function TruePut(Position: TCollectionPosition; const Association: IIntegerAssociation): IIntegerAssociation; override;
+ function TrueRemove2(Position: TCollectionPosition): IIntegerAssociation; override;
+ public
+ constructor Create; override;
+ constructor Create(NaturalItemsOnly: Boolean); override;
+ constructor Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor); overload; virtual;
+ destructor Destroy; override;
+ function GetCapacity: Integer; override;
+ procedure SetCapacity(Value: Integer); override;
+ function GetSize: Integer; override;
+ property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+ property TableSize: Integer read FTableSize write SetTableSize;
+ end;
+
+ THashStringMap = class(TAbstractStringMap)
+ private
+ FArray: TListArray;
+ FCapacity: Integer;
+ FMaxLoadFactor: Double;
+ FSize: Integer;
+ FTableSize: Integer;
+ protected
+ function GetAssociationIterator: IStringMapIterator; override;
+ procedure SetMaxLoadFactor(Value: Double); virtual;
+ procedure SetTableSize(Value: Integer); virtual;
+ procedure ChangeCapacity(Value: TListArray); virtual;
+ procedure CheckLoadFactor(AlwaysChangeCapacity: Boolean); virtual;
+ function GetHash(const Key: String): Integer; virtual;
+ function GetKeyPosition(const Key: String): TCollectionPosition; override;
+ procedure Rehash;
+ procedure TrueClear; override;
+ function TrueGet(Position: TCollectionPosition): IStringAssociation; override;
+ function TruePut(Position: TCollectionPosition; const Association: IStringAssociation): IStringAssociation; override;
+ function TrueRemove2(Position: TCollectionPosition): IStringAssociation; override;
+ public
+ constructor Create; override;
+ constructor Create(NaturalItemsOnly: Boolean); override;
+ constructor Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor); overload; virtual;
+ destructor Destroy; override;
+ function GetCapacity: Integer; override;
+ procedure SetCapacity(Value: Integer); override;
+ function GetSize: Integer; override;
+ property MaxLoadFactor: Double read FMaxLoadFactor write SetMaxLoadFactor;
+ property TableSize: Integer read FTableSize write SetTableSize;
+ end;
+
+implementation
+
+const
+ (* (sqrt(5) - 1)/2
+ See Introduction to Algorithms in Pascal, 1995, by Thomas W. Parsons,
+ published by John Wiley & Sons, Inc, ISBN 0-471-11600-9
+ *)
+ HashFactor = 0.618033988749894848204586834365638;
+
+type
+ THashIterator = class(TAbstractIterator)
+ private
+ FHashSet: THashSet;
+ FHash: Integer;
+ FChainIndex: Integer;
+ protected
+ constructor Create(HashSet: THashSet);
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ end;
+
+ THashAssociationIterator = class(TAbstractAssociationIterator)
+ private
+ FHashMap: THashMap;
+ FHash: Integer;
+ FChainIndex: Integer;
+ protected
+ constructor Create(HashMap: THashMap);
+ function TrueFirst: IAssociation; override;
+ function TrueNext: IAssociation; override;
+ procedure TrueRemove; override;
+ end;
+
+ THashIntegerIterator = class(TAbstractIntegerAssociationIterator)
+ private
+ FHashIntegerMap: THashIntegerMap;
+ FHash: Integer;
+ FChainIndex: Integer;
+ protected
+ constructor Create(HashIntegerMap: THashIntegerMap);
+ function TrueFirst: IIntegerAssociation; override;
+ function TrueNext: IIntegerAssociation; override;
+ procedure TrueRemove; override;
+ end;
+
+ THashStringIterator = class(TAbstractStringAssociationIterator)
+ private
+ FHashStringMap: THashStringMap;
+ FHash: Integer;
+ FChainIndex: Integer;
+ protected
+ constructor Create(HashStringMap: THashStringMap);
+ function TrueFirst: IStringAssociation; override;
+ function TrueNext: IStringAssociation; override;
+ procedure TrueRemove; override;
+ end;
+
+ THashPosition = class(TCollectionPosition)
+ private
+ FChain: TList;
+ FIndex: Integer;
+ public
+ constructor Create(Found: Boolean; Chain: TList; Index: Integer);
+ property Chain: TList read FChain;
+ property Index: Integer read FIndex;
+ end;
+
+{ THashMap }
+constructor THashMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+var
+ I: Integer;
+begin
+ // Force use of natural keys
+ inherited Create(NaturalItemsOnly, true);
+ FTableSize := DefaultTableSize;
+ FMaxLoadFactor := DefaultMaxLoadFactor;
+ SetLength(FArray, FTableSize);
+ for I := Low(FArray) to High(FArray) do
+ FArray[I] := TList.Create;
+ FCapacity := 0;
+ FSize := 0;
+ ChangeCapacity(FArray);
+end;
+
+destructor THashMap.Destroy;
+var
+ I: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ FArray[I].Free;
+ FArray := nil;
+ inherited Destroy;
+end;
+
+class function THashMap.GetAlwaysNaturalKeys: Boolean;
+begin
+ Result := true;
+end;
+
+function THashMap.GetNaturalKeyIID: TGUID;
+begin
+ Result := HashableIID;
+end;
+
+function THashMap.GetAssociationIterator: IMapIterator;
+begin
+ Result := THashAssociationIterator.Create(Self);
+end;
+
+procedure THashMap.SetTableSize(Value: Integer);
+begin
+ if (FTableSize <> Value) and (Value >= 1) then
+ begin
+ FTableSize := Value;
+ Rehash;
+ end;
+end;
+
+procedure THashMap.SetMaxLoadFactor(Value: Double);
+begin
+ if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+ begin
+ FMaxLoadFactor := Value;
+ CheckLoadFactor(false);
+ end;
+end;
+
+procedure THashMap.ChangeCapacity(Value: TListArray);
+var
+ Chain: TList;
+ I, Total, ChainCapacity: Integer;
+begin
+ if FCapacity mod FTableSize = 0 then
+ ChainCapacity := Trunc(FCapacity / FTableSize)
+ else
+ ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+ Total := 0;
+ for I := Low(Value) to High(Value) do
+ begin
+ Chain := Value[I];
+ Chain.Capacity := ChainCapacity;
+ Total := Total + Chain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashMap.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+ LoadFactor: Double;
+begin
+ LoadFactor := Capacity / TableSize;
+ if LoadFactor > MaxLoadFactor then
+ TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+ else if AlwaysChangeCapacity then
+ ChangeCapacity(FArray);
+end;
+
+function THashMap.GetHash(const Key: ICollectable): Integer;
+var
+ Hashable: IHashable;
+ HashCode: Cardinal;
+begin
+ Key.QueryInterface(IHashable, Hashable);
+ HashCode := Hashable.HashCode;
+ Result := Trunc(Frac(HashCode * HashFactor) * TableSize);
+end;
+
+function THashMap.GetKeyPosition(const Key: ICollectable): TCollectionPosition;
+var
+ Chain: TList;
+ I: Integer;
+ Success: Boolean;
+begin
+ Chain := FArray[GetHash(Key)];
+ Success := false;
+ for I := 0 to Chain.Count - 1 do
+ begin
+ Success := KeyComparator.Equals(Key, IAssociation(Chain[I]).GetKey);
+ if Success then
+ Break;
+ end;
+ Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashMap.Rehash;
+var
+ NewArray: TListArray;
+ OldChain, NewChain: TList;
+ Association: IAssociation;
+ Total: Integer;
+ I, J: Integer;
+ Hash: Integer;
+begin
+ // Create new chains
+ SetLength(NewArray, TableSize);
+ for I := Low(NewArray) to High(NewArray) do
+ begin
+ NewChain := TList.Create;
+ NewArray[I] := NewChain;
+ end;
+ ChangeCapacity(NewArray);
+
+ // Transfer from old chains to new and drop old
+ for I := Low(FArray) to High(FArray) do
+ begin
+ OldChain := FArray[I];
+ for J := 0 to OldChain.Count - 1 do
+ begin
+ Association := IAssociation(OldChain[J]);
+ Hash := GetHash(Association.GetKey);
+ NewArray[Hash].Add(Pointer(Association));
+ end;
+ OldChain.Free;
+ end;
+ FArray := NewArray;
+
+ // Find actual, new capacity
+ Total := 0;
+ for I := Low(FArray) to High(FArray) do
+ begin
+ NewChain := FArray[I];
+ Total := Total + NewChain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashMap.TrueClear;
+var
+ Association: IAssociation;
+ Chain: TList;
+ I, J: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ begin
+ Chain := FArray[I];
+ for J := 0 to Chain.Count - 1 do
+ begin
+ Association := IAssociation(Chain[J]);
+ Chain[J] := nil;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+ end;
+ Chain.Clear;
+ end;
+ FSize := 0;
+end;
+
+function THashMap.TrueGet(Position: TCollectionPosition): IAssociation;
+var
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Result := IAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+function THashMap.TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation;
+var
+ HashPosition: THashPosition;
+ OldAssociation: IAssociation;
+begin
+ HashPosition := THashPosition(Position);
+ if HashPosition.Found then
+ begin
+ OldAssociation := IAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+ HashPosition.Chain.Items[HashPosition.Index] := Pointer(Association);
+ Result := OldAssociation;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._AddRef;
+ OldAssociation._Release;
+ end
+ else
+ begin
+ HashPosition.Chain.Add(Pointer(Association));
+ Inc(FSize);
+ Result := nil;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._AddRef;
+ end;
+end;
+
+function THashMap.TrueRemove2(Position: TCollectionPosition): IAssociation;
+var
+ Association: IAssociation;
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Association := IAssociation(TrueGet(Position));
+ HashPosition.Chain.Delete(HashPosition.Index);
+ Dec(FSize);
+ Result := Association;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+end;
+
+function THashMap.GetCapacity;
+begin
+ Result := FCapacity;
+end;
+
+procedure THashMap.SetCapacity(Value: Integer);
+begin
+ FCapacity := Value;
+ CheckLoadFactor(true);
+end;
+
+function THashMap.GetSize: Integer;
+begin
+ Result := FSize;
+end;
+
+{ THashSet }
+constructor THashSet.Create(NaturalItemsOnly: Boolean);
+var
+ I: Integer;
+begin
+ // Force use of natural items
+ inherited Create(true);
+ FTableSize := DefaultTableSize;
+ FMaxLoadFactor := DefaultMaxLoadFactor;
+ SetLength(FArray, FTableSize);
+ for I := Low(FArray) to High(FArray) do
+ FArray[I] := TList.Create;
+ FSize := 0;
+end;
+
+destructor THashSet.Destroy;
+var
+ I: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ FArray[I].Free;
+ FArray := nil;
+ inherited Destroy;
+end;
+
+procedure THashSet.SetTableSize(Value: Integer);
+begin
+ if (FTableSize <> Value) and (Value >= 1) then
+ begin
+ FTableSize := Value;
+ Rehash;
+ end;
+end;
+
+procedure THashSet.SetMaxLoadFactor(Value: Double);
+begin
+ if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+ begin
+ FMaxLoadFactor := Value;
+ CheckLoadFactor(false);
+ end;
+end;
+
+procedure THashSet.ChangeCapacity(Value: TListArray);
+var
+ Chain: TList;
+ I, Total, ChainCapacity: Integer;
+begin
+ if FCapacity mod FTableSize = 0 then
+ ChainCapacity := Trunc(FCapacity / FTableSize)
+ else
+ ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+ Total := 0;
+ for I := Low(Value) to High(Value) do
+ begin
+ Chain := Value[I];
+ Chain.Capacity := ChainCapacity;
+ Total := Total + Chain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashSet.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+ LoadFactor: Double;
+begin
+ LoadFactor := Capacity / TableSize;
+ if LoadFactor > MaxLoadFactor then
+ TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+ else if AlwaysChangeCapacity then
+ ChangeCapacity(FArray);
+end;
+
+function THashSet.GetHash(const Item: ICollectable): Integer;
+var
+ Hashable: IHashable;
+ HashCode: Cardinal;
+begin
+ Item.QueryInterface(IHashable, Hashable);
+ HashCode := Hashable.HashCode;
+ Result := Trunc(Frac(HashCode * HashFactor) * TableSize);
+end;
+
+function THashSet.GetPosition(const Item: ICollectable): TCollectionPosition;
+var
+ Chain: TList;
+ I: Integer;
+ Success: Boolean;
+begin
+ Chain := FArray[GetHash(Item)];
+ Success := false;
+ for I := 0 to Chain.Count - 1 do
+ begin
+ Success := Comparator.Equals(Item, ICollectable(Chain[I]));
+ if Success then
+ Break;
+ end;
+ Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashSet.Rehash;
+var
+ NewArray: TListArray;
+ OldChain, NewChain: TList;
+ Item: ICollectable;
+ Total: Integer;
+ I, J: Integer;
+ Hash: Integer;
+begin
+ // Create new chains
+ SetLength(NewArray, TableSize);
+ for I := Low(NewArray) to High(NewArray) do
+ begin
+ NewChain := TList.Create;
+ NewArray[I] := NewChain;
+ end;
+ ChangeCapacity(NewArray);
+
+ // Transfer from old chains to new and drop old
+ for I := Low(FArray) to High(FArray) do
+ begin
+ OldChain := FArray[I];
+ for J := 0 to OldChain.Count - 1 do
+ begin
+ Item := ICollectable(OldChain[J]);
+ Hash := GetHash(Item);
+ NewArray[Hash].Add(Pointer(Item));
+ end;
+ OldChain.Free;
+ end;
+ FArray := NewArray;
+
+ // Find actual, new capacity
+ Total := 0;
+ for I := Low(FArray) to High(FArray) do
+ begin
+ NewChain := FArray[I];
+ Total := Total + NewChain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashSet.TrueAdd2(Position: TCollectionPosition; const Item: ICollectable);
+var
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ HashPosition.Chain.Add(Pointer(Item));
+ Inc(FSize);
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Item._AddRef;
+end;
+
+procedure THashSet.TrueClear;
+var
+ Item: ICollectable;
+ Chain: TList;
+ I, J: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ begin
+ Chain := FArray[I];
+ for J := 0 to Chain.Count - 1 do
+ begin
+ Item := ICollectable(Chain[J]);
+ Chain[J] := nil;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Item._Release;
+ end;
+ Chain.Clear;
+ end;
+ FSize := 0;
+end;
+
+function THashSet.TrueGet(Position: TCollectionPosition): ICollectable;
+var
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Result := ICollectable(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+procedure THashSet.TrueRemove2(Position: TCollectionPosition);
+var
+ Item: ICollectable;
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Item := TrueGet(Position);
+ HashPosition.Chain.Delete(HashPosition.Index);
+ Dec(FSize);
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Item._Release;
+end;
+
+class function THashSet.GetAlwaysNaturalItems: Boolean;
+begin
+ Result := true;
+end;
+
+function THashSet.GetIterator: IIterator;
+begin
+ Result := THashIterator.Create(Self);
+end;
+
+function THashSet.GetNaturalItemIID: TGUID;
+begin
+ Result := HashableIID;
+end;
+
+function THashSet.GetCapacity;
+begin
+ Result := FCapacity;
+end;
+
+procedure THashSet.SetCapacity(Value: Integer);
+begin
+ FCapacity := Value;
+ CheckLoadFactor(true);
+end;
+
+function THashSet.GetSize: Integer;
+begin
+ Result := FSize;
+end;
+
+{ THashIntegerMap }
+constructor THashIntegerMap.Create;
+begin
+ Create(false, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashIntegerMap.Create(NaturalItemsOnly: Boolean);
+begin
+ Create(NaturalItemsOnly, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashIntegerMap.Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor);
+var
+ I: Integer;
+begin
+ inherited Create(NaturalItemsOnly);
+ SetLength(FArray, TableSize);
+ for I := Low(FArray) to High(FArray) do
+ FArray[I] := TList.Create;
+ FTableSize := TableSize;
+ FMaxLoadFactor := MaxLoadFactor;
+ FSize := 0;
+end;
+
+destructor THashIntegerMap.Destroy;
+var
+ I: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ FArray[I].Free;
+ FArray := nil;
+ inherited Destroy;
+end;
+
+function THashIntegerMap.GetAssociationIterator: IIntegerMapIterator;
+begin
+ Result := THashIntegerIterator.Create(Self);
+end;
+
+procedure THashIntegerMap.SetTableSize(Value: Integer);
+begin
+ if (FTableSize <> Value) and (Value >= 1) then
+ begin
+ FTableSize := Value;
+ Rehash;
+ end;
+end;
+
+procedure THashIntegerMap.SetMaxLoadFactor(Value: Double);
+begin
+ if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+ begin
+ FMaxLoadFactor := Value;
+ CheckLoadFactor(false);
+ end;
+end;
+
+procedure THashIntegerMap.ChangeCapacity;
+var
+ Chain: TList;
+ I, Total, ChainCapacity: Integer;
+begin
+ if FCapacity mod FTableSize = 0 then
+ ChainCapacity := Trunc(FCapacity / FTableSize)
+ else
+ ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+ Total := 0;
+ for I := Low(Value) to High(Value) do
+ begin
+ Chain := Value[I];
+ Chain.Capacity := ChainCapacity;
+ Total := Total + Chain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashIntegerMap.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+ LoadFactor: Double;
+begin
+ LoadFactor := Capacity / TableSize;
+ if LoadFactor > MaxLoadFactor then
+ TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+ else if AlwaysChangeCapacity then
+ ChangeCapacity(FArray);
+end;
+
+function THashIntegerMap.GetHash(const Key: Integer): Integer;
+begin
+ Result := Trunc(Frac(Cardinal(Key) * HashFactor) * TableSize);
+end;
+
+function THashIntegerMap.GetKeyPosition(const Key: Integer): TCollectionPosition;
+var
+ Chain: TList;
+ I: Integer;
+ Success: Boolean;
+begin
+ Chain := FArray[GetHash(Key)];
+ Success := false;
+ for I := 0 to Chain.Count - 1 do
+ begin
+ Success := (Key = IIntegerAssociation(Chain[I]).GetKey);
+ if Success then
+ Break;
+ end;
+ Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashIntegerMap.Rehash;
+var
+ NewArray: TListArray;
+ OldChain, NewChain: TList;
+ Association: IIntegerAssociation;
+ Total: Integer;
+ I, J: Integer;
+ Hash: Integer;
+begin
+ // Create new chains
+ SetLength(NewArray, TableSize);
+ for I := Low(NewArray) to High(NewArray) do
+ begin
+ NewChain := TList.Create;
+ NewArray[I] := NewChain;
+ end;
+ ChangeCapacity(NewArray);
+
+ // Transfer from old chains to new and drop old
+ for I := Low(FArray) to High(FArray) do
+ begin
+ OldChain := FArray[I];
+ for J := 0 to OldChain.Count - 1 do
+ begin
+ Association := IIntegerAssociation(OldChain[J]);
+ Hash := GetHash(Association.GetKey);
+ NewArray[Hash].Add(Pointer(Association));
+ end;
+ OldChain.Free;
+ end;
+ FArray := NewArray;
+
+ // Find actual, new capacity
+ Total := 0;
+ for I := Low(FArray) to High(FArray) do
+ begin
+ NewChain := FArray[I];
+ Total := Total + NewChain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashIntegerMap.TrueClear;
+var
+ Association: IIntegerAssociation;
+ Chain: TList;
+ I, J: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ begin
+ Chain := FArray[I];
+ for J := 0 to Chain.Count - 1 do
+ begin
+ Association := IIntegerAssociation(Chain[J]);
+ Chain[J] := nil;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+ end;
+ Chain.Clear;
+ end;
+ FSize := 0;
+end;
+
+function THashIntegerMap.TrueGet(Position: TCollectionPosition): IIntegerAssociation;
+var
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Result := IIntegerAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+function THashIntegerMap.TruePut(Position: TCollectionPosition; const Association: IIntegerAssociation): IIntegerAssociation;
+var
+ HashPosition: THashPosition;
+ OldAssociation: IIntegerAssociation;
+begin
+ HashPosition := THashPosition(Position);
+ if HashPosition.Found then
+ begin
+ OldAssociation := IIntegerAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+ HashPosition.Chain.Items[HashPosition.Index] := Pointer(Association);
+ Result := OldAssociation;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._AddRef;
+ OldAssociation._Release;
+ end
+ else
+ begin
+ HashPosition.Chain.Add(Pointer(Association));
+ Inc(FSize);
+ Result := nil;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._AddRef;
+ end;
+end;
+
+function THashIntegerMap.TrueRemove2(Position: TCollectionPosition): IIntegerAssociation;
+var
+ Association: IIntegerAssociation;
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Association := IIntegerAssociation(TrueGet(Position));
+ HashPosition.Chain.Delete(HashPosition.Index);
+ Dec(FSize);
+ Result := Association;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+end;
+
+function THashIntegerMap.GetCapacity;
+begin
+ Result := FCapacity;
+end;
+
+procedure THashIntegerMap.SetCapacity(Value: Integer);
+begin
+ FCapacity := Value;
+ CheckLoadFactor(true);
+end;
+
+function THashIntegerMap.GetSize: Integer;
+begin
+ Result := FSize;
+end;
+
+{ THashStringMap }
+constructor THashStringMap.Create;
+begin
+ Create(false, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashStringMap.Create(NaturalItemsOnly: Boolean);
+begin
+ Create(NaturalItemsOnly, DefaultTableSize, DefaultMaxLoadFactor);
+end;
+
+constructor THashStringMap.Create(NaturalItemsOnly: Boolean; TableSize: Integer; MaxLoadFactor: Double = DefaultMaxLoadFactor);
+var
+ I: Integer;
+begin
+ inherited Create(NaturalItemsOnly);
+ SetLength(FArray, TableSize);
+ for I := Low(FArray) to High(FArray) do
+ FArray[I] := TList.Create;
+ FTableSize := TableSize;
+ FMaxLoadFactor := MaxLoadFactor;
+ FSize := 0;
+end;
+
+destructor THashStringMap.Destroy;
+var
+ I: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ FArray[I].Free;
+ FArray := nil;
+ inherited Destroy;
+end;
+
+function THashStringMap.GetAssociationIterator: IStringMapIterator;
+begin
+ Result := THashStringIterator.Create(Self);
+end;
+
+procedure THashStringMap.SetTableSize(Value: Integer);
+begin
+ if (FTableSize <> Value) and (Value >= 1) then
+ begin
+ FTableSize := Value;
+ Rehash;
+ end;
+end;
+
+procedure THashStringMap.SetMaxLoadFactor(Value: Double);
+begin
+ if (FMaxLoadFactor <> Value) and (Value >= MaxLoadFactorMin) then
+ begin
+ FMaxLoadFactor := Value;
+ CheckLoadFactor(false);
+ end;
+end;
+
+procedure THashStringMap.ChangeCapacity;
+var
+ Chain: TList;
+ I, Total, ChainCapacity: Integer;
+begin
+ if FCapacity mod FTableSize = 0 then
+ ChainCapacity := Trunc(FCapacity / FTableSize)
+ else
+ ChainCapacity := Trunc(FCapacity / FTableSize) + 1;
+ Total := 0;
+ for I := Low(Value) to High(Value) do
+ begin
+ Chain := Value[I];
+ Chain.Capacity := ChainCapacity;
+ Total := Total + Chain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashStringMap.CheckLoadFactor(AlwaysChangeCapacity: Boolean);
+var
+ LoadFactor: Double;
+begin
+ LoadFactor := Capacity / TableSize;
+ if LoadFactor > MaxLoadFactor then
+ TableSize := Trunc(Capacity / Max(MaxLoadFactor, MaxLoadFactorMin))
+ else if AlwaysChangeCapacity then
+ ChangeCapacity(FArray);
+end;
+
+function THashStringMap.GetHash(const Key: String): Integer;
+var
+ HashCode: Cardinal;
+ I: Integer;
+begin
+ HashCode := 0;
+ for I := 1 to Length(Key) do
+ HashCode := (HashCode shl 1) xor Ord(Key[I]);
+ Result := Trunc(Frac(HashCode * HashFactor) * TableSize);
+end;
+
+function THashStringMap.GetKeyPosition(const Key: String): TCollectionPosition;
+var
+ Chain: TList;
+ I: Integer;
+ Success: Boolean;
+begin
+ Chain := FArray[GetHash(Key)];
+ Success := false;
+ for I := 0 to Chain.Count - 1 do
+ begin
+ Success := (Key = IStringAssociation(Chain[I]).GetKey);
+ if Success then
+ Break;
+ end;
+ Result := THashPosition.Create(Success, Chain, I);
+end;
+
+procedure THashStringMap.Rehash;
+var
+ NewArray: TListArray;
+ OldChain, NewChain: TList;
+ Association: IStringAssociation;
+ Total: Integer;
+ I, J: Integer;
+ Hash: Integer;
+begin
+ // Create new chains
+ SetLength(NewArray, TableSize);
+ for I := Low(NewArray) to High(NewArray) do
+ begin
+ NewChain := TList.Create;
+ NewArray[I] := NewChain;
+ end;
+ ChangeCapacity(NewArray);
+
+ // Transfer from old chains to new and drop old
+ for I := Low(FArray) to High(FArray) do
+ begin
+ OldChain := FArray[I];
+ for J := 0 to OldChain.Count - 1 do
+ begin
+ Association := IStringAssociation(OldChain[J]);
+ Hash := GetHash(Association.GetKey);
+ NewArray[Hash].Add(Pointer(Association));
+ end;
+ OldChain.Free;
+ end;
+ FArray := NewArray;
+
+ // Find actual, new capacity
+ Total := 0;
+ for I := Low(FArray) to High(FArray) do
+ begin
+ NewChain := FArray[I];
+ Total := Total + NewChain.Capacity;
+ end;
+ FCapacity := Total;
+end;
+
+procedure THashStringMap.TrueClear;
+var
+ Association: IStringAssociation;
+ Chain: TList;
+ I, J: Integer;
+begin
+ for I := Low(FArray) to High(FArray) do
+ begin
+ Chain := FArray[I];
+ for J := 0 to Chain.Count - 1 do
+ begin
+ Association := IStringAssociation(Chain[J]);
+ Chain[J] := nil;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+ end;
+ Chain.Clear;
+ end;
+ FSize := 0;
+end;
+
+function THashStringMap.TrueGet(Position: TCollectionPosition): IStringAssociation;
+var
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Result := IStringAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+end;
+
+function THashStringMap.TruePut(Position: TCollectionPosition; const Association: IStringAssociation): IStringAssociation;
+var
+ HashPosition: THashPosition;
+ OldAssociation: IStringAssociation;
+begin
+ HashPosition := THashPosition(Position);
+ if HashPosition.Found then
+ begin
+ OldAssociation := IStringAssociation(HashPosition.Chain.Items[HashPosition.Index]);
+ HashPosition.Chain.Items[HashPosition.Index] := Pointer(Association);
+ Result := OldAssociation;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._AddRef;
+ OldAssociation._Release;
+ end
+ else
+ begin
+ HashPosition.Chain.Add(Pointer(Association));
+ Inc(FSize);
+ Result := nil;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._AddRef;
+ end;
+end;
+
+function THashStringMap.TrueRemove2(Position: TCollectionPosition): IStringAssociation;
+var
+ Association: IStringAssociation;
+ HashPosition: THashPosition;
+begin
+ HashPosition := THashPosition(Position);
+ Association := IStringAssociation(TrueGet(Position));
+ HashPosition.Chain.Delete(HashPosition.Index);
+ Dec(FSize);
+ Result := Association;
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+end;
+
+function THashStringMap.GetCapacity;
+begin
+ Result := FCapacity;
+end;
+
+procedure THashStringMap.SetCapacity(Value: Integer);
+begin
+ FCapacity := Value;
+ CheckLoadFactor(true);
+end;
+
+function THashStringMap.GetSize: Integer;
+begin
+ Result := FSize;
+end;
+
+{ THashPosition }
+constructor THashPosition.Create(Found: Boolean; Chain: TList; Index: Integer);
+begin
+ inherited Create(Found);
+ FChain := Chain;
+ FIndex := Index;
+end;
+
+{ THashIterator }
+constructor THashIterator.Create(HashSet: THashSet);
+begin
+ inherited Create(true);
+ FHashSet := HashSet;
+ First;
+end;
+
+function THashIterator.TrueFirst: ICollectable;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ FHash := 0;
+ FChainIndex := 0;
+ Success := false;
+ while FHash < FHashSet.TableSize do
+ begin
+ Chain := FHashSet.FArray[FHash];
+ Success := Chain.Count > 0;
+ if Success then
+ Break;
+ Inc(FHash);
+ end;
+ if Success then
+ Result := ICollectable(FHashSet.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+function THashIterator.TrueNext: ICollectable;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ Success := false;
+ Chain := FHashSet.FArray[FHash];
+ repeat
+ Inc(FChainIndex);
+ if FChainIndex >= Chain.Count then
+ begin
+ Inc(FHash);
+ FChainIndex := -1;
+ if FHash < FHashSet.TableSize then
+ Chain := FHashSet.FArray[FHash];
+ end
+ else
+ Success := true;
+ until Success or (FHash >= FHashSet.TableSize);
+ if Success then
+ Result := ICollectable(FHashSet.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+procedure THashIterator.TrueRemove;
+var
+ Item: ICollectable;
+begin
+ Item := ICollectable(FHashSet.FArray[FHash].Items[FChainIndex]);
+ FHashSet.FArray[FHash].Delete(FChainIndex);
+ Dec(FChainIndex);
+ Dec(FHashSet.FSize);
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Item._Release;
+end;
+
+
+{ THashAssociationIterator }
+constructor THashAssociationIterator.Create(HashMap: THashMap);
+begin
+ inherited Create(true);
+ FHashMap := HashMap;
+ First;
+end;
+
+function THashAssociationIterator.TrueFirst: IAssociation;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ FHash := 0;
+ FChainIndex := 0;
+ Success := false;
+ while FHash < FHashMap.TableSize do
+ begin
+ Chain := FHashMap.FArray[FHash];
+ Success := Chain.Count > 0;
+ if Success then
+ Break;
+ Inc(FHash);
+ end;
+ if Success then
+ Result := IAssociation(FHashMap.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+function THashAssociationIterator.TrueNext: IAssociation;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ Success := false;
+ Chain := FHashMap.FArray[FHash];
+ repeat
+ Inc(FChainIndex);
+ if FChainIndex >= Chain.Count then
+ begin
+ Inc(FHash);
+ FChainIndex := -1;
+ if FHash < FHashMap.TableSize then
+ Chain := FHashMap.FArray[FHash];
+ end
+ else
+ Success := true;
+ until Success or (FHash >= FHashMap.TableSize);
+ if Success then
+ Result := IAssociation(FHashMap.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+procedure THashAssociationIterator.TrueRemove;
+var
+ Association: IAssociation;
+begin
+ Association := IAssociation(FHashMap.FArray[FHash].Items[FChainIndex]);
+ FHashMap.FArray[FHash].Delete(FChainIndex);
+ Dec(FChainIndex);
+ Dec(FHashMap.FSize);
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+end;
+
+
+{ THashIntegerIterator }
+constructor THashIntegerIterator.Create(HashIntegerMap: THashIntegerMap);
+begin
+ inherited Create(true);
+ FHashIntegerMap := HashIntegerMap;
+ First;
+end;
+
+function THashIntegerIterator.TrueFirst: IIntegerAssociation;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ FHash := 0;
+ FChainIndex := 0;
+ Success := false;
+ while FHash < FHashIntegerMap.TableSize do
+ begin
+ Chain := FHashIntegerMap.FArray[FHash];
+ Success := Chain.Count > 0;
+ if Success then
+ Break;
+ Inc(FHash);
+ end;
+ if Success then
+ Result := IIntegerAssociation(FHashIntegerMap.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+function THashIntegerIterator.TrueNext: IIntegerAssociation;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ Success := false;
+ Chain := FHashIntegerMap.FArray[FHash];
+ repeat
+ Inc(FChainIndex);
+ if FChainIndex >= Chain.Count then
+ begin
+ Inc(FHash);
+ FChainIndex := -1;
+ if FHash < FHashIntegerMap.TableSize then
+ Chain := FHashIntegerMap.FArray[FHash];
+ end
+ else
+ Success := true;
+ until Success or (FHash >= FHashIntegerMap.TableSize);
+ if Success then
+ Result := IIntegerAssociation(FHashIntegerMap.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+procedure THashIntegerIterator.TrueRemove;
+var
+ Association: IIntegerAssociation;
+begin
+ Association := IIntegerAssociation(FHashIntegerMap.FArray[FHash].Items[FChainIndex]);
+ FHashIntegerMap.FArray[FHash].Delete(FChainIndex);
+ Dec(FChainIndex);
+ Dec(FHashIntegerMap.FSize);
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+end;
+
+{ THashStringIterator }
+constructor THashStringIterator.Create(HashStringMap: THashStringMap);
+begin
+ inherited Create(true);
+ FHashStringMap := HashStringMap;
+ First;
+end;
+
+function THashStringIterator.TrueFirst: IStringAssociation;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ FHash := 0;
+ FChainIndex := 0;
+ Success := false;
+ while FHash < FHashStringMap.TableSize do
+ begin
+ Chain := FHashStringMap.FArray[FHash];
+ Success := Chain.Count > 0;
+ if Success then
+ Break;
+ Inc(FHash);
+ end;
+ if Success then
+ Result := IStringAssociation(FHashStringMap.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+function THashStringIterator.TrueNext: IStringAssociation;
+var
+ Chain: TList;
+ Success: Boolean;
+begin
+ Success := false;
+ Chain := FHashStringMap.FArray[FHash];
+ repeat
+ Inc(FChainIndex);
+ if FChainIndex >= Chain.Count then
+ begin
+ Inc(FHash);
+ FChainIndex := -1;
+ if FHash < FHashStringMap.TableSize then
+ Chain := FHashStringMap.FArray[FHash];
+ end
+ else
+ Success := true;
+ until Success or (FHash >= FHashStringMap.TableSize);
+ if Success then
+ Result := IStringAssociation(FHashStringMap.FArray[FHash].Items[FChainIndex])
+ else
+ Result := nil;
+end;
+
+procedure THashStringIterator.TrueRemove;
+var
+ Association: IStringAssociation;
+begin
+ Association := IStringAssociation(FHashStringMap.FArray[FHash].Items[FChainIndex]);
+ FHashStringMap.FArray[FHash].Delete(FChainIndex);
+ Dec(FChainIndex);
+ Dec(FHashStringMap.FSize);
+ // Storing interface reference as a pointer does not update reference
+ // count automatically, so this must be done manually
+ Association._Release;
+end;
+
+
+end.
diff --git a/unicode/src/lib/collections/CollLibrary.pas b/unicode/src/lib/collections/CollLibrary.pas
new file mode 100644
index 00000000..b7e3d268
--- /dev/null
+++ b/unicode/src/lib/collections/CollLibrary.pas
@@ -0,0 +1,131 @@
+unit CollLibrary;
+
+(*****************************************************************************
+ * 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.0.1.1 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollLibrary.qbt $
+ *
+ * Initial version.
+ *
+ * Revision 1.0.1.1 by: Matthew Greet Rev date: 24/10/03 16:48:16
+ * v1.0 branch.
+ *
+ * Revision 1.0 by: Matthew Greet Rev date: 06/04/03 10:40:32
+ * Initial revision.
+ *
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+{$IFDEF FPC}
+ {$MODE Delphi}{$H+}
+{$ENDIF}
+
+interface
+
+uses
+ Collections, CollArray, CollHash, CollList, CollPArray, CollWrappers;
+
+type
+ TMiscCollectionLibrary = class
+ public
+ class function ClassNameToClassType(ClassName: String): TAbstractCollectionClass;
+ class function EqualIID(const IID1, IID2: TGUID): Boolean;
+ class function HashCode(Value: String): Integer;
+ class procedure ShuffleArray(var ItemArray: array of ICollectable);
+ class procedure ShuffleList(const List: IList);
+ end;
+
+implementation
+
+{ TMiscCollectionLibrary }
+class function TMiscCollectionLibrary.ClassNameToClassType(ClassName: String): TAbstractCollectionClass;
+begin
+ if ClassName = 'TArray' then
+ Result := TArray
+ else if ClassName = 'THashSet' then
+ Result := THashSet
+ else if ClassName = 'THashMap' then
+ Result := THashMap
+ else if ClassName = 'THashIntegerMap' then
+ Result := THashIntegerMap
+ else if ClassName = 'THashStringMap' then
+ Result := THashStringMap
+ else if ClassName = 'TListSet' then
+ Result := TListSet
+ else if ClassName = 'TListMap' then
+ Result := TListMap
+ else if ClassName = 'TPArrayBag' then
+ Result := TPArrayBag
+ else if ClassName = 'TPArraySet' then
+ Result := TPArraySet
+ else if ClassName = 'TPArrayList' then
+ Result := TPArrayList
+ else if ClassName = 'TPArrayMap' then
+ Result := TPArrayMap
+ else
+ Result := nil;
+end;
+
+class function TMiscCollectionLibrary.EqualIID(const IID1, IID2: TGUID): Boolean;
+begin
+ Result := (IID1.D1 = IID2.D1) and (IID1.D2 = IID2.D2) and (IID1.D3 = IID2.D3) and
+ (IID1.D4[0] = IID2.D4[0]) and (IID1.D4[1] = IID2.D4[1]) and
+ (IID1.D4[2] = IID2.D4[2]) and (IID1.D4[3] = IID2.D4[3]) and
+ (IID1.D4[4] = IID2.D4[4]) and (IID1.D4[5] = IID2.D4[5]) and
+ (IID1.D4[6] = IID2.D4[6]) and (IID1.D4[7] = IID2.D4[7]);
+end;
+
+class function TMiscCollectionLibrary.HashCode(Value: String): Integer;
+var
+ I: Integer;
+begin
+ Result := 0;
+ for I := 1 to Length(Value) do
+ Result := (Result shl 1) xor Ord(Value[I]);
+end;
+
+class procedure TMiscCollectionLibrary.ShuffleArray(var ItemArray: array of ICollectable);
+var
+ Item: ICollectable;
+ ArraySize, I, Index: Integer;
+begin
+ Randomize;
+ ArraySize := Length(ItemArray);
+ for I := 0 to ArraySize - 1 do
+ begin
+ Index := (I + Random(ArraySize - 1) + 1) mod ArraySize;
+ Item := ItemArray[I];
+ ItemArray[I] := ItemArray[Index];
+ ItemArray[Index] := Item;
+ end;
+end;
+
+class procedure TMiscCollectionLibrary.ShuffleList(const List: IList);
+var
+ ListSize, I: Integer;
+begin
+ Randomize;
+ ListSize := List.GetSize;
+ for I := 0 to ListSize - 1 do
+ begin
+ List.Exchange(I, (I + Random(ListSize - 1) + 1) mod ListSize);
+ end;
+end;
+
+
+end.
diff --git a/unicode/src/lib/collections/CollList.pas b/unicode/src/lib/collections/CollList.pas
new file mode 100644
index 00000000..68aa0d66
--- /dev/null
+++ b/unicode/src/lib/collections/CollList.pas
@@ -0,0 +1,270 @@
+unit CollList;
+
+(*****************************************************************************
+ * 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.1.1.2 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollList.qbt $
+ *
+ * Collection implementations based on sorted TPArrayList instances.
+ *
+ * Revision 1.1.1.2 by: Matthew Greet Rev date: 12/06/04 20:05:54
+ * Capacity property.
+ *
+ * Revision 1.1.1.1 by: Matthew Greet Rev date: 14/02/04 17:45:38
+ * v1.0 branch.
+ *
+ * Revision 1.1 by: Matthew Greet Rev date: 06/04/03 10:41:52
+ * Uses TExposedPArrayList to improve performance.
+ *
+ * Revision 1.0 by: Matthew Greet Rev date: 01/03/03 10:50:02
+ * Initial revision.
+ *
+ * FPC compatibility fixes by: UltraStar Deluxe Team
+ *
+ * $Endlog$
+ *****************************************************************************)
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}{$H+}
+{$ENDIF}
+
+uses
+ Collections, CollPArray;
+
+type
+ TListSet = class(TAbstractSet)
+ private
+ FList: TExposedPArrayList;
+ 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 GetNaturalItemIID: TGUID; override;
+ function GetSize: Integer; override;
+ end;
+
+ TListMap = class(TAbstractMap)
+ private
+ FList: TExposedPArrayList;
+ 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;
+ procedure SetKeyComparator(const Value: IComparator); override;
+ function GetNaturalKeyIID: TGUID; override;
+ function GetSize: Integer; override;
+ end;
+
+implementation
+
+type
+ TListPosition = class(TCollectionPosition)
+ private
+ FSearchResult: TSearchResult;
+ public
+ constructor Create(Found: Boolean; SearchResult: TSearchResult);
+ property SearchResult: TSearchResult read FSearchResult;
+ end;
+
+constructor TListSet.Create(NaturalItemsOnly: Boolean);
+begin
+ inherited Create(NaturalItemsOnly);
+ FList := TExposedPArrayList.Create(NaturalItemsOnly);
+ FList.Comparator := Comparator;
+ FList.Sort;
+end;
+
+destructor TListSet.Destroy;
+begin
+ FList.Free;
+ inherited Destroy;
+end;
+
+function TListSet.GetPosition(const Item: ICollectable): TCollectionPosition;
+var
+ SearchResult: TSearchResult;
+begin
+ SearchResult := FList.Search(Item);
+ Result := TListPosition.Create((SearchResult.ResultType = srFoundAtIndex), SearchResult);
+end;
+
+procedure TListSet.TrueAdd2(Position: TCollectionPosition; const Item: ICollectable);
+var
+ SearchResult: TSearchResult;
+ Index: Integer;
+begin
+ SearchResult := TListPosition(Position).SearchResult;
+ Index := SearchResult.Index;
+ if SearchResult.ResultType = srBeforeIndex then
+ FList.TrueInsert(Index, Item)
+ else
+ FList.TrueAppend(Item);
+end;
+
+procedure TListSet.TrueClear;
+begin
+ FList.Clear;
+end;
+
+function TListSet.TrueGet(Position: TCollectionPosition): ICollectable;
+begin
+ Result := FList.Items[TListPosition(Position).SearchResult.Index];
+end;
+
+procedure TListSet.TrueRemove2(Position: TCollectionPosition);
+begin
+ FList.Delete(TListPosition(Position).SearchResult.Index);
+end;
+
+function TListSet.GetCapacity: Integer;
+begin
+ Result := FList.Capacity;
+end;
+
+procedure TListSet.SetCapacity(Value: Integer);
+begin
+ FList.Capacity := Value;
+end;
+
+function TListSet.GetIterator: IIterator;
+begin
+ Result := FList.GetIterator;
+end;
+
+function TListSet.GetNaturalItemIID: TGUID;
+begin
+ Result := ComparableIID;
+end;
+
+function TListSet.GetSize: Integer;
+begin
+ Result := FList.Size;
+end;
+
+constructor TListMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+begin
+ inherited Create(NaturalItemsOnly, NaturalKeysOnly);
+ FList := TExposedPArrayList.Create(false);
+ FList.Comparator := AssociationComparator;
+ FList.Sort;
+end;
+
+destructor TListMap.Destroy;
+begin
+ FList.Free;
+ inherited Destroy;
+end;
+
+function TListMap.GetAssociationIterator: IMapIterator;
+begin
+ Result := TAssociationIterator.Create(FList.GetIterator);
+end;
+
+function TListMap.GetKeyPosition(const Key: ICollectable): TCollectionPosition;
+var
+ Association: IAssociation;
+ SearchResult: TSearchResult;
+begin
+ Association := TAssociation.Create(Key, nil);
+ SearchResult := FList.Search(Association);
+ Result := TListPosition.Create((SearchResult.ResultType = srFoundAtIndex), SearchResult);
+end;
+
+procedure TListMap.TrueClear;
+begin
+ FList.Clear;
+end;
+
+function TListMap.TrueGet(Position: TCollectionPosition): IAssociation;
+begin
+ Result := (FList.Items[TListPosition(Position).SearchResult.Index]) as IAssociation;
+end;
+
+function TListMap.TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation;
+var
+ SearchResult: TSearchResult;
+ Index: Integer;
+begin
+ SearchResult := TListPosition(Position).SearchResult;
+ Index := SearchResult.Index;
+ if SearchResult.ResultType = srFoundAtIndex then
+ begin
+ Result := (FList.Items[Index]) as IAssociation;
+ FList.Items[Index] := Association;
+ end
+ else if SearchResult.ResultType = srBeforeIndex then
+ FList.TrueInsert(Index, Association)
+ else
+ FList.TrueAppend(Association);
+end;
+
+function TListMap.TrueRemove2(Position: TCollectionPosition): IAssociation;
+begin
+ Result := (FList.Items[TListPosition(Position).SearchResult.Index]) as IAssociation;
+ FList.Delete(TListPosition(Position).SearchResult.Index);
+end;
+
+procedure TListMap.SetKeyComparator(const Value: IComparator);
+begin
+ inherited SetKeyComparator(Value);
+ FList.Sort;
+end;
+
+function TListMap.GetCapacity: Integer;
+begin
+ Result := FList.Capacity;
+end;
+
+procedure TListMap.SetCapacity(Value: Integer);
+begin
+ FList.Capacity := Value;
+end;
+
+function TListMap.GetNaturalKeyIID: TGUID;
+begin
+ Result := ComparableIID;
+end;
+
+function TListMap.GetSize: Integer;
+begin
+ Result := FList.Size;
+end;
+
+constructor TListPosition.Create(Found: Boolean; SearchResult: TSearchResult);
+begin
+ inherited Create(Found);
+ FSearchResult := SearchResult;
+end;
+
+end.
diff --git a/unicode/src/lib/collections/CollPArray.pas b/unicode/src/lib/collections/CollPArray.pas
new file mode 100644
index 00000000..5ebd534b
--- /dev/null
+++ b/unicode/src/lib/collections/CollPArray.pas
@@ -0,0 +1,689 @@
+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.
diff --git a/unicode/src/lib/collections/CollWrappers.pas b/unicode/src/lib/collections/CollWrappers.pas
new file mode 100644
index 00000000..513103a2
--- /dev/null
+++ b/unicode/src/lib/collections/CollWrappers.pas
@@ -0,0 +1,876 @@
+unit CollWrappers;
+
+(*****************************************************************************
+ * 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.1.1.1 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\CollWrappers.qbt $
+ *
+ * Various primitive type wrappers, adapters and abstract base classes for
+ * natural items.
+ *
+ * Revision 1.1.1.1 by: Matthew Greet Rev date: 24/10/03 16:48:16
+ * v1.0 branch.
+ *
+ * Revision 1.1 by: Matthew Greet Rev date: 06/04/03 10:51:04
+ * Primitive type wrapper interfaces added.
+ * Abstract, template classes added.
+ * All classes implement reference counting by descending from
+ * TInterfacedObject.
+ *
+ *
+ * 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
+ SysUtils,
+ Collections;
+
+type
+ IAssociationWrapper = interface
+ ['{54DF42E0-64F2-11D7-8120-0002E3165EF8}']
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetKey: ICollectable;
+ function GetValue: TObject;
+ property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+ property Key: ICollectable read GetKey;
+ property Value: TObject read GetValue;
+ end;
+
+ IBoolean = interface
+ ['{62D1D160-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: Boolean;
+ property Value: Boolean read GetValue;
+ end;
+
+ ICardinal = interface
+ ['{6AF7B1C0-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: Cardinal;
+ property Value: Cardinal read GetValue;
+ end;
+
+ IChar = interface
+ ['{73AD00E0-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: Char;
+ property Value: Char read GetValue;
+ end;
+
+ IClass = interface
+ ['{7A84B660-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: TClass;
+ property Value: TClass read GetValue;
+ end;
+
+ IDouble = interface
+ ['{815C6BE0-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: Double;
+ property Value: Double read GetValue;
+ end;
+
+ IInteger = interface
+ ['{88ECC300-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: Integer;
+ property Value: Integer read GetValue;
+ end;
+
+ IIntegerAssociationWrapper = interface
+ ['{8F582220-64F2-11D7-8120-0002E3165EF8}']
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetKey: Integer;
+ function GetValue: TObject;
+ property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+ property Key: Integer read GetKey;
+ property Value: TObject read GetValue;
+ end;
+
+ IInterfaceWrapper = interface
+ ['{962E5100-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: IUnknown;
+ property Value: IUnknown read GetValue;
+ end;
+
+ IObject = interface
+ ['{9C675580-64F2-11D7-8120-0002E3165EF8}']
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetValue: TObject;
+ property Value: TObject read GetValue;
+ end;
+
+ IString = interface
+ ['{A420DF80-64F2-11D7-8120-0002E3165EF8}']
+ function GetValue: String;
+ property Value: String read GetValue;
+ end;
+
+ IStringAssociationWrapper = interface
+ ['{AB98CCA0-64F2-11D7-8120-0002E3165EF8}']
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetKey: String;
+ function GetValue: TObject;
+ property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+ property Key: String read GetKey;
+ property Value: TObject read GetValue;
+ end;
+
+ TAbstractItem = class(TInterfacedObject, ICollectable)
+ public
+ function GetInstance: TObject; virtual;
+ end;
+
+ TAbstractIntegerMappable = class(TAbstractItem, IEquatable, IIntegerMappable)
+ private
+ FKey: Integer;
+ protected
+ function MakeKey: Integer; virtual; abstract;
+ public
+ procedure AfterConstruction; override;
+ function Equals(const Item: ICollectable): Boolean; virtual;
+ function GetKey: Integer; virtual;
+ end;
+
+ TAbstractMappable = class(TAbstractItem, IEquatable, IMappable)
+ private
+ FKey: ICollectable;
+ protected
+ function MakeKey: ICollectable; virtual; abstract;
+ public
+ destructor Destroy; override;
+ procedure AfterConstruction; override;
+ function Equals(const Item: ICollectable): Boolean; virtual;
+ function GetKey: ICollectable; virtual;
+ end;
+
+ TAbstractStringMappable = class(TAbstractItem, IEquatable, IStringMappable)
+ private
+ FKey: String;
+ protected
+ function MakeKey: String; virtual; abstract;
+ public
+ procedure AfterConstruction; override;
+ function Equals(const Item: ICollectable): Boolean; virtual;
+ function GetKey: String; virtual;
+ end;
+
+ TAssociationWrapper = class(TAbstractItem, IEquatable, IMappable, IAssociationWrapper)
+ private
+ FAutoDestroy: Boolean;
+ FKey: ICollectable;
+ FValue: TObject;
+ public
+ constructor Create(const Key: ICollectable; Value: TObject); overload;
+ constructor Create(Key: Integer; Value: TObject); overload;
+ constructor Create(Key: String; Value: TObject); overload;
+ constructor Create(Key, Value: TObject; AutoDestroyKey: Boolean = true); overload;
+ destructor Destroy; override;
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetKey: ICollectable;
+ function GetValue: TObject;
+ function Equals(const Item: ICollectable): Boolean;
+ property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+ property Key: ICollectable read GetKey;
+ property Value: TObject read GetValue;
+ end;
+
+ TBooleanWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IBoolean)
+ private
+ FValue: Boolean;
+ public
+ constructor Create(Value: Boolean);
+ function GetValue: Boolean;
+ function CompareTo(const Item: ICollectable): Integer;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ property Value: Boolean read GetValue;
+ end;
+
+ TCardinalWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, ICardinal)
+ private
+ FValue: Cardinal;
+ public
+ constructor Create(Value: Cardinal);
+ function GetValue: Cardinal;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ function CompareTo(const Item: ICollectable): Integer;
+ property Value: Cardinal read GetValue;
+ end;
+
+ TCharWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IChar)
+ private
+ FValue: Char;
+ public
+ constructor Create(Value: Char);
+ function GetValue: Char;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ function CompareTo(const Item: ICollectable): Integer;
+ property Value: Char read GetValue;
+ end;
+
+ TClassWrapper = class(TAbstractItem, IEquatable, IHashable, IClass)
+ private
+ FValue: TClass;
+ public
+ constructor Create(Value: TClass);
+ function GetValue: TClass;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ property Value: TClass read GetValue;
+ end;
+
+ TDoubleWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IDouble)
+ private
+ FValue: Double;
+ public
+ constructor Create(Value: Double);
+ function GetValue: Double;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ function CompareTo(const Item: ICollectable): Integer;
+ property Value: Double read GetValue;
+ end;
+
+ TIntegerWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IInteger)
+ private
+ FValue: Integer;
+ public
+ constructor Create(Value: Integer);
+ function GetValue: Integer;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ function CompareTo(const Item: ICollectable): Integer;
+ property Value: Integer read GetValue;
+ end;
+
+ TIntegerAssociationWrapper = class(TAbstractItem, IEquatable, IIntegerMappable, IIntegerAssociationWrapper)
+ private
+ FAutoDestroy: Boolean;
+ FKey: Integer;
+ FValue: TObject;
+ public
+ constructor Create(const Key: Integer; Value: TObject); overload;
+ destructor Destroy; override;
+ function Equals(const Item: ICollectable): Boolean;
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetKey: Integer;
+ function GetValue: TObject;
+ property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+ property Key: Integer read GetKey;
+ property Value: TObject read GetValue;
+ end;
+
+ TInterfaceWrapper = class(TAbstractItem, IHashable, IEquatable, IInterfaceWrapper)
+ private
+ FValue: IUnknown;
+ public
+ constructor Create(const Value: IUnknown);
+ destructor Destroy; override;
+ function GetValue: IUnknown;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ property Value: IUnknown read GetValue;
+ end;
+
+ TObjectWrapper = class(TAbstractItem, IEquatable, IComparable, IHashable, IObject)
+ private
+ FAutoDestroy: Boolean;
+ FValue: TObject;
+ public
+ constructor Create(Value: TObject); overload;
+ destructor Destroy; override;
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetValue: TObject;
+ function CompareTo(const Item: ICollectable): Integer;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ property AutoDestroy: Boolean read FAutoDestroy write FAutoDestroy;
+ property Value: TObject read GetValue;
+ end;
+
+ TStringWrapper = class(TAbstractItem, IEquatable, IHashable, IComparable, IString)
+ private
+ FValue: String;
+ public
+ constructor Create(Value: String);
+ function GetValue: String;
+ function Equals(const Item: ICollectable): Boolean;
+ function HashCode: Integer;
+ function CompareTo(const Item: ICollectable): Integer;
+ property Value: String read FValue;
+ end;
+
+ TStringAssociationWrapper = class(TAbstractItem, IEquatable, IStringMappable, IStringAssociationWrapper)
+ private
+ FAutoDestroy: Boolean;
+ FKey: String;
+ FValue: TObject;
+ public
+ constructor Create(const Key: String; Value: TObject); overload;
+ destructor Destroy; override;
+ function GetAutoDestroy: Boolean;
+ procedure SetAutoDestroy(Value: Boolean);
+ function GetKey: String;
+ function GetValue: TObject;
+ function Equals(const Item: ICollectable): Boolean;
+ property AutoDestroy: Boolean read GetAutoDestroy write SetAutoDestroy;
+ property Key: String read GetKey;
+ property Value: TObject read GetValue;
+ end;
+
+implementation
+
+{ TAbstractItem }
+function TAbstractItem.GetInstance: TObject;
+begin
+ Result := Self;
+end;
+
+
+{ TAbstractIntegerMappable }
+procedure TAbstractIntegerMappable.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ FKey := MakeKey;
+end;
+
+function TAbstractIntegerMappable.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self = Item.GetInstance);
+end;
+
+function TAbstractIntegerMappable.GetKey: Integer;
+begin
+ Result := FKey;
+end;
+
+{ TAbstractMappable }
+destructor TAbstractMappable.Destroy;
+begin
+ FKey := nil;
+ inherited Destroy;
+end;
+
+procedure TAbstractMappable.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ FKey := MakeKey;
+end;
+
+function TAbstractMappable.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self = Item.GetInstance);
+end;
+
+function TAbstractMappable.GetKey: ICollectable;
+begin
+ Result := FKey;
+end;
+
+{ TAbstractStringMappable }
+procedure TAbstractStringMappable.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ FKey := MakeKey;
+end;
+
+function TAbstractStringMappable.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self = Item.GetInstance);
+end;
+
+function TAbstractStringMappable.GetKey: String;
+begin
+ Result := FKey;
+end;
+
+{ TAssociationWrapper }
+constructor TAssociationWrapper.Create(const Key: ICollectable; Value: TObject);
+begin
+ inherited Create;
+ FAutoDestroy := true;
+ FKey := Key;
+ FValue := Value;
+end;
+
+constructor TAssociationWrapper.Create(Key: Integer; Value: TObject);
+begin
+ Create(TIntegerWrapper.Create(Key) as ICollectable, Value);
+end;
+
+constructor TAssociationWrapper.Create(Key: String; Value: TObject);
+begin
+ Create(TStringWrapper.Create(Key) as ICollectable, Value);
+end;
+
+constructor TAssociationWrapper.Create(Key, Value: TObject; AutoDestroyKey: Boolean);
+var
+ KeyWrapper: TObjectWrapper;
+begin
+ KeyWrapper := TObjectWrapper.Create(Key);
+ KeyWrapper.AutoDestroy := AutoDestroyKey;
+ Create(KeyWrapper as ICollectable, Value);
+end;
+
+destructor TAssociationWrapper.Destroy;
+begin
+ if FAutoDestroy then
+ FValue.Free;
+ FKey := nil;
+ inherited Destroy;
+end;
+
+function TAssociationWrapper.GetAutoDestroy: Boolean;
+begin
+ Result := FAutoDestroy;
+end;
+
+procedure TAssociationWrapper.SetAutoDestroy(Value: Boolean);
+begin
+ FAutoDestroy := Value;
+end;
+
+function TAssociationWrapper.GetKey: ICollectable;
+begin
+ Result := FKey;
+end;
+
+function TAssociationWrapper.GetValue: TObject;
+begin
+ Result := FValue;
+end;
+
+function TAssociationWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TAssociationWrapper).Value)
+end;
+
+{ TCardinalWrapper }
+constructor TCardinalWrapper.Create(Value: Cardinal);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+function TCardinalWrapper.GetValue: Cardinal;
+begin
+ Result := FValue;
+end;
+
+function TCardinalWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TCardinalWrapper).Value)
+end;
+
+function TCardinalWrapper.HashCode: Integer;
+begin
+ Result := FValue;
+end;
+
+function TCardinalWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+ Value2: Cardinal;
+begin
+ Value2 := (Item.GetInstance as TCardinalWrapper).Value;
+ if Value < Value2 then
+ Result := -1
+ else if Value > Value2 then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+{ TBooleanWrapper }
+constructor TBooleanWrapper.Create(Value: Boolean);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+function TBooleanWrapper.GetValue: Boolean;
+begin
+ Result := FValue;
+end;
+
+function TBooleanWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TBooleanWrapper).Value)
+end;
+
+function TBooleanWrapper.HashCode: Integer;
+begin
+ Result := Ord(FValue);
+end;
+
+function TBooleanWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+ Value2: Boolean;
+begin
+ Value2 := (Item.GetInstance as TBooleanWrapper).Value;
+ if not Value and Value2 then
+ Result := -1
+ else if Value and not Value2 then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+{ TCharWrapper }
+constructor TCharWrapper.Create(Value: Char);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+function TCharWrapper.GetValue: Char;
+begin
+ Result := FValue;
+end;
+
+function TCharWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TCharWrapper).Value)
+end;
+
+function TCharWrapper.HashCode: Integer;
+begin
+ Result := Integer(FValue);
+end;
+
+function TCharWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+ Value2: Char;
+begin
+ Value2 := (Item.GetInstance as TCharWrapper).Value;
+ if Value < Value2 then
+ Result := -1
+ else if Value > Value2 then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+{ TClassWrapper }
+constructor TClassWrapper.Create(Value: TClass);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+function TClassWrapper.GetValue: TClass;
+begin
+ Result := FValue;
+end;
+
+function TClassWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TClassWrapper).Value)
+end;
+
+function TClassWrapper.HashCode: Integer;
+begin
+ Result := Integer(FValue.ClassInfo);
+end;
+
+{ TDoubleWrapper }
+constructor TDoubleWrapper.Create(Value: Double);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+function TDoubleWrapper.GetValue: Double;
+begin
+ Result := FValue;
+end;
+
+function TDoubleWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TDoubleWrapper).Value)
+end;
+
+function TDoubleWrapper.HashCode: Integer;
+var
+ DblAsInt: array[0..1] of Integer;
+begin
+ Double(DblAsInt) := Value;
+ Result := DblAsInt[0] xor DblAsInt[1];
+end;
+
+function TDoubleWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+ Value2: Double;
+begin
+ Value2 := (Item.GetInstance as TDoubleWrapper).Value;
+ if Value < Value2 then
+ Result := -1
+ else if Value > Value2 then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+{ TIntegerWrapper }
+constructor TIntegerWrapper.Create(Value: Integer);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+function TIntegerWrapper.GetValue: Integer;
+begin
+ Result := FValue;
+end;
+
+function TIntegerWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TIntegerWrapper).Value)
+end;
+
+function TIntegerWrapper.HashCode: Integer;
+begin
+ Result := FValue;
+end;
+
+function TIntegerWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+ Value2: Integer;
+begin
+ Value2 := (Item.GetInstance as TIntegerWrapper).Value;
+ if Value < Value2 then
+ Result := -1
+ else if Value > Value2 then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+{ TIntegerAssociationWrapper }
+constructor TIntegerAssociationWrapper.Create(const Key: Integer; Value: TObject);
+begin
+ inherited Create;
+ FAutoDestroy := true;
+ FKey := Key;
+ FValue := Value;
+end;
+
+destructor TIntegerAssociationWrapper.Destroy;
+begin
+ if FAutoDestroy then
+ FValue.Free;
+ inherited Destroy;
+end;
+
+function TIntegerAssociationWrapper.GetAutoDestroy: Boolean;
+begin
+ Result := FAutoDestroy;
+end;
+
+procedure TIntegerAssociationWrapper.SetAutoDestroy(Value: Boolean);
+begin
+ FAutoDestroy := Value;
+end;
+
+function TIntegerAssociationWrapper.GetValue: TObject;
+begin
+ Result := FValue;
+end;
+
+function TIntegerAssociationWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TIntegerAssociationWrapper).Value)
+end;
+
+function TIntegerAssociationWrapper.GetKey: Integer;
+begin
+ Result := FKey;
+end;
+
+{ TStringAssociationWrapper }
+constructor TStringAssociationWrapper.Create(const Key: String; Value: TObject);
+begin
+ inherited Create;
+ FAutoDestroy := true;
+ FKey := Key;
+ FValue := Value;
+end;
+
+destructor TStringAssociationWrapper.Destroy;
+begin
+ if FAutoDestroy then
+ FValue.Free;
+ inherited Destroy;
+end;
+
+function TStringAssociationWrapper.GetAutoDestroy: Boolean;
+begin
+ Result := FAutoDestroy;
+end;
+
+procedure TStringAssociationWrapper.SetAutoDestroy(Value: Boolean);
+begin
+ FAutoDestroy := Value;
+end;
+
+function TStringAssociationWrapper.GetValue: TObject;
+begin
+ Result := FValue;
+end;
+
+function TStringAssociationWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TStringAssociationWrapper).Value)
+end;
+
+function TStringAssociationWrapper.GetKey: String;
+begin
+ Result := FKey;
+end;
+
+{ TInterfaceWrapper }
+constructor TInterfaceWrapper.Create(const Value: IUnknown);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+destructor TInterfaceWrapper.Destroy;
+begin
+ FValue := nil;
+ inherited Destroy;
+end;
+
+function TInterfaceWrapper.GetValue: IUnknown;
+begin
+ Result := FValue;
+end;
+
+function TInterfaceWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TInterfaceWrapper).Value)
+end;
+
+function TInterfaceWrapper.HashCode: Integer;
+begin
+ Result := Integer(Pointer(FValue));
+end;
+
+{ TObjectWrapper }
+constructor TObjectWrapper.Create(Value: TObject);
+begin
+ inherited Create;
+ FAutoDestroy := true;
+ FValue := Value;
+end;
+
+destructor TObjectWrapper.Destroy;
+begin
+ if FAutoDestroy then
+ FValue.Free;
+ inherited Destroy;
+end;
+
+function TObjectWrapper.GetAutoDestroy: Boolean;
+begin
+ Result := FAutoDestroy;
+end;
+
+procedure TObjectWrapper.SetAutoDestroy(Value: Boolean);
+begin
+ FAutoDestroy := Value;
+end;
+
+function TObjectWrapper.GetValue: TObject;
+begin
+ Result := FValue;
+end;
+
+function TObjectWrapper.CompareTo(const Item: ICollectable): Integer;
+var
+ Value1, Value2: Integer;
+begin
+ Value1 := Integer(Pointer(Self));
+ if Item <> nil then
+ Value2 := Integer(Pointer(Item))
+ else
+ Value2 := Low(Integer);
+ if (Value1 < Value2) then
+ Result := -1
+ else if (Value1 > Value2) then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+function TObjectWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TObjectWrapper).Value)
+end;
+
+function TObjectWrapper.HashCode: Integer;
+begin
+ Result := Integer(Pointer(FValue));
+end;
+
+{ TStringWrapper }
+constructor TStringWrapper.Create(Value: String);
+begin
+ inherited Create;
+ FValue := Value;
+end;
+
+function TStringWrapper.GetValue: String;
+begin
+ Result := FValue;
+end;
+
+function TStringWrapper.Equals(const Item: ICollectable): Boolean;
+begin
+ Result := (Self.Value = (Item.GetInstance as TStringWrapper).Value)
+end;
+
+function TStringWrapper.HashCode: Integer;
+var
+ I: Integer;
+begin
+ Result := 0;
+ for I := 1 to Length(FValue) do
+ Result := (Result shl 1) xor Ord(FValue[I]);
+end;
+
+function TStringWrapper.CompareTo(const Item: ICollectable): Integer;
+begin
+ Result := CompareStr(Self.Value, (Item.GetInstance as TStringWrapper).Value)
+end;
+
+
+end.
diff --git a/unicode/src/lib/collections/Collections.pas b/unicode/src/lib/collections/Collections.pas
new file mode 100644
index 00000000..0c94173d
--- /dev/null
+++ b/unicode/src/lib/collections/Collections.pas
@@ -0,0 +1,5318 @@
+unit Collections;
+(*****************************************************************************
+ * 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 $
+ * $Revision: 1.1.1.4 $
+ * $Log: D:\QVCS Repositories\Delphi Collections\Collections.qbt $
+ *
+ * Main unit containing all interface and abstract class definitions.
+ *
+ * Revision 1.1.1.4 by: Matthew Greet Rev date: 14/03/05 23:26:32
+ * Fixed RemoveAll for TAbstractList for sorted lists.
+ *
+ * Revision 1.1.1.3 by: Matthew Greet Rev date: 14/10/04 16:31:18
+ * Fixed memory lean in ContainsKey of TAbstractStringMap and
+ * TAbstractIntegerMap.
+ *
+ * Revision 1.1.1.2 by: Matthew Greet Rev date: 12/06/04 20:03:26
+ * Capacity property.
+ * Memory leak fixed.
+ *
+ * Revision 1.1.1.1 by: Matthew Greet Rev date: 13/02/04 16:12:10
+ * v1.0 branch.
+ *
+ * Revision 1.1 by: Matthew Greet Rev date: 06/04/03 10:36:30
+ * Added integer map and string map collection types with supporting
+ * classes.
+ * Add clone and filter functions with supporting classes.
+ * Added nil not allowed collection error.
+ * Properties appear in collection interfaces as well as abstract
+ * classes.
+ *
+ * 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, SysUtils;
+
+const
+ EquatableIID: TGUID = '{EAC823A7-0B90-11D7-8120-0002E3165EF8}';
+ HashableIID: TGUID = '{98998440-4C3E-11D7-8120-0002E3165EF8}';
+ ComparableIID: TGUID = '{9F4C96C0-0CF0-11D7-8120-0002E3165EF8}';
+ MappableIID: TGUID = '{DAEC8CA0-0DBB-11D7-8120-0002E3165EF8}';
+ StringMappableIID: TGUID = '{3CC61F40-5F92-11D7-8120-0002E3165EF8}';
+ IntegerMappableIID: TGUID = '{774FC760-5F92-11D7-8120-0002E3165EF8}';
+
+type
+ TDefaultComparator = class;
+ TNaturalComparator = class;
+ ICollectable = interface;
+
+ TCollectableArray = array of ICollectable;
+ TIntegerArray = array of Integer;
+ TStringArray = array of String;
+ TListArray = array of TList;
+
+ TCollectionError = (ceOK, ceDuplicate, ceDuplicateKey, ceFixedSize, ceNilNotAllowed, ceNotNaturalItem, ceOutOfRange);
+ TCollectionErrors = set of TCollectionError;
+
+ TSearchResultType = (srNotFound, srFoundAtIndex, srBeforeIndex, srAfterEnd);
+
+ TCollectionType = (ctBag, ctSet, ctList, ctMap, ctIntegerMap, ctStringMap);
+
+ TCollectionFilterFunc = function (const Item: ICollectable): Boolean of object;
+ TCollectionCompareFunc = function (const Item1, Item2: ICollectable): Integer of object;
+
+ TSearchResult = record
+ ResultType: TSearchResultType;
+ Index: Integer;
+ end;
+
+ ICollectable = interface
+ ['{98998441-4C3E-11D7-8120-0002E3165EF8}']
+ function GetInstance: TObject;
+ end;
+
+ IEquatable = interface
+ ['{EAC823A7-0B90-11D7-8120-0002E3165EF8}']
+ function GetInstance: TObject;
+ function Equals(const Item: ICollectable): Boolean;
+ end;
+
+ IHashable = interface(IEquatable)
+ ['{98998440-4C3E-11D7-8120-0002E3165EF8}']
+ function HashCode: Integer;
+ end;
+
+ IComparable = interface(IEquatable)
+ ['{9F4C96C0-0CF0-11D7-8120-0002E3165EF8}']
+ function CompareTo(const Item: ICollectable): Integer;
+ end;
+
+ IMappable = interface(IEquatable)
+ ['{DAEC8CA0-0DBB-11D7-8120-0002E3165EF8}']
+ function GetKey: ICollectable;
+ end;
+
+ IStringMappable = interface(IEquatable)
+ ['{3CC61F40-5F92-11D7-8120-0002E3165EF8}']
+ function GetKey: String;
+ end;
+
+ IIntegerMappable = interface(IEquatable)
+ ['{774FC760-5F92-11D7-8120-0002E3165EF8}']
+ function GetKey: Integer;
+ end;
+
+ IComparator = interface
+ ['{1F20CD60-10FE-11D7-8120-0002E3165EF8}']
+ function GetInstance: TObject;
+ function Compare(const Item1, Item2: ICollectable): Integer;
+ function Equals(const Item1, Item2: ICollectable): Boolean; overload;
+ function Equals(const Comparator: IComparator): Boolean; overload;
+ end;
+
+ IFilter = interface
+ ['{27FE44C0-638E-11D7-8120-0002E3165EF8}']
+ function Accept(const Item: ICollectable): Boolean;
+ end;
+
+ IIterator = interface
+ ['{F6930500-1113-11D7-8120-0002E3165EF8}']
+ function GetAllowRemoval: Boolean;
+ function CurrentItem: ICollectable;
+ function EOF: Boolean;
+ function First: ICollectable;
+ function Next: ICollectable;
+ function Remove: Boolean;
+ end;
+
+ IMapIterator = interface(IIterator)
+ ['{848CC0E0-2A31-11D7-8120-0002E3165EF8}']
+ function CurrentKey: ICollectable;
+ end;
+
+ IIntegerMapIterator = interface(IIterator)
+ ['{C7169780-606C-11D7-8120-0002E3165EF8}']
+ function CurrentKey: Integer;
+ end;
+
+ IStringMapIterator = interface(IIterator)
+ ['{1345ED20-5F93-11D7-8120-0002E3165EF8}']
+ function CurrentKey: String;
+ end;
+
+ IAssociation = interface(ICollectable)
+ ['{556CD700-4DB3-11D7-8120-0002E3165EF8}']
+ function GetKey: ICollectable;
+ function GetValue: ICollectable;
+ end;
+
+ IIntegerAssociation = interface(ICollectable)
+ ['{ED954420-5F94-11D7-8120-0002E3165EF8}']
+ function GetKey: Integer;
+ function GetValue: ICollectable;
+ end;
+
+ IStringAssociation = interface(ICollectable)
+ ['{FB87D2A0-5F94-11D7-8120-0002E3165EF8}']
+ function GetKey: String;
+ function GetValue: ICollectable;
+ end;
+
+ IAssociationComparator = interface(IComparator)
+ ['{EA9BE6E0-A852-11D8-B93A-0002E3165EF8}']
+ function GetKeyComparator: IComparator;
+ procedure SetKeyComparator(Value: IComparator);
+ property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+ end;
+
+ IIntegerAssociationComparator = interface(IComparator)
+ ['{EA9BE6E1-A852-11D8-B93A-0002E3165EF8}']
+ end;
+
+ IStringAssociationComparator = interface(IComparator)
+ ['{EA9BE6E2-A852-11D8-B93A-0002E3165EF8}']
+ end;
+
+ ICollection = interface
+ ['{EAC823AC-0B90-11D7-8120-0002E3165EF8}']
+ function GetAsArray: TCollectableArray;
+ function GetCapacity: Integer;
+ procedure SetCapacity(Value: Integer);
+ function GetComparator: IComparator;
+ procedure SetComparator(const Value: IComparator);
+ function GetDuplicates: Boolean;
+ function GetFixedSize: Boolean;
+ function GetIgnoreErrors: TCollectionErrors;
+ procedure SetIgnoreErrors(Value: TCollectionErrors);
+ function GetInstance: TObject;
+ function GetIterator: IIterator; overload;
+ function GetIterator(const Filter: IFilter): IIterator; overload;
+ function GetIterator(FilterFunc: TCollectionFilterFunc): IIterator; overload;
+ function GetNaturalItemIID: TGUID;
+ function GetNaturalItemsOnly: Boolean;
+ function GetSize: Integer;
+ function GetType: TCollectionType;
+ function Add(const Item: ICollectable): Boolean; overload;
+ function Add(const ItemArray: array of ICollectable): Integer; overload;
+ function Add(const Collection: ICollection): Integer; overload;
+ function Clear: Integer;
+ function Clone: ICollection;
+ function Contains(const Item: ICollectable): Boolean; overload;
+ function Contains(const ItemArray: array of ICollectable): Boolean; overload;
+ function Contains(const Collection: ICollection): Boolean; overload;
+ function Equals(const Collection: ICollection): Boolean;
+ function Find(const Filter: IFilter): ICollectable; overload;
+ function Find(FilterFunc: TCollectionFilterFunc): ICollectable; overload;
+ function FindAll(const Filter: IFilter = nil): ICollection; overload;
+ function FindAll(FilterFunc: TCollectionFilterFunc): ICollection; overload;
+ function IsEmpty: Boolean;
+ function IsNaturalItem(const Item: ICollectable): Boolean;
+ function IsNilAllowed: Boolean;
+ function ItemAllowed(const Item: ICollectable): TCollectionError;
+ function ItemCount(const Item: ICollectable): Integer; overload;
+ function ItemCount(const ItemArray: array of ICollectable): Integer; overload;
+ function ItemCount(const Collection: ICollection): Integer; overload;
+ function Matching(const ItemArray: array of ICollectable): ICollection; overload;
+ function Matching(const Collection: ICollection): ICollection; overload;
+ function Remove(const Item: ICollectable): ICollectable; overload;
+ function Remove(const ItemArray: array of ICollectable): ICollection; overload;
+ function Remove(const Collection: ICollection): ICollection; overload;
+ function RemoveAll(const Item: ICollectable): ICollection; overload;
+ function RemoveAll(const ItemArray: array of ICollectable): ICollection; overload;
+ function RemoveAll(const Collection: ICollection): ICollection; overload;
+ function Retain(const ItemArray: array of ICollectable): ICollection; overload;
+ function Retain(const Collection: ICollection): ICollection; overload;
+ property AsArray: TCollectableArray read GetAsArray;
+ property Capacity: Integer read GetCapacity write SetCapacity;
+ property Comparator: IComparator read GetComparator write SetComparator;
+ property FixedSize: Boolean read GetFixedSize;
+ property IgnoreErrors: TCollectionErrors read GetIgnoreErrors write SetIgnoreErrors;
+ property NaturalItemIID: TGUID read GetNaturalItemIID;
+ property NaturalItemsOnly: Boolean read GetNaturalItemsOnly;
+ property Size: Integer read GetSize;
+ end;
+
+ IBag = interface(ICollection)
+ ['{C29C9560-2D59-11D7-8120-0002E3165EF8}']
+ function CloneAsBag: IBag;
+ end;
+
+ ISet = interface(ICollection)
+ ['{DD7888E2-0BB1-11D7-8120-0002E3165EF8}']
+ function CloneAsSet: ISet;
+ function Complement(const Universe: ISet): ISet;
+ function Intersect(const Set2: ISet): ISet;
+ function Union(const Set2: ISet): ISet;
+ end;
+
+ IList = interface(ICollection)
+ ['{EE81AB60-0B9F-11D7-8120-0002E3165EF8}']
+ function GetDuplicates: Boolean;
+ procedure SetDuplicates(Value: Boolean);
+ function GetItem(Index: Integer): ICollectable;
+ procedure SetItem(Index: Integer; const Item: ICollectable);
+ function GetSorted: Boolean;
+ procedure SetSorted(Value: Boolean);
+ function CloneAsList: IList;
+ function Delete(Index: Integer): ICollectable;
+ procedure Exchange(Index1, Index2: Integer);
+ function First: ICollectable;
+ function IndexOf(const Item: ICollectable): Integer;
+ function Insert(Index: Integer; const Item: ICollectable): Boolean; overload;
+ function Insert(Index: Integer; const ItemArray: array of ICollectable): Integer; overload;
+ function Insert(Index: Integer; const Collection: ICollection): Integer; overload;
+ function Last: ICollectable;
+ procedure Sort(const Comparator: IComparator); overload;
+ procedure Sort(CompareFunc: TCollectionCompareFunc); overload;
+ property Duplicates: Boolean read GetDuplicates write SetDuplicates;
+ property Items[Index: Integer]: ICollectable read GetItem write SetItem; default;
+ property Sorted: Boolean read GetSorted write SetSorted;
+ end;
+
+ IMap = interface(ICollection)
+ ['{AD458280-2A6B-11D7-8120-0002E3165EF8}']
+ function GetItem(const Key: ICollectable): ICollectable;
+ procedure SetItem(const Key, Item: ICollectable);
+ function GetKeyComparator: IComparator;
+ procedure SetKeyComparator(const Value: IComparator);
+ function GetKeyIterator: IIterator;
+ function GetKeys: ISet;
+ function GetMapIterator: IMapIterator;
+ function GetMapIteratorByKey(const Filter: IFilter): IMapIterator; overload;
+ function GetMapIteratorByKey(FilterFunc: TCollectionFilterFunc): IMapIterator; overload;
+ function GetNaturalKeyIID: TGUID;
+ function GetNaturalKeysOnly: Boolean;
+ function GetValues: ICollection;
+ function CloneAsMap: IMap;
+ function ContainsKey(const Key: ICollectable): Boolean; overload;
+ function ContainsKey(const KeyArray: array of ICollectable): Boolean; overload;
+ function ContainsKey(const Collection: ICollection): Boolean; overload;
+ function Get(const Key: ICollectable): ICollectable;
+ function IsNaturalKey(const Key: ICollectable): Boolean;
+ function KeyAllowed(const Key: ICollectable): TCollectionError;
+ function MatchingKey(const KeyArray: array of ICollectable): ICollection; overload;
+ function MatchingKey(const Collection: ICollection): ICollection; overload;
+ function Put(const Item: ICollectable): ICollectable; overload;
+ function Put(const Key, Item: ICollectable): ICollectable; overload;
+ function Put(const ItemArray: array of ICollectable): ICollection; overload;
+ function Put(const Collection: ICollection): ICollection; overload;
+ function Put(const Map: IMap): ICollection; overload;
+ function RemoveKey(const Key: ICollectable): ICollectable; overload;
+ function RemoveKey(const KeyArray: array of ICollectable): ICollection; overload;
+ function RemoveKey(const Collection: ICollection): ICollection; overload;
+ function RetainKey(const KeyArray: array of ICollectable): ICollection; overload;
+ function RetainKey(const Collection: ICollection): ICollection; overload;
+ property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+ property Items[const Key: ICollectable]: ICollectable read GetItem write SetItem; default;
+ property NaturalKeyIID: TGUID read GetNaturalKeyIID;
+ property NaturalKeysOnly: Boolean read GetNaturalKeysOnly;
+ end;
+
+ IIntegerMap = interface(ICollection)
+ ['{93DBA9A0-606C-11D7-8120-0002E3165EF8}']
+ function GetItem(const Key: Integer): ICollectable;
+ procedure SetItem(const Key: Integer; const Item: ICollectable);
+ function GetKeys: ISet;
+ function GetMapIterator: IIntegerMapIterator;
+ function GetValues: ICollection;
+ function CloneAsIntegerMap: IIntegerMap;
+ function ContainsKey(const Key: Integer): Boolean; overload;
+ function ContainsKey(const KeyArray: array of Integer): Boolean; overload;
+ function Get(const Key: Integer): ICollectable;
+ function Put(const Item: ICollectable): ICollectable; overload;
+ function Put(const Key: Integer; const Item: ICollectable): ICollectable; overload;
+ function Put(const ItemArray: array of ICollectable): ICollection; overload;
+ function Put(const Collection: ICollection): ICollection; overload;
+ function Put(const Map: IIntegerMap): ICollection; overload;
+ function RemoveKey(const Key: Integer): ICollectable; overload;
+ function RemoveKey(const KeyArray: array of Integer): ICollection; overload;
+ function RetainKey(const KeyArray: array of Integer): ICollection; overload;
+ property Items[const Key: Integer]: ICollectable read GetItem write SetItem; default;
+ end;
+
+ IStringMap = interface(ICollection)
+ ['{20531A20-5F92-11D7-8120-0002E3165EF8}']
+ function GetItem(const Key: String): ICollectable;
+ procedure SetItem(const Key: String; const Item: ICollectable);
+ function GetKeys: ISet;
+ function GetMapIterator: IStringMapIterator;
+ function GetValues: ICollection;
+ function CloneAsStringMap: IStringMap;
+ function ContainsKey(const Key: String): Boolean; overload;
+ function ContainsKey(const KeyArray: array of String): Boolean; overload;
+ function Get(const Key: String): ICollectable;
+ function Put(const Item: ICollectable): ICollectable; overload;
+ function Put(const Key: String; const Item: ICollectable): ICollectable; overload;
+ function Put(const ItemArray: array of ICollectable): ICollection; overload;
+ function Put(const Collection: ICollection): ICollection; overload;
+ function Put(const Map: IStringMap): ICollection; overload;
+ function RemoveKey(const Key: String): ICollectable; overload;
+ function RemoveKey(const KeyArray: array of String): ICollection; overload;
+ function RetainKey(const KeyArray: array of String): ICollection; overload;
+ property Items[const Key: String]: ICollectable read GetItem write SetItem; default;
+ end;
+
+ TCollectionPosition = class
+ private
+ FFound: Boolean;
+ public
+ constructor Create(Found: Boolean);
+ property Found: Boolean read FFound;
+ end;
+
+ TAbstractComparator = class(TInterfacedObject, IComparator)
+ public
+ class function GetDefaultComparator: IComparator;
+ class function GetNaturalComparator: IComparator;
+ class function GetReverseNaturalComparator: IComparator;
+ function GetInstance: TObject;
+ function Compare(const Item1, Item2: ICollectable): Integer; virtual; abstract;
+ function Equals(const Item1, Item2: ICollectable): Boolean; overload; virtual; abstract;
+ function Equals(const Comparator: IComparator): Boolean; overload; virtual;
+ end;
+
+ TDefaultComparator = class(TAbstractComparator)
+ protected
+ constructor Create;
+ public
+ function Compare(const Item1, Item2: ICollectable): Integer; override;
+ function Equals(const Item1, Item2: ICollectable): Boolean; override;
+ end;
+
+ TNaturalComparator = class(TAbstractComparator)
+ protected
+ constructor Create;
+ public
+ function Compare(const Item1, Item2: ICollectable): Integer; override;
+ function Equals(const Item1, Item2: ICollectable): Boolean; override;
+ end;
+
+ TReverseNaturalComparator = class(TAbstractComparator)
+ protected
+ constructor Create;
+ public
+ function Compare(const Item1, Item2: ICollectable): Integer; override;
+ function Equals(const Item1, Item2: ICollectable): Boolean; override;
+ end;
+
+ TAssociation = class(TInterfacedObject, ICollectable, IAssociation)
+ private
+ FKey: ICollectable;
+ FValue: ICollectable;
+ public
+ constructor Create(const Key, Value: ICollectable); virtual;
+ destructor Destroy; override;
+ function GetInstance: TObject; virtual;
+ function GetKey: ICollectable;
+ function GetValue: ICollectable;
+ end;
+
+ TIntegerAssociation = class(TInterfacedObject, ICollectable, IIntegerAssociation)
+ private
+ FKey: Integer;
+ FValue: ICollectable;
+ public
+ constructor Create(const Key: Integer; const Value: ICollectable); virtual;
+ destructor Destroy; override;
+ function GetInstance: TObject; virtual;
+ function GetKey: Integer;
+ function GetValue: ICollectable;
+ end;
+
+ TStringAssociation = class(TInterfacedObject, ICollectable, IStringAssociation)
+ private
+ FKey: String;
+ FValue: ICollectable;
+ public
+ constructor Create(const Key: String; const Value: ICollectable); virtual;
+ destructor Destroy; override;
+ function GetInstance: TObject; virtual;
+ function GetKey: String;
+ function GetValue: ICollectable;
+ end;
+
+ TAssociationComparator = class(TAbstractComparator, IAssociationComparator)
+ private
+ FKeyComparator: IComparator;
+ public
+ constructor Create(NaturalKeys: Boolean = false);
+ destructor Destroy; override;
+ function GetKeyComparator: IComparator;
+ procedure SetKeyComparator(Value: IComparator);
+ function Compare(const Item1, Item2: ICollectable): Integer; override;
+ function Equals(const Item1, Item2: ICollectable): Boolean; override;
+ property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+ end;
+
+ TIntegerAssociationComparator = class(TAbstractComparator, IIntegerAssociationComparator)
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function Compare(const Item1, Item2: ICollectable): Integer; override;
+ function Equals(const Item1, Item2: ICollectable): Boolean; override;
+ end;
+
+ TStringAssociationComparator = class(TAbstractComparator, IStringAssociationComparator)
+ public
+ constructor Create;
+ destructor Destroy; override;
+ function Compare(const Item1, Item2: ICollectable): Integer; override;
+ function Equals(const Item1, Item2: ICollectable): Boolean; override;
+ end;
+
+
+
+ TAbstractCollection = class(TInterfacedObject, ICollection)
+ private
+ FCreated: Boolean; // Required to avoid passing destroyed object reference to exception
+ FComparator: IComparator;
+ FIgnoreErrors: TCollectionErrors;
+ FNaturalItemsOnly: Boolean;
+ protected
+ procedure CollectionError(ErrorType: TCollectionError);
+ procedure InitFrom(const Collection: ICollection); overload; virtual;
+ function TrueAdd(const Item: ICollectable): Boolean; virtual; abstract;
+ procedure TrueClear; virtual; abstract;
+ function TrueContains(const Item: ICollectable): Boolean; virtual; abstract;
+ function TrueItemCount(const Item: ICollectable): Integer; virtual;
+ function TrueRemove(const Item: ICollectable): ICollectable; virtual; abstract;
+ function TrueRemoveAll(const Item: ICollectable): ICollection; virtual; abstract;
+ public
+ constructor Create; overload; virtual;
+ constructor Create(NaturalItemsOnly: Boolean); overload; virtual;
+ constructor Create(const ItemArray: array of ICollectable); overload; virtual;
+ constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+ constructor Create(const Collection: ICollection); overload; virtual;
+ destructor Destroy; override;
+ class function GetAlwaysNaturalItems: Boolean; virtual;
+ function GetAsArray: TCollectableArray; virtual;
+ function GetCapacity: Integer; virtual; abstract;
+ procedure SetCapacity(Value: Integer); virtual; abstract;
+ function GetComparator: IComparator; virtual;
+ procedure SetComparator(const Value: IComparator); virtual;
+ function GetDuplicates: Boolean; virtual;
+ function GetFixedSize: Boolean; virtual;
+ function GetIgnoreErrors: TCollectionErrors;
+ procedure SetIgnoreErrors(Value: TCollectionErrors);
+ function GetInstance: TObject;
+ function GetIterator: IIterator; overload; virtual; abstract;
+ function GetIterator(const Filter: IFilter): IIterator; overload; virtual;
+ function GetIterator(FilterFunc: TCollectionFilterFunc): IIterator; overload; virtual;
+ function GetNaturalItemIID: TGUID; virtual; abstract;
+ function GetNaturalItemsOnly: Boolean; virtual;
+ function GetSize: Integer; virtual; abstract;
+ function GetType: TCollectionType; virtual; abstract;
+ function Add(const Item: ICollectable): Boolean; overload; virtual;
+ function Add(const ItemArray: array of ICollectable): Integer; overload; virtual;
+ function Add(const Collection: ICollection): Integer; overload; virtual;
+ procedure AfterConstruction; override;
+ procedure BeforeDestruction; override;
+ function Clear: Integer; virtual;
+ function Clone: ICollection; virtual;
+ function Contains(const Item: ICollectable): Boolean; overload; virtual;
+ function Contains(const ItemArray: array of ICollectable): Boolean; overload; virtual;
+ function Contains(const Collection: ICollection): Boolean; overload; virtual;
+ function Equals(const Collection: ICollection): Boolean; virtual;
+ function Find(const Filter: IFilter): ICollectable; overload; virtual;
+ function Find(FilterFunc: TCollectionFilterFunc): ICollectable; overload; virtual;
+ function FindAll(const Filter: IFilter): ICollection; overload; virtual;
+ function FindAll(FilterFunc: TCollectionFilterFunc): ICollection; overload; virtual;
+ function IsEmpty: Boolean; virtual;
+ function IsNaturalItem(const Item: ICollectable): Boolean; virtual;
+ function IsNilAllowed: Boolean; virtual; abstract;
+ function ItemAllowed(const Item: ICollectable): TCollectionError; virtual;
+ function ItemCount(const Item: ICollectable): Integer; overload; virtual;
+ function ItemCount(const ItemArray: array of ICollectable): Integer; overload; virtual;
+ function ItemCount(const Collection: ICollection): Integer; overload; virtual;
+ function Matching(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+ function Matching(const Collection: ICollection): ICollection; overload; virtual;
+ function Remove(const Item: ICollectable): ICollectable; overload; virtual;
+ function Remove(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+ function Remove(const Collection: ICollection): ICollection; overload; virtual;
+ function RemoveAll(const Item: ICollectable): ICollection; overload; virtual;
+ function RemoveAll(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+ function RemoveAll(const Collection: ICollection): ICollection; overload; virtual;
+ function Retain(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+ function Retain(const Collection: ICollection): ICollection; overload; virtual;
+ property AsArray: TCollectableArray read GetAsArray;
+ property Capacity: Integer read GetCapacity write SetCapacity;
+ property Comparator: IComparator read GetComparator write SetComparator;
+ property FixedSize: Boolean read GetFixedSize;
+ property IgnoreErrors: TCollectionErrors read GetIgnoreErrors write SetIgnoreErrors;
+ property NaturalItemIID: TGUID read GetNaturalItemIID;
+ property NaturalItemsOnly: Boolean read GetNaturalItemsOnly;
+ property Size: Integer read GetSize;
+ end;
+
+ TAbstractBag = class(TAbstractCollection, IBag)
+ public
+ function CloneAsBag: IBag; virtual;
+ function GetNaturalItemIID: TGUID; override;
+ function GetType: TCollectionType; override;
+ function IsNilAllowed: Boolean; override;
+ end;
+
+ TAbstractSet = class (TAbstractCollection, ISet)
+ protected
+ function GetPosition(const Item: ICollectable): TCollectionPosition; virtual; abstract;
+ function TrueAdd(const Item: ICollectable): Boolean; override;
+ procedure TrueAdd2(Position: TCollectionPosition; const Item: ICollectable); virtual; abstract;
+ function TrueContains(const Item: ICollectable): Boolean; override;
+ function TrueGet(Position: TCollectionPosition): ICollectable; virtual; abstract;
+ function TrueRemove(const Item: ICollectable): ICollectable; override;
+ procedure TrueRemove2(Position: TCollectionPosition); virtual; abstract;
+ function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+ public
+ function GetDuplicates: Boolean; override;
+ function GetNaturalItemIID: TGUID; override;
+ function GetType: TCollectionType; override;
+ function CloneAsSet: ISet; virtual;
+ function Complement(const Universe: ISet): ISet; overload; virtual;
+ function Intersect(const Set2: ISet): ISet; overload; virtual;
+ function IsNilAllowed: Boolean; override;
+ function Union(const Set2: ISet): ISet; overload; virtual;
+ end;
+
+ TAbstractList = class(TAbstractCollection, IList)
+ private
+ FDuplicates: Boolean;
+ FSorted: Boolean;
+ protected
+ function BinarySearch(const Item: ICollectable): TSearchResult; virtual;
+ procedure InitFrom(const Collection: ICollection); override;
+ procedure QuickSort(Lo, Hi: Integer; const Comparator: IComparator); overload; virtual;
+ procedure QuickSort(Lo, Hi: Integer; CompareFunc: TCollectionCompareFunc); overload; virtual;
+ function SequentialSearch(const Item: ICollectable; const SearchComparator: IComparator = nil): TSearchResult; virtual;
+ function TrueContains(const Item: ICollectable): Boolean; override;
+ function TrueGetItem(Index: Integer): ICollectable; virtual; abstract;
+ procedure TrueSetItem(Index: Integer; const Item: ICollectable); virtual; abstract;
+ function TrueAdd(const Item: ICollectable): Boolean; override;
+ procedure TrueAppend(const Item: ICollectable); virtual; abstract;
+ function TrueDelete(Index: Integer): ICollectable; virtual; abstract;
+ procedure TrueInsert(Index: Integer; const Item: ICollectable); virtual; abstract;
+ function TrueItemCount(const Item: ICollectable): Integer; override;
+ function TrueRemove(const Item: ICollectable): ICollectable; override;
+ function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+ public
+ constructor Create(NaturalItemsOnly: Boolean); override;
+ function GetDuplicates: Boolean; override;
+ procedure SetDuplicates(Value: Boolean); virtual;
+ function GetItem(Index: Integer): ICollectable; virtual;
+ procedure SetItem(Index: Integer; const Item: ICollectable); virtual;
+ function GetIterator: IIterator; override;
+ function GetNaturalItemIID: TGUID; override;
+ function GetSorted: Boolean; virtual;
+ procedure SetSorted(Value: Boolean); virtual;
+ function GetType: TCollectionType; override;
+ function CloneAsList: IList; virtual;
+ function Delete(Index: Integer): ICollectable; virtual;
+ procedure Exchange(Index1, Index2: Integer); virtual;
+ function First: ICollectable; virtual;
+ function IndexOf(const Item: ICollectable): Integer; virtual;
+ function Insert(Index: Integer; const Item: ICollectable): Boolean; overload; virtual;
+ function Insert(Index: Integer; const ItemArray: array of ICollectable): Integer; overload; virtual;
+ function Insert(Index: Integer; const Collection: ICollection): Integer; overload; virtual;
+ function IsNilAllowed: Boolean; override;
+ function Last: ICollectable; virtual;
+ function Search(const Item: ICollectable; const SearchComparator: IComparator = nil): TSearchResult; virtual;
+ procedure Sort(const SortComparator: IComparator = nil); overload; virtual;
+ procedure Sort(CompareFunc: TCollectionCompareFunc); overload; virtual;
+ property Duplicates: Boolean read GetDuplicates write SetDuplicates;
+ property Items[Index: Integer]: ICollectable read GetItem write SetItem; default;
+ property Sorted: Boolean read GetSorted write SetSorted;
+ end;
+
+ TAbstractMap = class(TAbstractCollection, IMap)
+ private
+ FAssociationComparator: IAssociationComparator;
+ FKeyComparator: IComparator;
+ FNaturalKeysOnly: Boolean;
+ protected
+ function GetAssociationIterator: IMapIterator; virtual; abstract;
+ function GetKeyPosition(const Key: ICollectable): TCollectionPosition; virtual; abstract;
+ procedure InitFrom(const Collection: ICollection); override;
+ function TrueAdd(const Item: ICollectable): Boolean; override;
+ function TrueContains(const Item: ICollectable): Boolean; override;
+ function TrueGet(Position: TCollectionPosition): IAssociation; virtual; abstract;
+ function TruePut(Position: TCollectionPosition; const Association: IAssociation): IAssociation; virtual; abstract;
+ function TrueRemove(const Item: ICollectable): ICollectable; override;
+ function TrueRemove2(Position: TCollectionPosition): IAssociation; virtual; abstract;
+ function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+ property AssociationComparator: IAssociationComparator read FAssociationComparator;
+ public
+ constructor Create; override;
+ constructor Create(NaturalItemsOnly: Boolean); override;
+ constructor Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); overload; virtual;
+ constructor Create(const ItemArray: array of ICollectable); overload; override;
+ constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; override;
+ constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); overload; virtual;
+ constructor Create(const KeyArray, ItemArray: array of ICollectable); overload; virtual;
+ constructor Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+ constructor Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean); overload; virtual;
+// Don't use this parameter signature as it hits a compiler bug in D5.
+// constructor Create(const KeyArray, ItemArray: TCollectableArray; NaturalItemsOnly: Boolean = false; NaturalKeysOnly: Boolean = true); overload; virtual;
+ constructor Create(const Map: IMap); overload; virtual;
+ destructor Destroy; override;
+ class function GetAlwaysNaturalKeys: Boolean; virtual;
+ function GetItem(const Key: ICollectable): ICollectable; virtual;
+ procedure SetItem(const Key, Item: ICollectable); virtual;
+ function GetIterator: IIterator; override;
+ function GetKeyComparator: IComparator; virtual;
+ procedure SetKeyComparator(const Value: IComparator); virtual;
+ function GetKeyIterator: IIterator; virtual;
+ function GetKeys: ISet; virtual;
+ function GetMapIterator: IMapIterator; virtual;
+ function GetMapIteratorByKey(const Filter: IFilter): IMapIterator; overload; virtual;
+ function GetMapIteratorByKey(FilterFunc: TCollectionFilterFunc): IMapIterator; overload; virtual;
+ function GetNaturalItemIID: TGUID; override;
+ function GetNaturalKeyIID: TGUID; virtual;
+ function GetNaturalKeysOnly: Boolean; virtual;
+ function GetType: TCollectionType; override;
+ function GetValues: ICollection; virtual;
+ function Clone: ICollection; override;
+ function CloneAsMap: IMap; virtual;
+ function ContainsKey(const Key: ICollectable): Boolean; overload; virtual;
+ function ContainsKey(const KeyArray: array of ICollectable): Boolean; overload; virtual;
+ function ContainsKey(const Collection: ICollection): Boolean; overload; virtual;
+ function Get(const Key: ICollectable): ICollectable; virtual;
+ function KeyAllowed(const Key: ICollectable): TCollectionError; virtual;
+ function IsNaturalKey(const Key: ICollectable): Boolean; virtual;
+ function IsNilAllowed: Boolean; override;
+ function MatchingKey(const KeyArray: array of ICollectable): ICollection; overload; virtual;
+ function MatchingKey(const Collection: ICollection): ICollection; overload; virtual;
+ function Put(const Item: ICollectable): ICollectable; overload; virtual;
+ function Put(const Key, Item: ICollectable): ICollectable; overload; virtual;
+ function Put(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+ function Put(const Collection: ICollection): ICollection; overload; virtual;
+ function Put(const Map: IMap): ICollection; overload; virtual;
+ function RemoveKey(const Key: ICollectable): ICollectable; overload; virtual;
+ function RemoveKey(const KeyArray: array of ICollectable): ICollection; overload; virtual;
+ function RemoveKey(const Collection: ICollection): ICollection; overload; virtual;
+ function RetainKey(const KeyArray: array of ICollectable): ICollection; overload; virtual;
+ function RetainKey(const Collection: ICollection): ICollection; overload; virtual;
+ property KeyComparator: IComparator read GetKeyComparator write SetKeyComparator;
+ property Items[const Key: ICollectable]: ICollectable read GetItem write SetItem; default;
+ property NaturalKeyIID: TGUID read GetNaturalKeyIID;
+ property NaturalKeysOnly: Boolean read GetNaturalKeysOnly;
+ end;
+
+ TAbstractIntegerMap = class(TAbstractCollection, IIntegerMap)
+ private
+ FAssociationComparator: IIntegerAssociationComparator;
+ protected
+ function GetAssociationIterator: IIntegerMapIterator; virtual; abstract;
+ function GetKeyPosition(const Key: Integer): TCollectionPosition; virtual; abstract;
+ function TrueAdd(const Item: ICollectable): Boolean; override;
+ function TrueContains(const Item: ICollectable): Boolean; override;
+ function TrueGet(Position: TCollectionPosition): IIntegerAssociation; virtual; abstract;
+ function TruePut(Position: TCollectionPosition; const Association: IIntegerAssociation): IIntegerAssociation; virtual; abstract;
+ function TrueRemove(const Item: ICollectable): ICollectable; override;
+ function TrueRemove2(Position: TCollectionPosition): IIntegerAssociation; virtual; abstract;
+ function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+ property AssociationComparator: IIntegerAssociationComparator read FAssociationComparator;
+ public
+ constructor Create(NaturalItemsOnly: Boolean); override;
+ constructor Create(const ItemArray: array of ICollectable); overload; override;
+ constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; override;
+ constructor Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable); overload; virtual;
+ constructor Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+ constructor Create(const Map: IIntegerMap); overload; virtual;
+ destructor Destroy; override;
+ function GetItem(const Key: Integer): ICollectable; virtual;
+ procedure SetItem(const Key: Integer; const Item: ICollectable); virtual;
+ function GetIterator: IIterator; override;
+ function GetKeys: ISet; virtual;
+ function GetMapIterator: IIntegerMapIterator; virtual;
+ function GetNaturalItemIID: TGUID; override;
+ function GetType: TCollectionType; override;
+ function GetValues: ICollection; virtual;
+ function Clone: ICollection; override;
+ function CloneAsIntegerMap: IIntegerMap; virtual;
+ function ContainsKey(const Key: Integer): Boolean; overload; virtual;
+ function ContainsKey(const KeyArray: array of Integer): Boolean; overload; virtual;
+ function Get(const Key: Integer): ICollectable; virtual;
+ function IsNilAllowed: Boolean; override;
+ function Put(const Item: ICollectable): ICollectable; overload; virtual;
+ function Put(const Key: Integer; const Item: ICollectable): ICollectable; overload; virtual;
+ function Put(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+ function Put(const Collection: ICollection): ICollection; overload; virtual;
+ function Put(const Map: IIntegerMap): ICollection; overload; virtual;
+ function RemoveKey(const Key: Integer): ICollectable; overload; virtual;
+ function RemoveKey(const KeyArray: array of Integer): ICollection; overload; virtual;
+ function RetainKey(const KeyArray: array of Integer): ICollection; overload; virtual;
+ property Items[const Key: Integer]: ICollectable read GetItem write SetItem; default;
+ end;
+
+ TAbstractStringMap = class(TAbstractCollection, IStringMap)
+ private
+ FAssociationComparator: IStringAssociationComparator;
+ protected
+ function GetAssociationIterator: IStringMapIterator; virtual; abstract;
+ function GetKeyPosition(const Key: String): TCollectionPosition; virtual; abstract;
+ function TrueAdd(const Item: ICollectable): Boolean; override;
+ function TrueContains(const Item: ICollectable): Boolean; override;
+ function TrueGet(Position: TCollectionPosition): IStringAssociation; virtual; abstract;
+ function TruePut(Position: TCollectionPosition; const Association: IStringAssociation): IStringAssociation; virtual; abstract;
+ function TrueRemove(const Item: ICollectable): ICollectable; override;
+ function TrueRemove2(Position: TCollectionPosition): IStringAssociation; virtual; abstract;
+ function TrueRemoveAll(const Item: ICollectable): ICollection; override;
+ property AssociationComparator: IStringAssociationComparator read FAssociationComparator;
+ public
+ constructor Create(NaturalItemsOnly: Boolean); override;
+ constructor Create(const ItemArray: array of ICollectable); overload; override;
+ constructor Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; override;
+ constructor Create(const KeyArray: array of String; const ItemArray: array of ICollectable); overload; virtual;
+ constructor Create(const KeyArray: array of String; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean); overload; virtual;
+ constructor Create(const Map: IStringMap); overload; virtual;
+ destructor Destroy; override;
+ function GetItem(const Key: String): ICollectable; virtual;
+ procedure SetItem(const Key: String; const Item: ICollectable); virtual;
+ function GetIterator: IIterator; override;
+ function GetKeys: ISet; virtual;
+ function GetMapIterator: IStringMapIterator; virtual;
+ function GetNaturalItemIID: TGUID; override;
+ function GetType: TCollectionType; override;
+ function GetValues: ICollection; virtual;
+ function Clone: ICollection; override;
+ function CloneAsStringMap: IStringMap; virtual;
+ function ContainsKey(const Key: String): Boolean; overload; virtual;
+ function ContainsKey(const KeyArray: array of String): Boolean; overload; virtual;
+ function Get(const Key: String): ICollectable; virtual;
+ function IsNilAllowed: Boolean; override;
+ function Put(const Item: ICollectable): ICollectable; overload; virtual;
+ function Put(const Key: String; const Item: ICollectable): ICollectable; overload; virtual;
+ function Put(const ItemArray: array of ICollectable): ICollection; overload; virtual;
+ function Put(const Collection: ICollection): ICollection; overload; virtual;
+ function Put(const Map: IStringMap): ICollection; overload; virtual;
+ function RemoveKey(const Key: String): ICollectable; overload; virtual;
+ function RemoveKey(const KeyArray: array of String): ICollection; overload; virtual;
+ function RetainKey(const KeyArray: array of String): ICollection; overload; virtual;
+ property Items[const Key: String]: ICollectable read GetItem write SetItem; default;
+ end;
+
+ TAbstractCollectionClass = class of TAbstractCollection;
+ TAbstractBagClass = class of TAbstractBag;
+ TAbstractSetClass = class of TAbstractSet;
+ TAbstractListClass = class of TAbstractList;
+ TAbstractMapClass = class of TAbstractMap;
+ TAbstractIntegerMapClass = class of TAbstractIntegerMap;
+ TAbstractStringMapClass = class of TAbstractStringMap;
+
+ TAbstractIterator = class(TInterfacedObject, IIterator)
+ private
+ FAllowRemoval: Boolean;
+ FEOF: Boolean;
+ FItem: ICollectable;
+ protected
+ constructor Create(AllowRemoval: Boolean = true);
+ function TrueFirst: ICollectable; virtual; abstract;
+ function TrueNext: ICollectable; virtual; abstract;
+ procedure TrueRemove; virtual; abstract;
+ public
+ procedure AfterConstruction; override;
+ function GetAllowRemoval: Boolean; virtual;
+ function CurrentItem: ICollectable; virtual;
+ function EOF: Boolean; virtual;
+ function First: ICollectable; virtual;
+ function Next: ICollectable; virtual;
+ function Remove: Boolean; virtual;
+ property AllowRemoval: Boolean read GetAllowRemoval;
+ end;
+
+ TAbstractListIterator = class(TAbstractIterator)
+ private
+ FCollection: TAbstractList;
+ FIndex: Integer;
+ protected
+ constructor Create(Collection: TAbstractList);
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ end;
+
+ TAbstractMapIterator = class(TAbstractIterator, IMapIterator)
+ public
+ function CurrentKey: ICollectable; virtual; abstract;
+ end;
+
+ TAbstractAssociationIterator = class(TInterfacedObject, IIterator, IMapIterator)
+ private
+ FAllowRemoval: Boolean;
+ FEOF: Boolean;
+ FAssociation: IAssociation;
+ protected
+ constructor Create(AllowRemoval: Boolean = true);
+ function TrueFirst: IAssociation; virtual; abstract;
+ function TrueNext: IAssociation; virtual; abstract;
+ procedure TrueRemove; virtual; abstract;
+ public
+ procedure AfterConstruction; override;
+ function GetAllowRemoval: Boolean; virtual;
+ function CurrentKey: ICollectable; virtual;
+ function CurrentItem: ICollectable; virtual;
+ function EOF: Boolean; virtual;
+ function First: ICollectable; virtual;
+ function Next: ICollectable; virtual;
+ function Remove: Boolean; virtual;
+ property AllowRemoval: Boolean read GetAllowRemoval;
+ end;
+
+ TAbstractIntegerAssociationIterator = class(TInterfacedObject, IIterator, IIntegerMapIterator)
+ private
+ FAllowRemoval: Boolean;
+ FEOF: Boolean;
+ FAssociation: IIntegerAssociation;
+ protected
+ constructor Create(AllowRemoval: Boolean = true);
+ function TrueFirst: IIntegerAssociation; virtual; abstract;
+ function TrueNext: IIntegerAssociation; virtual; abstract;
+ procedure TrueRemove; virtual; abstract;
+ public
+ procedure AfterConstruction; override;
+ function GetAllowRemoval: Boolean; virtual;
+ function CurrentKey: Integer; virtual;
+ function CurrentItem: ICollectable; virtual;
+ function EOF: Boolean; virtual;
+ function First: ICollectable; virtual;
+ function Next: ICollectable; virtual;
+ function Remove: Boolean; virtual;
+ property AllowRemoval: Boolean read GetAllowRemoval;
+ end;
+
+ TAbstractStringAssociationIterator = class(TInterfacedObject, IIterator, IStringMapIterator)
+ private
+ FAllowRemoval: Boolean;
+ FEOF: Boolean;
+ FAssociation: IStringAssociation;
+ protected
+ constructor Create(AllowRemoval: Boolean = true);
+ function TrueFirst: IStringAssociation; virtual; abstract;
+ function TrueNext: IStringAssociation; virtual; abstract;
+ procedure TrueRemove; virtual; abstract;
+ public
+ procedure AfterConstruction; override;
+ function GetAllowRemoval: Boolean; virtual;
+ function CurrentKey: String; virtual;
+ function CurrentItem: ICollectable; virtual;
+ function EOF: Boolean; virtual;
+ function First: ICollectable; virtual;
+ function Next: ICollectable; virtual;
+ function Remove: Boolean; virtual;
+ property AllowRemoval: Boolean read GetAllowRemoval;
+ end;
+
+ TAssociationIterator = class(TAbstractIterator, IMapIterator)
+ private
+ FIterator: IIterator;
+ protected
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ public
+ constructor Create(const Iterator: IIterator);
+ destructor Destroy; override;
+ function CurrentItem: ICollectable; override;
+ function CurrentKey: ICollectable; virtual;
+ end;
+
+ TAssociationKeyIterator = class(TAbstractIterator)
+ private
+ FIterator: IMapIterator;
+ protected
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ public
+ constructor Create(const Iterator: IMapIterator);
+ destructor Destroy; override;
+ end;
+
+ TAbstractFilter = class(TInterfacedObject, IFilter)
+ public
+ function Accept(const Item: ICollectable): Boolean; virtual; abstract;
+ end;
+
+ TFilterIterator = class(TAbstractIterator)
+ private
+ FIterator: IIterator;
+ FFilter: IFilter;
+ protected
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ public
+ constructor Create(const Iterator: IIterator; const Filter: IFilter; AllowRemoval: Boolean = true); virtual;
+ destructor Destroy; override;
+ end;
+
+ TFilterFuncIterator = class(TAbstractIterator)
+ private
+ FIterator: IIterator;
+ FFilterFunc: TCollectionFilterFunc;
+ protected
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ public
+ constructor Create(const Iterator: IIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true); virtual;
+ destructor Destroy; override;
+ end;
+
+ TKeyFilterMapIterator = class(TAbstractMapIterator)
+ private
+ FIterator: IMapIterator;
+ FFilter: IFilter;
+ protected
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ public
+ constructor Create(const Iterator: IMapIterator; const Filter: IFilter; AllowRemoval: Boolean = true); virtual;
+ destructor Destroy; override;
+ function CurrentKey: ICollectable; override;
+ end;
+
+ TKeyFilterFuncMapIterator = class(TAbstractMapIterator)
+ private
+ FIterator: IMapIterator;
+ FFilterFunc: TCollectionFilterFunc;
+ protected
+ function TrueFirst: ICollectable; override;
+ function TrueNext: ICollectable; override;
+ procedure TrueRemove; override;
+ public
+ constructor Create(const Iterator: IMapIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true); virtual;
+ destructor Destroy; override;
+ function CurrentKey: ICollectable; override;
+ end;
+
+
+ ECollectionError = class(Exception)
+ private
+ FCollection: ICollection;
+ FErrorType: TCollectionError;
+ public
+ constructor Create(const Msg: String; const Collection: ICollection; ErrorType: TCollectionError);
+ property Collection: ICollection read FCollection;
+ property ErrorType: TCollectionError read FErrorType;
+ end;
+
+implementation
+
+uses
+ Math,
+ CollArray, CollHash, CollList, CollPArray, CollWrappers;
+
+var
+ FDefaultComparator: IComparator;
+ FNaturalComparator: IComparator;
+ FReverseNaturalComparator: IComparator;
+
+{ TCollectionPosition }
+constructor TCollectionPosition.Create(Found: Boolean);
+begin
+ FFound := Found;
+end;
+
+{ TAbstractComparator }
+class function TAbstractComparator.GetDefaultComparator: IComparator;
+begin
+ if FDefaultComparator = nil then
+ FDefaultComparator := TDefaultComparator.Create;
+ Result := FDefaultComparator;
+end;
+
+class function TAbstractComparator.GetNaturalComparator: IComparator;
+begin
+ if FNaturalComparator = nil then
+ FNaturalComparator := TNaturalComparator.Create;
+ Result := FNaturalComparator;
+end;
+
+class function TAbstractComparator.GetReverseNaturalComparator: IComparator;
+begin
+ if FReverseNaturalComparator = nil then
+ FReverseNaturalComparator := TReverseNaturalComparator.Create;
+ Result := FReverseNaturalComparator;
+end;
+
+function TAbstractComparator.GetInstance: TObject;
+begin
+ Result := Self;
+end;
+
+function TAbstractComparator.Equals(const Comparator: IComparator): Boolean;
+begin
+ Result := (Self = Comparator.GetInstance);
+end;
+
+{ TDefaultComparator }
+constructor TDefaultComparator.Create;
+begin
+ // Empty
+end;
+
+function TDefaultComparator.Compare(const Item1, Item2: ICollectable): Integer;
+var
+ Value1, Value2: Integer;
+begin
+ if Item1 <> nil then
+ Value1 := Integer(Pointer(Item1))
+ else
+ Value1 := Low(Integer);
+ if Item2 <> nil then
+ Value2 := Integer(Pointer(Item2))
+ else
+ Value2 := Low(Integer);
+ if (Value1 < Value2) then
+ Result := -1
+ else if (Value1 > Value2) then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+function TDefaultComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+ Result := (Item1 = Item2);
+end;
+
+{ TNaturalComparator }
+constructor TNaturalComparator.Create;
+begin
+ // Empty
+end;
+
+function TNaturalComparator.Compare(const Item1, Item2: ICollectable): Integer;
+begin
+ if (Item1 = nil) and (Item2 <> nil) then
+ Result := -1
+ else if (Item1 <> nil) and (Item2 = nil) then
+ Result := 1
+ else if (Item1 = nil) and (Item2 = nil) then
+ Result := 0
+ else
+ Result := (Item1 as IComparable).CompareTo(Item2);
+end;
+
+function TNaturalComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+ if (Item1 = nil) or (Item2 = nil) then
+ Result := (Item1 = Item2)
+ else
+ begin
+ Result := (Item1 as IEquatable).Equals(Item2);
+ end;
+end;
+
+{ TReverseNaturalComparator }
+constructor TReverseNaturalComparator.Create;
+begin
+ // Empty
+end;
+
+function TReverseNaturalComparator.Compare(const Item1, Item2: ICollectable): Integer;
+begin
+ if (Item1 = nil) and (Item2 <> nil) then
+ Result := 1
+ else if (Item1 <> nil) and (Item2 = nil) then
+ Result := -1
+ else if (Item1 = nil) and (Item2 = nil) then
+ Result := 0
+ else
+ Result := -(Item1 as IComparable).CompareTo(Item2);
+end;
+
+function TReverseNaturalComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+ if (Item1 = nil) or (Item2 = nil) then
+ Result := (Item1 = Item2)
+ else
+ Result := (Item1 as IEquatable).Equals(Item2);
+end;
+
+{ TAssociation }
+constructor TAssociation.Create(const Key, Value: ICollectable);
+begin
+ FKey := Key;
+ FValue := Value;
+end;
+
+destructor TAssociation.Destroy;
+begin
+ FKey := nil;
+ FValue := nil;
+ inherited Destroy;
+end;
+
+function TAssociation.GetInstance: TObject;
+begin
+ Result := Self;
+end;
+
+function TAssociation.GetKey: ICollectable;
+begin
+ Result := FKey;
+end;
+
+function TAssociation.GetValue: ICollectable;
+begin
+ Result := FValue;
+end;
+
+
+{ TIntegerAssociation }
+constructor TIntegerAssociation.Create(const Key: Integer; const Value: ICollectable);
+begin
+ FKey := Key;
+ FValue := Value;
+end;
+
+destructor TIntegerAssociation.Destroy;
+begin
+ FValue := nil;
+ inherited Destroy;
+end;
+
+function TIntegerAssociation.GetInstance: TObject;
+begin
+ Result := Self;
+end;
+
+function TIntegerAssociation.GetKey: Integer;
+begin
+ Result := FKey;
+end;
+
+function TIntegerAssociation.GetValue: ICollectable;
+begin
+ Result := FValue;
+end;
+
+
+{ TStringAssociation }
+constructor TStringAssociation.Create(const Key: String; const Value: ICollectable);
+begin
+ FKey := Key;
+ FValue := Value;
+end;
+
+destructor TStringAssociation.Destroy;
+begin
+ FValue := nil;
+ inherited Destroy;
+end;
+
+function TStringAssociation.GetInstance: TObject;
+begin
+ Result := Self;
+end;
+
+function TStringAssociation.GetKey: String;
+begin
+ Result := FKey;
+end;
+
+function TStringAssociation.GetValue: ICollectable;
+begin
+ Result := FValue;
+end;
+
+
+{ TAbstractIterator }
+constructor TAbstractIterator.Create(AllowRemoval: Boolean);
+begin
+ inherited Create;
+ FAllowRemoval := AllowRemoval;
+ FEOF := true;
+ FItem := nil;
+end;
+
+procedure TAbstractIterator.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ First;
+end;
+
+function TAbstractIterator.GetAllowRemoval: Boolean;
+begin
+ Result := FAllowRemoval;
+end;
+
+function TAbstractIterator.CurrentItem: ICollectable;
+begin
+ Result := FItem;
+end;
+
+function TAbstractIterator.EOF: Boolean;
+begin
+ Result := FEOF;
+end;
+
+function TAbstractIterator.First: ICollectable;
+begin
+ FEOF := false;
+ FItem := TrueFirst;
+ if FItem = nil then
+ FEOF := true;
+ Result := FItem;
+end;
+
+function TAbstractIterator.Next: ICollectable;
+begin
+ if not FEOF then
+ begin
+ FItem := TrueNext;
+ if FItem = nil then
+ FEOF := true;
+ end;
+ Result := FItem;
+end;
+
+function TAbstractIterator.Remove: Boolean;
+begin
+ if (FItem <> nil) and FAllowRemoval then
+ begin
+ TrueRemove;
+ FItem := nil;
+ Result := true;
+ end
+ else
+ Result := false;
+end;
+
+{ TAbstractAssociationIterator }
+constructor TAbstractAssociationIterator.Create(AllowRemoval: Boolean);
+begin
+ inherited Create;
+ FAllowRemoval := AllowRemoval;
+ FEOF := true;
+ FAssociation := nil;
+end;
+
+procedure TAbstractAssociationIterator.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ First;
+end;
+
+function TAbstractAssociationIterator.GetAllowRemoval: Boolean;
+begin
+ Result := FAllowRemoval;
+end;
+
+function TAbstractAssociationIterator.CurrentKey: ICollectable;
+begin
+ if FAssociation <> nil then
+ Result := FAssociation.GetKey
+ else
+ Result := nil;
+end;
+
+function TAbstractAssociationIterator.CurrentItem: ICollectable;
+begin
+ if FAssociation <> nil then
+ Result := FAssociation.GetValue
+ else
+ Result := nil;
+end;
+
+function TAbstractAssociationIterator.EOF: Boolean;
+begin
+ Result := FEOF;
+end;
+
+function TAbstractAssociationIterator.First: ICollectable;
+begin
+ FAssociation := TrueFirst;
+ if FAssociation <> nil then
+ begin
+ Result := FAssociation.GetValue;
+ FEOF := false;
+ end
+ else
+ begin
+ Result := nil;
+ FEOF := true;
+ end;
+end;
+
+function TAbstractAssociationIterator.Next: ICollectable;
+begin
+ if not FEOF then
+ begin
+ FAssociation := TrueNext;
+ if FAssociation <> nil then
+ Result := FAssociation.GetValue
+ else
+ begin
+ Result := nil;
+ FEOF := true;
+ end;
+ end;
+end;
+
+function TAbstractAssociationIterator.Remove: Boolean;
+begin
+ if (FAssociation <> nil) and FAllowRemoval then
+ begin
+ TrueRemove;
+ FAssociation := nil;
+ Result := true;
+ end
+ else
+ Result := false;
+end;
+
+{ TAbstractIntegerAssociationIterator }
+constructor TAbstractIntegerAssociationIterator.Create(AllowRemoval: Boolean);
+begin
+ inherited Create;
+ FAllowRemoval := AllowRemoval;
+ FEOF := true;
+ FAssociation := nil;
+end;
+
+procedure TAbstractIntegerAssociationIterator.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ First;
+end;
+
+function TAbstractIntegerAssociationIterator.GetAllowRemoval: Boolean;
+begin
+ Result := FAllowRemoval;
+end;
+
+function TAbstractIntegerAssociationIterator.CurrentKey: Integer;
+begin
+ if FAssociation <> nil then
+ Result := FAssociation.GetKey
+ else
+ Result := 0;
+end;
+
+function TAbstractIntegerAssociationIterator.CurrentItem: ICollectable;
+begin
+ if FAssociation <> nil then
+ Result := FAssociation.GetValue
+ else
+ Result := nil;
+end;
+
+function TAbstractIntegerAssociationIterator.EOF: Boolean;
+begin
+ Result := FEOF;
+end;
+
+function TAbstractIntegerAssociationIterator.First: ICollectable;
+begin
+ FAssociation := TrueFirst;
+ if FAssociation <> nil then
+ begin
+ Result := FAssociation.GetValue;
+ FEOF := false;
+ end
+ else
+ begin
+ Result := nil;
+ FEOF := true;
+ end;
+end;
+
+function TAbstractIntegerAssociationIterator.Next: ICollectable;
+begin
+ if not FEOF then
+ begin
+ FAssociation := TrueNext;
+ if FAssociation <> nil then
+ Result := FAssociation.GetValue
+ else
+ begin
+ Result := nil;
+ FEOF := true;
+ end;
+ end;
+end;
+
+function TAbstractIntegerAssociationIterator.Remove: Boolean;
+begin
+ if (FAssociation <> nil) and FAllowRemoval then
+ begin
+ TrueRemove;
+ FAssociation := nil;
+ Result := true;
+ end
+ else
+ Result := false;
+end;
+
+{ TAbstractStringAssociationIterator }
+constructor TAbstractStringAssociationIterator.Create(AllowRemoval: Boolean);
+begin
+ inherited Create;
+ FAllowRemoval := AllowRemoval;
+ FEOF := true;
+ FAssociation := nil;
+end;
+
+procedure TAbstractStringAssociationIterator.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ First;
+end;
+
+function TAbstractStringAssociationIterator.GetAllowRemoval: Boolean;
+begin
+ Result := FAllowRemoval;
+end;
+
+function TAbstractStringAssociationIterator.CurrentKey: String;
+begin
+ if FAssociation <> nil then
+ Result := FAssociation.GetKey
+ else
+ Result := '';
+end;
+
+function TAbstractStringAssociationIterator.CurrentItem: ICollectable;
+begin
+ if FAssociation <> nil then
+ Result := FAssociation.GetValue
+ else
+ Result := nil;
+end;
+
+function TAbstractStringAssociationIterator.EOF: Boolean;
+begin
+ Result := FEOF;
+end;
+
+function TAbstractStringAssociationIterator.First: ICollectable;
+begin
+ FAssociation := TrueFirst;
+ if FAssociation <> nil then
+ begin
+ Result := FAssociation.GetValue;
+ FEOF := false;
+ end
+ else
+ begin
+ Result := nil;
+ FEOF := true;
+ end;
+end;
+
+function TAbstractStringAssociationIterator.Next: ICollectable;
+begin
+ if not FEOF then
+ begin
+ FAssociation := TrueNext;
+ if FAssociation <> nil then
+ Result := FAssociation.GetValue
+ else
+ begin
+ Result := nil;
+ FEOF := true;
+ end;
+ end;
+end;
+
+function TAbstractStringAssociationIterator.Remove: Boolean;
+begin
+ if (FAssociation <> nil) and FAllowRemoval then
+ begin
+ TrueRemove;
+ FAssociation := nil;
+ Result := true;
+ end
+ else
+ Result := false;
+end;
+
+{ TAssociationIterator }
+constructor TAssociationIterator.Create(const Iterator: IIterator);
+begin
+ inherited Create(Iterator.GetAllowRemoval);
+ FIterator := Iterator;
+end;
+
+destructor TAssociationIterator.Destroy;
+begin
+ FIterator := nil;
+ inherited Destroy;
+end;
+
+function TAssociationIterator.TrueFirst: ICollectable;
+var
+ Association: IAssociation;
+begin
+ Association := FIterator.First as IAssociation;
+ if Association <> nil then
+ Result := Association.GetValue
+ else
+ Result := nil;
+end;
+
+function TAssociationIterator.TrueNext: ICollectable;
+var
+ Association: IAssociation;
+begin
+ Association := (FIterator.Next as IAssociation);
+ if Association <> nil then
+ Result := Association.GetValue
+ else
+ Result := nil;
+end;
+
+procedure TAssociationIterator.TrueRemove;
+begin
+ FIterator.Remove;
+end;
+
+function TAssociationIterator.CurrentItem: ICollectable;
+var
+ Association: IAssociation;
+begin
+ Association := FIterator.CurrentItem as IAssociation;
+ if Association <> nil then
+ Result := Association.GetValue
+ else
+ Result := nil;
+end;
+
+function TAssociationIterator.CurrentKey: ICollectable;
+var
+ Association: IAssociation;
+begin
+ Association := FIterator.CurrentItem as IAssociation;
+ if Association <> nil then
+ Result := Association.GetKey
+ else
+ Result := nil;
+end;
+
+{ TAssociationComparator }
+constructor TAssociationComparator.Create(NaturalKeys: Boolean);
+begin
+ inherited Create;
+ if NaturalKeys then
+ FKeyComparator := TAbstractComparator.GetNaturalComparator
+ else
+ FKeyComparator := TAbstractComparator.GetDefaultComparator;
+end;
+
+destructor TAssociationComparator.Destroy;
+begin
+ FKeyComparator := nil;
+ inherited Destroy;
+end;
+
+function TAssociationComparator.GetKeyComparator: IComparator;
+begin
+ Result := FKeyComparator;
+end;
+
+procedure TAssociationComparator.SetKeyComparator(Value: IComparator);
+begin
+ FKeyComparator := Value;
+end;
+
+function TAssociationComparator.Compare(const Item1, Item2: ICollectable): Integer;
+begin
+ Result := KeyComparator.Compare((Item1 as IAssociation).GetKey, (Item2 as IAssociation).GetKey);
+end;
+
+function TAssociationComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+ Result := KeyComparator.Equals((Item1 as IAssociation).GetKey, (Item2 as IAssociation).GetKey);
+end;
+
+{ TIntegerAssociationComparator }
+constructor TIntegerAssociationComparator.Create;
+begin
+ inherited Create;
+end;
+
+destructor TIntegerAssociationComparator.Destroy;
+begin
+ inherited Destroy;
+end;
+
+function TIntegerAssociationComparator.Compare(const Item1, Item2: ICollectable): Integer;
+var
+ Key1, Key2: Integer;
+begin
+ Key1 := (Item1 as IIntegerAssociation).GetKey;
+ Key2 := (Item2 as IIntegerAssociation).GetKey;
+ if Key1 < Key2 then
+ Result := -1
+ else if Key1 > Key2 then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+function TIntegerAssociationComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+ Result := ((Item1 as IIntegerAssociation).GetKey = (Item2 as IIntegerAssociation).GetKey);
+end;
+
+{ TStringAssociationComparator }
+constructor TStringAssociationComparator.Create;
+begin
+ inherited Create;
+end;
+
+destructor TStringAssociationComparator.Destroy;
+begin
+ inherited Destroy;
+end;
+
+function TStringAssociationComparator.Compare(const Item1, Item2: ICollectable): Integer;
+var
+ Key1, Key2: String;
+begin
+ Key1 := (Item1 as IStringAssociation).GetKey;
+ Key2 := (Item2 as IStringAssociation).GetKey;
+ if Key1 < Key2 then
+ Result := -1
+ else if Key1 > Key2 then
+ Result := 1
+ else
+ Result := 0;
+end;
+
+function TStringAssociationComparator.Equals(const Item1, Item2: ICollectable): Boolean;
+begin
+ Result := ((Item1 as IStringAssociation).GetKey = (Item2 as IStringAssociation).GetKey);
+end;
+
+{ TAssociationKeyIterator }
+constructor TAssociationKeyIterator.Create(const Iterator: IMapIterator);
+begin
+ inherited Create(Iterator.GetAllowRemoval);
+ FIterator := Iterator;
+end;
+
+destructor TAssociationKeyIterator.Destroy;
+begin
+ FIterator := nil;
+ inherited Destroy;
+end;
+
+function TAssociationKeyIterator.TrueFirst: ICollectable;
+begin
+ FIterator.First;
+ Result := FIterator.CurrentKey;
+end;
+
+function TAssociationKeyIterator.TrueNext: ICollectable;
+begin
+ FIterator.Next;
+ Result := FIterator.CurrentKey;
+end;
+
+procedure TAssociationKeyIterator.TrueRemove;
+begin
+ FIterator.Remove;
+end;
+
+{ TFilterIterator }
+constructor TFilterIterator.Create(const Iterator: IIterator; const Filter: IFilter; AllowRemoval: Boolean = true);
+begin
+ FIterator := Iterator;
+ FFilter := Filter;
+end;
+
+destructor TFilterIterator.Destroy;
+begin
+ FIterator := nil;
+ FFilter := nil;
+end;
+
+function TFilterIterator.TrueFirst: ICollectable;
+var
+ Item: ICollectable;
+begin
+ Item := FIterator.First;
+ while not FIterator.EOF do
+ begin
+ if FFilter.Accept(Item) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+function TFilterIterator.TrueNext: ICollectable;
+var
+ Item: ICollectable;
+begin
+ Item := FIterator.Next;
+ while not FIterator.EOF do
+ begin
+ if FFilter.Accept(Item) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+procedure TFilterIterator.TrueRemove;
+begin
+ FIterator.Remove;
+end;
+
+{ TFilterFuncIterator }
+constructor TFilterFuncIterator.Create(const Iterator: IIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true);
+begin
+ FIterator := Iterator;
+ FFilterFunc := FilterFunc;
+end;
+
+destructor TFilterFuncIterator.Destroy;
+begin
+ FIterator := nil;
+ FFilterFunc := nil;
+end;
+
+function TFilterFuncIterator.TrueFirst: ICollectable;
+var
+ Item: ICollectable;
+begin
+ Item := FIterator.First;
+ while not FIterator.EOF do
+ begin
+ if FFilterFunc(Item) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+function TFilterFuncIterator.TrueNext: ICollectable;
+var
+ Item: ICollectable;
+begin
+ Item := FIterator.Next;
+ while not FIterator.EOF do
+ begin
+ if FFilterFunc(Item) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+procedure TFilterFuncIterator.TrueRemove;
+begin
+ FIterator.Remove;
+end;
+
+{ TKeyFilterMapIterator }
+constructor TKeyFilterMapIterator.Create(const Iterator: IMapIterator; const Filter: IFilter; AllowRemoval: Boolean = true);
+begin
+ FIterator := Iterator;
+ FFilter := Filter;
+end;
+
+destructor TKeyFilterMapIterator.Destroy;
+begin
+ FIterator := nil;
+ FFilter := nil;
+end;
+
+function TKeyFilterMapIterator.TrueFirst: ICollectable;
+var
+ Key, Item: ICollectable;
+begin
+ Item := FIterator.First;
+ while not FIterator.EOF do
+ begin
+ Key := FIterator.CurrentKey;
+ if FFilter.Accept(Key) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+function TKeyFilterMapIterator.TrueNext: ICollectable;
+var
+ Key, Item: ICollectable;
+begin
+ Item := FIterator.Next;
+ while not FIterator.EOF do
+ begin
+ Key := FIterator.CurrentKey;
+ if FFilter.Accept(Key) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+procedure TKeyFilterMapIterator.TrueRemove;
+begin
+ FIterator.Remove;
+end;
+
+function TKeyFilterMapIterator.CurrentKey: ICollectable;
+begin
+ Result := FIterator.CurrentKey;
+end;
+
+{ TKeyFilterFuncMapIterator }
+constructor TKeyFilterFuncMapIterator.Create(const Iterator: IMapIterator; FilterFunc: TCollectionFilterFunc; AllowRemoval: Boolean = true);
+begin
+ FIterator := Iterator;
+ FFilterFunc := FilterFunc;
+end;
+
+destructor TKeyFilterFuncMapIterator.Destroy;
+begin
+ FIterator := nil;
+ FFilterFunc := nil;
+end;
+
+function TKeyFilterFuncMapIterator.TrueFirst: ICollectable;
+var
+ Key, Item: ICollectable;
+begin
+ Item := FIterator.First;
+ while not FIterator.EOF do
+ begin
+ Key := FIterator.CurrentKey;
+ if FFilterFunc(Key) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+function TKeyFilterFuncMapIterator.TrueNext: ICollectable;
+var
+ Key, Item: ICollectable;
+begin
+ Item := FIterator.Next;
+ while not FIterator.EOF do
+ begin
+ Key := FIterator.CurrentKey;
+ if FFilterFunc(Key) then
+ break
+ else
+ Item := FIterator.Next;
+ end;
+ Result := Item;
+end;
+
+procedure TKeyFilterFuncMapIterator.TrueRemove;
+begin
+ FIterator.Remove;
+end;
+
+function TKeyFilterFuncMapIterator.CurrentKey: ICollectable;
+begin
+ Result := FIterator.CurrentKey;
+end;
+
+
+{ TAbstractCollection }
+constructor TAbstractCollection.Create;
+begin
+ Create(false);
+end;
+
+constructor TAbstractCollection.Create(NaturalItemsOnly: Boolean);
+begin
+ FCreated := false;
+ inherited Create;
+ FNaturalItemsOnly := NaturalItemsOnly or GetAlwaysNaturalItems;
+ if FNaturalItemsOnly then
+ FComparator := TAbstractComparator.GetNaturalComparator
+ else
+ FComparator := TAbstractComparator.GetDefaultComparator;
+ FIgnoreErrors := [ceDuplicate];
+end;
+
+constructor TAbstractCollection.Create(const ItemArray: array of ICollectable);
+begin
+ Create(ItemArray, false);
+end;
+
+// Fixed size collections must override this.
+constructor TAbstractCollection.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+ I: Integer;
+begin
+ Create(NaturalItemsOnly);
+ if not FixedSize then
+ begin
+ Capacity := Length(ItemArray);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Add(ItemArray[I]);
+ end;
+ end;
+end;
+
+// Fixed size collections must override this.
+constructor TAbstractCollection.Create(const Collection: ICollection);
+var
+ Iterator: IIterator;
+begin
+ Create(Collection.GetNaturalItemsOnly);
+ InitFrom(Collection);
+ if not FixedSize then
+ begin
+ Capacity := Collection.GetSize;
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Add(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ end;
+end;
+
+destructor TAbstractCollection.Destroy;
+begin
+ FCreated := false;
+ FComparator := nil;
+ inherited Destroy;
+end;
+
+procedure TAbstractCollection.CollectionError(ErrorType: TCollectionError);
+var
+ Msg: String;
+begin
+ if not (ErrorType in FIgnoreErrors) then
+ begin
+ case ErrorType of
+ ceDuplicate: Msg := 'Collection does not allow duplicates.';
+ ceDuplicateKey: Msg := 'Collection does not allow duplicate keys.';
+ ceFixedSize: Msg := 'Collection has fixed size.';
+ ceNilNotAllowed: Msg := 'Collection does not allow nil.';
+ ceNotNaturalItem: Msg := 'Collection only accepts natural items.';
+ ceOutOfRange: Msg := 'Index out of collection range.';
+ end;
+ // If exception is thrown during construction, collection cannot be
+ // passed to it as destructor is automatically called and this leaves an
+ // interface reference to a destroyed object and crashes.
+ if FCreated then
+ raise ECollectionError.Create(Msg, Self, ErrorType)
+ else
+ raise ECollectionError.Create(Msg, nil, ErrorType);
+ end;
+end;
+
+procedure TAbstractCollection.InitFrom(const Collection: ICollection);
+begin
+ Comparator := Collection.GetComparator;
+ IgnoreErrors := Collection.GetIgnoreErrors;
+end;
+
+// Implementations should override this if possible
+function TAbstractCollection.TrueItemCount(const Item: ICollectable): Integer;
+var
+ Iterator: IIterator;
+ Total: Integer;
+begin
+ Total := 0;
+ Iterator := GetIterator;
+ while not Iterator.EOF do
+ begin
+ if FComparator.Equals(Item, Iterator.CurrentItem) then
+ Inc(Total);
+ Iterator.Next;
+ end;
+ Result := Total;
+end;
+
+class function TAbstractCollection.GetAlwaysNaturalItems: Boolean;
+begin
+ Result := false;
+end;
+
+function TAbstractCollection.GetAsArray: TCollectableArray;
+var
+ Iterator: IIterator;
+ Working: TCollectableArray;
+ I: Integer;
+begin
+ SetLength(Working, Size);
+ I := 0;
+ Iterator := GetIterator;
+ while not Iterator.EOF do
+ begin
+ Working[I] := Iterator.CurrentItem;
+ Inc(I);
+ Iterator.Next;
+ end;
+ Result := Working;
+end;
+
+function TAbstractCollection.GetComparator: IComparator;
+begin
+ Result := FComparator;
+end;
+
+function TAbstractCollection.GetDuplicates: Boolean;
+begin
+ Result := true; // Sets and lists override this.
+end;
+
+procedure TAbstractCollection.SetComparator(const Value: IComparator);
+begin
+ if Value = nil then
+ begin
+ if NaturalItemsOnly then
+ FComparator := TAbstractComparator.GetNaturalComparator
+ else
+ FComparator := TAbstractComparator.GetDefaultComparator;
+ end
+ else
+ FComparator := Value;
+end;
+
+function TAbstractCollection.GetFixedSize: Boolean;
+begin
+ Result := false;
+end;
+
+function TAbstractCollection.GetIgnoreErrors: TCollectionErrors;
+begin
+ Result := FIgnoreErrors;
+end;
+
+procedure TAbstractCollection.SetIgnoreErrors(Value: TCollectionErrors);
+begin
+ FIgnoreErrors := Value;
+end;
+
+function TAbstractCollection.GetInstance: TObject;
+begin
+ Result := Self;
+end;
+
+function TAbstractCollection.GetIterator(const Filter: IFilter): IIterator;
+var
+ Iterator: IIterator;
+begin
+ Iterator := GetIterator;
+ Result := TFilterIterator.Create(Iterator, Filter, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractCollection.GetIterator(FilterFunc: TCollectionFilterFunc): IIterator;
+var
+ Iterator: IIterator;
+begin
+ Iterator := GetIterator;
+ Result := TFilterFuncIterator.Create(Iterator, FilterFunc, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractCollection.GetNaturalItemsOnly: Boolean;
+begin
+ Result := FNaturalItemsOnly;
+end;
+
+function TAbstractCollection.Add(const Item: ICollectable): Boolean;
+var
+ ItemError: TCollectionError;
+ Success: Boolean;
+begin
+ ItemError := ItemAllowed(Item); // Can be natural items only error or nil not allowed error
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Success := false;
+ end
+ else if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ Success := false;
+ end
+ else
+ begin
+ Success := TrueAdd(Item);
+ end;
+ Result := Success;
+end;
+
+function TAbstractCollection.Add(const ItemArray: array of ICollectable): Integer;
+var
+ Item: ICollectable;
+ ItemError: TCollectionError;
+ I, Count: Integer;
+ Success: Boolean;
+begin
+ Count := 0;
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ end
+ else
+ begin
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Item := ItemArray[I];
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Success := false;
+ end
+ else
+ begin
+ Success := TrueAdd(Item);
+ end;
+ if Success then
+ Inc(Count);
+ end;
+ end;
+ Result := Count;
+end;
+
+function TAbstractCollection.Add(const Collection: ICollection): Integer;
+var
+ Iterator: IIterator;
+ Item: ICollectable;
+ ItemError: TCollectionError;
+ Count: Integer;
+ Success: Boolean;
+begin
+ Count := 0;
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Success := false;
+ end
+ else if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ Success := false;
+ end
+ else
+ begin
+ Success := TrueAdd(Item);
+ end;
+ if Success then
+ Inc(Count);
+ Iterator.Next;
+ end;
+ Result := Count;
+end;
+
+procedure TAbstractCollection.AfterConstruction;
+begin
+ inherited AfterConstruction;
+ FCreated := true;
+end;
+
+procedure TAbstractCollection.BeforeDestruction;
+begin
+ if not FixedSize then
+ TrueClear;
+ inherited BeforeDestruction;
+end;
+
+function TAbstractCollection.Clear: Integer;
+begin
+ if not FixedSize then
+ begin
+ Result := Size;
+ TrueClear;
+ end
+ else
+ begin
+ CollectionError(ceFixedSize);
+ Result := 0;
+ end;
+end;
+
+function TAbstractCollection.Clone: ICollection;
+begin
+ Result := (TAbstractCollectionClass(ClassType)).Create(Self);
+end;
+
+function TAbstractCollection.Contains(const Item: ICollectable): Boolean;
+var
+ ItemError: TCollectionError;
+ Success: Boolean;
+begin
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Success := false;
+ end
+ else
+ begin
+ Success := TrueContains(Item);
+ end;
+ Result := Success;
+end;
+
+function TAbstractCollection.Contains(const ItemArray: array of ICollectable): Boolean;
+var
+ I: Integer;
+ Success: Boolean;
+begin
+ Success := true;
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Success := Success and Contains(ItemArray[I]);
+ if not Success then
+ break;
+ end;
+ Result := Success;
+end;
+
+function TAbstractCollection.Contains(const Collection: ICollection): Boolean;
+var
+ Iterator: IIterator;
+ Success: Boolean;
+begin
+ Success := true;
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Success := Success and Contains(Iterator.CurrentItem);
+ if not Success then
+ break;
+ Iterator.Next;
+ end;
+ Result := Success;
+end;
+
+function TAbstractCollection.Equals(const Collection: ICollection): Boolean;
+var
+ Iterator: IIterator;
+ Success: Boolean;
+begin
+ if Collection.GetType <> GetType then
+ Result := false
+ else if Collection.Size <> Size then
+ Result := false
+ else if not Collection.Comparator.Equals(Comparator) then
+ Result := false
+ else if not Collection.GetDuplicates and not GetDuplicates then
+ begin
+ // Not equal if any item not found in parameter collection
+ Success := true;
+ Iterator := GetIterator;
+ while not Iterator.EOF and Success do
+ begin
+ Success := Collection.Contains(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := Success;
+ end
+ else
+ begin
+ // Not equal if any item count not equal to item count in parameter collection
+ Success := true;
+ Iterator := GetIterator;
+ while not Iterator.EOF and Success do
+ begin
+ Success := (ItemCount(Iterator.CurrentItem) = Collection.ItemCount(Iterator.CurrentItem));
+ Iterator.Next;
+ end;
+ Result := Success;
+ end;
+end;
+
+function TAbstractCollection.Find(const Filter: IFilter): ICollectable;
+begin
+ Result := GetIterator(Filter).First;
+end;
+
+function TAbstractCollection.Find(FilterFunc: TCollectionFilterFunc): ICollectable;
+begin
+ Result := GetIterator(FilterFunc).First;
+end;
+
+function TAbstractCollection.FindAll(const Filter: IFilter): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Self.GetIterator(Filter);
+ while not Iterator.EOF do
+ begin
+ ResultCollection.Add(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.FindAll(FilterFunc: TCollectionFilterFunc): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Self.GetIterator(FilterFunc);
+ while not Iterator.EOF do
+ begin
+ ResultCollection.Add(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.IsEmpty: Boolean;
+begin
+ Result := (Size = 0);
+end;
+
+function TAbstractCollection.IsNaturalItem(const Item: ICollectable): Boolean;
+var
+ Temp: IUnknown;
+begin
+ if Item <> nil then
+ Result := (Item.QueryInterface(NaturalItemIID, Temp) <> E_NOINTERFACE)
+ else
+ Result := false;
+end;
+
+function TAbstractCollection.ItemAllowed(const Item: ICollectable): TCollectionError;
+begin
+ if NaturalItemsOnly and not IsNaturalItem(Item) then
+ Result := ceNotNaturalItem
+ else if not IsNilAllowed and (Item = nil) then
+ Result := ceNilNotAllowed
+ else
+ Result := ceOK;
+end;
+
+function TAbstractCollection.ItemCount(const Item: ICollectable): Integer;
+var
+ ItemError: TCollectionError;
+begin
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Result := 0;
+ end
+ else if GetDuplicates then
+ begin
+ Result := TrueItemCount(Item);
+ end
+ else
+ begin
+ // Where duplicates are not allowed, TrueContains will be faster than TrueItemCount.
+ if TrueContains(Item) then
+ Result := 1
+ else
+ Result := 0;
+ end;
+end;
+
+function TAbstractCollection.ItemCount(const ItemArray: array of ICollectable): Integer;
+var
+ I: Integer;
+ Total: Integer;
+begin
+ Total := 0;
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Total := Total + ItemCount(ItemArray[I]);
+ end;
+ Result := Total;
+end;
+
+function TAbstractCollection.ItemCount(const Collection: ICollection): Integer;
+var
+ Iterator: IIterator;
+ Total: Integer;
+begin
+ Total := 0;
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Total := Total + ItemCount(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := Total;
+end;
+
+function TAbstractCollection.Matching(const ItemArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ if Contains(ItemArray[I]) then
+ ResultCollection.Add(ItemArray[I]);
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.Matching(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ if Contains(Iterator.CurrentItem) then
+ ResultCollection.Add(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.Remove(const Item: ICollectable): ICollectable;
+var
+ ItemError: TCollectionError;
+begin
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Result := nil;
+ end
+ else if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ Result := nil;
+ end
+ else
+ begin
+ Result := TrueRemove(Item);
+ end;
+end;
+
+function TAbstractCollection.Remove(const ItemArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ ResultCollection.Add(Remove(ItemArray[I]));
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.Remove(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ ResultCollection.Add(Remove(Iterator.CurrentItem));
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.RemoveAll(const Item: ICollectable): ICollection;
+var
+ ItemError: TCollectionError;
+begin
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Result := nil;
+ end
+ else if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ Result := nil;
+ end
+ else
+ begin
+ Result := TrueRemoveAll(Item);
+ end;
+end;
+
+function TAbstractCollection.RemoveAll(const ItemArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ ResultCollection.Add(RemoveAll(ItemArray[I]));
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.RemoveAll(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ ResultCollection.Add(RemoveAll(Iterator.CurrentItem));
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.Retain(const ItemArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+ Item: ICollectable;
+ I: Integer;
+ Found, Success: Boolean;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := GetIterator;
+ while not Iterator.EOF do
+ begin
+ // Converting the array to a map would be faster but I don't want to
+ // couple base class code to a complex collection.
+ Found := false;
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Item := Iterator.CurrentItem;
+ Found := Comparator.Equals(Item, ItemArray[I]);
+ if Found then
+ break;
+ end;
+ if not Found then
+ begin
+ Success := Iterator.Remove;
+ if Success then
+ ResultCollection.Add(Item);
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractCollection.Retain(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+ Item: ICollectable;
+ Success: Boolean;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;
+ if not Collection.Contains(Item) then
+ begin
+ Success := Iterator.Remove;
+ if Success then
+ ResultCollection.Add(Item);
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+{ TAbstractBag }
+function TAbstractBag.CloneAsBag: IBag;
+begin
+ Result := (TAbstractBagClass(ClassType)).Create(Self);
+end;
+
+function TAbstractBag.GetNaturalItemIID: TGUID;
+begin
+ Result := EquatableIID;
+end;
+
+function TAbstractBag.GetType: TCollectionType;
+begin
+ Result := ctBag;
+end;
+
+function TAbstractBag.IsNilAllowed: Boolean;
+begin
+ Result := true;
+end;
+
+{ TAbstractSet }
+function TAbstractSet.TrueAdd(const Item: ICollectable): Boolean;
+var
+ Position: TCollectionPosition;
+begin
+ // Adds if not already present otherwise fails
+ Position := GetPosition(Item);
+ try
+ if Position.Found then
+ begin
+ CollectionError(ceDuplicate);
+ Result := false;
+ end
+ else
+ begin
+ TrueAdd2(Position, Item);
+ Result := true;
+ end;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractSet.TrueContains(const Item: ICollectable): Boolean;
+var
+ Position: TCollectionPosition;
+begin
+ Position := GetPosition(Item);
+ try
+ Result := Position.Found;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractSet.TrueRemove(const Item: ICollectable): ICollectable;
+var
+ Position: TCollectionPosition;
+begin
+ Position := GetPosition(Item);
+ try
+ if Position.Found then
+ begin
+ Result := TrueGet(Position);
+ TrueRemove2(Position);
+ end
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractSet.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ RemovedItem: ICollectable;
+begin
+ ResultCollection := TPArrayBag.Create;
+ RemovedItem := TrueRemove(Item);
+ if RemovedItem <> nil then
+ ResultCollection.Add(RemovedItem);
+ Result := ResultCollection;
+end;
+
+function TAbstractSet.GetDuplicates: Boolean;
+begin
+ Result := false;
+end;
+
+function TAbstractSet.GetNaturalItemIID: TGUID;
+begin
+ Result := EquatableIID;
+end;
+
+function TAbstractSet.GetType: TCollectionType;
+begin
+ Result := ctSet;
+end;
+
+function TAbstractSet.CloneAsSet: ISet;
+begin
+ Result := (TAbstractSetClass(ClassType)).Create(Self);
+end;
+
+function TAbstractSet.Complement(const Universe: ISet): ISet;
+var
+ ResultSet: ISet;
+ Iterator: IIterator;
+ Item: ICollectable;
+begin
+ // Return items in universe not found in self.
+ ResultSet := TAbstractSetClass(ClassType).Create(NaturalItemsOnly);
+ Iterator := Universe.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;
+ if not Contains(Item) then
+ ResultSet.Add(Item);
+ Iterator.Next;
+ end;
+ Result := ResultSet;
+end;
+
+function TAbstractSet.Intersect(const Set2: ISet): ISet;
+var
+ ResultSet: ISet;
+ Iterator: IIterator;
+ Item: ICollectable;
+begin
+ // Return items found in self and parameter.
+ ResultSet := TAbstractSetClass(ClassType).Create(NaturalItemsOnly);
+ Iterator := GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;
+ if Contains(Item) and Set2.Contains(Item) then
+ ResultSet.Add(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := ResultSet;
+end;
+
+function TAbstractSet.IsNilAllowed: Boolean;
+begin
+ Result := false;
+end;
+
+function TAbstractSet.Union(const Set2: ISet): ISet;
+var
+ ResultSet: ISet;
+ Iterator: IIterator;
+ Item: ICollectable;
+begin
+ // Return items found in self or parameter.
+ ResultSet := CloneAsSet;
+ Iterator := Set2.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;
+ if not Contains(Item) and Set2.Contains(Item) then
+ ResultSet.Add(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := ResultSet;
+end;
+
+{ TAbstractList }
+constructor TAbstractList.Create(NaturalItemsOnly: Boolean);
+begin
+ inherited Create(NaturalItemsOnly);
+ FDuplicates := true;
+ FSorted := false;
+end;
+
+procedure TAbstractList.InitFrom(const Collection: ICollection);
+var
+ List: IList;
+begin
+ inherited InitFrom(Collection);
+ if Collection.QueryInterface(IList, List) = S_OK then
+ begin
+ FDuplicates := List.GetDuplicates;
+ FSorted := List.GetSorted;
+ end;
+end;
+
+function TAbstractList.TrueAdd(const Item: ICollectable): Boolean;
+var
+ SearchResult: TSearchResult;
+begin
+ Result := True;
+ if Sorted then
+ begin
+ // Insert in appropriate place to maintain sort order, unless duplicate
+ // not allowed.
+ SearchResult := BinarySearch(Item);
+ case SearchResult.ResultType of
+ srBeforeIndex: TrueInsert(SearchResult.Index, Item);
+ srFoundAtIndex: begin
+ if Duplicates then
+ TrueInsert(SearchResult.Index, Item)
+ else
+ begin
+ CollectionError(ceDuplicate);
+ Result := false;
+ end;
+ end;
+ srAfterEnd: TrueAppend(Item);
+ end;
+ end
+ else
+ begin
+ // Add to end, unless duplicate not allowed.
+ if not Duplicates and (SequentialSearch(Item, Comparator).ResultType = srFoundAtIndex) then
+ begin
+ CollectionError(ceDuplicate);
+ Result := false;
+ end
+ else
+ TrueAppend(Item);
+ end;
+end;
+
+function TAbstractList.TrueContains(const Item: ICollectable): Boolean;
+begin
+ if Sorted then
+ Result := BinarySearch(Item).ResultType = srFoundAtIndex
+ else
+ Result := SequentialSearch(Item, Comparator).ResultType = srFoundAtIndex
+end;
+
+function TAbstractList.TrueItemCount(const Item: ICollectable): Integer;
+var
+ SearchResult: TSearchResult;
+ Count: Integer;
+begin
+ if Sorted then
+ begin
+ // If sorted, use binary search.
+ Count := 0;
+ SearchResult := BinarySearch(Item);
+ if SearchResult.ResultType = srFoundAtIndex then
+ begin
+ repeat
+ Inc(Count);
+ until not Comparator.Equals(Item, Items[SearchResult.Index]);
+ end;
+ Result := Count;
+ end
+ else
+ // Resort to sequential search for unsorted
+ Result := inherited TrueItemCount(Item);
+end;
+
+function TAbstractList.TrueRemove(const Item: ICollectable): ICollectable;
+var
+ SearchResult: TSearchResult;
+begin
+ Result := nil;
+ if Sorted then
+ begin
+ SearchResult := BinarySearch(Item);
+ if SearchResult.ResultType = srFoundAtIndex then
+ begin
+ Result := TrueDelete(SearchResult.Index);
+ end;
+ end
+ else
+ begin
+ SearchResult := SequentialSearch(Item);
+ if SearchResult.ResultType = srFoundAtIndex then
+ Result := TrueDelete(SearchResult.Index);
+ end;
+end;
+
+function TAbstractList.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ SearchResult: TSearchResult;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create;
+ if Sorted then
+ begin
+ SearchResult := BinarySearch(Item);
+ if SearchResult.ResultType = srFoundAtIndex then
+ begin
+ repeat
+ ResultCollection.Add(TrueDelete(SearchResult.Index));
+ until not Comparator.Equals(Item, Items[SearchResult.Index]);
+ end;
+ end
+ else
+ begin
+ I := 0;
+ while I < Size do
+ begin
+ if Comparator.Equals(Item, Items[I]) then
+ begin
+ ResultCollection.Add(TrueDelete(I));
+ end
+ else
+ Inc(I);
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+procedure TAbstractList.QuickSort(Lo, Hi: Integer; const Comparator: IComparator);
+var
+ I, J, Mid: Integer;
+begin
+ repeat
+ I := Lo;
+ J := Hi;
+ Mid := (Lo + Hi) div 2;
+ repeat
+ while Comparator.Compare(Items[I], Items[Mid]) < 0 do
+ Inc(I);
+ while Comparator.Compare(Items[J], Items[Mid]) > 0 do
+ Dec(J);
+ if I <= J then
+ begin
+ Exchange(I, J);
+ if Mid = I then
+ Mid := J
+ else if Mid = J then
+ Mid := I;
+ Inc(I);
+ Dec(J);
+ end;
+ until I > J;
+ if Lo < J then
+ QuickSort(Lo, J, Comparator);
+ Lo := I;
+ until I >= Hi;
+end;
+
+procedure TAbstractList.QuickSort(Lo, Hi: Integer; CompareFunc: TCollectionCompareFunc);
+var
+ I, J, Mid: Integer;
+begin
+ repeat
+ I := Lo;
+ J := Hi;
+ Mid := (Lo + Hi) div 2;
+ repeat
+ while CompareFunc(Items[I], Items[Mid]) < 0 do
+ Inc(I);
+ while CompareFunc(Items[J], Items[Mid]) > 0 do
+ Dec(J);
+ if I <= J then
+ begin
+ Exchange(I, J);
+ if Mid = I then
+ Mid := J
+ else if Mid = J then
+ Mid := I;
+ Inc(I);
+ Dec(J);
+ end;
+ until I > J;
+ if Lo < J then
+ QuickSort(Lo, J, CompareFunc);
+ Lo := I;
+ until I >= Hi;
+end;
+
+function TAbstractList.GetDuplicates: Boolean;
+begin
+ Result := FDuplicates;
+end;
+
+procedure TAbstractList.SetDuplicates(Value: Boolean);
+var
+ Iterator: IIterator;
+ Failed: Boolean;
+begin
+ Failed := false;
+ // If trying to set no duplicates, check there are no existing duplicates.
+ if not Value then
+ begin
+ Iterator := GetIterator;
+ while not Iterator.EOF and not Failed do
+ begin
+ Failed := (ItemCount(Iterator.CurrentItem) > 1);
+ Iterator.Next;
+ end;
+ if Failed then
+ CollectionError(ceDuplicate);
+ end;
+ if not Failed then
+ FDuplicates := Value;
+end;
+
+function TAbstractList.GetItem(Index: Integer): ICollectable;
+begin
+ if (Index < 0) or (Index >= Size) then
+ begin
+ CollectionError(ceOutOfRange);
+ Result := nil;
+ end
+ else
+ Result := TrueGetItem(Index);
+end;
+
+procedure TAbstractList.SetItem(Index: Integer; const Item: ICollectable);
+var
+ SearchResult: TSearchResult;
+begin
+ if (Index < 0) or (Index >= Size) then
+ begin
+ CollectionError(ceOutOfRange)
+ end
+ else if not Duplicates then
+ begin
+ // Find any duplicates
+ if Sorted then
+ begin
+ SearchResult := BinarySearch(Item);
+ case SearchResult.ResultType of
+ srBeforeIndex, srAfterEnd: begin // If item is not present
+ FSorted := false;
+ TrueSetItem(Index, Item);
+ end;
+ srFoundAtIndex: begin // If item is already present
+ CollectionError(ceDuplicate);
+ end;
+ end;
+ end
+ else
+ begin
+ // If item is already present
+ if SequentialSearch(Item, Comparator).ResultType = srFoundAtIndex then
+ begin
+ CollectionError(ceDuplicate);
+ end
+ else
+ begin
+ TrueSetItem(Index, Item);
+ end;
+ end;
+ end
+ else
+ begin
+ FSorted := false;
+ TrueSetItem(Index, Item);
+ end;
+end;
+
+function TAbstractList.GetIterator: IIterator;
+begin
+ Result := TAbstractListIterator.Create(Self);
+end;
+
+function TAbstractList.GetNaturalItemIID: TGUID;
+begin
+ Result := ComparableIID;
+end;
+
+function TAbstractList.GetSorted: Boolean;
+begin
+ Result := FSorted;
+end;
+
+procedure TAbstractList.SetSorted(Value: Boolean);
+begin
+ if Value then
+ Sort;
+end;
+
+function TAbstractList.GetType: TCollectionType;
+begin
+ Result := ctList;
+end;
+
+function TAbstractList.BinarySearch(const Item: ICollectable): TSearchResult;
+var
+ Lo, Hi, Mid: Integer;
+ CompareResult: Integer;
+ Success: Boolean;
+begin
+ if Size = 0 then
+ begin
+ Result.ResultType := srAfterEnd;
+ Exit;
+ end;
+ Lo := 0;
+ Hi := Size - 1;
+ Success := false;
+ repeat
+ Mid := (Lo + Hi) div 2;
+ CompareResult := Comparator.Compare(Item, Items[Mid]);
+ if CompareResult = 0 then
+ Success := true
+ else if CompareResult > 0 then
+ Lo := Mid + 1
+ else
+ Hi := Mid - 1;
+ until (Lo > Hi) or Success;
+ if Success then
+ begin
+ // Move index back if in cluster of duplicates
+ while (Mid > 0) and Comparator.Equals(Item, Items[Mid - 1]) do
+ Dec(Mid);
+ Result.ResultType := srFoundAtIndex;
+ Result.Index := Mid;
+ end
+ else if CompareResult < 0 then
+ begin
+ Result.ResultType := srBeforeIndex;
+ Result.Index := Mid;
+ end
+ else if Hi < Size - 1 then
+ begin
+ Result.ResultType := srBeforeIndex;
+ Result.Index := Mid + 1;
+ end
+ else
+ Result.ResultType := srAfterEnd;
+end;
+
+function TAbstractList.CloneAsList: IList;
+begin
+ Result := (TAbstractListClass(ClassType)).Create(Self);
+end;
+
+function TAbstractList.Delete(Index: Integer): ICollectable;
+begin
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ Result := nil;
+ end
+ else if (Index < 0) or (Index >= Size) then
+ begin
+ CollectionError(ceOutOfRange);
+ Result := nil;
+ end
+ else
+ begin
+ Result := TrueDelete(Index);
+ end;
+end;
+
+procedure TAbstractList.Exchange(Index1, Index2: Integer);
+var
+ Item: ICollectable;
+begin
+ if (Index1 < 0) or (Index1 >= Size) then
+ CollectionError(ceOutOfRange);
+ if (Index2 < 0) or (Index2 >= Size) then
+ CollectionError(ceOutOfRange);
+ FSorted := false;
+ Item := ICollectable(Items[Index1]);
+ Items[Index1] := Items[Index2];
+ Items[Index2] := Item;
+end;
+
+function TAbstractList.First: ICollectable;
+begin
+ if Size > 0 then
+ Result := Items[0]
+ else
+ Result := nil;
+end;
+
+function TAbstractList.IndexOf(const Item: ICollectable): Integer;
+var
+ SearchResult: TSearchResult;
+begin
+ if Sorted then
+ SearchResult := BinarySearch(Item)
+ else
+ SearchResult := SequentialSearch(Item, Comparator);
+ if SearchResult.ResultType = srFoundAtIndex then
+ Result := SearchResult.Index
+ else
+ Result := -1;
+end;
+
+function TAbstractList.Insert(Index: Integer; const Item: ICollectable): Boolean;
+var
+ ItemError: TCollectionError;
+begin
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Result := false;
+ end
+ else if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ Result := false;
+ end
+ else if (Index < 0) or (Index > Size) then
+ begin
+ CollectionError(ceOutOfRange);
+ Result := false;
+ end
+ else
+ begin
+ FSorted := false;
+ if Index = Size then
+ TrueAdd(Item)
+ else
+ TrueInsert(Index, Item);
+ Result := true;
+ end;
+end;
+
+function TAbstractList.Insert(Index: Integer; const ItemArray: array of ICollectable): Integer;
+var
+ Item: ICollectable;
+ ItemError: TCollectionError;
+ I, NewIndex, Count: Integer;
+ Success: Boolean;
+begin
+ Count := 0;
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ end
+ else if (Index < 0) or (Index > Size) then
+ begin
+ CollectionError(ceOutOfRange);
+ end
+ else
+ begin
+ // Insert entire array in place in correct order
+ NewIndex := Index;
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Item := ItemArray[I];
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ end
+ else
+ begin
+ Success := Insert(NewIndex, Item);
+ if Success then
+ begin
+ Inc(NewIndex);
+ Inc(Count);
+ end;
+ end;
+ end;
+ end;
+ Result := Count;
+end;
+
+function TAbstractList.Insert(Index: Integer; const Collection: ICollection): Integer;
+var
+ Iterator: IIterator;
+ Item: ICollectable;
+ ItemError: TCollectionError;
+ NewIndex, Count: Integer;
+ Success: Boolean;
+begin
+ Count := 0;
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ end
+ else if (Index < 0) or (Index > Size) then
+ begin
+ CollectionError(ceOutOfRange);
+ end
+ else
+ begin
+ // Insert entire collection in place in correct order
+ NewIndex := Index;
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ end
+ else
+ begin
+ Success := Insert(NewIndex, Item);
+ if Success then
+ begin
+ Inc(NewIndex);
+ Inc(Count);
+ end;
+ end;
+ Iterator.Next;
+ end;
+ end;
+ Result := Count;
+end;
+
+function TAbstractList.IsNilAllowed: Boolean;
+begin
+ Result := true;
+end;
+
+function TAbstractList.Last: ICollectable;
+begin
+ if Size > 0 then
+ Result := Items[Size - 1]
+ else
+ Result := nil;
+end;
+
+function TAbstractList.Search(const Item: ICollectable; const SearchComparator: IComparator = nil): TSearchResult;
+begin
+ if Sorted and (SearchComparator = nil) then
+ Result := BinarySearch(Item)
+ else
+ Result := SequentialSearch(Item, SearchComparator);
+end;
+
+function TAbstractList.SequentialSearch(const Item: ICollectable; const SearchComparator: IComparator): TSearchResult;
+var
+ WorkingComparator: IComparator;
+ I: Integer;
+ Success: Boolean;
+begin
+ if SearchComparator = nil then
+ WorkingComparator := Comparator
+ else
+ WorkingComparator := SearchComparator;
+ Result.ResultType := srNotFound;
+ I := 0;
+ Success := false;
+ while (I < Size) and not Success do
+ begin
+ if WorkingComparator.Equals(Item, Items[I]) then
+ begin
+ Result.ResultType := srFoundAtIndex;
+ Result.Index := I;
+ Success := true;
+ end
+ else
+ Inc(I);
+ end;
+end;
+
+procedure TAbstractList.Sort(const SortComparator: IComparator);
+begin
+ if SortComparator = nil then
+ begin
+ if Size > 0 then
+ QuickSort(0, Size - 1, Comparator);
+ FSorted := true;
+ end
+ else
+ begin
+ if Size > 0 then
+ QuickSort(0, Size - 1, SortComparator);
+ FSorted := false;
+ end;
+end;
+
+procedure TAbstractList.Sort(CompareFunc: TCollectionCompareFunc);
+begin
+ if Size > 0 then
+ QuickSort(0, Size - 1, CompareFunc);
+ FSorted := false;
+end;
+
+{ TAbstractMap }
+constructor TAbstractMap.Create;
+begin
+ Create(false, true);
+end;
+
+constructor TAbstractMap.Create(NaturalItemsOnly: Boolean);
+begin
+ Create(NaturalItemsOnly, true);
+end;
+
+constructor TAbstractMap.Create(NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+begin
+ inherited Create(NaturalItemsOnly);
+ FNaturalKeysOnly := NaturalKeysOnly or GetAlwaysNaturalKeys;
+ FAssociationComparator := TAssociationComparator.Create(FNaturalKeysOnly);
+ if FNaturalKeysOnly then
+ FKeyComparator := TAbstractComparator.GetNaturalComparator
+ else
+ FKeyComparator := TAbstractComparator.GetDefaultComparator;
+end;
+
+constructor TAbstractMap.Create(const ItemArray: array of ICollectable);
+begin
+ Create(ItemArray, true, true);
+end;
+
+constructor TAbstractMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+ Create(ItemArray, true, true);
+end;
+
+constructor TAbstractMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+var
+ I: Integer;
+begin
+ Create(true, NaturalKeysOnly);
+ if not FixedSize then
+ begin
+ Capacity := Length(ItemArray);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Add(ItemArray[I]);
+ end;
+ end;
+end;
+
+constructor TAbstractMap.Create(const KeyArray, ItemArray: array of ICollectable);
+begin
+ Create(KeyArray, ItemArray, false, true);
+end;
+
+constructor TAbstractMap.Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+ Create(KeyArray, ItemArray, NaturalItemsOnly, true);
+end;
+
+constructor TAbstractMap.Create(const KeyArray, ItemArray: array of ICollectable; NaturalItemsOnly: Boolean; NaturalKeysOnly: Boolean);
+var
+ I, Lo, Hi: Integer;
+begin
+ Create(NaturalItemsOnly, NaturalKeysOnly);
+ if not FixedSize then
+ begin
+ Capacity := Min(Length(KeyArray), Length(ItemArray));
+ Lo := Max(Low(KeyArray), Low(ItemArray));
+ Hi := Min(High(KeyArray), High(ItemArray));
+ for I := Lo to Hi do
+ begin
+ Put(KeyArray[I], ItemArray[I]);
+ end;
+ end;
+end;
+
+constructor TAbstractMap.Create(const Map: IMap);
+var
+ MapIterator: IMapIterator;
+begin
+ Create(Map.GetNaturalItemsOnly, Map.GetNaturalKeysOnly);
+ InitFrom(Map);
+ if not FixedSize then
+ begin
+ Capacity := Map.GetSize;
+ MapIterator := Map.GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ Put(MapIterator.CurrentKey, MapIterator.CurrentItem);
+ MapIterator.Next;
+ end;
+ end;
+end;
+
+destructor TAbstractMap.Destroy;
+begin
+ FKeyComparator := nil;
+ FAssociationComparator := nil;
+ inherited Destroy;
+end;
+
+procedure TAbstractMap.InitFrom(const Collection: ICollection);
+var
+ Map: IMap;
+begin
+ inherited InitFrom(Collection);
+ if Collection.QueryInterface(IMap, Map) = S_OK then
+ begin
+ FNaturalKeysOnly := Map.GetNaturalKeysOnly or GetAlwaysNaturalKeys;
+ KeyComparator := Map.GetKeyComparator;
+ end;
+end;
+
+function TAbstractMap.TrueAdd(const Item: ICollectable): Boolean;
+var
+ Position: TCollectionPosition;
+ Mappable: IMappable;
+begin
+ if IsNaturalItem(Item) then
+ begin
+ Mappable := Item as IMappable;
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ if Position.Found then
+ begin
+ CollectionError(ceDuplicateKey);
+ Result := false;
+ end
+ else
+ begin
+ TruePut(Position, TAssociation.Create(Mappable.GetKey, Item));
+ Result := true;
+ end;
+ finally
+ Position.Free;
+ end;
+ end
+ else
+ begin
+ CollectionError(ceNotNaturalItem);
+ Result := false;
+ end;
+end;
+
+function TAbstractMap.TrueContains(const Item: ICollectable): Boolean;
+var
+ Item2: ICollectable;
+ Success: Boolean;
+ Iterator: IIterator;
+begin
+ Iterator := GetIterator;
+ Success := false;
+ while not Iterator.EOF and not Success do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ Success := true;
+ Iterator.Next;
+ end;
+ Result := Success;
+end;
+
+function TAbstractMap.TrueRemove(const Item: ICollectable): ICollectable;
+var
+ Item2: ICollectable;
+ Iterator: IMapIterator;
+ Found: Boolean;
+begin
+ // Sequential search
+ Found := false;
+ Result := nil;
+ Iterator := GetAssociationIterator;
+ while not Iterator.EOF and not Found do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ begin
+ Result := Item2;
+ Iterator.Remove;
+ Found := true;
+ end;
+ Iterator.Next;
+ end;
+end;
+
+function TAbstractMap.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ Item2: ICollectable;
+ Iterator: IMapIterator;
+begin
+ // Sequential search
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := GetAssociationIterator;
+ while not Iterator.EOF do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ begin
+ ResultCollection.Add(Item2);
+ Iterator.Remove;
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+class function TAbstractMap.GetAlwaysNaturalKeys: Boolean;
+begin
+ Result := false;
+end;
+
+function TAbstractMap.GetItem(const Key: ICollectable): ICollectable;
+begin
+ Result := Get(Key);
+end;
+
+procedure TAbstractMap.SetItem(const Key, Item: ICollectable);
+begin
+ Put(Key, Item);
+end;
+
+function TAbstractMap.GetIterator: IIterator;
+begin
+ Result := GetAssociationIterator;
+end;
+
+function TAbstractMap.GetKeyComparator: IComparator;
+begin
+ Result := FKeyComparator;
+end;
+
+procedure TAbstractMap.SetKeyComparator(const Value: IComparator);
+begin
+ FKeyComparator := Value;
+ FAssociationComparator.KeyComparator := Value;
+end;
+
+function TAbstractMap.GetKeyIterator: IIterator;
+begin
+ Result := TAssociationKeyIterator.Create(GetAssociationIterator);
+end;
+
+function TAbstractMap.GetKeys: ISet;
+var
+ ResultCollection: TPArraySet;
+ KeyIterator: IIterator;
+begin
+ ResultCollection := TPArraySet.Create(NaturalKeysOnly);
+ ResultCollection.SetComparator(GetKeyComparator);
+ KeyIterator := GetKeyIterator;
+ while not KeyIterator.EOF do
+ begin
+ ResultCollection.Add(KeyIterator.CurrentItem);
+ KeyIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.GetMapIterator: IMapIterator;
+begin
+ Result := GetAssociationIterator;
+end;
+
+function TAbstractMap.GetMapIteratorByKey(const Filter: IFilter): IMapIterator;
+var
+ Iterator: IMapIterator;
+begin
+ Iterator := GetMapIterator;
+ Result := TKeyFilterMapIterator.Create(Iterator, Filter, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractMap.GetMapIteratorByKey(FilterFunc: TCollectionFilterFunc): IMapIterator;
+var
+ Iterator: IMapIterator;
+begin
+ Iterator := GetMapIterator;
+ Result := TKeyFilterFuncMapIterator.Create(Iterator, FilterFunc, Iterator.GetAllowRemoval);
+end;
+
+function TAbstractMap.GetNaturalItemIID: TGUID;
+begin
+ Result := MappableIID;
+end;
+
+function TAbstractMap.GetNaturalKeyIID: TGUID;
+begin
+ Result := EquatableIID;
+end;
+
+function TAbstractMap.GetNaturalKeysOnly: Boolean;
+begin
+ Result := FNaturalKeysOnly;
+end;
+
+function TAbstractMap.GetType: TCollectionType;
+begin
+ Result := ctMap;
+end;
+
+function TAbstractMap.GetValues: ICollection;
+var
+ ResultCollection: ICollection;
+ ValueIterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ ValueIterator := GetIterator;
+ while not ValueIterator.EOF do
+ begin
+ ResultCollection.Add(ValueIterator.CurrentItem);
+ ValueIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+// Overrides TAbstractCollection function, otherwise Create(ICollection) is
+// called, which cannot access keys.
+function TAbstractMap.Clone: ICollection;
+begin
+ Result := (TAbstractMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractMap.CloneAsMap: IMap;
+begin
+ Result := (TAbstractMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractMap.ContainsKey(const Key: ICollectable): Boolean;
+var
+ Position: TCollectionPosition;
+begin
+ Position := GetKeyPosition(Key);
+ try
+ Result := Position.Found;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractMap.ContainsKey(const KeyArray: array of ICollectable): Boolean;
+var
+ I: Integer;
+ Success: Boolean;
+begin
+ Success := true;
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Success := Success and ContainsKey(KeyArray[I]);
+ if not Success then
+ break;
+ end;
+ Result := Success;
+end;
+
+function TAbstractMap.ContainsKey(const Collection: ICollection): Boolean;
+var
+ Iterator: IIterator;
+ Success: Boolean;
+begin
+ Success := true;
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Success := Success and ContainsKey(Iterator.CurrentItem);
+ if not Success then
+ break;
+ Iterator.Next;
+ end;
+ Result := Success;
+end;
+
+function TAbstractMap.Get(const Key: ICollectable): ICollectable;
+var
+ KeyError: TCollectionError;
+ Position: TCollectionPosition;
+begin
+ KeyError := KeyAllowed(Key);
+ if KeyError <> ceOK then
+ begin
+ CollectionError(KeyError);
+ Result := nil;
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ Result := TrueGet(Position).GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractMap.KeyAllowed(const Key: ICollectable): TCollectionError;
+begin
+ if NaturalKeysOnly and not IsNaturalKey(Key) then
+ Result := ceNotNaturalItem
+ else if Key = nil then
+ Result := ceNilNotAllowed
+ else
+ Result := ceOK;
+end;
+
+function TAbstractMap.IsNaturalKey(const Key: ICollectable): Boolean;
+var
+ Temp: IUnknown;
+begin
+ if Key.QueryInterface(NaturalKeyIID, Temp) <> E_NOINTERFACE then
+ Result := true
+ else
+ Result := false;
+end;
+
+function TAbstractMap.IsNilAllowed: Boolean;
+begin
+ Result := true;
+end;
+
+function TAbstractMap.MatchingKey(const KeyArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ if ContainsKey(KeyArray[I]) then
+ ResultCollection.Add(KeyArray[I]);
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.MatchingKey(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Iterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ if ContainsKey(Iterator.CurrentItem) then
+ ResultCollection.Add(Iterator.CurrentItem);
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.Put(const Item: ICollectable): ICollectable;
+var
+ Mappable: IMappable;
+ OldAssociation, NewAssociation: IAssociation;
+ Position: TCollectionPosition;
+begin
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ Result := nil;
+ end
+ else
+ begin
+ Item.QueryInterface(IMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ Result := OldAssociation.GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractMap.Put(const Key, Item: ICollectable): ICollectable;
+var
+ OldAssociation, NewAssociation: IAssociation;
+ ItemError, KeyError: TCollectionError;
+ Position: TCollectionPosition;
+begin
+ ItemError := ItemAllowed(Item);
+ KeyError := KeyAllowed(Key);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Result := nil;
+ end
+ else if KeyError <> ceOK then
+ begin
+ CollectionError(KeyError);
+ Result := nil;
+ end
+ else
+ begin
+ // Find appropriate place, then place key-item association there
+ Position := GetKeyPosition(Key);
+ try
+ NewAssociation := TAssociation.Create(Key, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ Result := OldAssociation.GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractMap.Put(const ItemArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ Mappable: IMappable;
+ OldAssociation, NewAssociation: IAssociation;
+ Position: TCollectionPosition;
+ Item: ICollectable;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Item := ItemArray[I];
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ end
+ else
+ begin
+ // Find appropriate place, then place key-item association there
+ Item.QueryInterface(IMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.Put(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Mappable: IMappable;
+ OldAssociation, NewAssociation: IAssociation;
+ Position: TCollectionPosition;
+ Iterator: IIterator;
+ Item: ICollectable;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;;
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ end
+ else
+ begin
+ // Find appropriate place, then place key-item association there
+ Item.QueryInterface(IMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.Put(const Map: IMap): ICollection;
+var
+ ResultCollection: ICollection;
+ OldAssociation, NewAssociation: IAssociation;
+ ItemError, KeyError: TCollectionError;
+ Position: TCollectionPosition;
+ MapIterator: IMapIterator;
+ Key, Item: ICollectable;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ MapIterator := Map.GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ Key := MapIterator.CurrentKey;
+ Item := MapIterator.CurrentItem;
+
+ ItemError := ItemAllowed(Item);
+ KeyError := KeyAllowed(Key);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ end
+ else if KeyError <> ceOK then
+ begin
+ CollectionError(KeyError);
+ end
+ else
+ begin
+ // Find appropriate place, then place key-item association there
+ Position := GetKeyPosition(Key);
+ try
+ NewAssociation := TAssociation.Create(Key, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.RemoveKey(const Key: ICollectable): ICollectable;
+var
+ KeyError: TCollectionError;
+ Position: TCollectionPosition;
+ OldAssociation: IAssociation;
+begin
+ KeyError := KeyAllowed(Key);
+ if KeyError <> ceOK then
+ begin
+ CollectionError(KeyError);
+ Result := nil;
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ begin
+ OldAssociation := TrueRemove2(Position);
+ Result := OldAssociation.GetValue
+ end
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractMap.RemoveKey(const KeyArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ OldAssociation: IAssociation;
+ KeyError: TCollectionError;
+ Position: TCollectionPosition;
+ Key: ICollectable;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Key := KeyArray[I];
+ KeyError := KeyAllowed(Key);
+ if KeyError <> ceOK then
+ begin
+ CollectionError(KeyError);
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ begin
+ OldAssociation := TrueRemove2(Position);
+ ResultCollection.Add(OldAssociation.GetValue);
+ end;
+ finally
+ Position.Free;
+ end;
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.RemoveKey(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ OldAssociation: IAssociation;
+ KeyError: TCollectionError;
+ Position: TCollectionPosition;
+ Key: ICollectable;
+ Iterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Key := Iterator.CurrentItem;
+ KeyError := KeyAllowed(Key);
+ if KeyError <> ceOK then
+ begin
+ CollectionError(KeyError);
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ begin
+ OldAssociation := TrueRemove2(Position);
+ ResultCollection.Add(OldAssociation.GetValue);
+ end;
+ finally
+ Position.Free;
+ end;
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractMap.RetainKey(const KeyArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ MapIterator: IMapIterator;
+ I: Integer;
+ Found: Boolean;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ end
+ else
+ begin
+ MapIterator := GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ // Converting the array to a map would be faster but I don't want to
+ // couple base class code to a complex collection.
+ Found := false;
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Found := KeyComparator.Equals(MapIterator.CurrentKey, KeyArray[I]);
+ if Found then
+ break;
+ end;
+ if not Found then
+ begin
+ ResultCollection.Add(MapIterator.CurrentItem);
+ MapIterator.Remove;
+ end;
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+ end;
+end;
+
+function TAbstractMap.RetainKey(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ MapIterator: IMapIterator;
+ Key: ICollectable;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ end
+ else
+ begin
+ MapIterator := GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ Key := MapIterator.CurrentKey;
+ if not Collection.Contains(Key) then
+ begin
+ ResultCollection.Add(MapIterator.CurrentItem);
+ MapIterator.Remove;
+ end;
+ MapIterator.Next;
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+
+{ TAbstractIntegerMap }
+constructor TAbstractIntegerMap.Create(NaturalItemsOnly: Boolean);
+begin
+ inherited Create(NaturalItemsOnly);
+ FAssociationComparator := TIntegerAssociationComparator.Create;
+end;
+
+constructor TAbstractIntegerMap.Create(const ItemArray: array of ICollectable);
+begin
+ Create(ItemArray, true);
+end;
+
+constructor TAbstractIntegerMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+ inherited Create(ItemArray, true);
+end;
+
+constructor TAbstractIntegerMap.Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable);
+begin
+ Create(KeyArray, ItemArray, false);
+end;
+
+constructor TAbstractIntegerMap.Create(const KeyArray: array of Integer; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+ I, Lo, Hi: Integer;
+begin
+ Create(NaturalItemsOnly);
+ Capacity := Min(Length(KeyArray), Length(ItemArray));
+ if not FixedSize then
+ begin
+ Lo := Max(Low(KeyArray), Low(ItemArray));
+ Hi := Min(High(KeyArray), High(ItemArray));
+ for I := Lo to Hi do
+ begin
+ Put(KeyArray[I], ItemArray[I]);
+ end;
+ end;
+end;
+
+constructor TAbstractIntegerMap.Create(const Map: IIntegerMap);
+var
+ MapIterator: IIntegerMapIterator;
+begin
+ Create(Map.GetNaturalItemsOnly);
+ InitFrom(Map);
+ Capacity := Map.GetSize;
+ if not FixedSize then
+ begin
+ MapIterator := Map.GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ Put(MapIterator.CurrentKey, MapIterator.CurrentItem);
+ MapIterator.Next;
+ end;
+ end;
+end;
+
+destructor TAbstractIntegerMap.Destroy;
+begin
+ FAssociationComparator := nil;
+ inherited Destroy;
+end;
+
+function TAbstractIntegerMap.TrueAdd(const Item: ICollectable): Boolean;
+var
+ Position: TCollectionPosition;
+ Mappable: IIntegerMappable;
+begin
+ if IsNaturalItem(Item) then
+ begin
+ Mappable := Item as IIntegerMappable;
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ if Position.Found then
+ begin
+ CollectionError(ceDuplicateKey);
+ Result := false;
+ end
+ else
+ begin
+ TruePut(Position, TIntegerAssociation.Create(Mappable.GetKey, Item));
+ Result := true;
+ end;
+ finally
+ Position.Free;
+ end;
+ end
+ else
+ begin
+ CollectionError(ceNotNaturalItem);
+ Result := false;
+ end;
+end;
+
+function TAbstractIntegerMap.TrueContains(const Item: ICollectable): Boolean;
+var
+ Item2: ICollectable;
+ Success: Boolean;
+ Iterator: IIterator;
+begin
+ Iterator := GetIterator;
+ Success := false;
+ while not Iterator.EOF and not Success do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ Success := true;
+ Iterator.Next;
+ end;
+ Result := Success;
+end;
+
+function TAbstractIntegerMap.TrueRemove(const Item: ICollectable): ICollectable;
+var
+ Item2: ICollectable;
+ Iterator: IIntegerMapIterator;
+ Found: Boolean;
+begin
+ // Sequential search
+ Found := false;
+ Result := nil;
+ Iterator := GetAssociationIterator;
+ while not Iterator.EOF and not Found do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ begin
+ Result := Item2;
+ Iterator.Remove;
+ Found := true;
+ end;
+ Iterator.Next;
+ end;
+end;
+
+function TAbstractIntegerMap.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ Item2: ICollectable;
+ Iterator: IIntegerMapIterator;
+begin
+ // Sequential search
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := GetAssociationIterator;
+ while not Iterator.EOF do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ begin
+ ResultCollection.Add(Item2);
+ Iterator.Remove;
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.GetItem(const Key: Integer): ICollectable;
+begin
+ Result := Get(Key);
+end;
+
+procedure TAbstractIntegerMap.SetItem(const Key: Integer; const Item: ICollectable);
+begin
+ Put(Key, Item);
+end;
+
+function TAbstractIntegerMap.GetIterator: IIterator;
+begin
+ Result := GetAssociationIterator;
+end;
+
+function TAbstractIntegerMap.GetKeys: ISet;
+var
+ ResultCollection: TPArraySet;
+ MapIterator: IIntegerMapIterator;
+begin
+ ResultCollection := TPArraySet.Create(true);
+ MapIterator := GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ ResultCollection.Add(TIntegerWrapper.Create(MapIterator.CurrentKey) as ICollectable);
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.GetMapIterator: IIntegerMapIterator;
+begin
+ Result := GetAssociationIterator;
+end;
+
+function TAbstractIntegerMap.GetNaturalItemIID: TGUID;
+begin
+ Result := IntegerMappableIID;
+end;
+
+function TAbstractIntegerMap.GetType: TCollectionType;
+begin
+ Result := ctIntegerMap;
+end;
+
+function TAbstractIntegerMap.GetValues: ICollection;
+var
+ ResultCollection: ICollection;
+ ValueIterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ ValueIterator := GetIterator;
+ while not ValueIterator.EOF do
+ begin
+ ResultCollection.Add(ValueIterator.CurrentItem);
+ ValueIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+// Overrides TAbstractCollection function, otherwise Create(ICollection) is
+// called, which cannot access keys.
+function TAbstractIntegerMap.Clone: ICollection;
+begin
+ Result := (TAbstractIntegerMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractIntegerMap.CloneAsIntegerMap: IIntegerMap;
+begin
+ Result := (TAbstractIntegerMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractIntegerMap.ContainsKey(const Key: Integer): Boolean;
+var
+ Position: TCollectionPosition;
+begin
+ Position := GetKeyPosition(Key);
+ try
+ Result := Position.Found;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractIntegerMap.ContainsKey(const KeyArray: array of Integer): Boolean;
+var
+ I: Integer;
+ Success: Boolean;
+begin
+ Success := true;
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Success := Success and ContainsKey(KeyArray[I]);
+ if not Success then
+ break;
+ end;
+ Result := Success;
+end;
+
+function TAbstractIntegerMap.Get(const Key: Integer): ICollectable;
+var
+ Position: TCollectionPosition;
+begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ Result := TrueGet(Position).GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractIntegerMap.IsNilAllowed: Boolean;
+begin
+ Result := true;
+end;
+
+function TAbstractIntegerMap.Put(const Item: ICollectable): ICollectable;
+var
+ Mappable: IIntegerMappable;
+ OldAssociation, NewAssociation: IIntegerAssociation;
+ Position: TCollectionPosition;
+begin
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ Result := nil;
+ end
+ else
+ begin
+ Item.QueryInterface(IIntegerMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TIntegerAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ Result := OldAssociation.GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractIntegerMap.Put(const Key: Integer; const Item: ICollectable): ICollectable;
+var
+ OldAssociation, NewAssociation: IIntegerAssociation;
+ ItemError: TCollectionError;
+ Position: TCollectionPosition;
+begin
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Result := nil;
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ NewAssociation := TIntegerAssociation.Create(Key, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ Result := OldAssociation.GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractIntegerMap.Put(const ItemArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ Mappable: IIntegerMappable;
+ OldAssociation, NewAssociation: IIntegerAssociation;
+ Position: TCollectionPosition;
+ Item: ICollectable;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Item := ItemArray[I];
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ end
+ else
+ begin
+ Item.QueryInterface(IIntegerMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TIntegerAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.Put(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Mappable: IIntegerMappable;
+ OldAssociation, NewAssociation: IIntegerAssociation;
+ Position: TCollectionPosition;
+ Iterator: IIterator;
+ Item: ICollectable;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;;
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ end
+ else
+ begin
+ Item.QueryInterface(IIntegerMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TIntegerAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.Put(const Map: IIntegerMap): ICollection;
+var
+ ResultCollection: ICollection;
+ OldAssociation, NewAssociation: IIntegerAssociation;
+ ItemError: TCollectionError;
+ Position: TCollectionPosition;
+ MapIterator: IIntegerMapIterator;
+ Item: ICollectable;
+ Key: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ MapIterator := Map.GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ Key := MapIterator.CurrentKey;
+ Item := MapIterator.CurrentItem;
+
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ NewAssociation := TIntegerAssociation.Create(Key, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.RemoveKey(const Key: Integer): ICollectable;
+var
+ Position: TCollectionPosition;
+ OldAssociation: IIntegerAssociation;
+begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ begin
+ OldAssociation := TrueRemove2(Position);
+ Result := OldAssociation.GetValue
+ end
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractIntegerMap.RemoveKey(const KeyArray: array of Integer): ICollection;
+var
+ ResultCollection: ICollection;
+ OldAssociation: IIntegerAssociation;
+ Position: TCollectionPosition;
+ Key: Integer;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Key := KeyArray[I];
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ begin
+ OldAssociation := TrueRemove2(Position);
+ ResultCollection.Add(OldAssociation.GetValue);
+ end;
+ finally
+ Position.Free;
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractIntegerMap.RetainKey(const KeyArray: array of Integer): ICollection;
+var
+ ResultCollection: ICollection;
+ MapIterator: IIntegerMapIterator;
+ I: Integer;
+ Found: Boolean;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ end
+ else
+ begin
+ MapIterator := GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ // Converting the array to a map would be faster but I don't want to
+ // couple base class code to a complex collection.
+ Found := false;
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Found := (MapIterator.CurrentKey = KeyArray[I]);
+ if Found then
+ break;
+ end;
+ if not Found then
+ begin
+ ResultCollection.Add(MapIterator.CurrentItem);
+ MapIterator.Remove;
+ end;
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+ end;
+end;
+
+
+{ TAbstractStringMap }
+constructor TAbstractStringMap.Create(NaturalItemsOnly: Boolean);
+begin
+ inherited Create(NaturalItemsOnly);
+ FAssociationComparator := TStringAssociationComparator.Create;
+end;
+
+constructor TAbstractStringMap.Create(const ItemArray: array of ICollectable);
+begin
+ Create(ItemArray, true);
+end;
+
+constructor TAbstractStringMap.Create(const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+begin
+ inherited Create(ItemArray, true);
+end;
+
+constructor TAbstractStringMap.Create(const KeyArray: array of String; const ItemArray: array of ICollectable);
+begin
+ Create(KeyArray, ItemArray, false);
+end;
+
+constructor TAbstractStringMap.Create(const KeyArray: array of String; const ItemArray: array of ICollectable; NaturalItemsOnly: Boolean);
+var
+ I, Lo, Hi: Integer;
+begin
+ Create(NaturalItemsOnly);
+ Capacity := Min(Length(KeyArray), Length(ItemArray));
+ if not FixedSize then
+ begin
+ Lo := Max(Low(KeyArray), Low(ItemArray));
+ Hi := Min(High(KeyArray), High(ItemArray));
+ for I := Lo to Hi do
+ begin
+ Put(KeyArray[I], ItemArray[I]);
+ end;
+ end;
+end;
+
+constructor TAbstractStringMap.Create(const Map: IStringMap);
+var
+ MapIterator: IStringMapIterator;
+begin
+ Create(Map.GetNaturalItemsOnly);
+ InitFrom(Map);
+ Capacity := Map.GetSize;
+ if not FixedSize then
+ begin
+ MapIterator := Map.GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ Put(MapIterator.CurrentKey, MapIterator.CurrentItem);
+ MapIterator.Next;
+ end;
+ end;
+end;
+
+destructor TAbstractStringMap.Destroy;
+begin
+ FAssociationComparator := nil;
+ inherited Destroy;
+end;
+
+function TAbstractStringMap.TrueAdd(const Item: ICollectable): Boolean;
+var
+ Position: TCollectionPosition;
+ Mappable: IStringMappable;
+begin
+ if IsNaturalItem(Item) then
+ begin
+ Mappable := Item as IStringMappable;
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ if Position.Found then
+ begin
+ CollectionError(ceDuplicateKey);
+ Result := false;
+ end
+ else
+ begin
+ TruePut(Position, TStringAssociation.Create(Mappable.GetKey, Item));
+ Result := true;
+ end;
+ finally
+ Position.Free;
+ end;
+ end
+ else
+ begin
+ CollectionError(ceNotNaturalItem);
+ Result := false;
+ end;
+end;
+
+function TAbstractStringMap.TrueContains(const Item: ICollectable): Boolean;
+var
+ Item2: ICollectable;
+ Success: Boolean;
+ Iterator: IIterator;
+begin
+ Iterator := GetIterator;
+ Success := false;
+ while not Iterator.EOF and not Success do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ Success := true;
+ Iterator.Next;
+ end;
+ Result := Success;
+end;
+
+function TAbstractStringMap.TrueRemove(const Item: ICollectable): ICollectable;
+var
+ Item2: ICollectable;
+ Iterator: IStringMapIterator;
+ Found: Boolean;
+begin
+ // Sequential search
+ Found := false;
+ Result := nil;
+ Iterator := GetAssociationIterator;
+ while not Iterator.EOF and not Found do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ begin
+ Result := Item2;
+ Iterator.Remove;
+ Found := true;
+ end;
+ Iterator.Next;
+ end;
+end;
+
+function TAbstractStringMap.TrueRemoveAll(const Item: ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ Item2: ICollectable;
+ Iterator: IIterator;
+begin
+ // Sequential search
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := GetAssociationIterator;
+ while not Iterator.EOF do
+ begin
+ Item2 := Iterator.CurrentItem;
+ if Comparator.Equals(Item, Item2) then
+ begin
+ ResultCollection.Add(Item2);
+ Iterator.Remove;
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractStringMap.GetItem(const Key: String): ICollectable;
+begin
+ Result := Get(Key);
+end;
+
+procedure TAbstractStringMap.SetItem(const Key: String; const Item: ICollectable);
+begin
+ Put(Key, Item);
+end;
+
+function TAbstractStringMap.GetIterator: IIterator;
+begin
+ Result := GetAssociationIterator;
+end;
+
+function TAbstractStringMap.GetKeys: ISet;
+var
+ ResultCollection: TPArraySet;
+ MapIterator: IStringMapIterator;
+begin
+ ResultCollection := TPArraySet.Create(true);
+ MapIterator := GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ ResultCollection.Add(TStringWrapper.Create(MapIterator.CurrentKey) as ICollectable);
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractStringMap.GetMapIterator: IStringMapIterator;
+begin
+ Result := GetAssociationIterator;
+end;
+
+function TAbstractStringMap.GetNaturalItemIID: TGUID;
+begin
+ Result := StringMappableIID;
+end;
+
+function TAbstractStringMap.GetType: TCollectionType;
+begin
+ Result := ctStringMap;
+end;
+
+function TAbstractStringMap.GetValues: ICollection;
+var
+ ResultCollection: ICollection;
+ ValueIterator: IIterator;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ ValueIterator := GetIterator;
+ while not ValueIterator.EOF do
+ begin
+ ResultCollection.Add(ValueIterator.CurrentItem);
+ ValueIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+// Overrides TAbstractCollection function, otherwise Create(ICollection) is
+// called, which cannot access keys.
+function TAbstractStringMap.Clone: ICollection;
+begin
+ Result := (TAbstractStringMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractStringMap.CloneAsStringMap: IStringMap;
+begin
+ Result := (TAbstractStringMapClass(ClassType)).Create(Self);
+end;
+
+function TAbstractStringMap.ContainsKey(const Key: String): Boolean;
+var
+ Position: TCollectionPosition;
+begin
+ Position := GetKeyPosition(Key);
+ try
+ Result := Position.Found;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractStringMap.ContainsKey(const KeyArray: array of String): Boolean;
+var
+ I: Integer;
+ Success: Boolean;
+begin
+ Success := true;
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Success := Success and ContainsKey(KeyArray[I]);
+ if not Success then
+ break;
+ end;
+ Result := Success;
+end;
+
+function TAbstractStringMap.Get(const Key: String): ICollectable;
+var
+ Position: TCollectionPosition;
+begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ Result := TrueGet(Position).GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractStringMap.IsNilAllowed: Boolean;
+begin
+ Result := true;
+end;
+
+function TAbstractStringMap.Put(const Item: ICollectable): ICollectable;
+var
+ Mappable: IStringMappable;
+ OldAssociation, NewAssociation: IStringAssociation;
+ Position: TCollectionPosition;
+begin
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ Result := nil;
+ end
+ else
+ begin
+ Item.QueryInterface(IStringMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TStringAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ Result := OldAssociation.GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractStringMap.Put(const Key: String; const Item: ICollectable): ICollectable;
+var
+ OldAssociation, NewAssociation: IStringAssociation;
+ ItemError: TCollectionError;
+ Position: TCollectionPosition;
+begin
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ Result := nil;
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ NewAssociation := TStringAssociation.Create(Key, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ Result := OldAssociation.GetValue
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+ end;
+end;
+
+function TAbstractStringMap.Put(const ItemArray: array of ICollectable): ICollection;
+var
+ ResultCollection: ICollection;
+ Mappable: IStringMappable;
+ OldAssociation, NewAssociation: IStringAssociation;
+ Position: TCollectionPosition;
+ Item: ICollectable;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(ItemArray) to High(ItemArray) do
+ begin
+ Item := ItemArray[I];
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ end
+ else
+ begin
+ Item.QueryInterface(IStringMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TStringAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractStringMap.Put(const Collection: ICollection): ICollection;
+var
+ ResultCollection: ICollection;
+ Mappable: IStringMappable;
+ OldAssociation, NewAssociation: IStringAssociation;
+ Position: TCollectionPosition;
+ Iterator: IIterator;
+ Item: ICollectable;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ Iterator := Collection.GetIterator;
+ while not Iterator.EOF do
+ begin
+ Item := Iterator.CurrentItem;;
+ if not IsNaturalItem(Item) then
+ begin
+ CollectionError(ceNotNaturalItem);
+ end
+ else
+ begin
+ Item.QueryInterface(IStringMappable, Mappable);
+ Position := GetKeyPosition(Mappable.GetKey);
+ try
+ NewAssociation := TStringAssociation.Create(Mappable.GetKey, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ Iterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractStringMap.Put(const Map: IStringMap): ICollection;
+var
+ ResultCollection: ICollection;
+ OldAssociation, NewAssociation: IStringAssociation;
+ ItemError: TCollectionError;
+ Position: TCollectionPosition;
+ MapIterator: IStringMapIterator;
+ Item: ICollectable;
+ Key: String;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ MapIterator := Map.GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ Key := MapIterator.CurrentKey;
+ Item := MapIterator.CurrentItem;
+
+ ItemError := ItemAllowed(Item);
+ if ItemError <> ceOK then
+ begin
+ CollectionError(ItemError);
+ end
+ else
+ begin
+ Position := GetKeyPosition(Key);
+ try
+ NewAssociation := TStringAssociation.Create(Key, Item);
+ OldAssociation := TruePut(Position, NewAssociation);
+ if OldAssociation <> nil then
+ ResultCollection.Add(OldAssociation.GetValue);
+ finally
+ Position.Free;
+ end;
+ end;
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractStringMap.RemoveKey(const Key: String): ICollectable;
+var
+ Position: TCollectionPosition;
+ OldAssociation: IStringAssociation;
+begin
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ begin
+ OldAssociation := TrueRemove2(Position);
+ Result := OldAssociation.GetValue
+ end
+ else
+ Result := nil;
+ finally
+ Position.Free;
+ end;
+end;
+
+function TAbstractStringMap.RemoveKey(const KeyArray: array of String): ICollection;
+var
+ ResultCollection: ICollection;
+ OldAssociation: IStringAssociation;
+ Position: TCollectionPosition;
+ Key: String;
+ I: Integer;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Key := KeyArray[I];
+ Position := GetKeyPosition(Key);
+ try
+ if Position.Found then
+ begin
+ OldAssociation := TrueRemove2(Position);
+ ResultCollection.Add(OldAssociation.GetValue);
+ end;
+ finally
+ Position.Free;
+ end;
+ end;
+ Result := ResultCollection;
+end;
+
+function TAbstractStringMap.RetainKey(const KeyArray: array of String): ICollection;
+var
+ ResultCollection: ICollection;
+ MapIterator: IStringMapIterator;
+ I: Integer;
+ Found: Boolean;
+begin
+ ResultCollection := TPArrayBag.Create(NaturalItemsOnly);
+ if FixedSize then
+ begin
+ CollectionError(ceFixedSize);
+ end
+ else
+ begin
+ MapIterator := GetMapIterator;
+ while not MapIterator.EOF do
+ begin
+ // Converting the array to a map would be faster but I don't want to
+ // couple base class code to a complex collection.
+ Found := false;
+ for I := Low(KeyArray) to High(KeyArray) do
+ begin
+ Found := (MapIterator.CurrentKey = KeyArray[I]);
+ if Found then
+ break;
+ end;
+ if not Found then
+ begin
+ ResultCollection.Add(MapIterator.CurrentItem);
+ MapIterator.Remove;
+ end;
+ MapIterator.Next;
+ end;
+ Result := ResultCollection;
+ end;
+end;
+
+
+{ ECollectionError }
+constructor ECollectionError.Create(const Msg: String; const Collection: ICollection; ErrorType: TCollectionError);
+begin
+ inherited Create(Msg);
+ FCollection := Collection;
+ FErrorType := ErrorType;
+end;
+
+{ TAbstractListIterator }
+constructor TAbstractListIterator.Create(Collection: TAbstractList);
+begin
+ inherited Create(true);
+ FCollection := Collection;
+ First;
+end;
+
+function TAbstractListIterator.TrueFirst: ICollectable;
+begin
+ FIndex := 0;
+ if FIndex < FCollection.GetSize then
+ Result := FCollection.GetItem(FIndex)
+ else
+ Result := nil;
+end;
+
+function TAbstractListIterator.TrueNext: ICollectable;
+begin
+ Inc(FIndex);
+ if FIndex < FCollection.GetSize then
+ Result := FCollection.GetItem(FIndex)
+ else
+ Result := nil;
+end;
+
+procedure TAbstractListIterator.TrueRemove;
+begin
+ FCollection.Delete(FIndex);
+ Dec(FIndex);
+end;
+
+end.
diff --git a/unicode/src/lib/collections/readme.txt b/unicode/src/lib/collections/readme.txt
new file mode 100644
index 00000000..1f6477de
--- /dev/null
+++ b/unicode/src/lib/collections/readme.txt
@@ -0,0 +1,14 @@
+Delphi Collections by Matthew Greet
+http://www.warmachine.u-net.com/delphi_collections/
+
+Help files (MS .hlp format) at
+http://www.warmachine.u-net.com/downloads/delphi_collections_1_0_help.zip
+
+Changes
+=====================
+2008-11-06 FPC compatibility fixes by UltraStar Deluxe Team
+2005-03-14 Maintenance release v1.0.5 - bug fix for sorted lists and functional tests checks unsorted and sorted lists.
+2004-10-14 Maintenance release v1.0.4 - memory leak fixed.
+2004-06-12 Maintenance release v1.0.3 - memory leak fixed, memory leak test, new Capacity property.
+2004-02-13 Maintenance release v1.0.2 - expanded introduction and quick start sections in help file.
+2003-10-25 Maintenance release v1.0.1 - packages and test harness no longer list unused packages. \ No newline at end of file
diff --git a/unicode/src/lib/ffmpeg/avcodec.pas b/unicode/src/lib/ffmpeg/avcodec.pas
index 0954ee06..6039835c 100644
--- a/unicode/src/lib/ffmpeg/avcodec.pas
+++ b/unicode/src/lib/ffmpeg/avcodec.pas
@@ -27,7 +27,7 @@
(*
* Conversion of libavcodec/avcodec.h
* Min. version: 51.16.0, revision 6577, Sat Oct 7 15:30:46 2006 UTC
- * Max. version: 52.0.0, revision 15448, Sun Sep 28 19:11:26 2008 UTC
+ * Max. version: 52.11.0, revision 16912, Sun Feb 1 02:00:19 2009 UTC
*)
unit avcodec;
@@ -51,6 +51,7 @@ uses
avutil,
rational,
opt,
+ SysUtils,
{$IFDEF UNIX}
BaseUnix,
{$ENDIF}
@@ -59,7 +60,7 @@ uses
const
(* Max. supported version by this header *)
LIBAVCODEC_MAX_VERSION_MAJOR = 52;
- LIBAVCODEC_MAX_VERSION_MINOR = 0;
+ LIBAVCODEC_MAX_VERSION_MINOR = 11;
LIBAVCODEC_MAX_VERSION_RELEASE = 0;
LIBAVCODEC_MAX_VERSION = (LIBAVCODEC_MAX_VERSION_MAJOR * VERSION_MAJOR) +
(LIBAVCODEC_MAX_VERSION_MINOR * VERSION_MINOR) +
@@ -231,6 +232,7 @@ type
CODEC_ID_CMV,
CODEC_ID_MOTIONPIXELS,
CODEC_ID_TGV,
+ CODEC_ID_TGQ,
//* various PCM "codecs" */
CODEC_ID_PCM_S16LE= $10000,
@@ -286,6 +288,7 @@ type
CODEC_ID_ADPCM_IMA_EA_EACS,
CODEC_ID_ADPCM_EA_XAS,
CODEC_ID_ADPCM_EA_MAXIS_XA,
+ CODEC_ID_ADPCM_IMA_ISS,
//* AMR */
CODEC_ID_AMR_NB= $12000,
@@ -350,6 +353,7 @@ type
CODEC_ID_ATRAC3P,
CODEC_ID_EAC3,
CODEC_ID_SIPR,
+ CODEC_ID_MP1,
//* subtitle codecs */
CODEC_ID_DVD_SUBTITLE= $17000,
@@ -403,6 +407,43 @@ type
_TSampleFormatArray = array [0 .. MaxInt div SizeOf(TSampleFormat)-1] of TSampleFormat;
PSampleFormatArray = ^_TSampleFormatArray;
+const
+ {* Audio channel masks *}
+ CH_FRONT_LEFT = $00000001;
+ CH_FRONT_RIGHT = $00000002;
+ CH_FRONT_CENTER = $00000004;
+ CH_LOW_FREQUENCY = $00000008;
+ CH_BACK_LEFT = $00000010;
+ CH_BACK_RIGHT = $00000020;
+ CH_FRONT_LEFT_OF_CENTER = $00000040;
+ CH_FRONT_RIGHT_OF_CENTER = $00000080;
+ CH_BACK_CENTER = $00000100;
+ CH_SIDE_LEFT = $00000200;
+ CH_SIDE_RIGHT = $00000400;
+ CH_TOP_CENTER = $00000800;
+ CH_TOP_FRONT_LEFT = $00001000;
+ CH_TOP_FRONT_CENTER = $00002000;
+ CH_TOP_FRONT_RIGHT = $00004000;
+ CH_TOP_BACK_LEFT = $00008000;
+ CH_TOP_BACK_CENTER = $00010000;
+ CH_TOP_BACK_RIGHT = $00020000;
+ CH_STEREO_LEFT = $20000000; ///< Stereo downmix.
+ CH_STEREO_RIGHT = $40000000; ///< See CH_STEREO_LEFT.
+
+ {* Audio channel convenience macros *}
+ CH_LAYOUT_MONO = (CH_FRONT_CENTER);
+ CH_LAYOUT_STEREO = (CH_FRONT_LEFT or CH_FRONT_RIGHT);
+ CH_LAYOUT_SURROUND = (CH_LAYOUT_STEREO or CH_FRONT_CENTER);
+ CH_LAYOUT_QUAD = (CH_LAYOUT_STEREO or CH_BACK_LEFT or CH_BACK_RIGHT);
+ CH_LAYOUT_5POINT0 = (CH_LAYOUT_SURROUND or CH_SIDE_LEFT or CH_SIDE_RIGHT);
+ CH_LAYOUT_5POINT1 = (CH_LAYOUT_5POINT0 or CH_LOW_FREQUENCY);
+ CH_LAYOUT_7POINT1 = (CH_LAYOUT_5POINT1 or CH_BACK_LEFT or CH_BACK_RIGHT);
+ CH_LAYOUT_7POINT1_WIDE = (CH_LAYOUT_SURROUND or CH_LOW_FREQUENCY or
+ CH_BACK_LEFT or CH_BACK_RIGHT or
+ CH_FRONT_LEFT_OF_CENTER or CH_FRONT_RIGHT_OF_CENTER);
+ CH_LAYOUT_STEREO_DOWNMIX = (CH_STEREO_LEFT or CH_STEREO_RIGHT);
+
+
const
{* in bytes *}
AVCODEC_MAX_AUDIO_FRAME_SIZE = 192000; // 1 second of 48khz 32bit audio
@@ -559,6 +600,11 @@ const
*)
CODEC_CAP_SMALL_LAST_FRAME = $0040;
+ (**
+ * Codec can export data for HW decoding (VDPAU).
+ *)
+ CODEC_CAP_HWACCEL_VDPAU = $0080;
+
//the following defines may change, don't expect compatibility if you use them
MB_TYPE_INTRA4x4 = $001;
MB_TYPE_INTRA16x16 = $002; //FIXME h264 specific
@@ -850,6 +896,38 @@ type
*)
bits_per_raw_sample: cint;
{$IFEND}
+
+ {$IF LIBAVCODEC_VERSION >= 52002000} // 52.2.0
+ (**
+ * Audio channel layout.
+ * - encoding: set by user.
+ * - decoding: set by libavcodec.
+ *)
+ channel_layout: cint64;
+
+ (**
+ * Request decoder to use this channel layout if it can (0 for default)
+ * - encoding: unused
+ * - decoding: Set by user.
+ *)
+ request_channel_layout: cint64;
+ {$IFEND}
+
+ {$IF LIBAVCODEC_VERSION >= 52004000} // 52.4.0
+ (**
+ * Ratecontrol attempt to use, at maximum, <value> of what can be used without an underflow.
+ * - encoding: Set by user.
+ * - decoding: unused.
+ *)
+ rc_max_available_vbv_use: cfloat;
+
+ (**
+ * Ratecontrol attempt to use, at least, <value> times the amount needed to prevent a vbv overflow.
+ * - encoding: Set by user.
+ * - decoding: unused.
+ *)
+ rc_min_vbv_overflow_use: cfloat;
+ {$IFEND}
end;
const
@@ -918,21 +996,25 @@ const
FF_IDCT_SIMPLEVIS = 18;
FF_IDCT_WMV2 = 19;
FF_IDCT_FAAN = 20;
+ FF_IDCT_EA = 21;
+ FF_IDCT_SIMPLENEON = 22;
+ FF_IDCT_SIMPLEALPHA = 23;
FF_EC_GUESS_MVS = 1;
FF_EC_DEBLOCK = 2;
- FF_MM_FORCE = $80000000; (* force usage of selected flags (OR) *)
+ FF_MM_FORCE = $80000000; (* force usage of selected flags (OR) *)
(* lower 16 bits - CPU features *)
- FF_MM_MMX = $0001; ///< standard MMX
- FF_MM_3DNOW = $0004; ///< AMD 3DNOW
- FF_MM_MMXEXT = $0002; ///< SSE integer functions or AMD MMX ext
- FF_MM_SSE = $0008; ///< SSE functions
- FF_MM_SSE2 = $0010; ///< PIV SSE2 functions
- FF_MM_3DNOWEXT = $0020; ///< AMD 3DNowExt
+ FF_MM_MMX = $0001; ///< standard MMX
+ FF_MM_3DNOW = $0004; ///< AMD 3DNOW
+ FF_MM_MMXEXT = $0002; ///< SSE integer functions or AMD MMX ext
+ FF_MM_SSE = $0008; ///< SSE functions
+ FF_MM_SSE2 = $0010; ///< PIV SSE2 functions
+ FF_MM_3DNOWEXT = $0020; ///< AMD 3DNowExt
FF_MM_SSE3 = $0040; ///< Prescott SSE3 functions
FF_MM_SSSE3 = $0080; ///< Conroe SSSE3 functions
- FF_MM_IWMMXT = $0100; ///< XScale IWMMXT
+ FF_MM_IWMMXT = $0100; ///< XScale IWMMXT
+ FF_MM_ALTIVEC = $0001; ///< standard AltiVec
FF_PRED_LEFT = 0;
FF_PRED_PLANE = 1;
@@ -1066,13 +1148,13 @@ type
// int (*func)(struct AVCodecContext *c2, void *arg)
TExecuteFunc = function(c2: PAVCodecContext; arg: Pointer): cint; cdecl;
- TAVClass = record {12}
- class_name: pchar;
+ TAVClass = record
+ class_name: PAnsiChar;
(* actually passing a pointer to an AVCodecContext
- or AVFormatContext, which begin with an AVClass.
- Needed because av_log is in libavcodec and has no visibility
- of AVIn/OutputFormat *)
- item_name: function (): pchar; cdecl;
+ or AVFormatContext, which begin with an AVClass.
+ Needed because av_log is in libavcodec and has no visibility
+ of AVIn/OutputFormat *)
+ item_name: function(): PAnsiChar; cdecl;
option: PAVOption;
end;
@@ -1334,7 +1416,7 @@ type
*)
opaque: pointer;
- codec_name: array [0..31] of char;
+ codec_name: array [0..31] of AnsiChar;
codec_type: TCodecType; (* see CODEC_TYPE_xxx *)
codec_id: TCodecID; (* see CODEC_ID_xxx *)
@@ -1451,7 +1533,7 @@ type
* - encoding: Set by libavcodec.
* - decoding: unused
*)
- stats_out: pchar;
+ stats_out: PByteArray;
(**
* pass2 encoding statistics input buffer
@@ -1459,7 +1541,7 @@ type
* - encoding: Allocated/set/freed by user.
* - decoding: unused
*)
- stats_in: pchar;
+ stats_in: PByteArray;
(**
* ratecontrol qmin qmax limiting method
@@ -1485,7 +1567,7 @@ type
* - encoding: Set by user
* - decoding: unused
*)
- rc_eq: {const} pchar;
+ rc_eq: {const} PByteArray;
(**
* maximum bitrate
@@ -1886,7 +1968,7 @@ type
* - encoding: unused
* - decoding: Set by user, will be converted to uppercase by libavcodec during init.
*)
- stream_codec_tag: array [0..3] of char; //cuint;
+ stream_codec_tag: array [0..3] of AnsiChar; //cuint;
(**
* scene change detection threshold
@@ -1994,7 +2076,11 @@ type
* - encoding: Set by libavcodec, user can override.
* - decoding: Set by libavcodec, user can override.
*)
+ {$IF LIBAVCODEC_VERSION < 52004000} // < 52.4.0
execute: function (c: PAVCodecContext; func: TExecuteFunc; arg: PPointer; ret: PCint; count: cint): cint; cdecl;
+ {$ELSE}
+ execute: function (c: PAVCodecContext; func: TExecuteFunc; arg: Pointer; ret: PCint; count: cint; size: cint): cint; cdecl;
+ {$IFEND}
(**
* thread opaque
@@ -2197,7 +2283,7 @@ type
(**
* number of reference frames
* - encoding: Set by user.
- * - decoding: unused
+ * - decoding: Set by lavc.
*)
refs: cint;
@@ -2349,13 +2435,16 @@ type
{$IFEND}
{$IF LIBAVCODEC_VERSION >= 51042000} // 51.42.0
+ {$IF LIBAVCODEC_MAX_VERSION_MAJOR < 53}
(**
* Decoder should decode to this many channels if it can (0 for default)
* - encoding: unused
* - decoding: Set by user.
+ * @deprecated Deprecated in favor of request_channel_layout.
*)
request_channels: cint;
{$IFEND}
+ {$IFEND}
{$IF LIBAVCODEC_VERSION > 51049000} // > 51.49.0
(**
@@ -2382,15 +2471,15 @@ type
* AVCodec.
*)
TAVCodec = record
- name: pchar;
+ name: PAnsiChar;
type_: TCodecType;
id: TCodecID;
priv_data_size: cint;
init: function (avctx: PAVCodecContext): cint; cdecl; (* typo corretion by the Creative CAT *)
- encode: function (avctx: PAVCodecContext; buf: pchar; buf_size: cint; data: pointer): cint; cdecl;
+ encode: function (avctx: PAVCodecContext; buf: PByteArray; buf_size: cint; data: pointer): cint; cdecl;
close: function (avctx: PAVCodecContext): cint; cdecl;
decode: function (avctx: PAVCodecContext; outdata: pointer; var outdata_size: cint;
- buf: {const} pchar; buf_size: cint): cint; cdecl;
+ buf: {const} PByteArray; buf_size: cint): cint; cdecl;
(**
* Codec capabilities.
* see CODEC_CAP_*
@@ -2409,7 +2498,7 @@ type
* Descriptive name for the codec, meant to be more human readable than \p name.
* You \e should use the NULL_IF_CONFIG_SMALL() macro to define it.
*)
- long_name: {const} PChar;
+ long_name: {const} PAnsiChar;
{$IFEND}
{$IF LIBAVCODEC_VERSION >= 51056000} // 51.56.0
supported_samplerates: {const} PCint; ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
@@ -2417,6 +2506,9 @@ type
{$IF LIBAVCODEC_VERSION >= 51062000} // 51.62.0
sample_fmts: {const} PSampleFormatArray; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
{$IFEND}
+ {$IF LIBAVCODEC_VERSION >= 52002000} // 52.2.0
+ channel_layouts: {const} PCint64; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
+ {$IFEND}
end;
(**
@@ -2425,30 +2517,81 @@ type
*)
PAVPicture = ^TAVPicture;
TAVPicture = record
- data: array [0..3] of pchar;
+ data: array [0..3] of PByteArray;
linesize: array [0..3] of cint; ///< number of bytes per line
end;
type
+ TAVSubtitleType = (
+ SUBTITLE_NONE,
+
+ SUBTITLE_BITMAP, ///< A bitmap, pict will be set
+
+ (**
+ * Plain text, the text field must be set by the decoder and is
+ * authoritative. ass and pict fields may contain approximations.
+ *)
+ SUBTITLE_TEXT,
+
+ (**
+ * Formatted text, the ass field must be set by the decoder and is
+ * authoritative. pict and text fields may contain approximations.
+ *)
+ SUBTITLE_ASS
+ );
+
+type
+ PPAVSubtitleRect = ^PAVSubtitleRect;
PAVSubtitleRect = ^TAVSubtitleRect;
+ {$IF LIBAVCODEC_VERSION < 52010000} // < 52.10.0
TAVSubtitleRect = record
- x: word;
- y: word;
- w: word;
- h: word;
- nb_colors: word;
+ x: cuint16;
+ y: cuint16;
+ w: cuint16;
+ h: cuint16;
+ nb_colors: cuint16;
linesize: cint;
- rgba_palette: PCuint;
- bitmap: pchar;
+ rgba_palette: PCuint32;
+ bitmap: PCuint8;
+ end;
+ {$ELSE}
+ TAVSubtitleRect = record
+ x: cint; ///< top left corner of pict, undefined when pict is not set
+ y: cint; ///< top left corner of pict, undefined when pict is not set
+ w: cint; ///< width of pict, undefined when pict is not set
+ h: cint; ///< height of pict, undefined when pict is not set
+ nb_colors: cint; ///< number of colors in pict, undefined when pict is not set
+
+ (**
+ * data+linesize for the bitmap of this subtitle.
+ * can be set for text/ass as well once they where rendered
+ *)
+ pict: TAVPicture;
+ type_: TAVSubtitleType;
+
+ text: PAnsiChar; ///< 0 terminated plain UTF-8 text
+
+ (**
+ * 0 terminated ASS/SSA compatible event line.
+ * The pressentation of this is unaffected by the other values in this
+ * struct.
+ *)
+ ass: PByteArray;
end;
+ {$IFEND}
+ PPAVSubtitle = ^PAVSubtitle;
PAVSubtitle = ^TAVSubtitle;
- TAVSubtitle = record {20}
- format: word; (* 0 = graphics *)
- start_display_time: cuint; (* relative to packet pts, in ms *)
- end_display_time: cuint; (* relative to packet pts, in ms *)
+ TAVSubtitle = record
+ format: cuint16; (* 0 = graphics *)
+ start_display_time: cuint32; (* relative to packet pts, in ms *)
+ end_display_time: cuint32; (* relative to packet pts, in ms *)
num_rects: cuint;
+ {$IF LIBAVCODEC_VERSION < 52010000} // < 52.10.0
rects: PAVSubtitleRect;
+ {$ELSE}
+ rects: PPAVSubtitleRect;
+ {$IFEND}
end;
@@ -2563,7 +2706,7 @@ function avpicture_fill (picture: PAVPicture; ptr: pointer;
function avpicture_layout (src: {const} PAVPicture; pix_fmt: TAVPixelFormat;
width: cint; height: cint;
- dest: pchar; dest_size: cint): cint;
+ dest: PByteArray; dest_size: cint): cint;
cdecl; external av__codec;
(**
@@ -2581,13 +2724,13 @@ function avpicture_get_size (pix_fmt: TAVPixelFormat; width: cint; height: cint)
procedure avcodec_get_chroma_sub_sample (pix_fmt: TAVPixelFormat; var h_shift: cint; var v_shift: cint);
cdecl; external av__codec;
-function avcodec_get_pix_fmt_name(pix_fmt: TAVPixelFormat): pchar;
+function avcodec_get_pix_fmt_name(pix_fmt: TAVPixelFormat): PAnsiChar;
cdecl; external av__codec;
procedure avcodec_set_dimensions(s: PAVCodecContext; width: cint; height: cint);
cdecl; external av__codec;
-function avcodec_get_pix_fmt(name: {const} pchar): TAVPixelFormat;
+function avcodec_get_pix_fmt(name: {const} PAnsiChar): TAVPixelFormat;
cdecl; external av__codec;
function avcodec_pix_fmt_to_codec_tag(p: TAVPixelFormat): cuint;
@@ -2665,7 +2808,7 @@ function avcodec_find_best_pix_fmt(pix_fmt_mask: cint; src_pix_fmt: TAVPixelForm
* a negative value to print the corresponding header.
* Meaningful values for obtaining a pixel format info vary from 0 to PIX_FMT_NB -1.
*)
-procedure avcodec_pix_fmt_string (buf: PChar; buf_size: cint; pix_fmt: cint);
+procedure avcodec_pix_fmt_string (buf: PAnsiChar; buf_size: cint; pix_fmt: cint);
cdecl; external av__codec;
{$IFEND}
@@ -2734,7 +2877,12 @@ function avcodec_build(): cuint;
procedure avcodec_init();
cdecl; external av__codec;
-procedure register_avcodec(format: PAVCodec);
+(**
+ * Register the codec \p codec and initialize libavcodec.
+ *
+ * @see avcodec_init()
+ *)
+procedure register_avcodec(codec: PAVCodec);
cdecl; external av__codec;
(**
@@ -2752,7 +2900,7 @@ function avcodec_find_encoder(id: TCodecID): PAVCodec;
* @param name name of the requested encoder
* @return An encoder if one was found, NULL otherwise.
*)
-function avcodec_find_encoder_by_name(name: pchar): PAVCodec;
+function avcodec_find_encoder_by_name(name: PAnsiChar): PAVCodec;
cdecl; external av__codec;
(**
@@ -2770,9 +2918,9 @@ function avcodec_find_decoder(id: TCodecID): PAVCodec;
* @param name name of the requested decoder
* @return A decoder if one was found, NULL otherwise.
*)
-function avcodec_find_decoder_by_name(name: pchar): PAVCodec;
+function avcodec_find_decoder_by_name(name: PAnsiChar): PAVCodec;
cdecl; external av__codec;
-procedure avcodec_string(buf: pchar; buf_size: cint; enc: PAVCodecContext; encode: cint);
+procedure avcodec_string(buf: PAnsiChar; buf_size: cint; enc: PAVCodecContext; encode: cint);
cdecl; external av__codec;
(**
@@ -2851,10 +2999,23 @@ function avcodec_thread_init(s: PAVCodecContext; thread_count: cint): cint;
cdecl; external av__codec;
procedure avcodec_thread_free(s: PAVCodecContext);
cdecl; external av__codec;
+
+
+{$IF LIBAVCODEC_VERSION < 52004000} // < 52.4.0
function avcodec_thread_execute(s: PAVCodecContext; func: TExecuteFunc; arg: PPointer; var ret: cint; count: cint): cint;
cdecl; external av__codec;
+{$ELSE}
+function avcodec_thread_execute(s: PAVCodecContext; func: TExecuteFunc; arg: Pointer; var ret: cint; count: cint; size: cint): cint;
+ cdecl; external av__codec;
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION < 52004000} // < 52.4.0
function avcodec_default_execute(s: PAVCodecContext; func: TExecuteFunc; arg: PPointer; var ret: cint; count: cint): cint;
cdecl; external av__codec;
+{$ELSE}
+function avcodec_default_execute(s: PAVCodecContext; func: TExecuteFunc; arg: Pointer; var ret: cint; count: cint; size: cint): cint;
+ cdecl; external av__codec;
+{$IFEND}
//FIXME func typedef
(**
@@ -2893,7 +3054,7 @@ function avcodec_open(avctx: PAVCodecContext; codec: PAVCodec): cint;
*)
function avcodec_decode_audio(avctx: PAVCodecContext; samples: PSmallint;
var frame_size_ptr: cint;
- buf: {const} pchar; buf_size: cint): cint;
+ buf: {const} PByteArray; buf_size: cint): cint;
cdecl; external av__codec;
{$IFEND}
@@ -2926,6 +3087,9 @@ function avcodec_decode_audio(avctx: PAVCodecContext; samples: PSmallint;
* the linesize is not a multiple of 16 then there's no sense in aligning the
* start of the buffer to 16.
*
+ * @note Some codecs have a delay between input and output, these need to be
+ * feeded with buf=NULL, buf_size=0 at the end to return the remaining frames.
+ *
* @param avctx the codec context
* @param[out] samples the output buffer
* @param[in,out] frame_size_ptr the output buffer size in bytes
@@ -2936,7 +3100,7 @@ function avcodec_decode_audio(avctx: PAVCodecContext; samples: PSmallint;
*)
function avcodec_decode_audio2(avctx: PAVCodecContext; samples: PSmallint;
var frame_size_ptr: cint;
- buf: {const} pchar; buf_size: cint): cint;
+ buf: {const} PByteArray; buf_size: cint): cint;
cdecl; external av__codec;
{$IFEND}
@@ -2973,7 +3137,7 @@ function avcodec_decode_audio2(avctx: PAVCodecContext; samples: PSmallint;
*)
function avcodec_decode_video(avctx: PAVCodecContext; picture: PAVFrame;
var got_picture_ptr: cint;
- buf: {const} PChar; buf_size: cint): cint;
+ buf: {const} PByteArray; buf_size: cint): cint;
cdecl; external av__codec;
(* Decode a subtitle message. Return -1 if error, otherwise return the
@@ -2981,11 +3145,11 @@ function avcodec_decode_video(avctx: PAVCodecContext; picture: PAVFrame;
* got_sub_ptr is zero. Otherwise, the subtitle is stored in *sub. *)
function avcodec_decode_subtitle(avctx: PAVCodecContext; sub: PAVSubtitle;
var got_sub_ptr: cint;
- buf: {const} pchar; buf_size: cint): cint;
+ buf: {const} PByteArray; buf_size: cint): cint;
cdecl; external av__codec;
function avcodec_parse_frame(avctx: PAVCodecContext; pdata: PPointer;
data_size_ptr: PCint;
- buf: pchar; buf_size: cint): cint;
+ buf: PByteArray; buf_size: cint): cint;
cdecl; external av__codec;
(**
@@ -3025,18 +3189,28 @@ function avcodec_encode_audio(avctx: PAVCodecContext; buf: PByte;
* @param[in] buf_size the size of the output buffer in bytes
* @param[in] pict the input picture to encode
* @return On error a negative value is returned, on success zero or the number
- * of bytes used from the input buffer.
+ * of bytes used from the output buffer.
*)
function avcodec_encode_video(avctx: PAVCodecContext; buf: PByte;
buf_size: cint; pict: PAVFrame): cint;
cdecl; external av__codec;
-function avcodec_encode_subtitle(avctx: PAVCodecContext; buf: pchar;
+function avcodec_encode_subtitle(avctx: PAVCodecContext; buf: PByteArray;
buf_size: cint; sub: {const} PAVSubtitle): cint;
cdecl; external av__codec;
function avcodec_close(avctx: PAVCodecContext): cint;
cdecl; external av__codec;
+(**
+ * Register all the codecs, parsers and bitstream filters which were enabled at
+ * configuration time. If you do not call this function you can select exactly
+ * which formats you want to support, by using the individual registration
+ * functions.
+ *
+ * @see register_avcodec
+ * @see av_register_codec_parser
+ * @see av_register_bitstream_filter
+ *)
procedure avcodec_register_all();
cdecl; external av__codec;
@@ -3057,7 +3231,7 @@ procedure avcodec_default_free_buffers(s: PAVCodecContext);
* @param[in] pict_type the picture type
* @return A single character representing the picture type.
*)
-function av_get_pict_type_char(pict_type: cint): char;
+function av_get_pict_type_char(pict_type: cint): AnsiChar;
cdecl; external av__codec;
(**
@@ -3127,9 +3301,9 @@ type
parser_init: function(s: PAVCodecParserContext): cint; cdecl;
parser_parse: function(s: PAVCodecParserContext; avctx: PAVCodecContext;
poutbuf: {const} PPointer; poutbuf_size: PCint;
- buf: {const} pchar; buf_size: cint): cint; cdecl;
+ buf: {const} PByteArray; buf_size: cint): cint; cdecl;
parser_close: procedure(s: PAVCodecParserContext); cdecl;
- split: function(avctx: PAVCodecContext; buf: {const} pchar;
+ split: function(avctx: PAVCodecContext; buf: {const} PByteArray;
buf_size: cint): cint; cdecl;
next: PAVCodecParser;
end;
@@ -3156,13 +3330,13 @@ function av_parser_init(codec_id: cint): PAVCodecParserContext;
function av_parser_parse(s: PAVCodecParserContext;
avctx: PAVCodecContext;
poutbuf: PPointer; poutbuf_size: PCint;
- buf: {const} pchar; buf_size: cint;
+ buf: {const} PByteArray; buf_size: cint;
pts: cint64; dts: cint64): cint;
cdecl; external av__codec;
function av_parser_change(s: PAVCodecParserContext;
avctx: PAVCodecContext;
poutbuf: PPointer; poutbuf_size: PCint;
- buf: {const} pchar; buf_size: cint; keyframe: cint): cint;
+ buf: {const} PByteArray; buf_size: cint; keyframe: cint): cint;
cdecl; external av__codec;
procedure av_parser_close(s: PAVCodecParserContext);
cdecl; external av__codec;
@@ -3179,10 +3353,10 @@ type
end;
TAVBitStreamFilter = record
- name: pchar;
+ name: PAnsiChar;
priv_data_size: cint;
filter: function(bsfc: PAVBitStreamFilterContext;
- avctx: PAVCodecContext; args: pchar;
+ avctx: PAVCodecContext; args: PByteArray;
poutbuf: PPointer; poutbuf_size: PCint;
buf: PByte; buf_size: cint; keyframe: cint): cint; cdecl;
{$IF LIBAVCODEC_VERSION >= 51043000} // 51.43.0
@@ -3194,11 +3368,11 @@ type
procedure av_register_bitstream_filter(bsf: PAVBitStreamFilter);
cdecl; external av__codec;
-function av_bitstream_filter_init(name: pchar): PAVBitStreamFilterContext;
+function av_bitstream_filter_init(name: PAnsiChar): PAVBitStreamFilterContext;
cdecl; external av__codec;
function av_bitstream_filter_filter(bsfc: PAVBitStreamFilterContext;
- avctx: PAVCodecContext; args: pchar;
+ avctx: PAVCodecContext; args: PByteArray;
poutbuf: PPointer; poutbuf_size: PCint;
buf: PByte; buf_size: cint; keyframe: cint): cint;
cdecl; external av__codec;
@@ -3317,7 +3491,7 @@ function av_xiphlacing(s: PByte; v: cuint): cuint;
* @param[in,out] height_ptr pointer to the variable which will contain the detected
* frame height value
*)
-function av_parse_video_frame_size(width_ptr: PCint; height_ptr: PCint; str: {const} PChar): cint;
+function av_parse_video_frame_size(width_ptr: PCint; height_ptr: PCint; str: {const} PAnsiChar): cint;
cdecl; external av__codec;
(**
@@ -3329,22 +3503,7 @@ function av_parse_video_frame_size(width_ptr: PCint; height_ptr: PCint; str: {co
* @param[in,out] frame_rate pointer to the AVRational which will contain the detected
* frame rate
*)
-function av_parse_video_frame_rate(frame_rate: PAVRational; str: {const} PChar): cint;
- cdecl; external av__codec;
-{$IFEND}
-
-{$IF LIBAVCODEC_VERSION >= 51064000} // 51.64.0
-(**
- * Logs a generic warning message about a missing feature.
- * @param[in] avc a pointer to an arbitrary struct of which the first field is
- * a pointer to an AVClass struct
- * @param[in] feature string containing the name of the missing feature
- * @param[in] want_sample indicates if samples are wanted which exhibit this feature.
- * If \p want_sample is non-zero, additional verbage will be added to the log
- * message which tells the user how to report samples to the development
- * mailing list.
- *)
-procedure av_log_missing_feature(avc: Pointer; feature: {const} PChar; want_sample: cint);
+function av_parse_video_frame_rate(frame_rate: PAVRational; str: {const} PAnsiChar): cint;
cdecl; external av__codec;
{$IFEND}
diff --git a/unicode/src/lib/ffmpeg/avformat.pas b/unicode/src/lib/ffmpeg/avformat.pas
index c516aea0..62df8a83 100644
--- a/unicode/src/lib/ffmpeg/avformat.pas
+++ b/unicode/src/lib/ffmpeg/avformat.pas
@@ -27,7 +27,7 @@
(*
* Conversion of libavformat/avformat.h
* Min. version: 50.5.0 , revision 6577, Sat Oct 7 15:30:46 2006 UTC
- * Max. version: 52.22.1, revision 15441, Sat Sep 27 20:05:12 2008 UTC
+ * Max. version: 52.25.0, revision 16986, Wed Feb 4 05:56:39 2009 UTC
*)
unit avformat;
@@ -54,13 +54,14 @@ uses
avutil,
avio,
rational,
+ SysUtils,
UConfig;
const
(* Max. supported version by this header *)
LIBAVFORMAT_MAX_VERSION_MAJOR = 52;
- LIBAVFORMAT_MAX_VERSION_MINOR = 22;
- LIBAVFORMAT_MAX_VERSION_RELEASE = 1;
+ LIBAVFORMAT_MAX_VERSION_MINOR = 25;
+ LIBAVFORMAT_MAX_VERSION_RELEASE = 0;
LIBAVFORMAT_MAX_VERSION = (LIBAVFORMAT_MAX_VERSION_MAJOR * VERSION_MAJOR) +
(LIBAVFORMAT_MAX_VERSION_MINOR * VERSION_MINOR) +
(LIBAVFORMAT_MAX_VERSION_RELEASE * VERSION_RELEASE);
@@ -95,6 +96,68 @@ function avformat_version(): cuint;
type
PAVFile = Pointer;
+(*
+ * Public Metadata API.
+ * !!WARNING!! This is a work in progress. Don't use outside FFmpeg for now.
+ * The metadata API allows libavformat to export metadata tags to a client
+ * application using a sequence of key/value pairs.
+ * Important concepts to keep in mind:
+ * 1. Keys are unique; there can never be 2 tags with the same key. This is
+ * also meant semantically, i.e., a demuxer should not knowingly produce
+ * several keys that are literally different but semantically identical.
+ * E.g., key=Author5, key=Author6. In this example, all authors must be
+ * placed in the same tag.
+ * 2. Metadata is flat, not hierarchical; there are no subtags. If you
+ * want to store, e.g., the email address of the child of producer Alice
+ * and actor Bob, that could have key=alice_and_bobs_childs_email_address.
+ * 3. A tag whose value is localized for a particular language is appended
+ * with a dash character ('-') and the ISO 639 3-letter language code.
+ * For example: Author-ger=Michael, Author-eng=Mike
+ * The original/default language is in the unqualified "Author" tag.
+ * A demuxer should set a default if it sets any translated tag.
+ *)
+const
+ AV_METADATA_MATCH_CASE = 1;
+ AV_METADATA_IGNORE_SUFFIX = 2;
+
+type
+ PAVMetadataTag = ^TAVMetadataTag;
+ TAVMetadataTag = record
+ key: PAnsiChar;
+ value: PAnsiChar;
+ end;
+
+ PAVMetadata = Pointer;
+
+{$IF LIBAVFORMAT_VERSION > 52024001} // > 52.24.1
+
+(**
+ * gets a metadata element with matching key.
+ * @param prev set to the previous matching element to find the next.
+ * @param flags allows case as well as suffix insensitive comparisons.
+ * @return found tag or NULL, changing key or value leads to undefined behavior.
+ *)
+function av_metadata_get(m: PAVMetadata; key: {const} PAnsiChar;
+ prev: {const} PAVMetadataTag ; flags: cint): PAVMetadataTag;
+ cdecl; external av__format;
+
+(**
+ * sets the given tag in m, overwriting an existing tag.
+ * @param key tag key to add to m (will be av_strduped).
+ * @param value tag value to add to m (will be av_strduped).
+ * @return >= 0 if success otherwise error code that is <0.
+ *)
+function av_metadata_set(var pm: PAVMetadata; key: {const} PAnsiChar; value: {const} PAnsiChar): cint;
+ cdecl; external av__format;
+
+(**
+ * Free all the memory allocated for an AVMetadata struct.
+ *)
+procedure av_metadata_free(var m: PAVMetadata);
+ cdecl; external av__format;
+
+{$IFEND}
+
(* packet functions *)
type
@@ -117,7 +180,7 @@ type
* Can be AV_NOPTS_VALUE if it is not stored in the file.
*)
dts: cint64;
- data: PChar;
+ data: PByteArray;
size: cint;
stream_index: cint;
flags: cint;
@@ -126,7 +189,7 @@ type
* Equals next_pts - this_pts in presentation order.
*)
duration: cint;
- destruct: procedure (p: PAVPacket); cdecl;
+ destruct: procedure (p: PAVPacket); cdecl;
priv: pointer;
pos: cint64; ///< byte position in stream, -1 if unknown
@@ -220,7 +283,7 @@ type
PAVFrac = ^TAVFrac;
TAVFrac = record
val, num, den: cint64;
- end; {deprecated}
+ end;
(*************************************************)
(* input/output formats *)
@@ -228,8 +291,8 @@ type
type
(** This structure contains the data a format has to probe a file. *)
TAVProbeData = record
- filename: pchar;
- buf: pchar;
+ filename: PAnsiChar;
+ buf: PByteArray;
buf_size: cint;
end;
@@ -309,7 +372,10 @@ type
id: cint; ///< unique ID to identify the chapter
time_base: TAVRational; ///< time base in which the start/end timestamps are specified
start, end_: cint64; ///< chapter start/end time in time_base units
- title: PChar; ///< chapter title
+ title: PAnsiChar; ///< chapter title
+ {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+ metadata: PAVMetadata;
+ {$IFEND}
end;
TAVChapterArray = array[0..(MaxInt div SizeOf(TAVChapter))-1] of TAVChapter;
PAVChapterArray = ^TAVChapterArray;
@@ -326,9 +392,9 @@ type
{$IFEND}
channel: cint; (**< Used to select DV channel. *)
{$IF LIBAVFORMAT_VERSION_MAJOR < 52}
- device: pchar; (* video, audio or DV device, if LIBAVFORMAT_VERSION_INT < (52<<16) *)
+ device: PAnsiChar; (* video, audio or DV device, if LIBAVFORMAT_VERSION_INT < (52<<16) *)
{$IFEND}
- standard: pchar; (**< TV standard, NTSC, PAL, SECAM *)
+ standard: PAnsiChar; (**< TV standard, NTSC, PAL, SECAM *)
{ Delphi does not support bit fields -> use bf_flags instead
unsigned int mpeg2ts_raw:1; (**< Force raw MPEG-2 transport stream output, if possible. *)
unsigned int mpeg2ts_compute_pcr:1; (**< Compute exact PCR for each transport
@@ -346,15 +412,15 @@ type
end;
TAVOutputFormat = record
- name: pchar;
+ name: PAnsiChar;
(**
* Descriptive name for the format, meant to be more human-readable
* than \p name. You \e should use the NULL_IF_CONFIG_SMALL() macro
* to define it.
*)
- long_name: pchar;
- mime_type: pchar;
- extensions: pchar; (**< comma-separated filename extensions *)
+ long_name: PAnsiChar;
+ mime_type: PAnsiChar;
+ extensions: PAnsiChar; (**< comma-separated filename extensions *)
(** Size of private data so that it can be allocated in the wrapper. *)
priv_data_size: cint;
(* output support *)
@@ -387,13 +453,13 @@ type
end;
TAVInputFormat = record
- name: pchar;
+ name: PAnsiChar;
(**
* Descriptive name for the format, meant to be more human-readable
* than \p name. You \e should use the NULL_IF_CONFIG_SMALL() macro
* to define it.
*)
- long_name: pchar;
+ long_name: PAnsiChar;
(** Size of private data so that it can be allocated in the wrapper. *)
priv_data_size: cint;
(**
@@ -435,7 +501,7 @@ type
(** If extensions are defined, then no probe is done. You should
usually not use extension format guessing because it is not
reliable enough *)
- extensions: pchar;
+ extensions: PAnsiChar;
(** General purpose read-only value that the format can use. *)
value: cint;
@@ -533,7 +599,7 @@ type
*)
duration: cint64;
- language: array [0..3] of char; (* ISO 639 3-letter language code (empty string if undefined) *)
+ language: array [0..3] of PAnsiChar; (* ISO 639 3-letter language code (empty string if undefined) *)
(* av_read_frame() support *)
need_parsing: TAVStreamParseType;
@@ -555,7 +621,7 @@ type
{$IFEND}
{$IF LIBAVFORMAT_VERSION >= 52006000} // 52.6.0
- filename: PChar; (**< source filename of the stream *)
+ filename: PAnsiChar; (**< source filename of the stream *)
{$IFEND}
{$IF LIBAVFORMAT_VERSION >= 52008000} // 52.8.0
@@ -576,6 +642,17 @@ type
*)
sample_aspect_ratio: TAVRational;
{$IFEND}
+
+ {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+ metadata: PAVMetadata;
+ {$IFEND}
+
+ {$IF LIBAVFORMAT_VERSION > 52024001} // > 52.24.1
+ {* av_read_frame() support *}
+ cur_ptr: {const} PCuint8;
+ cur_len: cint;
+ cur_pkt: TAVPacket;
+ {$IFEND}
end;
(**
@@ -600,17 +677,17 @@ type
nb_streams: cuint;
streams: array [0..MAX_STREAMS - 1] of PAVStream;
- filename: array [0..1023] of char; (* input or output filename *)
+ filename: array [0..1023] of AnsiChar; (* input or output filename *)
(* stream info *)
timestamp: cint64;
- title: array [0..511] of char;
- author: array [0..511] of char;
- copyright: array [0..511] of char;
- comment: array [0..511] of char;
- album: array [0..511] of char;
+ title: array [0..511] of AnsiChar;
+ author: array [0..511] of AnsiChar;
+ copyright: array [0..511] of AnsiChar;
+ comment: array [0..511] of AnsiChar;
+ album: array [0..511] of AnsiChar;
year: cint; (**< ID3 year, 0 if none *)
track: cint; (**< track number, 0 if none *)
- genre: array [0..31] of char; (**< ID3 genre *)
+ genre: array [0..31] of AnsiChar; (**< ID3 genre *)
ctx_flags: cint; (**< Format-specific flags, see AVFMTCTX_xx *)
(* private data for pts handling (do not modify directly). *)
@@ -636,9 +713,11 @@ type
(* av_read_frame() support *)
cur_st: PAVStream;
- cur_ptr: pbyte;
- cur_len: cint;
- cur_pkt: TAVPacket;
+ {$IF LIBAVFORMAT_VERSION_MAJOR < 53}
+ cur_ptr_deprecated: pbyte;
+ cur_len_deprecated: cint;
+ cur_pkt_deprecated: TAVPacket;
+ {$IFEND}
(* av_seek_frame() support *)
data_offset: cint64; (* offset of the first packet *)
@@ -740,6 +819,10 @@ type
packet_buffer_end: PAVPacketList;
{$IFEND}
+
+ {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+ metadata: PAVMetadata;
+ {$IFEND}
end;
(**
@@ -750,14 +833,17 @@ type
*)
TAVProgram = record
id : cint;
- provider_name : PChar; ///< network name for DVB streams
- name : PChar; ///< service name for DVB streams
+ provider_name : PAnsiChar; ///< network name for DVB streams
+ name : PAnsiChar; ///< service name for DVB streams
flags : cint;
discard : TAVDiscard; ///< selects which program to discard and which to feed to the caller
{$IF LIBAVFORMAT_VERSION >= 51016000} // 51.16.0
stream_index : PCardinal;
nb_stream_indexes : PCardinal;
{$IFEND}
+ {$IF LIBAVFORMAT_VERSION >= 52024001} // 52.24.1
+ metadata: PAVMetadata;
+ {$IFEND}
end;
TAVPacketList = record
@@ -779,8 +865,8 @@ type
end; {deprecated}
TAVImageFormat = record
- name: pchar;
- extensions: pchar;
+ name: PAnsiChar;
+ extensions: PAnsiChar;
(* tell if a given file has a chance of being parsing by this format *)
img_probe: function (d: PAVProbeData): cint; cdecl;
(* read a whole image. 'alloc_cb' is called when the image size is
@@ -801,10 +887,10 @@ procedure av_register_image_format(img_fmt: PAVImageFormat);
function av_probe_image_format(pd: PAVProbeData): PAVImageFormat;
cdecl; external av__format; deprecated;
-function guess_image_format(filename: pchar): PAVImageFormat;
+function guess_image_format(filename: PAnsiChar): PAVImageFormat;
cdecl; external av__format; deprecated;
-function av_read_image(pb: PByteIOContext; filename: pchar;
+function av_read_image(pb: PByteIOContext; filename: PAnsiChar;
fmt: PAVImageFormat;
alloc_cb: pointer; opaque: pointer): cint;
cdecl; external av__format; deprecated;
@@ -828,7 +914,7 @@ function av_oformat_next(f: PAVOutputFormat): PAVOutputFormat;
cdecl; external av__format;
{$IFEND}
-function av_guess_image2_codec(filename: {const} PChar): TCodecID;
+function av_guess_image2_codec(filename: {const} PAnsiChar): TCodecID;
cdecl; external av__format;
(* XXX: use automatic init with either ELF sections or C file parser *)
@@ -841,21 +927,21 @@ procedure av_register_input_format(format: PAVInputFormat);
procedure av_register_output_format(format: PAVOutputFormat);
cdecl; external av__format;
-function guess_stream_format(short_name: pchar;
- filename: pchar;
- mime_type: pchar): PAVOutputFormat;
+function guess_stream_format(short_name: PAnsiChar;
+ filename: PAnsiChar;
+ mime_type: PAnsiChar): PAVOutputFormat;
cdecl; external av__format;
-function guess_format(short_name: pchar;
- filename: pchar;
- mime_type: pchar): PAVOutputFormat;
+function guess_format(short_name: PAnsiChar;
+ filename: PAnsiChar;
+ mime_type: PAnsiChar): PAVOutputFormat;
cdecl; external av__format;
(**
* Guesses the codec ID based upon muxer and filename.
*)
-function av_guess_codec(fmt: PAVOutputFormat; short_name: pchar;
- filename: pchar; mime_type: pchar;
+function av_guess_codec(fmt: PAVOutputFormat; short_name: PAnsiChar;
+ filename: PAnsiChar; mime_type: PAnsiChar;
type_: TCodecType): TCodecID;
cdecl; external av__format;
@@ -868,7 +954,7 @@ function av_guess_codec(fmt: PAVOutputFormat; short_name: pchar;
*
* @see av_hex_dump_log, av_pkt_dump, av_pkt_dump_log
*)
-procedure av_hex_dump(f: PAVFile; buf: pchar; size: cint);
+procedure av_hex_dump(f: PAVFile; buf: PByteArray; size: cint);
cdecl; external av__format;
{$IF LIBAVFORMAT_VERSION >= 51011000} // 51.11.0
@@ -884,7 +970,7 @@ procedure av_hex_dump(f: PAVFile; buf: pchar; size: cint);
*
* @see av_hex_dump, av_pkt_dump, av_pkt_dump_log
*)
-procedure av_hex_dump_log(avcl: Pointer; level: cint; buf: PChar; size: cint);
+procedure av_hex_dump_log(avcl: Pointer; level: cint; buf: PByteArray; size: cint);
cdecl; external av__format;
{$IFEND}
@@ -913,6 +999,15 @@ procedure av_pkt_dump_log(avcl: Pointer; level: cint; pkt: PAVPacket; dump_paylo
cdecl; external av__format;
{$IFEND}
+(**
+ * Initialize libavformat and register all the muxers, demuxers and
+ * protocols. If you do not call this function, then you can select
+ * exactly which formats you want to support.
+ *
+ * @see av_register_input_format()
+ * @see av_register_output_format()
+ * @see register_protocol()
+ *)
procedure av_register_all();
cdecl; external av__format;
@@ -929,7 +1024,7 @@ function av_codec_get_tag(var tags: PAVCodecTag; id: TCodecID): cuint;
(**
* Finds AVInputFormat based on the short name of the input format.
*)
-function av_find_input_format(short_name: pchar): PAVInputFormat;
+function av_find_input_format(short_name: PAnsiChar): PAVInputFormat;
cdecl; external av__format;
(**
@@ -946,7 +1041,7 @@ function av_probe_input_format(pd: PAVProbeData; is_opened: cint): PAVInputForma
* This does not open the needed codecs for decoding the stream[s].
*)
function av_open_input_stream(ic_ptr: PAVFormatContext;
- pb: PByteIOContext; filename: pchar;
+ pb: PByteIOContext; filename: PAnsiChar;
fmt: PAVInputFormat; ap: PAVFormatParameters): cint;
cdecl; external av__format;
@@ -962,7 +1057,7 @@ function av_open_input_stream(ic_ptr: PAVFormatContext;
* (NULL if default).
* @return 0 if OK, AVERROR_xxx otherwise
*)
-function av_open_input_file(var ic_ptr: PAVFormatContext; filename: pchar;
+function av_open_input_file(var ic_ptr: PAVFormatContext; filename: PAnsiChar;
fmt: PAVInputFormat; buf_size: cint;
ap: PAVFormatParameters): cint;
cdecl; external av__format;
@@ -1105,7 +1200,7 @@ function av_new_program(s: PAVFormatContext; id: cint): PAVProgram;
* @return AVChapter or NULL on error
*)
function ff_new_chapter(s: PAVFormatContext; id: cint; time_base: TAVRational;
- start, end_: cint64; title: {const} Pchar): PAVChapter;
+ start, end_: cint64; title: {const} PAnsiChar): PAVChapter;
cdecl; external av__format;
{$IFEND}
@@ -1287,7 +1382,7 @@ function av_interleave_packet_per_dts(s: PAVFormatContext; _out: PAVPacket;
function av_write_trailer(s: pAVFormatContext): cint;
cdecl; external av__format;
-procedure dump_format(ic: PAVFormatContext; index: cint; url: pchar;
+procedure dump_format(ic: PAVFormatContext; index: cint; url: PAnsiChar;
is_output: cint);
cdecl; external av__format;
@@ -1296,16 +1391,18 @@ procedure dump_format(ic: PAVFormatContext; index: cint; url: pchar;
* @deprecated Use av_parse_video_frame_size instead.
*)
function parse_image_size(width_ptr: PCint; height_ptr: PCint;
- str: pchar): cint;
+ str: PAnsiChar): cint;
cdecl; external av__format; deprecated;
+{$IF LIBAVFORMAT_VERSION_MAJOR < 53}
(**
* Converts frame rate from string to a fraction.
* @deprecated Use av_parse_video_frame_rate instead.
*)
function parse_frame_rate(frame_rate: PCint; frame_rate_base: PCint;
- arg: pchar): cint;
+ arg: PByteArray): cint;
cdecl; external av__format; deprecated;
+{$IFEND}
(**
* Parses \p datestr and returns a corresponding number of microseconds.
@@ -1333,7 +1430,7 @@ function parse_frame_rate(frame_rate: PCint; frame_rate_base: PCint;
* not zero \p datestr is interpreted as a duration, otherwise as a
* date.
*)
-function parse_date(datestr: pchar; duration: cint): cint64;
+function parse_date(datestr: PAnsiChar; duration: cint): cint64;
cdecl; external av__format;
(** Gets the current time in microseconds. *)
@@ -1359,7 +1456,7 @@ procedure ffm_set_write_index(s: PAVFormatContext; pos: cint64; file_size: cint6
* syntax: '?tag1=val1&tag2=val2...'. Little URL decoding is done.
* Return 1 if found.
*)
-function find_info_tag(arg: pchar; arg_size: cint; tag1: pchar; info: pchar): cint;
+function find_info_tag(arg: PAnsiChar; arg_size: cint; tag1: PAnsiChar; info: PAnsiChar): cint;
cdecl; external av__format;
(**
@@ -1374,8 +1471,8 @@ function find_info_tag(arg: pchar; arg_size: cint; tag1: pchar; info: pchar): ci
* @param number frame number
* @return 0 if OK, -1 on format error
*)
-function av_get_frame_filename(buf: pchar; buf_size: cint;
- path: pchar; number: cint): cint;
+function av_get_frame_filename(buf: PAnsiChar; buf_size: cint;
+ path: PAnsiChar; number: cint): cint;
cdecl; external av__format
{$IF LIBAVFORMAT_VERSION <= 50006000} // 50.6.0
name 'get_frame_filename'
@@ -1387,7 +1484,7 @@ function av_get_frame_filename(buf: pchar; buf_size: cint;
* @param filename possible numbered sequence string
* @return 1 if a valid numbered sequence string, 0 otherwise
*)
-function av_filename_number_test(filename: pchar): cint;
+function av_filename_number_test(filename: PAnsiChar): cint;
cdecl; external av__format
{$IF LIBAVFORMAT_VERSION <= 50006000} // 50.6.0
name 'filename_number_test'
@@ -1408,7 +1505,7 @@ function av_filename_number_test(filename: pchar): cint;
* @param size the size of the buffer
* @return 0 if OK, AVERROR_xxx on error
*)
-function avf_sdp_create(ac: PPAVFormatContext; n_files: cint; buff: PChar; size: cint): cint;
+function avf_sdp_create(ac: PPAVFormatContext; n_files: cint; buff: PByteArray; size: cint): cint;
cdecl; external av__format;
{$IFEND}
diff --git a/unicode/src/lib/ffmpeg/avio.pas b/unicode/src/lib/ffmpeg/avio.pas
index 5107a9fb..33778206 100644
--- a/unicode/src/lib/ffmpeg/avio.pas
+++ b/unicode/src/lib/ffmpeg/avio.pas
@@ -27,7 +27,7 @@
(*
* Conversion of libavformat/avio.h
- * revision 15120, Sun Aug 31 07:39:47 2008 UTC
+ * revision 16100, Sat Dec 13 13:39:13 2008 UTC
*)
unit avio;
@@ -48,13 +48,9 @@ uses
ctypes,
avutil,
avcodec,
+ SysUtils,
UConfig;
-(* output byte stream handling *)
-
-type
- TOffset = cint64;
-
(* unbuffered I/O *)
const
@@ -92,7 +88,7 @@ type
is_streamed: cint; (**< true if streamed (no seek possible), default = false *)
max_packet_size: cint; (**< if non zero, the stream is packetized with this max packet size *)
priv_data: pointer;
- filename: PChar; (**< specified filename *)
+ filename: PAnsiChar; (**< specified filename *)
end;
PPURLContext = ^PURLContext;
@@ -104,11 +100,11 @@ type
end;
TURLProtocol = record
- name: PChar;
- url_open: function (h: PURLContext; filename: {const} PChar; flags: cint): cint; cdecl;
- url_read: function (h: PURLContext; buf: PChar; size: cint): cint; cdecl;
- url_write: function (h: PURLContext; buf: PChar; size: cint): cint; cdecl;
- url_seek: function (h: PURLContext; pos: TOffset; whence: cint): TOffset; cdecl;
+ name: PAnsiChar;
+ url_open: function (h: PURLContext; filename: {const} PAnsiChar; flags: cint): cint; cdecl;
+ url_read: function (h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+ url_write: function (h: PURLContext; buf: PByteArray; size: cint): cint; cdecl;
+ url_seek: function (h: PURLContext; pos: cint64; whence: cint): cint64; cdecl;
url_close: function (h: PURLContext): cint; cdecl;
next: PURLProtocol;
{$IF (LIBAVFORMAT_VERSION >= 52001000) and (LIBAVFORMAT_VERSION < 52004000)} // 52.1.0 .. 52.4.0
@@ -119,8 +115,8 @@ type
url_read_pause: function (h: PURLContext; pause: cint): cint; cdecl;
{$IFEND}
{$IF LIBAVFORMAT_VERSION >= 52001000} // 52.1.0
- url_read_seek: function (h: PURLContext;
- stream_index: cint; timestamp: cint64; flags: cint): TOffset; cdecl;
+ url_read_seek: function (h: PURLContext; stream_index: cint;
+ timestamp: cint64; flags: cint): cint64; cdecl;
{$IFEND}
end;
@@ -133,23 +129,23 @@ type
*)
PByteIOContext = ^TByteIOContext;
TByteIOContext = record
- buffer: PChar;
+ buffer: PByteArray;
buffer_size: cint;
- buf_ptr: PChar;
- buf_end: PChar;
+ buf_ptr: PByteArray;
+ buf_end: PByteArray;
opaque: pointer;
- read_packet: function (opaque: pointer; buf: PChar; buf_size: cint): cint; cdecl;
- write_packet: function (opaque: pointer; buf: PChar; buf_size: cint): cint; cdecl;
- seek: function (opaque: pointer; offset: TOffset; whence: cint): TOffset; cdecl;
- pos: TOffset; (* position in the file of the current buffer *)
+ read_packet: function (opaque: pointer; buf: PByteArray; buf_size: cint): cint; cdecl;
+ write_packet: function (opaque: pointer; buf: PByteArray; buf_size: cint): cint; cdecl;
+ seek: function (opaque: pointer; offset: cint64; whence: cint): cint64; cdecl;
+ pos: cint64; (* position in the file of the current buffer *)
must_flush: cint; (* true if the next seek should flush *)
eof_reached: cint; (* true if eof reached *)
write_flag: cint; (* true if open for writing *)
is_streamed: cint;
max_packet_size: cint;
checksum: culong;
- checksum_ptr: PCuchar;
- update_checksum: function (checksum: culong; buf: {const} PChar; size: cuint): culong; cdecl;
+ checksum_ptr: PByteArray;
+ update_checksum: function (checksum: culong; buf: {const} PByteArray; size: cuint): culong; cdecl;
error: cint; ///< contains the error code or 0 if no error happened
{$IF (LIBAVFORMAT_VERSION >= 52001000) and (LIBAVFORMAT_VERSION < 52004000)} // 52.1.0 .. 52.4.0
read_play: function(opaque: Pointer): cint; cdecl;
@@ -159,30 +155,30 @@ type
read_pause: function(opaque: Pointer; pause: cint): cint; cdecl;
{$IFEND}
{$IF LIBAVFORMAT_VERSION >= 52001000} // 52.1.0
- read_seek: function(opaque: Pointer;
- stream_index: cint; timestamp: cint64; flags: cint): TOffset; cdecl;
+ read_seek: function(opaque: Pointer; stream_index: cint;
+ timestamp: cint64; flags: cint): cint64; cdecl;
{$IFEND}
end;
{$IF LIBAVFORMAT_VERSION >= 52021000} // 52.21.0
function url_open_protocol(puc: PPURLContext; up: PURLProtocol;
- filename: {const} PChar; flags: cint): cint;
+ filename: {const} PAnsiChar; flags: cint): cint;
cdecl; external av__format;
{$IFEND}
-function url_open(h: PPointer; filename: {const} PChar; flags: cint): cint;
+function url_open(h: PPointer; filename: {const} PAnsiChar; flags: cint): cint;
cdecl; external av__format;
-function url_read (h: PURLContext; buf: PChar; size: cint): cint;
+function url_read (h: PURLContext; buf: PByteArray; size: cint): cint;
cdecl; external av__format;
-function url_write (h: PURLContext; buf: PChar; size: cint): cint;
+function url_write (h: PURLContext; buf: PByteArray; size: cint): cint;
cdecl; external av__format;
-function url_seek (h: PURLContext; pos: TOffset; whence: cint): TOffset;
+function url_seek (h: PURLContext; pos: cint64; whence: cint): cint64;
cdecl; external av__format;
function url_close (h: PURLContext): cint;
cdecl; external av__format;
-function url_exist(filename: {const} PChar): cint;
+function url_exist(filename: {const} PAnsiChar): cint;
cdecl; external av__format;
-function url_filesize (h: PURLContext): TOffset;
+function url_filesize (h: PURLContext): cint64;
cdecl; external av__format;
(**
@@ -195,7 +191,7 @@ function url_filesize (h: PURLContext): TOffset;
*)
function url_get_max_packet_size(h: PURLContext): cint;
cdecl; external av__format;
-procedure url_get_filename(h: PURLContext; buf: PChar; buf_size: cint);
+procedure url_get_filename(h: PURLContext; buf: PAnsiChar; buf_size: cint);
cdecl; external av__format;
(**
@@ -239,8 +235,8 @@ function av_url_read_pause(h: PURLContext; pause: cint): cint;
* @return >= 0 on success
* @see AVInputFormat::read_seek
*)
-function av_url_read_seek(h: PURLContext;
- stream_index: cint; timestamp: cint64; flags: cint): TOffset;
+function av_url_read_seek(h: PURLContext; stream_index: cint;
+ timestamp: cint64; flags: cint): cint64;
cdecl; external av__format;
{$IFEND}
@@ -259,11 +255,11 @@ function register_protocol (protocol: PURLProtocol): cint;
cdecl; external av__format;
type
- TReadWriteFunc = function (opaque: Pointer; buf: PChar; buf_size: cint): cint; cdecl;
- TSeekFunc = function (opaque: Pointer; offset: TOffset; whence: cint): TOffset; cdecl;
+ TReadWriteFunc = function (opaque: Pointer; buf: PByteArray; buf_size: cint): cint; cdecl;
+ TSeekFunc = function (opaque: Pointer; offset: cint64; whence: cint): cint64; cdecl;
function init_put_byte(s: PByteIOContext;
- buffer: PChar;
+ buffer: PByteArray;
buffer_size: cint; write_flag: cint;
opaque: pointer;
read_packet: TReadWriteFunc;
@@ -272,7 +268,7 @@ function init_put_byte(s: PByteIOContext;
cdecl; external av__format;
{$IF LIBAVFORMAT_VERSION >= 52004000} // 52.4.0
function av_alloc_put_byte(
- buffer: PChar;
+ buffer: PByteArray;
buffer_size: cint;
write_flag: cint;
opaque: Pointer;
@@ -284,7 +280,7 @@ function av_alloc_put_byte(
procedure put_byte(s: PByteIOContext; b: cint);
cdecl; external av__format;
-procedure put_buffer (s: PByteIOContext; buf: {const} PChar; size: cint);
+procedure put_buffer (s: PByteIOContext; buf: {const} PByteArray; size: cint);
cdecl; external av__format;
procedure put_le64(s: PByteIOContext; val: cuint64);
cdecl; external av__format;
@@ -302,38 +298,38 @@ procedure put_le16(s: PByteIOContext; val: cuint);
cdecl; external av__format;
procedure put_be16(s: PByteIOContext; val: cuint);
cdecl; external av__format;
-procedure put_tag(s: PByteIOContext; tag: {const} PChar);
+procedure put_tag(s: PByteIOContext; tag: {const} PAnsiChar);
cdecl; external av__format;
-procedure put_strz(s: PByteIOContext; buf: {const} PChar);
+procedure put_strz(s: PByteIOContext; buf: {const} PAnsiChar);
cdecl; external av__format;
(**
* fseek() equivalent for ByteIOContext.
* @return new position or AVERROR.
*)
-function url_fseek(s: PByteIOContext; offset: TOffset; whence: cint): TOffset;
+function url_fseek(s: PByteIOContext; offset: cint64; whence: cint): cint64;
cdecl; external av__format;
(**
* Skip given number of bytes forward.
* @param offset number of bytes
*)
-procedure url_fskip(s: PByteIOContext; offset: TOffset);
+procedure url_fskip(s: PByteIOContext; offset: cint64);
cdecl; external av__format;
(**
* ftell() equivalent for ByteIOContext.
* @return position or AVERROR.
*)
-function url_ftell(s: PByteIOContext): TOffset;
+function url_ftell(s: PByteIOContext): cint64;
cdecl; external av__format;
(**
* Gets the filesize.
* @return filesize or AVERROR
*)
-function url_fsize(s: PByteIOContext): TOffset;
+function url_fsize(s: PByteIOContext): cint64;
cdecl; external av__format;
(**
@@ -351,8 +347,8 @@ function av_url_read_fpause(h: PByteIOContext; pause: cint): cint;
cdecl; external av__format;
{$IFEND}
{$IF LIBAVFORMAT_VERSION >= 52001000} // 52.1.0
-function av_url_read_fseek(h: PByteIOContext;
- stream_index: cint; timestamp: cint64; flags: cint): TOffset;
+function av_url_read_fseek(h: PByteIOContext; stream_index: cint;
+ timestamp: cint64; flags: cint): cint64;
cdecl; external av__format;
{$IFEND}
@@ -363,12 +359,12 @@ function url_fgetc(s: PByteIOContext): cint;
cdecl; external av__format;
(** @warning currently size is limited *)
-function url_fprintf(s: PByteIOContext; fmt: {const} PChar; args: array of const): cint;
+function url_fprintf(s: PByteIOContext; fmt: {const} PAnsiChar; args: array of const): cint;
cdecl; external av__format;
(** @note unlike fgets, the EOL character is not returned and a whole
line is parsed. return NULL if first char read was EOF *)
-function url_fgets(s: PByteIOContext; buf: PChar; buf_size: cint): PChar;
+function url_fgets(s: PByteIOContext; buf: PAnsiChar; buf_size: cint): PAnsiChar;
cdecl; external av__format;
procedure put_flush_packet (s: PByteIOContext);
@@ -379,7 +375,7 @@ procedure put_flush_packet (s: PByteIOContext);
* Reads size bytes from ByteIOContext into buf.
* @returns number of bytes read or AVERROR
*)
-function get_buffer(s: PByteIOContext; buf: PChar; size: cint): cint;
+function get_buffer(s: PByteIOContext; buf: PByteArray; size: cint): cint;
cdecl; external av__format;
(**
@@ -388,7 +384,7 @@ function get_buffer(s: PByteIOContext; buf: PChar; size: cint): cint;
* returned.
* @returns number of bytes read or AVERROR
*)
-function get_partial_buffer(s: PByteIOContext; buf: PChar; size: cint): cint;
+function get_partial_buffer(s: PByteIOContext; buf: PByteArray; size: cint): cint;
cdecl; external av__format;
(** @note return 0 if EOF, so you cannot use it if EOF handling is
@@ -404,7 +400,7 @@ function get_le64(s: PByteIOContext): cuint64;
function get_le16(s: PByteIOContext): cuint;
cdecl; external av__format;
-function get_strz(s: PByteIOContext; buf: PChar; maxlen: cint): PChar;
+function get_strz(s: PByteIOContext; buf: PAnsiChar; maxlen: cint): PAnsiChar;
cdecl; external av__format;
function get_be16(s: PByteIOContext): cuint;
cdecl; external av__format;
@@ -447,9 +443,9 @@ function url_resetbuf(s: PByteIOContext; flags: cint): cint;
(** @note when opened as read/write, the buffers are only used for
writing *)
{$IF LIBAVFORMAT_VERSION >= 52000000} // 52.0.0
-function url_fopen(var s: PByteIOContext; filename: {const} PChar; flags: cint): cint;
+function url_fopen(var s: PByteIOContext; filename: {const} PAnsiChar; flags: cint): cint;
{$ELSE}
-function url_fopen(s: PByteIOContext; filename: {const} PChar; flags: cint): cint;
+function url_fopen(s: PByteIOContext; filename: {const} PAnsiChar; flags: cint): cint;
{$IFEND}
cdecl; external av__format;
function url_fclose(s: PByteIOContext): cint;
@@ -469,9 +465,9 @@ function url_fget_max_packet_size (s: PByteIOContext): cint;
cdecl; external av__format;
{$IF LIBAVFORMAT_VERSION >= 52000000} // 52.0.0
-function url_open_buf(var s: PByteIOContext; buf: PChar; buf_size: cint; flags: cint): cint;
+function url_open_buf(var s: PByteIOContext; buf: PAnsiChar; buf_size: cint; flags: cint): cint;
{$ELSE}
-function url_open_buf(s: PByteIOContext; buf: PChar; buf_size: cint; flags: cint): cint;
+function url_open_buf(s: PByteIOContext; buf: PAnsiChar; buf_size: cint; flags: cint): cint;
{$IFEND}
cdecl; external av__format;
@@ -519,16 +515,19 @@ function url_close_dyn_buf(s: PByteIOContext; pbuffer:PPointer): cint;
cdecl; external av__format;
{$IF LIBAVFORMAT_VERSION >= 51017001} // 51.17.1
-function ff_crc04C11DB7_update(checksum: culong; buf: {const} PChar; len: cuint): culong;
+function ff_crc04C11DB7_update(checksum: culong; buf: {const} PByteArray;
+ len: cuint): culong;
cdecl; external av__format;
{$IFEND}
function get_checksum(s: PByteIOContext): culong;
cdecl; external av__format;
-procedure init_checksum (s: PByteIOContext; update_checksum: pointer; checksum: culong);
+procedure init_checksum(s: PByteIOContext;
+ update_checksum: pointer;
+ checksum: culong);
cdecl; external av__format;
(* udp.c *)
-function udp_set_remote_url(h: PURLContext; uri: {const} PChar): cint;
+function udp_set_remote_url(h: PURLContext; uri: {const} PAnsiChar): cint;
cdecl; external av__format;
function udp_get_local_port(h: PURLContext): cint;
cdecl; external av__format;
diff --git a/unicode/src/lib/ffmpeg/avutil.pas b/unicode/src/lib/ffmpeg/avutil.pas
index b4fae422..6de35f1b 100644
--- a/unicode/src/lib/ffmpeg/avutil.pas
+++ b/unicode/src/lib/ffmpeg/avutil.pas
@@ -29,13 +29,13 @@
*
* libavutil/avutil.h:
* Min. version: 49.0.1, revision 6577, Sat Oct 7 15:30:46 2006 UTC
- * Max. version: 49.11.0, revision 15415, Thu Sep 25 19:23:13 2008 UTC
+ * Max. version: 49.14.0, revision 16912, Sun Feb 1 02:00:19 2009 UTC
*
* libavutil/mem.h:
- * revision 15120, Sun Aug 31 07:39:47 2008 UTC
+ * revision 16590, Tue Jan 13 23:44:16 2009 UTC
*
* libavutil/log.h:
- * revision 15120, Sun Aug 31 07:39:47 2008 UTC
+ * revision 16571, Tue Jan 13 00:14:43 2009 UTC
*)
unit avutil;
@@ -63,7 +63,7 @@ uses
const
(* Max. supported version by this header *)
LIBAVUTIL_MAX_VERSION_MAJOR = 49;
- LIBAVUTIL_MAX_VERSION_MINOR = 11;
+ LIBAVUTIL_MAX_VERSION_MINOR = 14;
LIBAVUTIL_MAX_VERSION_RELEASE = 0;
LIBAVUTIL_MAX_VERSION = (LIBAVUTIL_MAX_VERSION_MAJOR * VERSION_MAJOR) +
(LIBAVUTIL_MAX_VERSION_MINOR * VERSION_MINOR) +
@@ -98,15 +98,15 @@ type
(**
* Pixel format. Notes:
*
- * PIX_FMT_RGB32 is handled in an endian-specific manner. A RGBA
+ * PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA
* color is put together as:
* (A << 24) | (R << 16) | (G << 8) | B
- * This is stored as BGRA on little endian CPU architectures and ARGB on
- * big endian CPUs.
+ * This is stored as BGRA on little-endian CPU architectures and ARGB on
+ * big-endian CPUs.
*
* When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized
* image data is stored in AVFrame.data[0]. The palette is transported in
- * AVFrame.data[1] and, is 1024 bytes long (256 4-byte entries) and is
+ * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is
* formatted the same as in PIX_FMT_RGB32 described above (i.e., it is
* also endian-specific). Note also that the individual RGB palette
* components stored in AVFrame.data[1] should be in the range 0..255.
@@ -117,48 +117,53 @@ type
PAVPixelFormat = ^TAVPixelFormat;
TAVPixelFormat = (
PIX_FMT_NONE= -1,
- PIX_FMT_YUV420P, ///< Planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
- PIX_FMT_YUYV422, ///< Packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
- PIX_FMT_RGB24, ///< Packed RGB 8:8:8, 24bpp, RGBRGB...
- PIX_FMT_BGR24, ///< Packed RGB 8:8:8, 24bpp, BGRBGR...
- PIX_FMT_YUV422P, ///< Planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
- PIX_FMT_YUV444P, ///< Planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
- PIX_FMT_RGB32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in cpu endianness
- PIX_FMT_YUV410P, ///< Planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
- PIX_FMT_YUV411P, ///< Planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
- PIX_FMT_RGB565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), in cpu endianness
- PIX_FMT_RGB555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in cpu endianness most significant bit to 1
+ PIX_FMT_YUV420P, ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+ PIX_FMT_YUYV422, ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+ PIX_FMT_RGB24, ///< packed RGB 8:8:8, 24bpp, RGBRGB...
+ PIX_FMT_BGR24, ///< packed RGB 8:8:8, 24bpp, BGRBGR...
+ PIX_FMT_YUV422P, ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+ PIX_FMT_YUV444P, ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
+ PIX_FMT_RGB32, ///< packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in CPU endianness
+ PIX_FMT_YUV410P, ///< planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
+ PIX_FMT_YUV411P, ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
+ PIX_FMT_RGB565, ///< packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), in CPU endianness
+ PIX_FMT_RGB555, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in CPU endianness, most significant bit to 0
PIX_FMT_GRAY8, ///< Y , 8bpp
PIX_FMT_MONOWHITE, ///< Y , 1bpp, 0 is white, 1 is black
PIX_FMT_MONOBLACK, ///< Y , 1bpp, 0 is black, 1 is white
PIX_FMT_PAL8, ///< 8 bit with PIX_FMT_RGB32 palette
- PIX_FMT_YUVJ420P, ///< Planar YUV 4:2:0, 12bpp, full scale (jpeg)
- PIX_FMT_YUVJ422P, ///< Planar YUV 4:2:2, 16bpp, full scale (jpeg)
- PIX_FMT_YUVJ444P, ///< Planar YUV 4:4:4, 24bpp, full scale (jpeg)
+ PIX_FMT_YUVJ420P, ///< planar YUV 4:2:0, 12bpp, full scale (JPEG)
+ PIX_FMT_YUVJ422P, ///< planar YUV 4:2:2, 16bpp, full scale (JPEG)
+ PIX_FMT_YUVJ444P, ///< planar YUV 4:4:4, 24bpp, full scale (JPEG)
PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h)
PIX_FMT_XVMC_MPEG2_IDCT,
- PIX_FMT_UYVY422, ///< Packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
- PIX_FMT_UYYVYY411, ///< Packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
- PIX_FMT_BGR32, ///< Packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in cpu endianness
- PIX_FMT_BGR565, ///< Packed RGB 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), in cpu endianness
- PIX_FMT_BGR555, ///< Packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in cpu endianness most significant bit to 1
- PIX_FMT_BGR8, ///< Packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
- PIX_FMT_BGR4, ///< Packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb)
- PIX_FMT_BGR4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
- PIX_FMT_RGB8, ///< Packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
- PIX_FMT_RGB4, ///< Packed RGB 1:2:1, 4bpp, (msb)1R 2G 1B(lsb)
- PIX_FMT_RGB4_BYTE, ///< Packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
- PIX_FMT_NV12, ///< Planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
+ PIX_FMT_UYVY422, ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
+ PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
+ PIX_FMT_BGR32, ///< packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in CPU endianness
+ PIX_FMT_BGR565, ///< packed RGB 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), in CPU endianness
+ PIX_FMT_BGR555, ///< packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in CPU endianness, most significant bit to 1
+ PIX_FMT_BGR8, ///< packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
+ PIX_FMT_BGR4, ///< packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb)
+ PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
+ PIX_FMT_RGB8, ///< packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
+ PIX_FMT_RGB4, ///< packed RGB 1:2:1, 4bpp, (msb)1R 2G 1B(lsb)
+ PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
+ PIX_FMT_NV12, ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
PIX_FMT_NV21, ///< as above, but U and V bytes are swapped
- PIX_FMT_RGB32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in cpu endianness
- PIX_FMT_BGR32_1, ///< Packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in cpu endianness
+ PIX_FMT_RGB32_1, ///< packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in CPU endianness
+ PIX_FMT_BGR32_1, ///< packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in CPU endianness
PIX_FMT_GRAY16BE, ///< Y , 16bpp, big-endian
PIX_FMT_GRAY16LE, ///< Y , 16bpp, little-endian
- PIX_FMT_YUV440P, ///< Planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
- PIX_FMT_YUVJ440P, ///< Planar YUV 4:4:0 full scale (jpeg)
- PIX_FMT_YUVA420P, ///< Planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
+ PIX_FMT_YUV440P, ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
+ PIX_FMT_YUVJ440P, ///< planar YUV 4:4:0 full scale (JPEG)
+ PIX_FMT_YUVA420P, ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
+ PIX_FMT_VDPAU_H264,///< H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_MPEG1,///< MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_MPEG2,///< MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_WMV3,///< WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+ PIX_FMT_VDPAU_VC1, ///< VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
);
@@ -185,7 +190,7 @@ const
(* common.h *)
-function MKTAG(a,b,c,d: char): integer;
+function MKTAG(a,b,c,d: AnsiChar): integer;
(* mem.h *)
@@ -244,7 +249,7 @@ function av_mallocz(size: cuint): pointer;
* @return Pointer to a newly allocated string containing a
* copy of \p s or NULL if it cannot be allocated.
*)
-function av_strdup({const} s: PChar): PChar;
+function av_strdup({const} s: PAnsiChar): PAnsiChar;
cdecl; external av__util; {av_malloc_attrib}
(**
@@ -312,7 +317,7 @@ procedure av_log_set_level(level: cint);
implementation
-function MKTAG(a,b,c,d: char): integer;
+function MKTAG(a,b,c,d: AnsiChar): integer;
begin
Result := (ord(a) or (ord(b) shl 8) or (ord(c) shl 16) or (ord(d) shl 24));
end;
diff --git a/unicode/src/lib/ffmpeg/mathematics.pas b/unicode/src/lib/ffmpeg/mathematics.pas
index 606d9189..fb57ccea 100644
--- a/unicode/src/lib/ffmpeg/mathematics.pas
+++ b/unicode/src/lib/ffmpeg/mathematics.pas
@@ -26,7 +26,7 @@
(*
* Conversion of libavutil/mathematics.h
- * revision 15120, Sun Aug 31 07:39:47 2008 UTC
+ * revision 16844, Wed Jan 28 08:50:10 2009 UTC
*)
unit mathematics;
@@ -55,29 +55,34 @@ const
type
TAVRounding = (
- AV_ROUND_ZERO = 0, ///< round toward zero
- AV_ROUND_INF = 1, ///< round away from zero
- AV_ROUND_DOWN = 2, ///< round toward -infinity
- AV_ROUND_UP = 3, ///< round toward +infinity
- AV_ROUND_NEAR_INF = 5 ///< round to nearest and halfway cases away from zero
+ AV_ROUND_ZERO = 0, ///< Round toward zero
+ AV_ROUND_INF = 1, ///< Round away from zero
+ AV_ROUND_DOWN = 2, ///< Round toward -infinity
+ AV_ROUND_UP = 3, ///< Round toward +infinity
+ AV_ROUND_NEAR_INF = 5 ///< Round to nearest and halfway cases away from zero
);
+{$IF LIBAVUTIL_VERSION >= 49013000} // 49.13.0
+function av_gcd(a: cint64; b: cint64): cint64;
+ cdecl; external av__util; {av_const}
+{$IFEND}
+
(**
- * rescale a 64bit integer with rounding to nearest.
- * a simple a*b/c isn't possible as it can overflow
+ * Rescales a 64-bit integer with rounding to nearest.
+ * A simple a*b/c isn't possible as it can overflow.
*)
function av_rescale (a, b, c: cint64): cint64;
cdecl; external av__util; {av_const}
(**
- * rescale a 64bit integer with specified rounding.
- * a simple a*b/c isn't possible as it can overflow
+ * Rescales a 64-bit integer with specified rounding.
+ * A simple a*b/c isn't possible as it can overflow.
*)
function av_rescale_rnd (a, b, c: cint64; enum: TAVRounding): cint64;
cdecl; external av__util; {av_const}
(**
- * rescale a 64bit integer by 2 rational numbers.
+ * Rescales a 64-bit integer by 2 rational numbers.
*)
function av_rescale_q (a: cint64; bq, cq: TAVRational): cint64;
cdecl; external av__util; {av_const}
diff --git a/unicode/src/lib/ffmpeg/opt.pas b/unicode/src/lib/ffmpeg/opt.pas
index e734aa9f..833dc247 100644
--- a/unicode/src/lib/ffmpeg/opt.pas
+++ b/unicode/src/lib/ffmpeg/opt.pas
@@ -27,7 +27,7 @@
(*
* Conversion of libavcodec/opt.h
- * revision 15120, Sun Aug 31 07:39:47 2008 UTC
+ * revision 16912, Sun Feb 1 02:00:19 2009 UTC
*)
unit opt;
@@ -74,13 +74,13 @@ type
*)
PAVOption = ^TAVOption;
TAVOption = record
- name: {const} PChar;
+ name: {const} PAnsiChar;
(**
* short English help text
* @todo What about other languages?
*)
- help: {const} PChar;
+ help: {const} PAnsiChar;
(**
* The offset relative to the context structure where the option
@@ -104,7 +104,7 @@ type
* options and corresponding named constants share the same
* unit. May be NULL.
*)
- unit_: {const} PChar;
+ unit_: {const} PAnsiChar;
end;
{$IF LIBAVCODEC_VERSION >= 51039000} // 51.39.0
@@ -114,24 +114,39 @@ type
* for which it is the case that opt->flags & mask == flags).
*
* @param[in] obj a pointer to a struct whose first element is a
- * pointer to an #AVClass
+ * pointer to an AVClass
* @param[in] name the name of the option to look for
* @param[in] unit the unit of the option to look for, or any if NULL
* @return a pointer to the option found, or NULL if no option
* has been found
*)
-function av_find_opt(obj: Pointer; {const} name: {const} PChar; {const} unit_: PChar; mask: cint; flags: cint): {const} PAVOption;
+function av_find_opt(obj: Pointer; {const} name: {const} PAnsiChar; {const} unit_: PAnsiChar; mask: cint; flags: cint): {const} PAVOption;
cdecl; external av__codec;
{$IFEND}
+{$IF LIBAVCODEC_VERSION_MAJOR < 53}
+
(**
* @see av_set_string2()
*)
-function av_set_string(obj: pointer; name: {const} pchar; val: {const} pchar): {const} PAVOption;
+function av_set_string(obj: pointer; name: {const} PAnsiChar; val: {const} PAnsiChar): {const} PAVOption;
cdecl; external av__codec; deprecated;
{$IF LIBAVCODEC_VERSION >= 51059000} // 51.59.0
(**
+ * @return a pointer to the AVOption corresponding to the field set or
+ * NULL if no matching AVOption exists, or if the value \p val is not
+ * valid
+ * @see av_set_string3()
+ *)
+function av_set_string2(obj: Pointer; name: {const} PAnsiChar; val: {const} PAnsiChar; alloc: cint): {const} PAVOption;
+ cdecl; external av__codec; deprecated;
+{$IFEND}
+
+{$IFEND}
+
+{$IF LIBAVCODEC_VERSION >= 52007000} // 52.7.0
+(**
* Sets the field of obj with the given name to value.
*
* @param[in] obj A struct whose first element is a pointer to an
@@ -147,36 +162,37 @@ function av_set_string(obj: pointer; name: {const} pchar; val: {const} pchar): {
* scalars or named flags separated by '+' or '-'. Prefixing a flag
* with '+' causes it to be set without affecting the other flags;
* similarly, '-' unsets a flag.
- * @return a pointer to the AVOption corresponding to the field set or
- * NULL if no matching AVOption exists, or if the value \p val is not
- * valid
+ * @param[out] o_out if non-NULL put here a pointer to the AVOption
+ * found
* @param alloc when 1 then the old value will be av_freed() and the
* new av_strduped()
* when 0 then no av_free() nor av_strdup() will be used
+ * @return 0 if the value has been set, an AVERROR* error code if no
+ * matching option exists, or if the value \p val is not valid
*)
-function av_set_string2(obj: Pointer; name: {const} PChar; val: {const} PChar; alloc: cint): {const} PAVOption;
+function av_set_string3(obj: Pointer; name: {const} PAnsiChar; val: {const} PAnsiChar; alloc: cint; out o_out: {const} PAVOption): cint;
cdecl; external av__codec;
{$IFEND}
-function av_set_double(obj: pointer; name: {const} pchar; n: cdouble): PAVOption;
+function av_set_double(obj: pointer; name: {const} PAnsiChar; n: cdouble): PAVOption;
cdecl; external av__codec;
-function av_set_q(obj: pointer; name: {const} pchar; n: TAVRational): PAVOption;
+function av_set_q(obj: pointer; name: {const} PAnsiChar; n: TAVRational): PAVOption;
cdecl; external av__codec;
-function av_set_int(obj: pointer; name: {const} pchar; n: cint64): PAVOption;
+function av_set_int(obj: pointer; name: {const} PAnsiChar; n: cint64): PAVOption;
cdecl; external av__codec;
-function av_get_double(obj: pointer; name: {const} pchar; var o_out: PAVOption): cdouble;
+function av_get_double(obj: pointer; name: {const} PAnsiChar; var o_out: PAVOption): cdouble;
cdecl; external av__codec;
-function av_get_q(obj: pointer; name: {const} pchar; var o_out: PAVOption): TAVRational;
+function av_get_q(obj: pointer; name: {const} PAnsiChar; var o_out: PAVOption): TAVRational;
cdecl; external av__codec;
-function av_get_int(obj: pointer; name: {const} pchar; var o_out: {const} PAVOption): cint64;
+function av_get_int(obj: pointer; name: {const} PAnsiChar; var o_out: {const} PAVOption): cint64;
cdecl; external av__codec;
-function av_get_string(obj: pointer; name: {const} pchar; var o_out: {const} PAVOption; buf: pchar; buf_len: cint): pchar;
+function av_get_string(obj: pointer; name: {const} PAnsiChar; var o_out: {const} PAVOption; buf: PAnsiChar; buf_len: cint): PAnsiChar;
cdecl; external av__codec;
function av_next_option(obj: pointer; last: {const} PAVOption): PAVOption;
diff --git a/unicode/src/lib/ffmpeg/rational.pas b/unicode/src/lib/ffmpeg/rational.pas
index 02d594ff..6762aa26 100644
--- a/unicode/src/lib/ffmpeg/rational.pas
+++ b/unicode/src/lib/ffmpeg/rational.pas
@@ -1,5 +1,5 @@
(*
- * Rational numbers
+ * rational numbers
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
*
* This library is free software; you can redistribute it and/or
@@ -27,7 +27,7 @@
(*
* Conversion of libavutil/rational.h
- * revision 15415, Thu Sep 25 19:23:13 2008 UTC
+ * revision 16912, Sun Feb 1 02:00:19 2009 UTC
*)
unit rational;
@@ -49,9 +49,9 @@ uses
UConfig;
type
-(*
- * Rational number num/den.
- *)
+ (*
+ * rational number numerator/denominator
+ *)
PAVRational = ^TAVRational;
TAVRational = record
num: cint; ///< numerator
@@ -62,65 +62,65 @@ type
PAVRationalArray = ^TAVRationalArray;
(**
- * Compare two rationals.
+ * Compares two rationals.
* @param a first rational
* @param b second rational
- * @return 0 if a==b, 1 if a>b and -1 if a<b.
+ * @return 0 if a==b, 1 if a>b and -1 if a<b
*)
function av_cmp_q(a: TAVRational; b: TAVRational): cint; {$IFDEF HasInline}inline;{$ENDIF}
(**
- * Rational to double conversion.
+ * Converts rational to double.
* @param a rational to convert
* @return (double) a
*)
function av_q2d(a: TAVRational): cdouble; {$IFDEF HasInline}inline;{$ENDIF}
(**
- * Reduce a fraction.
+ * Reduces a fraction.
* This is useful for framerate calculations.
- * @param dst_nom destination numerator
+ * @param dst_num destination numerator
* @param dst_den destination denominator
- * @param nom source numerator
+ * @param num source numerator
* @param den source denominator
- * @param max the maximum allowed for dst_nom & dst_den
+ * @param max the maximum allowed for dst_num & dst_den
* @return 1 if exact, 0 otherwise
*)
-function av_reduce(dst_nom: PCint; dst_den: PCint; nom: cint64; den: cint64; max: cint64): cint;
+function av_reduce(dst_num: PCint; dst_den: PCint; num: cint64; den: cint64; max: cint64): cint;
cdecl; external av__util;
(**
* Multiplies two rationals.
- * @param b first rational.
- * @param c second rational.
- * @return b*c.
+ * @param b first rational
+ * @param c second rational
+ * @return b*c
*)
function av_mul_q(b: TAVRational; c: TAVRational): TAVRational;
cdecl; external av__util; {av_const}
(**
* Divides one rational by another.
- * @param b first rational.
- * @param c second rational.
- * @return b/c.
+ * @param b first rational
+ * @param c second rational
+ * @return b/c
*)
function av_div_q(b: TAVRational; c: TAVRational): TAVRational;
cdecl; external av__util; {av_const}
(**
* Adds two rationals.
- * @param b first rational.
- * @param c second rational.
- * @return b+c.
+ * @param b first rational
+ * @param c second rational
+ * @return b+c
*)
function av_add_q(b: TAVRational; c: TAVRational): TAVRational;
cdecl; external av__util; {av_const}
(**
* Subtracts one rational from another.
- * @param b first rational.
- * @param c second rational.
- * @return b-c.
+ * @param b first rational
+ * @param c second rational
+ * @return b-c
*)
function av_sub_q(b: TAVRational; c: TAVRational): TAVRational;
cdecl; external av__util; {av_const}
@@ -129,7 +129,7 @@ function av_sub_q(b: TAVRational; c: TAVRational): TAVRational;
* Converts a double precision floating point number to a rational.
* @param d double to convert
* @param max the maximum allowed numerator and denominator
- * @return (AVRational) d.
+ * @return (AVRational) d
*)
function av_d2q(d: cdouble; max: cint): TAVRational;
cdecl; external av__util; {av_const}
diff --git a/unicode/src/lib/requirements.txt b/unicode/src/lib/requirements.txt
index ace3165a..d3955585 100644
--- a/unicode/src/lib/requirements.txt
+++ b/unicode/src/lib/requirements.txt
@@ -44,5 +44,5 @@ Install the FreePascal compiler (version 2.2.2 or later) using fink or a package
Install these libs and their dependences using fink:
- fink install pkgconfig ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libtheora0
- fink install portaudio2 SDL SDL-image SDL-ttf libpng3 imlib2 sqlite3-dev \ No newline at end of file
+ fink install pkgconfig libavcodec-dev libavformat-dev libavutil-dev libswscale-dev
+ fink install portaudio2 SDL SDL-image libpng3 sqlite3-dev \ No newline at end of file