浏览代码

rtl: add enumerators to the basic classes
tests: add enumerators test which compiles and work both by fpc and dcc

git-svn-id: branches/paul/features@13909 -

paul 16 年之前
父节点
当前提交
69f50bc594

+ 1 - 0
.gitattributes

@@ -8176,6 +8176,7 @@ tests/test/tcmp0.pp svneol=native#text/plain
 tests/test/tendian1.pp svneol=native#text/plain
 tests/test/tenum1.pp svneol=native#text/plain
 tests/test/tenum2.pp svneol=native#text/plain
+tests/test/tenumerators1.pp svneol=native#text/pascal
 tests/test/testcmem.pp svneol=native#text/plain
 tests/test/testda1.pp svneol=native#text/plain
 tests/test/testfpuc.pp svneol=native#text/plain

+ 78 - 0
rtl/objpas/classes/classesh.inc

@@ -166,6 +166,18 @@ type
 {$IFNDEF FPC_TESTGENERICS}
 
   TListAssignOp = (laCopy, laAnd, laOr, laXor, laSrcUnique, laDestUnique);
+  TFPList = class;
+
+  TFPListEnumerator = class
+  private
+    FList: TFPList;
+    FPosition: Integer;
+  public
+    constructor Create(AList: TFPList);
+    function GetCurrent: Pointer;
+    function MoveNext: Boolean;
+    property Current: Pointer read GetCurrent;
+  end;
 
   TFPList = class(TObject)
   private
