codetools: finding and removing duplicate strings in define trees

git-svn-id: trunk@19913 -
This commit is contained in:
mattias 2009-05-10 21:20:49 +00:00
parent b21b6284da
commit 8bc4612fcd
4 changed files with 126 additions and 11 deletions

View File

@ -141,6 +141,19 @@ type
public public
constructor Create(CaseInsensitive: boolean); constructor Create(CaseInsensitive: boolean);
end; 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;
end;
function CompareStringToStringItems(Data1, Data2: Pointer): integer; function CompareStringToStringItems(Data1, Data2: Pointer): integer;
function CompareStringAndStringToStringTreeItem(Key, Data: Pointer): integer; function CompareStringAndStringToStringTreeItem(Key, Data: Pointer): integer;
@ -154,6 +167,7 @@ function CompareFilenameAndFilenameToStringTreeItem(Key, Data: Pointer): integer
function CompareFilenameToStringItemsI(Data1, Data2: Pointer): integer; function CompareFilenameToStringItemsI(Data1, Data2: Pointer): integer;
function CompareFilenameAndFilenameToStringTreeItemI(Key, Data: Pointer): integer; function CompareFilenameAndFilenameToStringTreeItemI(Key, Data: Pointer): integer;
function CompareAnsiStringPtrs(Data1, Data2: Pointer): integer;
implementation implementation
@ -204,6 +218,11 @@ begin
PStringToStringTreeItem(Data)^.Name); PStringToStringTreeItem(Data)^.Name);
end; end;
function CompareAnsiStringPtrs(Data1, Data2: Pointer): integer;
begin
Result:=CompareStr(AnsiString(Data1),AnsiString(Data2));
end;
{ TCodeXYPositions } { TCodeXYPositions }
function TCodeXYPositions.GetItems(Index: integer): PCodeXYPosition; function TCodeXYPositions.GetItems(Index: integer): PCodeXYPosition;
@ -539,5 +558,65 @@ begin
@CompareFilenameAndFilenameToStringTreeItem); @CompareFilenameAndFilenameToStringTreeItem);
end; end;
{ TStringTree }
constructor TStringTree.Create;
begin
Tree:=TAVLTree.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
Node:=FindNode(s);
if Node=nil then begin
// increase refcount
h:=s;
Tree.Add(Pointer(h));
Pointer(h):=nil; // keep refcount
end else
s:=AnsiString(Node.Data);
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;
end. end.

View File

