mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 04:21:36 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			602 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			602 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|  ***************************************************************************
 | |
|  *                                                                         *
 | |
|  *   This source is free software; you can redistribute it and/or modify   *
 | |
|  *   it under the terms of the GNU General Public License as published by  *
 | |
|  *   the Free Software Foundation; either version 2 of the License, or     *
 | |
|  *   (at your option) any later version.                                   *
 | |
|  *                                                                         *
 | |
|  *   This code is distributed in the hope that it will be useful, but      *
 | |
|  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 | |
|  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 | |
|  *   General Public License for more details.                              *
 | |
|  *                                                                         *
 | |
|  *   A copy of the GNU General Public License is available on the World    *
 | |
|  *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
 | |
|  *   obtain it by writing to the Free Software Foundation,                 *
 | |
|  *   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA.   *
 | |
|  *                                                                         *
 | |
|  ***************************************************************************
 | |
| 
 | |
|   Author: Mattias Gaertner
 | |
| 
 | |
|   Abstract:
 | |
|     Most codetools returns simple values like a single code position or a
 | |
|     string. But some creates lists of data.
 | |
|     This unit provides structures for complex results.
 | |
| }
 | |
| unit CodeToolsStructs;
 | |
| 
 | |
| {$mode objfpc}{$H+}
 | |
| 
 | |
| interface
 | |
| 
 | |
| uses
 | |
|   Classes, SysUtils, Laz_AVL_Tree,
 | |
|   // LazUtils
 | |
|   LazUtilities, LazDbgLog, AvgLvlTree,
 | |
|   // Codetools
 | |
|   BasicCodeTools;
 | |
| 
 | |
| type
 | |
|   TResourcestringInsertPolicy = (
 | |
|     rsipNone,          // do not add/insert
 | |
|     rsipAppend,        // append at end
 | |
|     rsipAlphabetically,// insert alphabetically
 | |
|     rsipContext        // insert context sensitive
 | |
|     );
 | |
| 
 | |
|   TPascalClassSection = (
 | |
|     pcsPrivate,
 | |
|     pcsProtected,
 | |
|     pcsPublic,
 | |
|     pcsPublished
 | |
|     );
 | |
|   TPascalClassSections = set of TPascalClassSection;
 | |
|   
 | |
| const
 | |
|   AllPascalClassSections = [low(TPascalClassSection)..high(TPascalClassSection)];
 | |
|   
 | |
| const
 | |
|   PascalClassSectionKeywords: array[TPascalClassSection] of string = (
 | |
|     'private',
 | |
|     'protected',
 | |
|     'public',
 | |
|     'published'
 | |
|     );
 | |
| 
 | |
| type
 | |
| 
 | |
|   { TMTAVLTreeNodeMemManager }
 | |
| 
 | |
|   TMTAVLTreeNodeMemManager = class(TAVLTreeNodeMemManager)
 | |
|   public
 | |
|     procedure DisposeNode(ANode: TAVLTreeNode); override;
 | |
|     function NewNode: TAVLTreeNode; override;
 | |
|   end;
 | |
| 
 | |
|   { TMTAVLTree - TAVLTree with a multithreaded node manager }
 | |
| 
 | |
|   TMTAVLTree = class(TAVLTree)
 | |
|   protected
 | |
|     fNodeManager: TAVLTreeNodeMemManager;
 | |
|   public
 | |
|     constructor Create(OnCompareMethod: TListSortCompare);
 | |
|     destructor Destroy; override;
 | |
|   end;
 | |
| 
 | |
|   TPointerToPointerItem = record
 | |
|     Key, Value: Pointer;
 | |
|   end;
 | |
|   PPointerToPointerItem = ^TPointerToPointerItem;
 | |
| 
 | |
|   { TPointerToPointerTree }
 | |
| 
 | |
|   TPointerToPointerTree = class
 | |
|   private
 | |
|     FTree: TAVLTree;// tree of PPointerToPointerItem
 | |
|     function GetItems(Key: Pointer): Pointer;
 | |
|     procedure SetItems(Key: Pointer; AValue: Pointer);
 | |
|   protected
 | |
|     procedure DisposeItem(p: PPointerToPointerItem); virtual;
 | |
|   public
 | |
|     constructor Create;
 | |
|     destructor Destroy; override;
 | |
|     procedure Clear; virtual;
 | |
