Browse Source

* Patch from Daniel Plachotich to allow regular procedures as iterators

git-svn-id: trunk@33221 -
michael 9 years ago
parent
commit
674b539293

+ 1 - 0
.gitattributes

@@ -1926,6 +1926,7 @@ packages/fcl-base/examples/b64test2.pp svneol=native#text/plain
 packages/fcl-base/examples/base64decodingtestcase.pas svneol=native#text/plain
 packages/fcl-base/examples/base64decodingtestcase.pas svneol=native#text/plain
 packages/fcl-base/examples/cachetest.pp svneol=native#text/plain
 packages/fcl-base/examples/cachetest.pp svneol=native#text/plain
 packages/fcl-base/examples/cfgtest.pp svneol=native#text/plain
 packages/fcl-base/examples/cfgtest.pp svneol=native#text/plain
+packages/fcl-base/examples/contit.pp svneol=native#text/plain
 packages/fcl-base/examples/crittest.pp svneol=native#text/plain
 packages/fcl-base/examples/crittest.pp svneol=native#text/plain
 packages/fcl-base/examples/dbugsrv.pp svneol=native#text/plain
 packages/fcl-base/examples/dbugsrv.pp svneol=native#text/plain
 packages/fcl-base/examples/debugtest.pp svneol=native#text/plain
 packages/fcl-base/examples/debugtest.pp svneol=native#text/plain

+ 2 - 1
packages/fcl-base/examples/README.txt

@@ -73,4 +73,5 @@ poolmm2.pp   Test for pooledmm (nonfree) (VS)
 testweb.pp   Test for fpcgi (MVC)
 testweb.pp   Test for fpcgi (MVC)
 daemon.pp    Test for daemonapp (MVC)
 daemon.pp    Test for daemonapp (MVC)
 testtimer.pp Test for TFPTimer (MVC)
 testtimer.pp Test for TFPTimer (MVC)
-testini.pp   Test/Demo for inifiles, ReadSectionValues.
+testini.pp   Test/Demo for inifiles, ReadSectionValues.
+contit.pp    Test/Demo for iterators in contnr.pp

+ 118 - 0
packages/fcl-base/examples/contit.pp

@@ -0,0 +1,118 @@
+{$MODE OBJFPC}
+{$H+}
+{$C+}
+program test;
+
+uses
+  contnrs,
+  sysutils;
+
+const
+  KEYS: array [0..5] of string = (
+    'a',
+    'b',
+    'c',
+    'd',
+    'e',
+    'f'
+    );
+
+  TERMINATE_KEY_ID = 2;
+
+
+procedure DataStaticIterator(Item: Pointer; const Key: string; var Continue: Boolean);
+begin
+  Assert(Key = String(Item^));
+  Continue := TRUE;
+end;
+
+procedure DataStaticIteratorTerminated(Item: Pointer; const Key: string; var Continue: Boolean);
+begin
+  Continue := Key <> KEYS[TERMINATE_KEY_ID];
+end;
+
+
+procedure StringStaticIterator(Item: String; const Key: string; var Continue: Boolean);
+begin
+  Assert(Key = Item);
+  Continue := TRUE;
+end;
+
+procedure StringStaticIteratorTerminated(Item: String; const Key: string; var Continue: Boolean);
+begin
+  Continue := Key <> KEYS[TERMINATE_KEY_ID];
+end;
+
+
+type
+  TTestObject = class
+  private
+    FStr: string;
+  public
+    constructor Create(const S: string);
+    property Str: string read FStr;
+  end;
+
+constructor TTestObject.Create(const S: string);
+begin
+  FStr := S;
+end;
+
+
+procedure ObjectStaticIterator(Item: TObject; const Key: string; var Continue: Boolean);
+begin
+  Assert(Key = TTestObject(Item).Str);
+  Continue := TRUE;
+end;
+
+procedure ObjectStaticIteratorTerminated(Item: TObject; const Key: string; var Continue: Boolean);
+begin
+  Continue := Key <> KEYS[TERMINATE_KEY_ID];
+end;
+
+
+var
+  i: integer;
+  data_hash_table: TFPDataHashTable;
+  last_data: pointer;
+  string_hash_table: TFPStringHashTable;
+  last_string: string;
+  object_hash_table: TFPObjectHashTable;
+  last_object: TTestObject;
+
+begin
+  data_hash_table := TFPDataHashTable.Create;
+  for i := 0 to High(KEYS) do
+    data_hash_table.Add(KEYS[i], @KEYS[i]);
+
+  last_data := data_hash_table.Iterate(@DataStaticIterator);
+  Assert(last_data = NIL);
+  last_data := data_hash_table.Iterate(@DataStaticIteratorTerminated);
+  Assert(last_data = @KEYS[TERMINATE_KEY_ID]);
+
+  data_hash_table.Free;
+
+  string_hash_table := TFPStringHashTable.Create;
+  for i := 0 to High(KEYS) do
+    string_hash_table.Add(KEYS[i], KEYS[i]);
+
+  last_string := string_hash_table.Iterate(@StringStaticIterator);
+  Assert(last_string = '');
+  last_string := string_hash_table.Iterate(@StringStaticIteratorTerminated);
+  Assert(last_string = KEYS[TERMINATE_KEY_ID]);
+
+  string_hash_table.Free;
+
+  object_hash_table := TFPObjectHashTable.Create(TRUE);
+  for i := 0 to High(KEYS) do
+    object_hash_table.Add(KEYS[i], TTestObject.Create(KEYS[i]));
+
+  last_object := TTestObject(object_hash_table.Iterate(@ObjectStaticIterator));
+  Assert(last_object = NIL);
+  last_object := TTestObject(object_hash_table.Iterate(@ObjectStaticIteratorTerminated));
+  Assert(last_object.Str = KEYS[TERMINATE_KEY_ID]);
+
+  object_hash_table.Free;
+
+  WriteLn('All is OK');
+end.