@ -55,7 +55,7 @@ interface
uses uses
Classes, SysUtils, CodeToolsStrConsts, ExprEval, DirectoryCacher, Classes, SysUtils, CodeToolsStrConsts, ExprEval, DirectoryCacher,
Laz_XMLCfg, AVL_Tree, Laz_XMLCfg, AVL_Tree, CodeToolsStructs,
Process, KeywordFuncLists, FileProcs; Process, KeywordFuncLists, FileProcs;
const const
@ -354,6 +354,7 @@ type
FDirectoryCachePool: TCTDirectoryCachePool; FDirectoryCachePool: TCTDirectoryCachePool;
FFirstDefineTemplate: TDefineTemplate; FFirstDefineTemplate: TDefineTemplate;
FCache: TAVLTree; // tree of TDirectoryDefines FCache: TAVLTree; // tree of TDirectoryDefines
FDefineStrings: TStringTree;
FChangeStep: integer; FChangeStep: integer;
FErrorDescription: string; FErrorDescription: string;
FErrorTemplate: TDefineTemplate; FErrorTemplate: TDefineTemplate;
@ -368,6 +369,7 @@ type
function Calculate(DirDef: TDirectoryDefines): boolean; function Calculate(DirDef: TDirectoryDefines): boolean;
procedure IncreaseChangeStep; procedure IncreaseChangeStep;
procedure SetDirectoryCachePool(const AValue: TCTDirectoryCachePool); procedure SetDirectoryCachePool(const AValue: TCTDirectoryCachePool);
procedure RemoveDoubles(Defines: TDirectoryDefines);
protected protected
function FindDirectoryInCache(const Path: string): TDirectoryDefines; function FindDirectoryInCache(const Path: string): TDirectoryDefines;
function GetDirDefinesForDirectory(const Path: string; function GetDirDefinesForDirectory(const Path: string;
@ -1821,7 +1823,7 @@ begin
Stats.Add('TDirectoryDefines',PtrUInt(InstanceSize) Stats.Add('TDirectoryDefines',PtrUInt(InstanceSize)
+MemSizeString(Path)); +MemSizeString(Path));
if Values<>nil then if Values<>nil then
Stats.Add('TDirectoryDefines.Values',Values.CalcMemSize); Stats.Add('TDirectoryDefines.Values',Values.CalcMemSize(false,nil));
end; end;
@ -1888,7 +1890,8 @@ begin
inherited Create; inherited Create;
FFirstDefineTemplate:=nil; FFirstDefineTemplate:=nil;
FCache:=TAVLTree.Create(@CompareDirectoryDefines); FCache:=TAVLTree.Create(@CompareDirectoryDefines);
FDefineStrings:=TStringTree.Create;
FMacroFunctions:=TKeyWordFunctionList.Create; FMacroFunctions:=TKeyWordFunctionList.Create;
FMacroFunctions.AddExtended('Ext',nil,@MacroFuncExtractFileExt); FMacroFunctions.AddExtended('Ext',nil,@MacroFuncExtractFileExt);
FMacroFunctions.AddExtended('PATH',nil,@MacroFuncExtractFilePath); FMacroFunctions.AddExtended('PATH',nil,@MacroFuncExtractFilePath);
@ -1904,6 +1907,7 @@ begin
FMacroVariables.Free; FMacroVariables.Free;
FMacroFunctions.Free; FMacroFunctions.Free;
FCache.Free; FCache.Free;
FreeAndNil(FDefineStrings);
inherited Destroy; inherited Destroy;
end; end;
@ -1953,6 +1957,7 @@ begin
//DebugLn('[TDefineTree.GetDirDefinesForDirectory] B ',ExpPath,' '); //DebugLn('[TDefineTree.GetDirDefinesForDirectory] B ',ExpPath,' ');
if Calculate(Result) then begin if Calculate(Result) then begin
//DebugLn('[TDefineTree.GetDirDefinesForDirectory] C success'); //DebugLn('[TDefineTree.GetDirDefinesForDirectory] C success');
RemoveDoubles(Result);
FCache.Add(Result); FCache.Add(Result);
end else begin end else begin
//DebugLn('[TDefineTree.GetDirDefinesForDirectory] D failed'); //DebugLn('[TDefineTree.GetDirDefinesForDirectory] D failed');
@ -1974,6 +1979,7 @@ begin
FVirtualDirCache.Path:=VirtualDirectory; FVirtualDirCache.Path:=VirtualDirectory;
if Calculate(FVirtualDirCache) then begin if Calculate(FVirtualDirCache) then begin
//DebugLn('TDefineTree.GetDirDefinesForVirtualDirectory '); //DebugLn('TDefineTree.GetDirDefinesForVirtualDirectory ');
RemoveDoubles(FVirtualDirCache);
end else begin end else begin
FVirtualDirCache.Free; FVirtualDirCache.Free;
FVirtualDirCache:=nil; FVirtualDirCache:=nil;
@ -2029,6 +2035,7 @@ begin
FVirtualDirCache:=nil; FVirtualDirCache:=nil;
end; end;
IncreaseChangeStep; IncreaseChangeStep;
FDefineStrings.Clear;
end; end;
procedure TDefineTree.DoPrepareTree; procedure TDefineTree.DoPrepareTree;
@ -2621,6 +2628,12 @@ begin
FDirectoryCachePool:=AValue; FDirectoryCachePool:=AValue;
end; end;
procedure TDefineTree.RemoveDoubles(Defines: TDirectoryDefines);
begin
if Defines=nil then exit;
Defines.Values.RemoveDoubles(@FDefineStrings.ReplaceString);
end;
procedure TDefineTree.Add(ADefineTemplate: TDefineTemplate); procedure TDefineTree.Add(ADefineTemplate: TDefineTemplate);
// add as last // add as last
var LastDefTempl: TDefineTemplate; var LastDefTempl: TDefineTemplate;
@ -2797,6 +2810,8 @@ begin
FFirstDefineTemplate.CalcMemSize(Stats); FFirstDefineTemplate.CalcMemSize(Stats);
if FVirtualDirCache<>nil then if FVirtualDirCache<>nil then
FVirtualDirCache.CalcMemSize(Stats); FVirtualDirCache.CalcMemSize(Stats);
if FDefineStrings<>nil then
Stats.Add('TDefineTree.FDefineStrings',FDefineStrings.CalcMemSize);
if FCache<>nil then begin if FCache<>nil then begin
Stats.Add('TDefineTree.FCache.Count',FCache.Count); Stats.Add('TDefineTree.FCache.Count',FCache.Count);
Node:=FCache.FindLowest; Node:=FCache.FindLowest;

View File

@ -40,7 +40,7 @@ const
type type
TOnValuesChanged = procedure of object; TOnValuesChanged = procedure of object;
TOnGetSameString = procedure(var s: string) of object;
ArrayOfAnsiString = ^AnsiString; ArrayOfAnsiString = ^AnsiString;
@ -85,9 +85,10 @@ type
function AsString: string; function AsString: string;
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
procedure RemoveDoubles(OnGetSameString: TOnGetSameString);
procedure ConsistencyCheck; procedure ConsistencyCheck;
procedure WriteDebugReport; procedure WriteDebugReport;
function CalcMemSize: PtrUInt; function CalcMemSize(WithNamesAndValues: boolean = true; Original: TExpressionEvaluator = nil): PtrUInt;
property ChangeStamp: integer read FChangeStamp; property ChangeStamp: integer read FChangeStamp;
procedure IncreaseChangeStamp; inline; procedure IncreaseChangeStamp; inline;
end; end;
@ -224,6 +225,16 @@ begin
inherited Destroy; inherited Destroy;
end; end;
procedure TExpressionEvaluator.RemoveDoubles(OnGetSameString: TOnGetSameString);
var
i: Integer;
begin
for i:=0 to FCount-1 do begin
OnGetSameString(FNames[i]);
OnGetSameString(FValues[i]);
end;
end;
function TExpressionEvaluator.Eval(const Expression: string): string; function TExpressionEvaluator.Eval(const Expression: string): string;
// 1 = true // 1 = true
// 0 = syntax error // 0 = syntax error
@ -757,16 +768,26 @@ begin
ConsistencyCheck; ConsistencyCheck;
end; end;
function TExpressionEvaluator.CalcMemSize: PtrUInt; function TExpressionEvaluator.CalcMemSize(WithNamesAndValues: boolean;
Original: TExpressionEvaluator): PtrUInt;
var var
i: Integer; i: Integer;
j: LongInt;
begin begin
Result:=PtrUInt(InstanceSize) Result:=PtrUInt(InstanceSize)
+MemSizeString(Expr) +MemSizeString(Expr)
+SizeOf(Pointer)*FCount*2; +SizeOf(Pointer)*FCount*2;
for i:=0 to FCount-1 do begin if WithNamesAndValues then begin
inc(Result,MemSizeString(FNames[i])); for i:=0 to FCount-1 do begin
inc(Result,MemSizeString(FValues[i])); if Original<>nil then begin
j:=Original.IndexOfName(FNames[i],false);
if j>=0 then begin
if Pointer(FNames[i])=Pointer(Original.FNames[j]) then continue;
end;
end;
inc(Result,MemSizeString(FNames[i]));
inc(Result,MemSizeString(FValues[i]));
end;
end; end;
end; end;

View File

@ -1416,7 +1416,7 @@ begin
FLinkCapacity*SizeOf(TSourceLink)); FLinkCapacity*SizeOf(TSourceLink));
if FInitValues<>nil then if FInitValues<>nil then
Stats.Add('TLinkScanner.FInitValues', Stats.Add('TLinkScanner.FInitValues',
FInitValues.CalcMemSize); FInitValues.CalcMemSize(false)); // FInitValues are copies of strings of TDefineTree
if FSourceChangeSteps<>nil then if FSourceChangeSteps<>nil then
Stats.Add('TLinkScanner.FSourceChangeSteps', Stats.Add('TLinkScanner.FSourceChangeSteps',
FSourceChangeSteps.InstanceSize FSourceChangeSteps.InstanceSize
@ -1426,7 +1426,7 @@ begin
FIncludeStack.InstanceSize+FIncludeStack.Capacity*SizeOf(TSourceLink)); FIncludeStack.InstanceSize+FIncludeStack.Capacity*SizeOf(TSourceLink));
if Values<>nil then if Values<>nil then
Stats.Add('TLinkScanner.Values', Stats.Add('TLinkScanner.Values',
Values.CalcMemSize); Values.CalcMemSize(true,FInitValues));
if FMissingIncludeFiles<>nil then if FMissingIncludeFiles<>nil then
Stats.Add('TLinkScanner.FMissingIncludeFiles', Stats.Add('TLinkScanner.FMissingIncludeFiles',
FMissingIncludeFiles.InstanceSize); FMissingIncludeFiles.InstanceSize);