|     function Contains(Key: Pointer): boolean;
 | |
|     procedure Remove(Key: Pointer); virtual;
 | |
|     property Tree: TAVLTree read FTree; // tree of PPointerToPointerItem
 | |
|     function GetNodeData(AVLNode: TAVLTreeNode): PPointerToPointerItem; inline;
 | |
|     function Count: integer;
 | |
|     function FindNode(Key: Pointer): TAVLTreeNode;
 | |
|     procedure Add(Key, Value: Pointer); virtual;
 | |
|     property Items[Key: Pointer]: Pointer read GetItems write SetItems; default;
 | |
|   end;
 | |
| 
 | |
|   { TIdentStringToStringTree }
 | |
| 
 | |
|   TIdentStringToStringTree = class(TStringToStringTree)
 | |
|   private
 | |
|   protected
 | |
|   public
 | |
|     function FindNodeWithIdentifierAsPrefix(P: PChar): TAVLTreeNode;
 | |
|   end;
 | |
| 
 | |
|   TStringTree = class;
 | |
| 
 | |
|   { TStringTreeEnumerator }
 | |
| 
 | |
|   TStringTreeEnumerator = class
 | |
|   private
 | |
|     FTree: TStringTree;
 | |
|     FCurrent: TAVLTreeNode;
 | |
|     function GetCurrent: string;
 | |
|   public
 | |
|     constructor Create(Tree: TStringTree);
 | |
|     function MoveNext: boolean;
 | |
|     property Current: string read GetCurrent;
 | |
|   end;
 | |
| 
 | |
|   { TStringTree }
 | |
| 
 | |
|   TStringTree = class
 | |
|   public
 | |
|     Tree: TAVLTree;
 | |
|     constructor Create;
 | |
|     destructor Destroy; override;
 | |
|     procedure Clear;
 | |
|     function FindNode(const s: string): TAVLTreeNode; inline;
 | |
|     procedure ReplaceString(var s: string);
 | |
|     function CalcMemSize: PtrUInt;
 | |
|     function GetEnumerator: TStringTreeEnumerator;
 | |
|   end;
 | |
| 
 | |
| type
 | |
|   TCTComponentAccess = class(TComponent);
 | |
| 
 | |
|   { TComponentChildCollector }
 | |
| 
 | |
|   TComponentChildCollector = class
 | |
|   private
 | |
|     FChildren: TFPList;
 | |
|     FRoot: TComponent;
 | |
|     procedure AddChildComponent(Child: TComponent);
 | |
|   public
 | |
|     constructor Create;
 | |
|     destructor Destroy; override;
 | |
|     function GetComponents(RootComponent: TComponent; AddRoot: boolean = true): TFPList;
 | |
|     property Children: TFPList read FChildren;
 | |
|     property Root: TComponent read FRoot;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| function ComparePointerToPointerItems(Data1, Data2: Pointer): integer;
 | |
| function ComparePointerAndP2PItem(Key, Data: Pointer): integer;
 | |
| 
 | |
| // case sensitive
 | |
| //function CompareStringToStringItems(Data1, Data2: Pointer): integer;
 | |
| //function CompareStringAndStringToStringTreeItem(Key, Data: Pointer): integer;
 | |
| //function CompareIdentifierAndStringToStringTreeItem(Identifier, Data: Pointer): integer;
 | |
| function CompareIdentifierPrefixAndStringToStringTreeItem(Identifier, Data: Pointer): integer;
 | |
| 
 | |
| // case insensitive
 | |
| //function CompareStringToStringItemsI(Data1, Data2: Pointer): integer;
 | |
| //function CompareStringAndStringToStringTreeItemI(Key, Data: Pointer): integer;
 | |
| //function CompareIdentifierAndStringToStringTreeItemI(Identifier, Data: Pointer): integer;
 | |
| function CompareIdentifierPrefixAndStringToStringTreeItemI(Identifier, Data: Pointer): integer;
 | |
| 
 | |
| //function CompareFilenameToStringItems(Data1, Data2: Pointer): integer;
 | |
| //function CompareFilenameAndFilenameToStringTreeItem(Key, Data: Pointer): integer;
 | |
| 
 | |
| //function CompareFilenameToStringItemsI(Data1, Data2: Pointer): integer;
 | |
| //function CompareFilenameAndFilenameToStringTreeItemI(Key, Data: Pointer): integer;
 | |
| 
 | |