+ 50 - 0
packages/fcl-base/src/contnrs.pp

@@ -412,10 +412,15 @@ type
   THTNode = THTDataNode;
   THTNode = THTDataNode;
 
 
   TDataIteratorMethod = Procedure(Item: Pointer; const Key: string; var Continue: Boolean) of object;
   TDataIteratorMethod = Procedure(Item: Pointer; const Key: string; var Continue: Boolean) of object;
+  TDataIteratorCallBack = Procedure(Item: Pointer; const Key: string; var Continue: Boolean);
+
   // For compatibility
   // For compatibility
   TIteratorMethod = TDataIteratorMethod;
   TIteratorMethod = TDataIteratorMethod;
 
 
   TFPDataHashTable = Class(TFPCustomHashTable)
   TFPDataHashTable = Class(TFPCustomHashTable)
+  Private
+    FIteratorCallBack: TDataIteratorCallBack;
+    Procedure CallbackIterator(Item: Pointer; const Key: string; var Continue: Boolean);
   Protected
   Protected
     Function CreateNewNode(const aKey : String) : THTCustomNode; override;
     Function CreateNewNode(const aKey : String) : THTCustomNode; override;
     Procedure AddNode(ANode : THTCustomNode); override;
     Procedure AddNode(ANode : THTCustomNode); override;
@@ -424,6 +429,7 @@ type
     Function ForEachCall(aMethod: TDataIteratorMethod): THTDataNode; virtual;
     Function ForEachCall(aMethod: TDataIteratorMethod): THTDataNode; virtual;
   Public
   Public
     Function Iterate(aMethod: TDataIteratorMethod): Pointer; virtual;
     Function Iterate(aMethod: TDataIteratorMethod): Pointer; virtual;
+    Function Iterate(aMethod: TDataIteratorCallBack): Pointer; virtual;
     Procedure Add(const aKey: string; AItem: pointer); virtual;
     Procedure Add(const aKey: string; AItem: pointer); virtual;
     property Items[const index: string]: Pointer read GetData write SetData; default;
     property Items[const index: string]: Pointer read GetData write SetData; default;
   end;
   end;
@@ -435,9 +441,14 @@ type
   public
   public
     property Data: String read FData write FData;
     property Data: String read FData write FData;
   end;
   end;
+  
   TStringIteratorMethod = Procedure(Item: String; const Key: string; var Continue: Boolean) of object;
   TStringIteratorMethod = Procedure(Item: String; const Key: string; var Continue: Boolean) of object;
+  TStringIteratorCallback = Procedure(Item: String; const Key: string; var Continue: Boolean);
 
 
   TFPStringHashTable = Class(TFPCustomHashTable)
   TFPStringHashTable = Class(TFPCustomHashTable)
+  Private
+    FIteratorCallBack: TStringIteratorCallback;
+    Procedure CallbackIterator(Item: String; const Key: string; var Continue: Boolean);
   Protected
   Protected
     Function CreateNewNode(const aKey : String) : THTCustomNode; override;
     Function CreateNewNode(const aKey : String) : THTCustomNode; override;
     Procedure AddNode(ANode : THTCustomNode); override;
     Procedure AddNode(ANode : THTCustomNode); override;
@@ -446,6 +457,7 @@ type
     Function ForEachCall(aMethod: TStringIteratorMethod): THTStringNode; virtual;
     Function ForEachCall(aMethod: TStringIteratorMethod): THTStringNode; virtual;
   Public
   Public
     Function Iterate(aMethod: TStringIteratorMethod): String; virtual;
     Function Iterate(aMethod: TStringIteratorMethod): String; virtual;
