SynEdit: Refactor AVL

git-svn-id: trunk@40174 -
This commit is contained in:
martin 2013-02-04 13:03:39 +00:00
parent 4bfedf1d24
commit c13054e9c5
2 changed files with 158 additions and 64 deletions

View File

@ -201,6 +201,7 @@ type
protected
// will be reset by TSynEditMarkLine.ChangeSize;
FLastIteratorIndex: Integer;
function CreateNode(APosition: Integer): TSynSizedDifferentialAVLNode; override;
public
constructor Create(AOwner: TSynEditMarkList);
destructor Destroy; override;
@ -717,26 +718,11 @@ begin
end;
function TSynEditMarkLineList.GetMarkLineByMarkIndex(var AMarkIndex: Integer): TSynEditMarkLine;
var
d1, d2: Integer;
begin
Result := TSynEditMarkLine(FRoot);
while Result <> nil do begin
if AMarkIndex < Result.LeftSizeSum then begin
Result := Result.Left;
continue;
end;
AMarkIndex := AMarkIndex - Result.LeftSizeSum;
if AMarkIndex < Result.Size then begin
break;
end
else begin
AMarkIndex := AMarkIndex - Result.Size;
Result := Result.Right;
continue;
end;
end;
Result := TSynEditMarkLine(FindNodeAtLeftSize(AMarkIndex, d1, d2));
AMarkIndex := AMarkIndex - d2;
end;
function TSynEditMarkLineList.GetMarkLine(LineNum: Integer): TSynEditMarkLine;
@ -749,50 +735,15 @@ function TSynEditMarkLineList.GetOrAddMarkLine(LineNum: Integer;
var
rStartPosition: Integer;
p: TSynEditMarkLine;
d1, d2: Integer;
begin
Result := TSynEditMarkLine(FRoot);
if (Result = nil) and AddIfNotExist then begin
Result := TSynEditMarkLine.Create(LineNum, Self);
SetRoot(Result);
exit;
end;
rStartPosition := fRootOffset;
p := nil;
while (Result <> nil) do begin
rStartPosition := rStartPosition + Result.FPositionOffset;
if rStartPosition > LineNum then begin
if (Result.Left = nil) and AddIfNotExist then begin
p := Result;
Result := TSynEditMarkLine.Create(LineNum, Self);
p.SetLeftChild(Result, -rStartPosition);
BalanceAfterInsert(Result);
break;
end;
// Store current in p, as posible UseNext
p := Result;
Result := Result.Left;
end
else if LineNum = rStartPosition then begin
break;
end
else if rStartPosition < LineNum then begin
if (Result.Right = nil) and AddIfNotExist then begin
p := Result;
Result := TSynEditMarkLine.Create(LineNum, Self);
p.SetRightChild(Result, -rStartPosition);
BalanceAfterInsert(Result);
break;
end;
Result := Result.Right;
end;
end; // while
if UseNext and (Result = nil) then
Result := p;
if AddIfNotExist then
Result := TSynEditMarkLine(FindNodeAtPosition(LineNum, afmCreate, d1, d2))
else
if UseNext then
Result := TSynEditMarkLine(FindNodeAtPosition(LineNum, afmNext, d1, d2))
else
Result := TSynEditMarkLine(FindNodeAtPosition(LineNum, afmNil, d1, d2));
end;
procedure TSynEditMarkLineList.AdjustForLinesInserted(AStartLine, ALineCount: Integer);
@ -856,6 +807,11 @@ begin
end;
end;
function TSynEditMarkLineList.CreateNode(APosition: Integer): TSynSizedDifferentialAVLNode;
begin
Result := TSynEditMarkLine.Create(APosition, Self);
end;
constructor TSynEditMarkLineList.Create(AOwner: TSynEditMarkList);
begin
inherited Create;

View File

@ -483,7 +483,7 @@ type
FParent, FLeft, FRight : TSynSizedDifferentialAVLNode; (* AVL Links *)
FBalance : shortint; (* AVL Balance *)
(* Position: sores difference to parent value
(* Position: stores difference to parent value
*)
FPositionOffset: Integer;
@ -494,6 +494,7 @@ type
FSize: Integer;
FLeftSizeSum: Integer;
property LeftSizeSum: Integer read FLeftSizeSum;
{$IFDEF SynDebug}
function Debug: String; virtual;
{$ENDIF}
@ -517,14 +518,18 @@ type
procedure AdjustLeftCount(AValue : Integer);
procedure AdjustParentLeftCount(AValue : Integer);
function GetSizesBeforeSum: Integer;
function Precessor: TSynSizedDifferentialAVLNode;
function Successor: TSynSizedDifferentialAVLNode;
function Precessor(var aStartPosition, aSizesBeforeSum : Integer): TSynSizedDifferentialAVLNode;
function Successor(var aStartPosition, aSizesBeforeSum : Integer): TSynSizedDifferentialAVLNode;
function GetSizesBeforeSum: Integer;
function GetPosition: Integer;
end;
TSynSizedDiffAVLFindMode = (afmNil, afmCreate, afmPrev, afmNext);
{ TSynSizedDifferentialAVLTree }
TSynSizedDifferentialAVLTree = class
@ -542,6 +547,8 @@ type
procedure RemoveNode(ANode: TSynSizedDifferentialAVLNode);
procedure BalanceAfterInsert(ANode: TSynSizedDifferentialAVLNode);
procedure BalanceAfterDelete(ANode: TSynSizedDifferentialAVLNode);
function CreateNode(APosition: Integer): TSynSizedDifferentialAVLNode; virtual;
public
constructor Create;
destructor Destroy; override;
@ -554,6 +561,11 @@ type
function Last: TSynSizedDifferentialAVLNode;
function First(out aStartPosition, aSizesBeforeSum : Integer): TSynSizedDifferentialAVLNode;
function Last(out aStartPosition, aSizesBeforeSum : Integer): TSynSizedDifferentialAVLNode;
function FindNodeAtLeftSize(ALeftSum: INteger;
out aStartPosition, aSizesBeforeSum : Integer): TSynSizedDifferentialAVLNode;
function FindNodeAtPosition(APosition: INteger; AMode: TSynSizedDiffAVLFindMode;
out aStartPosition, aSizesBeforeSum : Integer): TSynSizedDifferentialAVLNode;
end;
@ -1912,6 +1924,18 @@ begin
end;
end;
function TSynSizedDifferentialAVLNode.GetPosition: Integer;
var
N: TSynSizedDifferentialAVLNode;
begin
Result := FPositionOffset;
N := FParent;
while N <> nil do begin
Result := Result + N.FPositionOffset;
N := N.FParent;
end;
end;
function TSynSizedDifferentialAVLNode.Precessor: TSynSizedDifferentialAVLNode;
begin
Result := FLeft;
@ -2430,6 +2454,11 @@ begin
end;
end;
function TSynSizedDifferentialAVLTree.CreateNode(APosition: Integer): TSynSizedDifferentialAVLNode;
begin
Result := TSynSizedDifferentialAVLNode.Create;
end;
constructor TSynSizedDifferentialAVLTree.Create;
begin
inherited;
@ -2530,5 +2559,114 @@ begin
end;
end;
function TSynSizedDifferentialAVLTree.FindNodeAtLeftSize(ALeftSum: INteger; out
aStartPosition, aSizesBeforeSum: Integer): TSynSizedDifferentialAVLNode;
begin
Result := FRoot;
aStartPosition := 0;
aSizesBeforeSum := 0;
if Result = nil then
exit;
aStartPosition := Result.FPositionOffset;
while Result <> nil do begin
if ALeftSum < Result.FLeftSizeSum then begin
Result := Result.FLeft;
aStartPosition := aStartPosition + Result.FPositionOffset;
continue;
end;
ALeftSum := ALeftSum - Result.FLeftSizeSum;
if ALeftSum < Result.FSize then begin
break;
end
else begin
ALeftSum := ALeftSum - Result.FSize;
aSizesBeforeSum := aSizesBeforeSum + Result.FLeftSizeSum + Result.FSize;
Result := Result.FRight;
aStartPosition := aStartPosition + Result.FPositionOffset;
continue;
end;
end;
end;
function TSynSizedDifferentialAVLTree.FindNodeAtPosition(APosition: INteger;
AMode: TSynSizedDiffAVLFindMode; out aStartPosition,
aSizesBeforeSum: Integer): TSynSizedDifferentialAVLNode;
function CreateRoot: TSynSizedDifferentialAVLNode;
begin
Result := CreateNode(APosition);
Result.FPositionOffset := APosition;
SetRoot(Result);
end;
function CreateLeft(N: TSynSizedDifferentialAVLNode; ACurOffs: Integer): TSynSizedDifferentialAVLNode;
begin
Result := CreateNode(APosition);
Result.FPositionOffset := APosition;
N.SetLeftChild(Result, -ACurOffs);
BalanceAfterInsert(Result);
end;
function CreateRight(N: TSynSizedDifferentialAVLNode; ACurOffs: Integer): TSynSizedDifferentialAVLNode;
begin
Result := CreateNode(APosition);
Result.FPositionOffset := APosition;
N.SetRightChild(Result, -ACurOffs);
BalanceAfterInsert(Result);
end;
begin
aSizesBeforeSum := 0;
aStartPosition := fRootOffset;
Result := FRoot;
if (Result = nil) then begin
if (AMode = afmCreate) then begin
Result := CreateRoot;
aStartPosition := aStartPosition + Result.FPositionOffset;
end;
exit;
end;
while (Result <> nil) do begin
aStartPosition := aStartPosition + Result.FPositionOffset;
if aStartPosition > APosition then begin
if (Result.FLeft = nil) then begin
case AMode of
afmCreate: Result := CreateLeft(Result, aStartPosition);
afmNil: Result := nil;
afmPrev: Result := Result.Precessor(aStartPosition, aStartPosition);
// afmNext: Result already contains next node
end;
break;
end;
Result := Result.FLeft;
end
else
if APosition = aStartPosition then begin
break;
end
else
if aStartPosition < APosition then begin
if (Result.FRight = nil) then begin
case AMode of
afmCreate: Result := CreateRight(Result, aStartPosition);
afmNil: Result := nil;
afmNext: Result := Result.Successor(aStartPosition, aStartPosition);
// afmPrev : Result already contains prev node
end;
break;
end;
aSizesBeforeSum := aSizesBeforeSum + Result.FLeftSizeSum + Result.FSize;
Result := Result.FRight;
end;
end; // while
end;
end.