2
***************************************************************************
4
* This source is free software; you can redistribute it and/or modify *
5
* it under the terms of the GNU General Public License as published by *
6
* the Free Software Foundation; either version 2 of the License, or *
7
* (at your option) any later version. *
9
* This code is distributed in the hope that it will be useful, but *
10
* WITHOUT ANY WARRANTY; without even the implied warranty of *
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12
* General Public License for more details. *
14
* A copy of the GNU General Public License is available on the World *
15
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
16
* obtain it by writing to the Free Software Foundation, *
17
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19
***************************************************************************
21
Author: Mattias Gaertner
24
Most codetools returns simple values like a single code position or a
25
string. But some creates lists of data.
26
This unit provides structures for complex results.
28
unit CodeToolsStructs;
35
Classes, SysUtils, FileProcs, AVL_Tree, BasicCodeTools;
38
TResourcestringInsertPolicy = (
39
rsipNone, // do not add/insert
40
rsipAppend, // append at end
41
rsipAlphabetically,// insert alphabetically
42
rsipContext // insert context sensitive
45
TPascalClassSection = (
51
TPascalClassSections = set of TPascalClassSection;
54
AllPascalClassSections = [low(TPascalClassSection)..high(TPascalClassSection)];
57
PascalClassSectionKeywords: array[TPascalClassSection] of string = (
66
{ TMTAVLTreeNodeMemManager }
68
TMTAVLTreeNodeMemManager = class(TAVLTreeNodeMemManager)
70
procedure DisposeNode(ANode: TAVLTreeNode); override;
71
function NewNode: TAVLTreeNode; override;
74
{ TMTAVLTree - TAVLTree with a multithreaded node manager }
76
TMTAVLTree = class(TAVLTree)
78
fNodeManager: TAVLTreeNodeMemManager;
80
constructor Create(OnCompareMethod: TListSortCompare);
81
destructor Destroy; override;
84
TPointerToPointerItem = record
87
PPointerToPointerItem = ^TPointerToPointerItem;
89
{ TPointerToPointerTree }
91
TPointerToPointerTree = class
93
FTree: TAVLTree;// tree of PPointerToPointerItem
94
function GetItems(Key: Pointer): Pointer;
95
procedure SetItems(Key: Pointer; AValue: Pointer);
97
procedure DisposeItem(p: PPointerToPointerItem); virtual;
100
destructor Destroy; override;
101
procedure Clear; virtual;
102
function Contains(Key: Pointer): boolean;
103
procedure Remove(Key: Pointer); virtual;
104
property Tree: TAVLTree read FTree; // tree of PPointerToPointerItem
105
function GetNodeData(AVLNode: TAVLTreeNode): PPointerToPointerItem; inline;
106
function Count: integer;
107
function FindNode(Key: Pointer): TAVLTreeNode;
108
procedure Add(Key, Value: Pointer); virtual;
109
property Items[Key: Pointer]: Pointer read GetItems write SetItems; default;
114
TStringMapItem = record
117
PStringMapItem = ^TStringMapItem;
119
{ TStringMapEnumerator }
121
TStringMapEnumerator = class
124
FCurrent: TAVLTreeNode;
126
constructor Create(Tree: TAVLTree);
127
function MoveNext: boolean;
128
// "Current" is implemented by the descendant classes
135
FCompareKeyItemFunc: TListSortCompare;
136
FTree: TAVLTree;// tree of PStringMapItem
137
FCaseSensitive: boolean;
138
function GetCompareItemsFunc: TListSortCompare;
140
procedure DisposeItem(p: PStringMapItem); virtual;
141
function ItemsAreEqual(p1, p2: PStringMapItem): boolean; virtual;
142
function CreateCopy(Src: PStringMapItem): PStringMapItem; virtual;
144
constructor Create(TheCaseSensitive: boolean);
145
destructor Destroy; override;
146
procedure Clear; virtual;
147
function Contains(const s: string): boolean;
148
function ContainsIdentifier(P: PChar): boolean;
149
function FindNodeWithIdentifierAsPrefix(P: PChar): TAVLTreeNode;
150
procedure GetNames(List: TStrings);
151
procedure Remove(const Name: string); virtual;
152
property CaseSensitive: boolean read FCaseSensitive;
153
property Tree: TAVLTree read FTree; // tree of PStringMapItem
154
function GetNodeData(AVLNode: TAVLTreeNode): PStringMapItem; inline;
155
function Count: integer;
156
function FindNode(const s: string): TAVLTreeNode;
157
function Equals(OtherTree: TStringMap): boolean; reintroduce;
158
procedure Assign(Source: TStringMap); virtual;
159
procedure WriteDebugReport; virtual;
160
function CalcMemSize: PtrUint; virtual;
161
property CompareItemsFunc: TListSortCompare read GetCompareItemsFunc;
162
property CompareKeyItemFunc: TListSortCompare read FCompareKeyItemFunc;
163
procedure SetCompareFuncs(
164
const NewCompareItemsFunc, NewCompareKeyItemFunc: TListSortCompare);
167
TStringToStringTreeItem = record
171
PStringToStringTreeItem = ^TStringToStringTreeItem;
173
TStringToStringTree = class;
175
{ TStringToStringTreeEnumerator }
177
TStringToStringTreeEnumerator = class(TStringMapEnumerator)
179
function GetCurrent: PStringToStringTreeItem;
181
property Current: PStringToStringTreeItem read GetCurrent;
184
{ TStringToStringTree }
186
TStringToStringTree = class(TStringMap)
188
function GetStrings(const s: string): string;
189
procedure SetStrings(const s: string; const AValue: string);
191
procedure DisposeItem(p: PStringMapItem); override;
192
function ItemsAreEqual(p1, p2: PStringMapItem): boolean; override;
193
function CreateCopy(Src: PStringMapItem): PStringMapItem; override;
195
function GetString(const Name: string; out Value: string): boolean;
196
procedure Add(const Name, Value: string); virtual;
197
property Strings[const s: string]: string read GetStrings write SetStrings; default;
198
function GetNodeData(AVLNode: TAVLTreeNode): PStringToStringTreeItem; inline;
199
function AsText: string;
200
procedure WriteDebugReport; override;
201
function CalcMemSize: PtrUint; override;
202
function GetEnumerator: TStringToStringTreeEnumerator;
205
TStringToPointerTree = class;
207
TStringToPointerTreeItem = record
211
PStringToPointerTreeItem = ^TStringToPointerTreeItem;
213
{ TStringToPointerTreeEnumerator }
215
TStringToPointerTreeEnumerator = class(TStringMapEnumerator)
217
function GetCurrent: PStringToPointerTreeItem;
219
property Current: PStringToPointerTreeItem read GetCurrent;
222
{ TStringToPointerTree - Tree contains PStringToPointerTreeItem }
224
TStringToPointerTree = class(TStringMap)
226
FFreeValues: boolean;
227
function GetItems(const s: string): Pointer;
228
procedure SetItems(const s: string; AValue: Pointer);
230
procedure DisposeItem(p: PStringMapItem); override;
231
function ItemsAreEqual(p1, p2: PStringMapItem): boolean; override;
232
function CreateCopy(Src: PStringMapItem): PStringMapItem; override;
234
function GetItem(const Name: string; out Value: Pointer): boolean;
235
procedure Add(const Name: string; const Value: Pointer); virtual;
236
property Items[const s: string]: Pointer read GetItems write SetItems; default;
237
function GetNodeData(AVLNode: TAVLTreeNode): PStringToPointerTreeItem; inline;
238
procedure Assign(Source: TStringMap); override;
239
function GetEnumerator: TStringToPointerTreeEnumerator;
240
property FreeValues: boolean read FFreeValues write FFreeValues;
243
{ TFilenameToStringTree }
245
TFilenameToStringTree = class(TStringToStringTree)
247
constructor Create(CaseInsensitive: boolean); // false = system default
250
{ TFilenameToPointerTree }
252
TFilenameToPointerTree = class(TStringToPointerTree)
254
constructor Create(CaseInsensitive: boolean); // false = system default
259
{ TStringTreeEnumerator }
261
TStringTreeEnumerator = class
264
FCurrent: TAVLTreeNode;
265
function GetCurrent: string;
267
constructor Create(Tree: TStringTree);
268
function MoveNext: boolean;
269
property Current: string read GetCurrent;
278
destructor Destroy; override;
280
function FindNode(const s: string): TAVLTreeNode; inline;
281
procedure ReplaceString(var s: string);
282
function CalcMemSize: PtrUInt;
283
function GetEnumerator: TStringTreeEnumerator;
287
TCTComponentAccess = class(TComponent);
289
{ TComponentChildCollector }
291
TComponentChildCollector = class
295
procedure AddChildComponent(Child: TComponent);
298
destructor Destroy; override;
299
function GetComponents(RootComponent: TComponent; AddRoot: boolean = true): TFPList;
300
property Children: TFPList read FChildren;
301
property Root: TComponent read FRoot;
305
function ComparePointerToPointerItems(Data1, Data2: Pointer): integer;
306
function ComparePointerAndP2PItem(Key, Data: Pointer): integer;
309
function CompareStringToStringItems(Data1, Data2: Pointer): integer;
310
function CompareStringAndStringToStringTreeItem(Key, Data: Pointer): integer;
311
function CompareIdentifierAndStringToStringTreeItem(Identifier, Data: Pointer): integer;
312
function CompareIdentifierPrefixAndStringToStringTreeItem(Identifier, Data: Pointer): integer;
315
function CompareStringToStringItemsI(Data1, Data2: Pointer): integer;
316
function CompareStringAndStringToStringTreeItemI(Key, Data: Pointer): integer;
317
function CompareIdentifierAndStringToStringTreeItemI(Identifier, Data: Pointer): integer;
318
function CompareIdentifierPrefixAndStringToStringTreeItemI(Identifier, Data: Pointer): integer;
320
function CompareFilenameToStringItems(Data1, Data2: Pointer): integer;
321
function CompareFilenameAndFilenameToStringTreeItem(Key, Data: Pointer): integer;
323
function CompareFilenameToStringItemsI(Data1, Data2: Pointer): integer;
324
function CompareFilenameAndFilenameToStringTreeItemI(Key, Data: Pointer): integer;
326
function CompareAnsiStringPtrs(Data1, Data2: Pointer): integer;
328
{$IF FPC_FULLVERSION<20701}
329
{$DEFINE EnableAVLFindPointerFix}
331
function AVLFindPointer(Tree: TAVLTree; Data: Pointer): TAVLTreeNode; {$IFNDEF EnableAVLFindPointerFix}inline;{$ENDIF}
332
procedure AVLRemovePointer(Tree: TAVLTree; Data: Pointer); {$IFNDEF EnableAVLFindPointerFix}inline;{$ENDIF}
336
function ComparePointerToPointerItems(Data1, Data2: Pointer): integer;
338
P2PItem1: PPointerToPointerItem absolute Data1;
339
P2PItem2: PPointerToPointerItem absolute Data2;
341
Result:=ComparePointers(P2PItem1^.Key,P2PItem2^.Key);
344
function ComparePointerAndP2PItem(Key, Data: Pointer): integer;
346
P2PItem: PPointerToPointerItem absolute Data;
348
Result:=ComparePointers(Key,P2PItem^.Key);
351
function CompareStringToStringItems(Data1, Data2: Pointer): integer;
353
Result:=CompareStr(PStringToStringTreeItem(Data1)^.Name,
354
PStringToStringTreeItem(Data2)^.Name);
357
function CompareStringToStringItemsI(Data1, Data2: Pointer): integer;
359
Result:=CompareText(PStringToStringTreeItem(Data1)^.Name,
360
PStringToStringTreeItem(Data2)^.Name);
363
function CompareFilenameToStringItems(Data1, Data2: Pointer): integer;
365
Result:=CompareFilenames(PStringToStringTreeItem(Data1)^.Name,
366
PStringToStringTreeItem(Data2)^.Name);
369
function CompareStringAndStringToStringTreeItem(Key, Data: Pointer): integer;
371
Result:=CompareStr(String(Key),PStringToStringTreeItem(Data)^.Name);
374
function CompareIdentifierAndStringToStringTreeItem(Identifier, Data: Pointer
377
Id: PChar absolute Identifier;
378
Item: PStringToStringTreeItem absolute Data;
382
Result:=-CompareIdentifiersCaseSensitive(Id,PChar(Item^.Name));
383
if Result=0 then begin
384
IdLen:=GetIdentLen(Id);
385
ItemLen:=length(Item^.Name);
386
if IdLen=Itemlen then
388
else if IdLen>ItemLen then
395
function CompareIdentifierPrefixAndStringToStringTreeItem(Identifier,
396
Data: Pointer): integer;
398
Id: PChar absolute Identifier;
399
Item: PStringToStringTreeItem absolute Data;
401
Result:=-CompareIdentifiersCaseSensitive(Id,PChar(Item^.Name));
404
function CompareStringAndStringToStringTreeItemI(Key, Data: Pointer): integer;
406
Result:=CompareText(String(Key),PStringToStringTreeItem(Data)^.Name);
409
function CompareIdentifierAndStringToStringTreeItemI(Identifier, Data: Pointer
412
Id: PChar absolute Identifier;
413
Item: PStringToStringTreeItem absolute Data;
417
Result:=-CompareIdentifiers(Id,PChar(Item^.Name));
418
if Result=0 then begin
419
IdLen:=GetIdentLen(Id);
420
ItemLen:=length(Item^.Name);
421
if IdLen=Itemlen then
423
else if IdLen>ItemLen then
430
function CompareIdentifierPrefixAndStringToStringTreeItemI(Identifier,
431
Data: Pointer): integer;
433
Id: PChar absolute Identifier;
434
Item: PStringToStringTreeItem absolute Data;
436
Result:=-CompareIdentifiers(Id,PChar(Item^.Name));
439
function CompareFilenameAndFilenameToStringTreeItem(Key, Data: Pointer
442
Result:=CompareFilenames(String(Key),PStringToStringTreeItem(Data)^.Name);
445
function CompareFilenameToStringItemsI(Data1, Data2: Pointer): integer;
447
Result:=CompareFilenamesIgnoreCase(PStringToStringTreeItem(Data1)^.Name,
448
PStringToStringTreeItem(Data2)^.Name);
451
function CompareFilenameAndFilenameToStringTreeItemI(Key, Data: Pointer
454
Result:=CompareFilenamesIgnoreCase(String(Key),
455
PStringToStringTreeItem(Data)^.Name);
458
function CompareAnsiStringPtrs(Data1, Data2: Pointer): integer;
460
Result:=CompareStr(AnsiString(Data1),AnsiString(Data2));
463
function AVLFindPointer(Tree: TAVLTree; Data: Pointer): TAVLTreeNode;
465
{$IFDEF EnableAVLFindPointerFix}
466
Result:=Tree.FindLeftMost(Data);
467
while (Result<>nil) do begin
468
if Result.Data=Data then break;
469
Result:=Tree.FindSuccessor(Result);
470
if Result=nil then exit;
471
if Tree.OnCompare(Data,Result.Data)<>0 then exit(nil);
474
Result:=Tree.FindPointer(Data);
478
procedure AVLRemovePointer(Tree: TAVLTree; Data: Pointer);
479
{$IFDEF EnableAVLFindPointerFix}
484
{$IFDEF EnableAVLFindPointerFix}
485
Node:=AVLFindPointer(Tree,Data);
489
Tree.RemovePointer(Data);
493
{ TPointerToPointerTree }
495
function TPointerToPointerTree.GetItems(Key: Pointer): Pointer;
501
Result:=PPointerToPointerItem(Node.Data)^.Value
506
procedure TPointerToPointerTree.SetItems(Key: Pointer; AValue: Pointer);
509
NewItem: PPointerToPointerItem;
512
if Node<>nil then begin
513
PPointerToPointerItem(Node.Data)^.Value:=AValue;
517
NewItem^.Value:=AValue;
522
procedure TPointerToPointerTree.DisposeItem(p: PPointerToPointerItem);
527
constructor TPointerToPointerTree.Create;
529
FTree:=TMTAVLTree.Create(@ComparePointerToPointerItems);
532
destructor TPointerToPointerTree.Destroy;
539
procedure TPointerToPointerTree.Clear;
543
Node:=FTree.FindLowest;
544
while Node<>nil do begin
545
DisposeItem(PPointerToPointerItem(Node.Data));
546
Node:=FTree.FindSuccessor(Node);
551
function TPointerToPointerTree.Contains(Key: Pointer): boolean;
553
Result:=FindNode(Key)<>nil;
556
procedure TPointerToPointerTree.Remove(Key: Pointer);
559
Item: PPointerToPointerItem;
562
if Node<>nil then begin
563
Item:=PPointerToPointerItem(Node.Data);
569
function TPointerToPointerTree.GetNodeData(AVLNode: TAVLTreeNode
570
): PPointerToPointerItem;
572
Result:=PPointerToPointerItem(AVLNode.Data);
575
function TPointerToPointerTree.Count: integer;
580
function TPointerToPointerTree.FindNode(Key: Pointer): TAVLTreeNode;
582
Result:=FTree.FindKey(Key,@ComparePointerAndP2PItem);
585
procedure TPointerToPointerTree.Add(Key, Value: Pointer);
592
constructor TMTAVLTree.Create(OnCompareMethod: TListSortCompare);
594
inherited Create(OnCompareMethod);
595
fNodeManager:=TMTAVLTreeNodeMemManager.Create;
596
SetNodeManager(fNodeManager);
599
destructor TMTAVLTree.Destroy;
602
FreeAndNil(fNodeManager);
605
{ TMTAVLTreeNodeMemManager }
607
procedure TMTAVLTreeNodeMemManager.DisposeNode(ANode: TAVLTreeNode);
612
function TMTAVLTreeNodeMemManager.NewNode: TAVLTreeNode;
614
Result:=TAVLTreeNode.Create;
617
{ TFilenameToPointerTree }
619
constructor TFilenameToPointerTree.Create(CaseInsensitive: boolean);
621
inherited Create(true);
622
if CaseInsensitive then
623
SetCompareFuncs(@CompareFilenameToStringItemsI,
624
@CompareFilenameAndFilenameToStringTreeItemI)
626
SetCompareFuncs(@CompareFilenameToStringItems,
627
@CompareFilenameAndFilenameToStringTreeItem);
630
{ TStringToPointerTree }
632
function TStringToPointerTree.GetItems(const s: string): Pointer;
638
Result:=PStringToPointerTreeItem(Node.Data)^.Value
643
procedure TStringToPointerTree.SetItems(const s: string; AValue: Pointer);
646
NewItem: PStringToPointerTreeItem;
649
if Node<>nil then begin
650
NewItem:=PStringToPointerTreeItem(Node.Data);
652
TObject(NewItem^.Value).Free;
653
NewItem^.Value:=AValue;
657
NewItem^.Value:=AValue;
662
procedure TStringToPointerTree.DisposeItem(p: PStringMapItem);
664
Item: PStringToPointerTreeItem absolute p;
667
TObject(Item^.Value).Free;
671
function TStringToPointerTree.ItemsAreEqual(p1, p2: PStringMapItem): boolean;
673
Item1: PStringToPointerTreeItem absolute p1;
674
Item2: PStringToPointerTreeItem absolute p2;
676
Result:=(Item1^.Name=Item2^.Name)
677
and (Item1^.Value=Item2^.Value);
680
function TStringToPointerTree.CreateCopy(Src: PStringMapItem): PStringMapItem;
682
SrcItem: PStringToPointerTreeItem absolute Src;
683
NewItem: PStringToPointerTreeItem;
686
NewItem^.Name:=SrcItem^.Name;
687
NewItem^.Value:=SrcItem^.Value;
688
Result:=PStringMapItem(NewItem);
691
function TStringToPointerTree.GetItem(const Name: string; out Value: Pointer
696
Node:=FindNode(Name);
697
if Node<>nil then begin
698
Value:=PStringToPointerTreeItem(Node.Data)^.Value;
705
procedure TStringToPointerTree.Add(const Name: string; const Value: Pointer);
710
function TStringToPointerTree.GetNodeData(AVLNode: TAVLTreeNode
711
): PStringToPointerTreeItem;
713
Result:=PStringToPointerTreeItem(AVLNode.Data);
716
procedure TStringToPointerTree.Assign(Source: TStringMap);
719
Item: PStringToPointerTreeItem;
721
if (Source=nil) or (Source.ClassType<>ClassType) then
722
raise Exception.Create('invalid class');
724
Node:=Source.Tree.FindLowest;
725
while Node<>nil do begin
726
Item:=PStringToPointerTreeItem(Node.Data);
727
Items[Item^.Name]:=Item^.Value;
728
Node:=Source.Tree.FindSuccessor(Node);
732
function TStringToPointerTree.GetEnumerator: TStringToPointerTreeEnumerator;
734
Result:=TStringToPointerTreeEnumerator.Create(FTree);
737
{ TStringMapEnumerator }
739
constructor TStringMapEnumerator.Create(Tree: TAVLTree);
744
function TStringMapEnumerator.MoveNext: boolean;
747
FCurrent:=FTree.FindLowest
749
FCurrent:=FTree.FindSuccessor(FCurrent);
750
Result:=FCurrent<>nil;
753
{ TStringToPointerTreeEnumerator }
755
function TStringToPointerTreeEnumerator.GetCurrent: PStringToPointerTreeItem;
757
Result:=PStringToPointerTreeItem(FCurrent.Data);
762
function TStringMap.GetCompareItemsFunc: TListSortCompare;
764
Result:=Tree.OnCompare;
767
function TStringMap.FindNode(const s: string): TAVLTreeNode;
769
Result:=FTree.FindKey(Pointer(s),FCompareKeyItemFunc);
772
procedure TStringMap.DisposeItem(p: PStringMapItem);
777
function TStringMap.ItemsAreEqual(p1, p2: PStringMapItem): boolean;
779
Result:=p1^.Name=p2^.Name;
782
function TStringMap.CreateCopy(Src: PStringMapItem): PStringMapItem;
785
Result^.Name:=Src^.Name;
788
constructor TStringMap.Create(TheCaseSensitive: boolean);
790
FCaseSensitive:=TheCaseSensitive;
791
if CaseSensitive then begin
792
FCompareKeyItemFunc:=@CompareStringAndStringToStringTreeItem;
793
FTree:=TMTAVLTree.Create(@CompareStringToStringItems);
795
FCompareKeyItemFunc:=@CompareStringAndStringToStringTreeItemI;
796
FTree:=TMTAVLTree.Create(@CompareStringToStringItemsI);
800
destructor TStringMap.Destroy;
808
procedure TStringMap.Clear;
812
Node:=FTree.FindLowest;
813
while Node<>nil do begin
814
DisposeItem(PStringMapItem(Node.Data));
815
Node:=FTree.FindSuccessor(Node);
820
function TStringMap.Contains(const s: string): boolean;
822
Result:=FindNode(s)<>nil;
825
function TStringMap.ContainsIdentifier(P: PChar): boolean;
827
if CaseSensitive then
828
Result:=FTree.FindKey(p,@CompareIdentifierAndStringToStringTreeItem)<>nil
830
Result:=FTree.FindKey(p,@CompareIdentifierAndStringToStringTreeItemI)<>nil;
833
function TStringMap.FindNodeWithIdentifierAsPrefix(P: PChar): TAVLTreeNode;
835
if CaseSensitive then
836
Result:=FTree.FindKey(p,@CompareIdentifierPrefixAndStringToStringTreeItem)
838
Result:=FTree.FindKey(p,@CompareIdentifierPrefixAndStringToStringTreeItemI);
841
procedure TStringMap.GetNames(List: TStrings);
844
Item: PStringMapItem;
846
Node:=Tree.FindLowest;
847
while Node<>nil do begin
848
Item:=PStringMapItem(Node.Data);
849
List.Add(Item^.Name);
850
Node:=Tree.FindSuccessor(Node);
854
procedure TStringMap.Remove(const Name: string);
857
Item: PStringMapItem;
859
Node:=FindNode(Name);
860
if Node<>nil then begin
861
Item:=PStringMapItem(Node.Data);
867
function TStringMap.GetNodeData(AVLNode: TAVLTreeNode): PStringMapItem;
869
Result:=PStringMapItem(AVLNode.Data);
872
function TStringMap.Count: integer;
877
function TStringMap.Equals(OtherTree: TStringMap): boolean;
880
OtherNode: TAVLTreeNode;
881
OtherItem: PStringMapItem;
882
Item: PStringMapItem;
885
if (OtherTree=nil) or (OtherTree.ClassType<>ClassType) then exit;
886
if Tree.Count<>OtherTree.Tree.Count then exit;
887
Node:=Tree.FindLowest;
888
OtherNode:=OtherTree.Tree.FindLowest;
889
while Node<>nil do begin
890
if OtherNode=nil then exit;
891
Item:=PStringMapItem(Node.Data);
892
OtherItem:=PStringMapItem(OtherNode.Data);
893
if not ItemsAreEqual(Item,OtherItem) then exit;
894
OtherNode:=OtherTree.Tree.FindSuccessor(OtherNode);
895
Node:=Tree.FindSuccessor(Node);
897
if OtherNode<>nil then exit;
901
procedure TStringMap.Assign(Source: TStringMap);
903
SrcNode: TAVLTreeNode;
904
SrcItem: PStringMapItem;
906
if (Source=nil) or (Source.ClassType<>ClassType) then
907
raise Exception.Create('invalid class');
909
SrcNode:=Source.Tree.FindLowest;
910
while SrcNode<>nil do begin
911
SrcItem:=PStringMapItem(SrcNode.Data);
912
Tree.Add(CreateCopy(SrcItem));
913
SrcNode:=Source.Tree.FindSuccessor(SrcNode);
917
procedure TStringMap.WriteDebugReport;
920
Item: PStringMapItem;
922
DebugLn(['TStringMap.WriteDebugReport ',Tree.Count]);
923
Node:=Tree.FindLowest;
924
while Node<>nil do begin
925
Item:=PStringMapItem(Node.Data);
926
DebugLn([Item^.Name]);
927
Node:=Tree.FindSuccessor(Node);
931
function TStringMap.CalcMemSize: PtrUint;
934
Item: PStringMapItem;
936
Result:=PtrUInt(InstanceSize)
937
+PtrUInt(FTree.InstanceSize)
938
+PtrUint(FTree.Count)*SizeOf(TAVLTreeNode);
939
Node:=FTree.FindLowest;
940
while Node<>nil do begin
941
Item:=PStringMapItem(Node.Data);
942
inc(Result,MemSizeString(Item^.Name)
943
+SizeOf(TStringMapItem));
944
Node:=FTree.FindSuccessor(Node);
948
procedure TStringMap.SetCompareFuncs(const NewCompareItemsFunc,
949
NewCompareKeyItemFunc: TListSortCompare);
951
FCompareKeyItemFunc:=NewCompareKeyItemFunc;
952
Tree.OnCompare:=NewCompareItemsFunc;
955
{ TStringToStringTreeEnumerator }
957
function TStringToStringTreeEnumerator.GetCurrent: PStringToStringTreeItem;
959
Result:=PStringToStringTreeItem(FCurrent.Data);
962
{ TStringTreeEnumerator }
964
function TStringTreeEnumerator.GetCurrent: string;
966
Result:=AnsiString(FCurrent.Data);
969
constructor TStringTreeEnumerator.Create(Tree: TStringTree);
974
function TStringTreeEnumerator.MoveNext: boolean;
977
FCurrent:=FTree.Tree.FindLowest
979
FCurrent:=FTree.Tree.FindSuccessor(FCurrent);
980
Result:=FCurrent<>nil;
983
{ TStringToStringTree }
985
function TStringToStringTree.GetStrings(const s: string): string;
991
Result:=PStringToStringTreeItem(Node.Data)^.Value
996
procedure TStringToStringTree.SetStrings(const s: string; const AValue: string);
999
NewItem: PStringToStringTreeItem;
1002
if Node<>nil then begin
1003
PStringToStringTreeItem(Node.Data)^.Value:=AValue;
1007
NewItem^.Value:=AValue;
1012
procedure TStringToStringTree.DisposeItem(p: PStringMapItem);
1014
Item: PStringToStringTreeItem absolute p;
1019
function TStringToStringTree.ItemsAreEqual(p1, p2: PStringMapItem): boolean;
1021
Item1: PStringToStringTreeItem absolute p1;
1022
Item2: PStringToStringTreeItem absolute p2;
1024
Result:=(Item1^.Name=Item2^.Name)
1025
and (Item1^.Value=Item2^.Value);
1028
function TStringToStringTree.CreateCopy(Src: PStringMapItem): PStringMapItem;
1030
SrcItem: PStringToStringTreeItem absolute Src;
1031
NewItem: PStringToStringTreeItem;
1034
NewItem^.Name:=SrcItem^.Name;
1035
NewItem^.Value:=SrcItem^.Value;
1036
Result:=PStringMapItem(NewItem);
1039
function TStringToStringTree.GetString(const Name: string; out Value: string
1044
Node:=FindNode(Name);
1045
if Node<>nil then begin
1046
Value:=PStringToStringTreeItem(Node.Data)^.Value;
1053
procedure TStringToStringTree.Add(const Name, Value: string);
1055
Strings[Name]:=Value;
1058
function TStringToStringTree.GetNodeData(AVLNode: TAVLTreeNode
1059
): PStringToStringTreeItem;
1061
Result:=PStringToStringTreeItem(AVLNode.Data);
1064
function TStringToStringTree.AsText: string;
1067
Item: PStringToStringTreeItem;
1070
Node:=Tree.FindLowest;
1071
while Node<>nil do begin
1072
Item:=PStringToStringTreeItem(Node.Data);
1073
Result:=Result+Item^.Name+'='+Item^.Value+LineEnding;
1074
Node:=Tree.FindSuccessor(Node);
1078
procedure TStringToStringTree.WriteDebugReport;
1081
Item: PStringToStringTreeItem;
1083
DebugLn(['TStringToStringTree.WriteDebugReport ',Tree.Count]);
1084
Node:=Tree.FindLowest;
1085
while Node<>nil do begin
1086
Item:=PStringToStringTreeItem(Node.Data);
1087
DebugLn([Item^.Name,'=',Item^.Value]);
1088
Node:=Tree.FindSuccessor(Node);
1092
function TStringToStringTree.CalcMemSize: PtrUint;
1095
Item: PStringToStringTreeItem;
1097
Result:=PtrUInt(InstanceSize)
1098
+PtrUInt(FTree.InstanceSize)
1099
+PtrUint(FTree.Count)*SizeOf(TAVLTreeNode);
1100
Node:=FTree.FindLowest;
1101
while Node<>nil do begin
1102
Item:=PStringToStringTreeItem(Node.Data);
1103
inc(Result,MemSizeString(Item^.Name)
1104
+MemSizeString(Item^.Value)
1105
+SizeOf(TStringToStringTreeItem));
1106
Node:=FTree.FindSuccessor(Node);
1110
function TStringToStringTree.GetEnumerator: TStringToStringTreeEnumerator;
1112
Result:=TStringToStringTreeEnumerator.Create(FTree);
1115
{ TFilenameToStringTree }
1117
constructor TFilenameToStringTree.Create(CaseInsensitive: boolean);
1119
inherited Create(true);
1120
if CaseInsensitive then
1121
SetCompareFuncs(@CompareFilenameToStringItemsI,
1122
@CompareFilenameAndFilenameToStringTreeItemI)
1124
SetCompareFuncs(@CompareFilenameToStringItems,
1125
@CompareFilenameAndFilenameToStringTreeItem);
1130
constructor TStringTree.Create;
1132
Tree:=TMTAVLTree.Create(@CompareAnsiStringPtrs);
1135
destructor TStringTree.Destroy;
1142
procedure TStringTree.Clear;
1146
Node:=Tree.FindLowest;
1147
while Node<>nil do begin
1148
AnsiString(Node.Data):='';
1149
Node:=Tree.FindSuccessor(Node);
1154
function TStringTree.FindNode(const s: string): TAVLTreeNode;
1156
Result:=Tree.Find(Pointer(s));
1159
procedure TStringTree.ReplaceString(var s: string);
1164
if GetStringRefCount(s)<=0 then exit;
1166
if Node=nil then begin
1167
// increase refcount
1169
Tree.Add(Pointer(h));
1170
Pointer(h):=nil; // keep refcount
1171
//debugln(['TStringTree.ReplaceString new string: refcount=',GetStringRefCount(s)]);
1172
//debugln(['TStringTree.ReplaceString NewString="',dbgstr(s),'"']);
1174
s:=AnsiString(Node.Data);
1175
//debugln(['TStringTree.ReplaceString old string: refcount=',GetStringRefCount(s)]);
1176
//debugln(['TStringTree.ReplaceString OldString="',dbgstr(s),'"']);
1178
//debugln(['TStringTree.ReplaceString ',GetStringRefCount(s),' ',Node<>nil]);
1181
function TStringTree.CalcMemSize: PtrUInt;
1185
Result:=PtrUInt(InstanceSize)
1186
+PtrUInt(Tree.InstanceSize)
1187
+PtrUInt(TAVLTreeNode.InstanceSize)*PtrUInt(Tree.Count);
1188
Node:=Tree.FindLowest;
1189
while Node<>nil do begin
1190
inc(Result,MemSizeString(AnsiString(Node.Data)));
1191
Node:=Tree.FindSuccessor(Node);
1195
function TStringTree.GetEnumerator: TStringTreeEnumerator;
1197
Result:=TStringTreeEnumerator.Create(Self);
1200
{ TComponentChildCollector }
1202
procedure TComponentChildCollector.AddChildComponent(Child: TComponent);
1204
OldRoot: TComponent;
1206
//debugln(['TComponentChildCollector.AddChildComponent ',DbgSName(Child)]);
1207
Children.Add(Child);
1210
if csInline in Child.ComponentState then
1212
TCTComponentAccess(Child).GetChildren(@AddChildComponent,Root);
1218
constructor TComponentChildCollector.Create;
1220
FChildren:=TFPList.Create;
1223
destructor TComponentChildCollector.Destroy;
1225
FreeAndNil(FChildren);
1229
function TComponentChildCollector.GetComponents(RootComponent: TComponent;
1230
AddRoot: boolean): TFPList;
1234
Children.Add(RootComponent);
1235
FRoot:=RootComponent;
1236
TCTComponentAccess(RootComponent).GetChildren(@AddChildComponent,FRoot);