+    Function Iterate(aMethod: TStringIteratorCallback): String; virtual;
     Procedure Add(const aKey,aItem: string); virtual;
     Procedure Add(const aKey,aItem: string); virtual;
     property Items[const index: string]: String read GetData write SetData; default;
     property Items[const index: string]: String read GetData write SetData; default;
   end;
   end;
@@ -464,11 +476,15 @@ type
   public
   public
     destructor Destroy; override;
     destructor Destroy; override;
   end;
   end;
+
   TObjectIteratorMethod = Procedure(Item: TObject; const Key: string; var Continue: Boolean) of object;
   TObjectIteratorMethod = Procedure(Item: TObject; const Key: string; var Continue: Boolean) of object;
+  TObjectIteratorCallback = Procedure(Item: TObject; const Key: string; var Continue: Boolean);
 
 
   TFPObjectHashTable = Class(TFPCustomHashTable)
   TFPObjectHashTable = Class(TFPCustomHashTable)
   Private
   Private
     FOwnsObjects : Boolean;
     FOwnsObjects : Boolean;
+    FIteratorCallBack: TObjectIteratorCallback;
+    procedure CallbackIterator(Item: TObject; const Key: string; var Continue: Boolean);
   Protected
   Protected
     Function CreateNewNode(const aKey : String) : THTCustomNode; override;
     Function CreateNewNode(const aKey : String) : THTCustomNode; override;
     Procedure AddNode(ANode : THTCustomNode); override;
     Procedure AddNode(ANode : THTCustomNode); override;
@@ -479,6 +495,7 @@ type
     constructor Create(AOwnsObjects : Boolean = True);
     constructor Create(AOwnsObjects : Boolean = True);
     constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
     constructor CreateWith(AHashTableSize: Longword; aHashFunc: THashFunction; AOwnsObjects : Boolean = True);
     Function Iterate(aMethod: TObjectIteratorMethod): TObject; virtual;
     Function Iterate(aMethod: TObjectIteratorMethod): TObject; virtual;
+    Function Iterate(aMethod: TObjectIteratorCallback): TObject; virtual;
     Procedure Add(const aKey: string; AItem : TObject); virtual;
     Procedure Add(const aKey: string; AItem : TObject); virtual;
     property Items[const index: string]: TObject read GetData write SetData; default;
     property Items[const index: string]: TObject read GetData write SetData; default;
     Property OwnsObjects : Boolean Read FOwnsObjects;
     Property OwnsObjects : Boolean Read FOwnsObjects;
@@ -2242,6 +2259,17 @@ begin
     Result:=nil;
     Result:=nil;
 end;
 end;
 
 
+Procedure TFPDataHashTable.CallbackIterator(Item: Pointer; const Key: string; var Continue: Boolean);
+begin
+  FIteratorCallBack(Item, Key, Continue);
+end;
+
+Function TFPDataHashTable.Iterate(aMethod: TDataIteratorCallBack): Pointer;
+begin
+  FIteratorCallBack := aMethod;
+  Result := Iterate(@CallbackIterator);
+end;
+
 Function TFPDataHashTable.ForEachCall(aMethod: TDataIteratorMethod): THTDataNode;
 Function TFPDataHashTable.ForEachCall(aMethod: TDataIteratorMethod): THTDataNode;
 var
 var
   i, j: Longword;
   i, j: Longword;
@@ -2321,6 +2349,17 @@ begin
     Result:='';
     Result:='';
 end;
 end;
 
 
+Procedure TFPStringHashTable.CallbackIterator(Item: String; const Key: string; var Continue: Boolean);
+begin
+  FIteratorCallBack(Item, Key, Continue);
+end;
+
+Function TFPStringHashTable.Iterate(aMethod: TStringIteratorCallback): String;
+begin
+  FIteratorCallBack := aMethod;
+  Result := Iterate(@CallbackIterator);
+end;
+
 Function TFPStringHashTable.ForEachCall(aMethod: TStringIteratorMethod): THTStringNode;
 Function TFPStringHashTable.ForEachCall(aMethod: TStringIteratorMethod): THTStringNode;
 var
 var
   i, j: Longword;
   i, j: Longword;
@@ -2398,6 +2437,17 @@ begin
     Result:=nil;
     Result:=nil;
 end;
 end;
 
 
+Procedure TFPObjectHashTable.CallbackIterator(Item: TObject; const Key: string; var Continue: Boolean);
+begin
+  FIteratorCallBack(Item, Key, Continue);
+end;
+
+Function TFPObjectHashTable.Iterate(aMethod: TObjectIteratorCallback): TObject;
+begin
+  FIteratorCallBack := aMethod;
+  Result := Iterate(@CallbackIterator);
+end;
+
 Function TFPObjectHashTable.ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode;
 Function TFPObjectHashTable.ForEachCall(aMethod: TObjectIteratorMethod): THTObjectNode;
 var
 var
   i, j: Longword;
   i, j: Longword;