@@ -197,6 +209,7 @@ type
     function Expand: TFPList; {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
     function Extract(Item: Pointer): Pointer;
     function First: Pointer;
+    function GetEnumerator: TFPListEnumerator;
     function IndexOf(Item: Pointer): Integer;
     procedure Insert(Index: Integer; Item: Pointer); {$ifdef CLASSESINLINE} inline; {$endif CLASSESINLINE}
     function Last: Pointer;
@@ -228,8 +241,20 @@ type
 {$endif}
 
 { TList class}
+
   TListNotification = (lnAdded, lnExtracted, lnDeleted);
+  TList = class;
 
+  TListEnumerator = class
+  private
+    FList: TList;
+    FPosition: Integer;
+  public
+    constructor Create(AList: TList);
+    function GetCurrent: Pointer;
+    function MoveNext: Boolean;
+    property Current: Pointer read GetCurrent;
+  end;
 
   TList = class(TObject)
   private
@@ -264,6 +289,7 @@ type
     function Expand: TList;
     function Extract(item: Pointer): Pointer;
     function First: Pointer;
+    function GetEnumerator: TListEnumerator;
     function IndexOf(Item: Pointer): Integer;
     procedure Insert(Index: Integer; Item: Pointer);
     function Last: Pointer;
@@ -424,6 +450,17 @@ type
     property DisplayName: string read GetDisplayName write SetDisplayName;
   end;
 
+  TCollectionEnumerator = class
+  private
+    FCollection: TCollection;
+    FPosition: Integer;
+  public
+    constructor Create(ACollection: TCollection);
+    function GetCurrent: TCollectionItem;
+    function MoveNext: Boolean;
+    property Current: TCollectionItem read GetCurrent;
+  end;
+
   TCollectionItemClass = class of TCollectionItem;
   TCollectionNotification = (cnAdded, cnExtracting, cnDeleting);
   TCollectionSortCompare = function (Item1, Item2: TCollectionItem): Integer;
@@ -463,6 +500,7 @@ type
     procedure Clear;
     procedure EndUpdate; virtual;
     procedure Delete(Index: Integer);
+    function GetEnumerator: TCollectionEnumerator;
     function GetNamePath: string; override;
     function Insert(Index: Integer): TCollectionItem;
     function FindItemID(ID: Integer): TCollectionItem;
@@ -492,6 +530,19 @@ type
     procedure ReleaseStrings;
   end;
 
+{ TStringsEnumerator class }
+
+  TStringsEnumerator = class
+  private
+    FStrings: TStrings;
+    FPosition: Integer;
+  public
+    constructor Create(AStrings: TStrings);
+    function GetCurrent: String;
+    function MoveNext: Boolean;
+    property Current: String read GetCurrent;
+  end;
+
 { TStrings class }
 
   TStrings = class(TPersistent)
@@ -551,6 +602,7 @@ type
     procedure EndUpdate;
     function Equals(TheStrings: TStrings): Boolean;
     procedure Exchange(Index1, Index2: Integer); virtual;
+    function GetEnumerator: TStringsEnumerator;
     function GetText: PChar; virtual;
     function IndexOf(const S: string): Integer; virtual;
     function IndexOfName(const Name: string): Integer; virtual;
@@ -1481,6 +1533,17 @@ type
     procedure Notification(AnObject: TPersistent; Operation: TOperation);
   end;
 
+  TComponentEnumerator = class
+  private
+    FComponent: TComponent;
+    FPosition: Integer;
+  public
+    constructor Create(AComponent: TComponent);
+    function GetCurrent: TComponent;
+    function MoveNext: Boolean;
+    property Current: TComponent read GetCurrent;
+  end;
+
   TBasicAction = class;
 
   { TComponent }
@@ -1565,6 +1628,7 @@ type
     procedure FreeNotification(AComponent: TComponent);
     procedure RemoveFreeNotification(AComponent: TComponent);
     procedure FreeOnRelease;
+    function GetEnumerator: TComponentEnumerator;
     function GetNamePath: string; override;
     function GetParentComponent: TComponent; dynamic;
     function HasParent: Boolean; dynamic;
@@ -1672,6 +1736,19 @@ type
     property Items[index : Integer] : IUnknown read Get write Put;default;
   end;
 
+  TInterfaceList = class;
+
+  TInterfaceListEnumerator = class
+  private
+    FList: TInterfaceList;
+    FPosition: Integer;
+  public
+    constructor Create(AList: TInterfaceList);
+    function GetCurrent: IUnknown;
+    function MoveNext: Boolean;
+    property Current: IUnknown read GetCurrent;
+  end;
+
   TInterfaceList = class(TInterfacedObject,IInterfaceList)
   private
     FList : TThreadList;
@@ -1690,6 +1767,7 @@ type
     procedure Delete(index : Integer);
     procedure Exchange(index1,index2 : Integer);
     function First : IUnknown;
+    function GetEnumerator: TInterfaceListEnumerator;
     function IndexOf(item : IUnknown) : Integer;
     function Add(item : IUnknown) : Integer;
     procedure Insert(i : Integer;item : IUnknown);

+ 29 - 0
rtl/objpas/classes/collect.inc

@@ -117,6 +117,29 @@ begin
   Inherited Destroy;
 end;
 
+{****************************************************************************}
+{*                          TCollectionEnumerator                           *}
+{****************************************************************************}
+
+constructor TCollectionEnumerator.Create(ACollection: TCollection);
+begin
+  inherited Create;
+  FCollection := ACollection;
+  FPosition := -1;
+end;
+
+function TCollectionEnumerator.GetCurrent: TCollectionItem;
+begin
+  Result := FCollection.Items[FPosition];
+end;
+
+function TCollectionEnumerator.MoveNext: Boolean;
+begin
+  Inc(FPosition);
+  Result := FPosition < FCollection.Count;
+end;
+
+
 {****************************************************************************}
 {*                             TCollection                                  *}
 {****************************************************************************}
@@ -198,6 +221,12 @@ begin
 end;
 
 
+function TCollection.GetEnumerator: TCollectionEnumerator;
+begin
+  Result := TCollectionEnumerator.Create(Self);
+end;
+
+
 function TCollection.GetNamePath: string;
 var o : TObject;
 begin

+ 29 - 0
rtl/objpas/classes/compon.inc

@@ -11,6 +11,29 @@
 
  **********************************************************************}
 
+{****************************************************************************}
+{*                        TComponentEnumerator                              *}
+{****************************************************************************}
+
+constructor TComponentEnumerator.Create(AComponent: TComponent);
+begin
+  inherited Create;
+  FComponent := AComponent;
+  FPosition := -1;
+end;
+
+function TComponentEnumerator.GetCurrent: TComponent;
+begin
+  Result := FComponent.Components[FPosition];
+end;
+
+function TComponentEnumerator.MoveNext: Boolean;
+begin
+  Inc(FPosition);
+  Result := FPosition < FComponent.ComponentCount;
+end;
+
+
 {****************************************************************************}
 {*                             TComponent                                   *}
 {****************************************************************************}
@@ -207,6 +230,12 @@ begin
 end;
 
 
+Function  TComponent.GetEnumerator: TComponentEnumerator;
+
+begin
+  Result:=TComponentEnumerator.Create(Self);
+end;
+
 Function  TComponent.GetNamePath: string;
 
 begin

+ 29 - 0
rtl/objpas/classes/intf.inc

@@ -10,6 +10,29 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
  **********************************************************************}