| function CompareAnsiStringPtrs(Data1, Data2: Pointer): integer;
 | |
| 
 | |
| function AVLFindPointer(Tree: TAVLTree; Data: Pointer): TAVLTreeNode; inline;
 | |
| procedure AVLRemovePointer(Tree: TAVLTree; Data: Pointer); inline;
 | |
| 
 | |
| implementation
 | |
| 
 | |
| function ComparePointerToPointerItems(Data1, Data2: Pointer): integer;
 | |
| var
 | |
|   P2PItem1: PPointerToPointerItem absolute Data1;
 | |
|   P2PItem2: PPointerToPointerItem absolute Data2;
 | |
| begin
 | |
|   Result:=ComparePointers(P2PItem1^.Key,P2PItem2^.Key);
 | |
| end;
 | |
| 
 | |
| function ComparePointerAndP2PItem(Key, Data: Pointer): integer;
 | |
| var
 | |
|   P2PItem: PPointerToPointerItem absolute Data;
 | |
| begin
 | |
|   Result:=ComparePointers(Key,P2PItem^.Key);
 | |
| end;
 | |
| {
 | |
| function CompareStringToStringItems(Data1, Data2: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareStr(PStringToStringTreeItem(Data1)^.Name,
 | |
|                      PStringToStringTreeItem(Data2)^.Name);
 | |
| end;
 | |
| 
 | |
| function CompareStringToStringItemsI(Data1, Data2: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareText(PStringToStringTreeItem(Data1)^.Name,
 | |
|                       PStringToStringTreeItem(Data2)^.Name);
 | |
| end;
 | |
| 
 | |
| function CompareFilenameToStringItems(Data1, Data2: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareFilenames(PStringToStringTreeItem(Data1)^.Name,
 | |
|                            PStringToStringTreeItem(Data2)^.Name);
 | |
| end;
 | |
| 
 | |
| function CompareStringAndStringToStringTreeItem(Key, Data: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareStr(String(Key),PStringToStringTreeItem(Data)^.Name);
 | |
| end;
 | |
| 
 | |
| function CompareIdentifierAndStringToStringTreeItem(Identifier, Data: Pointer
 | |
|   ): integer;
 | |
| var
 | |
|   Id: PChar absolute Identifier;
 | |
|   Item: PStringToStringTreeItem absolute Data;
 | |
|   IdLen: LongInt;
 | |
|   ItemLen: PtrInt;
 | |
| begin
 | |
|   Result:=-CompareIdentifiersCaseSensitive(Id,PChar(Item^.Name));
 | |
|   if Result=0 then begin
 | |
|     IdLen:=GetIdentLen(Id);
 | |
|     ItemLen:=length(Item^.Name);
 | |
|     if IdLen=Itemlen then
 | |
|       Result:=0
 | |
|     else if IdLen>ItemLen then
 | |
|       Result:=1
 | |
|     else
 | |
|       Result:=-1;
 | |
|   end;
 | |
| end;
 | |
| }
 | |
| function CompareIdentifierPrefixAndStringToStringTreeItem(Identifier, Data: Pointer): integer;
 | |
| var
 | |
|   Id: PChar absolute Identifier;
 | |
|   Item: PStringToStringItem absolute Data;
 | |
| begin
 | |
|   Result:=-CompareIdentifiersCaseSensitive(Id,PChar(Item^.Name));
 | |
| end;
 | |
| {
 | |
| function CompareStringAndStringToStringTreeItemI(Key, Data: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareText(String(Key),PStringToStringTreeItem(Data)^.Name);
 | |
| end;
 | |
| 
 | |
| function CompareIdentifierAndStringToStringTreeItemI(Identifier, Data: Pointer
 | |
|   ): integer;
 | |
| var
 | |
|   Id: PChar absolute Identifier;
 | |
|   Item: PStringToStringTreeItem absolute Data;
 | |
|   IdLen: LongInt;
 | |
|   ItemLen: PtrInt;
 | |
| begin
 | |
|   Result:=-CompareIdentifiers(Id,PChar(Item^.Name));
 | |
|   if Result=0 then begin
 | |
|     IdLen:=GetIdentLen(Id);
 | |
|     ItemLen:=length(Item^.Name);
 | |
|     if IdLen=Itemlen then
 | |
|       Result:=0
 | |
|     else if IdLen>ItemLen then
 | |
|       Result:=1
 | |
|     else
 | |
|       Result:=-1;
 | |
|   end;
 | |
| end;
 | |
| }
 | |
| function CompareIdentifierPrefixAndStringToStringTreeItemI(Identifier, Data: Pointer): integer;
 | |
| var
 | |
|   Id: PChar absolute Identifier;
 | |
|   Item: PStringToStringItem absolute Data;
 | |
| begin
 | |
|   Result:=-CompareIdentifiers(Id,PChar(Item^.Name));
 | |
| end;
 | |
| {
 | |
| function CompareFilenameAndFilenameToStringTreeItem(Key, Data: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareFilenames(String(Key),PStringToStringTreeItem(Data)^.Name);
 | |
| end;
 | |
| 
 | |
| function CompareFilenameToStringItemsI(Data1, Data2: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareFilenamesIgnoreCase(PStringToStringTreeItem(Data1)^.Name,
 | |
|                                      PStringToStringTreeItem(Data2)^.Name);
 | |
| end;
 | |
| 
 | |
| function CompareFilenameAndFilenameToStringTreeItemI(Key, Data: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareFilenamesIgnoreCase(String(Key),
 | |
|                                      PStringToStringTreeItem(Data)^.Name);
 | |
| end;
 | |
| }
 | |
| function CompareAnsiStringPtrs(Data1, Data2: Pointer): integer;
 | |
| begin
 | |
|   Result:=CompareStr(AnsiString(Data1),AnsiString(Data2));
 | |
| end;
 | |
| 
 | |
| function AVLFindPointer(Tree: TAVLTree; Data: Pointer): TAVLTreeNode;
 | |
| begin
 | |
|   Result:=Tree.FindPointer(Data);
 | |
| end;
 | |
| 
 | |
| procedure AVLRemovePointer(Tree: TAVLTree; Data: Pointer);
 | |
| begin
 | |
|   Tree.RemovePointer(Data);
 | |
| end;
 | |
| 
 | |
| { TPointerToPointerTree }
 | |
| 
 | |
| function TPointerToPointerTree.GetItems(Key: Pointer): Pointer;
 | |
| var
 | |
|   Node: TAVLTreeNode;
 | |
| begin
 | |
|   Node:=FindNode(Key);
 | |
|   if Node<>nil then
 | |
|     Result:=PPointerToPointerItem(Node.Data)^.Value
 | |
|   else
 | |
|     Result:=nil;
 | |
| end;
 | |
| 
 | |
| procedure TPointerToPointerTree.SetItems(Key: Pointer; AValue: Pointer);
 | |
| var
 | |
|   Node: TAVLTreeNode;
 | |
|   NewItem: PPointerToPointerItem;
 | |
| begin
 | |
|   Node:=FindNode(Key);
 | |
|   if Node<>nil then begin
 | |
|     PPointerToPointerItem(Node.Data)^.Value:=AValue;
 | |
|   end else begin
 | |
|     New(NewItem);
 | |
|     NewItem^.Key:=Key;
 | |
|     NewItem^.Value:=AValue;
 | |
|     FTree.Add(NewItem);
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TPointerToPointerTree.DisposeItem(p: PPointerToPointerItem);
 | |
| begin
 | |
|   Dispose(p);
 | |
| end;
 | |
| 
 | |
| constructor TPointerToPointerTree.Create;
 | |
| begin
 | |
|   FTree:=TMTAVLTree.Create(@ComparePointerToPointerItems);
 | |
| end;
 | |
| 
 | |
| destructor TPointerToPointerTree.Destroy;
 | |
| begin
 | |
|   Clear;
 | |
|   FreeAndNil(FTree);
 | |
|   inherited Destroy;
 | |
| end;
 | |
| 
 | |
| procedure TPointerToPointerTree.Clear;
 | |
| var
 | |
|   Node: TAVLTreeNode;
 | |
| begin
 | |
|   Node:=FTree.FindLowest;
 | |
|   while Node<>nil do begin
 | |
|     DisposeItem(PPointerToPointerItem(Node.Data));
 | |
|     Node:=FTree.FindSuccessor(Node);
 | |
|   end;
 | |
|   FTree.Clear;
 | |
| end;
 | |
| 
 | |
| function TPointerToPointerTree.Contains(Key: Pointer): boolean;
 | |
| begin
 | |
|   Result:=FindNode(Key)<>nil;
 | |
| end;
 | |
| 
 | |
| procedure TPointerToPointerTree.Remove(Key: Pointer);
 | |
| var
 | |
|   Node: TAVLTreeNode;
 | |
|   Item: PPointerToPointerItem;
 | |
| begin
 | |
|   Node:=FindNode(Key);
 | |
|   if Node<>nil then begin
 | |
|     Item:=PPointerToPointerItem(Node.Data);
 | |
|     FTree.Delete(Node);
 | |
|     DisposeItem(Item);
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function TPointerToPointerTree.GetNodeData(AVLNode: TAVLTreeNode): PPointerToPointerItem;
 | |
| begin
 | |
|   Result:=PPointerToPointerItem(AVLNode.Data);
 | |
| end;
 | |
| 
 | |
| function TPointerToPointerTree.Count: integer;
 | |
| begin
 | |
|   Result:=FTree.Count;
 | |
| end;
 | |
| 
 | |
| function TPointerToPointerTree.FindNode(Key: Pointer): TAVLTreeNode;
 | |
| begin
 | |
|   Result:=FTree.FindKey(Key,@ComparePointerAndP2PItem);
 | |
| end;
 | |
| 
 | |
| procedure TPointerToPointerTree.Add(Key, Value: Pointer);
 | |
| begin
 | |
|   Items[Key]:=Value;
 | |
| end;
 | |
| 
 | |
| { TMTAVLTree }
 | |
| 
 | |
| constructor TMTAVLTree.Create(OnCompareMethod: TListSortCompare);
 | |
| begin
 | |
|   inherited Create(OnCompareMethod);
 | |
|   fNodeManager:=TMTAVLTreeNodeMemManager.Create;
 | |
|   SetNodeManager(fNodeManager);
 | |
| end;
 | |
| 
 | |
| destructor TMTAVLTree.Destroy;
 | |
| begin
 | |
|   inherited Destroy;
 | |
|   FreeAndNil(fNodeManager);
 | |
| end;
 | |
| 
 | |
| { TMTAVLTreeNodeMemManager }
 | |
| 
 | |
| procedure TMTAVLTreeNodeMemManager.DisposeNode(ANode: TAVLTreeNode);
 | |
| begin
 | |
|   ANode.Free;
 | |
| end;
 | |
| 
 | |
| function TMTAVLTreeNodeMemManager.NewNode: TAVLTreeNode;
 | |
| begin
 | |
|   Result:=TAVLTreeNode.Create;
 | |
| end;
 | |
| 
 | |
| { TIdentStringToStringTree }
 | |
| 
 | |
| function TIdentStringToStringTree.FindNodeWithIdentifierAsPrefix(P: PChar): TAVLTreeNode;
 | |
| begin
 | |
|   if CaseSensitive then
 | |
|     Result:=Tree.FindKey(p,@CompareIdentifierPrefixAndStringToStringTreeItem)
 | |
|   else
 | |
|     Result:=Tree.FindKey(p,@CompareIdentifierPrefixAndStringToStringTreeItemI);
 | |
| end;
 | |
| 
 | |
| { TStringTreeEnumerator }
 | |
| 
 | |
| function TStringTreeEnumerator.GetCurrent: string;
 | |
| begin
 | |
|   Result:=AnsiString(FCurrent.Data);
 | |
| end;
 | |
| 
 | |
| constructor TStringTreeEnumerator.Create(Tree: TStringTree);
 | |
| begin
 | |
|   FTree:=Tree;
 | |
| end;
 | |
| 
 | |
| function TStringTreeEnumerator.MoveNext: boolean;
 | |
| begin
 | |
|   if FCurrent=nil then
 | |
|     FCurrent:=FTree.Tree.FindLowest
 | |
|   else
 | |
|     FCurrent:=FTree.Tree.FindSuccessor(FCurrent);
 | |
|   Result:=FCurrent<>nil;
 | |
| end;
 | |
| 
 | |
| { TStringTree }
 | |
| 
 | |
| constructor TStringTree.Create;
 | |
| begin
 | |
|   Tree:=TMTAVLTree.Create(@CompareAnsiStringPtrs);
 | |
| end;
 | |
| 
 | |
| destructor TStringTree.Destroy;
 | |
| begin
 | |
|   Clear;
 | |
|   FreeAndNil(Tree);
 | |
|   inherited Destroy;
 | |
| end;
 | |
| 
 | |
| procedure TStringTree.Clear;
 | |
| var
 | |
|   Node: TAVLTreeNode;
 | |
| begin
 | |
|   Node:=Tree.FindLowest;
 | |
|   while Node<>nil do begin
 | |
|     AnsiString(Node.Data):='';
 | |
|     Node:=Tree.FindSuccessor(Node);
 | |
|   end;
 | |
|   Tree.Clear;
 | |
| end;
 | |
| 
 | |
| function TStringTree.FindNode(const s: string): TAVLTreeNode;
 | |
| begin
 | |
|   Result:=Tree.Find(Pointer(s));
 | |
| end;
 | |
| 
 | |
| procedure TStringTree.ReplaceString(var s: string);
 | |
| var
 | |
|   Node: TAVLTreeNode;
 | |
|   h: String;
 | |
| begin
 | |
|   if GetStringRefCount(s)<=0 then exit;
 | |
|   Node:=FindNode(s);
 | |
|   if Node=nil then begin
 | |
|     // increase refcount
 | |
|     h:=s;
 | |
|     Tree.Add(Pointer(h));
 | |
|     Pointer(h):=nil; // keep refcount
 | |
|     //debugln(['TStringTree.ReplaceString new string: refcount=',GetStringRefCount(s)]);
 | |
|     //debugln(['TStringTree.ReplaceString NewString="',dbgstr(s),'"']);
 | |
|   end else begin
 | |
|     s:=AnsiString(Node.Data);
 | |
|     //debugln(['TStringTree.ReplaceString old string: refcount=',GetStringRefCount(s)]);
 | |
|     //debugln(['TStringTree.ReplaceString OldString="',dbgstr(s),'"']);
 | |
|   end;
 | |
|   //debugln(['TStringTree.ReplaceString ',GetStringRefCount(s),' ',Node<>nil]);
 | |
| end;
 | |
| 
 | |
| function TStringTree.CalcMemSize: PtrUInt;
 | |
| var
 | |
|   Node: TAVLTreeNode;
 | |
| begin
 | |
|   Result:=PtrUInt(InstanceSize)
 | |
|     +PtrUInt(Tree.InstanceSize)
 | |
|     +PtrUInt(TAVLTreeNode.InstanceSize)*PtrUInt(Tree.Count);
 | |
|   Node:=Tree.FindLowest;
 | |
|   while Node<>nil do begin
 | |
|     inc(Result,MemSizeString(AnsiString(Node.Data)));
 | |
|     Node:=Tree.FindSuccessor(Node);
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function TStringTree.GetEnumerator: TStringTreeEnumerator;
 | |
| begin
 | |
|   Result:=TStringTreeEnumerator.Create(Self);
 | |
| end;
 | |
| 
 | |
| { TComponentChildCollector }
 | |
| 
 | |
| procedure TComponentChildCollector.AddChildComponent(Child: TComponent);
 | |
| var
 | |
|   OldRoot: TComponent;
 | |
| begin
 | |
|   //debugln(['TComponentChildCollector.AddChildComponent ',DbgSName(Child)]);
 | |
|   Children.Add(Child);
 | |
|   OldRoot := Root;
 | |
|   try
 | |
|     if csInline in Child.ComponentState then
 | |
|       FRoot := Child;
 | |
|     TCTComponentAccess(Child).GetChildren(@AddChildComponent,Root);
 | |
|   finally
 | |
|     FRoot := OldRoot;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| constructor TComponentChildCollector.Create;
 | |
| begin
 | |
|   FChildren:=TFPList.Create;
 | |
| end;
 | |
| 
 | |
| destructor TComponentChildCollector.Destroy;
 | |
| begin
 | |
|   FreeAndNil(FChildren);
 | |
|   inherited Destroy;
 | |
| end;
 | |
| 
 | |
| function TComponentChildCollector.GetComponents(RootComponent: TComponent;
 | |
|   AddRoot: boolean): TFPList;
 | |
| begin
 | |
|   Children.Clear;
 | |
|   if AddRoot then
 | |
|     Children.Add(RootComponent);
 | |
|   FRoot:=RootComponent;
 | |
|   TCTComponentAccess(RootComponent).GetChildren(@AddChildComponent,FRoot);
 | |
|   Result:=Children;
 | |
| end;
 | |
| 
 | |
| end.
 | |
| 
 | 