+{ TInerfaceListEnumerator }
+
+    constructor TInterfaceListEnumerator.Create(AList: TInterfaceList);
+      begin
+        inherited create;
+        FList:=AList;
+        FPosition:=-1;
+      end;
+
+
+    function TInterfaceListEnumerator.GetCurrent: IUnknown;
+      begin
+        Result:=FList[FPosition];
+      end;
+
+
+    function TInterfaceListEnumerator.MoveNext: Boolean;
+      begin
+        Inc(FPosition);
+        Result:=FPosition<FList.Count;
+      end;
+
+{ TInterfaceList }
 
     constructor TInterfaceList.Create;
       begin
@@ -142,6 +165,12 @@
       end;
 
 
+    function TInterfaceList.GetEnumerator: TInterfaceListEnumerator;
+      begin
+        result:=TInterfaceListEnumerator.Create(Self)
+      end;
+
+
     function TInterfaceList.IndexOf(item : IUnknown) : Integer;
       begin
         FList.Locklist;

+ 52 - 2
rtl/objpas/classes/lists.inc

@@ -13,6 +13,28 @@
 
 {$if defined(VER2_0) or not defined(FPC_TESTGENERICS)}
 
+{****************************************************************************}
+{*                           TFPListEnumerator                              *}
+{****************************************************************************}
+
+constructor TFPListEnumerator.Create(AList: TFPList);
+begin
+  inherited Create;
+  FList := AList;
+  FPosition := -1;
+end;
+
+function TFPListEnumerator.GetCurrent: Pointer;
+begin
+  Result := FList[FPosition];
+end;
+
+function TFPListEnumerator.MoveNext: Boolean;
+begin
+  Inc(FPosition);
+  Result := FPosition < FList.Count;
+end;
+
 {****************************************************************************}
 {*                           TFPList                                        *}
 {****************************************************************************}
@@ -169,6 +191,11 @@ begin
     Result := Items[0];
 end;
 
+function TFPList.GetEnumerator: TFPListEnumerator;
+begin
+  Result := TFPListEnumerator.Create(Self);
+end;
+
 function TFPList.IndexOf(Item: Pointer): Integer;
 begin
   Result := 0;
@@ -480,7 +507,27 @@ end;
 
 {$endif}
 
+{****************************************************************************}
+{*                TListEnumerator                                           *}
+{****************************************************************************}
+
+constructor TListEnumerator.Create(AList: TList);
+begin
+  inherited Create;
+  FList := AList;
+  FPosition := -1;
+end;
+
+function TListEnumerator.GetCurrent: Pointer;
+begin
+  Result := FList[FPosition];
+end;
 
+function TListEnumerator.MoveNext: Boolean;
+begin
+  Inc(FPosition);
+  Result := FPosition < FList.Count;
+end;
 
 {****************************************************************************}
 {*                TList                                                     *}
@@ -491,8 +538,6 @@ end;
     FList: TFPList;
 }
 
-
-
 function TList.Get(Index: Integer): Pointer;
 begin
   Result := FList.Get(Index);
@@ -616,6 +661,11 @@ begin
   Result := FList.First;
 end;
 
+function TList.GetEnumerator: TListEnumerator;
+begin
+  Result := TListEnumerator.Create(Self);
+end;
+
 function TList.IndexOf(Item: Pointer): Integer;
 begin
   Result := FList.IndexOf(Item);

+ 28 - 0
rtl/objpas/classes/stringl.inc

@@ -10,6 +10,29 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
  **********************************************************************}
+
+{****************************************************************************}
+{*                        TStringsEnumerator                                *}
+{****************************************************************************}
+
+constructor TStringsEnumerator.Create(AStrings: TStrings);
+begin
+  inherited Create;
+  FStrings := AStrings;
+  FPosition := -1;
+end;
+
+function TStringsEnumerator.GetCurrent: String;
+begin
+  Result := FStrings[FPosition];
+end;
+
+function TStringsEnumerator.MoveNext: Boolean;
+begin
+  Inc(FPosition);
+  Result := FPosition < FStrings.Count;
+end;
+
 {****************************************************************************}
 {*                             TStrings                                     *}
 {****************************************************************************}
@@ -666,6 +689,11 @@ begin
 end;
 
 
+function TStrings.GetEnumerator: TStringsEnumerator;
+begin
+  Result:=TStringsEnumerator.Create(Self);
+end;
+
 
 Function TStrings.GetText: PChar;
 begin

+ 166 - 0
tests/test/tenumerators1.pp

@@ -0,0 +1,166 @@
+program tenumerators1;
+
+{$ifdef fpc}
+{$mode objfpc}{$H+}
+{$endif}
+{$apptype console}
+uses
+  Classes;
+
+{$ifndef fpc}
+type
+  PtrInt = integer;
+{$endif}
+
+{$ifdef fpc}
+procedure CheckFPListEnumerator;
+var
+  Item: Pointer;
+  List: TFPList;
+  Enumerator: TFPListEnumerator;
+begin
+  // check TFPList enumerator
+  List := TFPList.Create;
+  List.Add(Pointer(1));
+  List.Add(Pointer(2));
+  List.Add(Pointer(3));
+
+  Enumerator := List.GetEnumerator;
+  while Enumerator.MoveNext do
+  begin
+    Item := Enumerator.Current;
+    WriteLn(PtrInt(Item));
+  end;
+  Enumerator.Free;
+  List.Free;
+end;
+{$endif}
+
+procedure CheckListEnumerator;
+var
+  Item: Pointer;
+  List: TList;
+  Enumerator: TListEnumerator;
+begin
+  // check TList enumerator
+  List := TList.Create;
+  List.Add(Pointer(1));
+  List.Add(Pointer(2));
+  List.Add(Pointer(3));
+
+  Enumerator := List.GetEnumerator;
+  while Enumerator.MoveNext do
+  begin
+    Item := Enumerator.Current;
+    WriteLn(PtrInt(Item));
+  end;
+  Enumerator.Free;
+  List.Free;
+end;
+
+procedure CheckCollectionEnumerator;
+var
+  Item: TCollectionItem;
+  Collection: TCollection;
+  Enumerator: TCollectionEnumerator;
+begin
+  // check TCollection enumerator
+  Collection := TCollection.Create(TCollectionItem);
+  Collection.Add;
+  Collection.Add;
+  Collection.Add;
+
+  Enumerator := Collection.GetEnumerator;
+  while Enumerator.MoveNext do
+  begin
+    Item := Enumerator.Current;
+    WriteLn(PtrInt(Item));
+  end;
+  Enumerator.Free;
+  Collection.Free;
+end;
+
+procedure CheckStringsEnumerator;
+var
+  Item: String;
+  Strings: TStrings;
+  Enumerator: TStringsEnumerator;
+begin
+  // check TStrings enumerator
+  Strings := TStringList.Create;
+  Strings.Add('1');
+  Strings.Add('2');
+  Strings.Add('3');
+
+  Enumerator := Strings.GetEnumerator;
+  while Enumerator.MoveNext do
+  begin
+    Item := Enumerator.Current;
+    WriteLn(Item);
+  end;
+  Enumerator.Free;
+  Strings.Free;
+end;
+
+procedure CheckComponentEnumerator;
+var
+  Item: TComponent;
+  Component: TComponent;
+  Enumerator: TComponentEnumerator;
+begin
+  // check TComponent enumerator
+  Component := TComponent.Create(nil);
+  TComponent.Create(Component);
+  TComponent.Create(Component);
+  TComponent.Create(Component);
+
+  Enumerator := Component.GetEnumerator;
+  while Enumerator.MoveNext do
+  begin
+    Item := Enumerator.Current;
+    WriteLn(PtrInt(Item));
+  end;
+  Enumerator.Free;
+  Component.Free;
+end;
+
+procedure CheckInterfaceListEnumerator;
+var
+  Item: IUnknown;
+  List: TInterfaceList;
+  Enumerator: TInterfaceListEnumerator;
+begin
+  // check TInterfaceList enumerator
+  List := TInterfaceList.Create;
+  Item := TInterfacedObject.Create;
+  List.Add(Item);
+  Item := TInterfacedObject.Create;
+  List.Add(Item);
+  Item := TInterfacedObject.Create;
+  List.Add(Item);
+
+  Enumerator := List.GetEnumerator;
+  while Enumerator.MoveNext do
+  begin
+    Item := Enumerator.Current;
+    WriteLn(PtrInt(Item));
+  end;
+  Enumerator.Free;
+  Item := nil;
+  List.Free;
+end;
+
+begin
+{$ifdef fpc}
+  WriteLn('Testing FPC');
+  CheckFPListEnumerator;
+{$else}
+  WriteLn('Testing Delphi');
+{$endif}
+  CheckListEnumerator;
+  CheckCollectionEnumerator;
+  CheckStringsEnumerator;
+  CheckComponentEnumerator;
+  CheckInterfaceListEnumerator;
+end.
+