accelerated TLazXPMReader

git-svn-id: trunk@4410 -
This commit is contained in:
mattias 2003-07-16 20:35:42 +00:00
parent 62cb8e4eaf
commit 1bed9a9f68
2 changed files with 474 additions and 71 deletions

View File

@ -1061,7 +1061,7 @@ var
ExpectedMemAvail : longint; ExpectedMemAvail : longint;
begin begin
pp:=heap_mem_root; pp:=heap_mem_root;
Writeln(ptext^,'Heap dump by heaptrc unit'); Writeln(ptext^,'Heap dump by memcheck unit');
{$ifdef EXTRA} {$ifdef EXTRA}
Writeln(ptext^,'compiled with EXTRA features'); Writeln(ptext^,'compiled with EXTRA features');
{$endif EXTRA} {$endif EXTRA}
@ -1187,7 +1187,7 @@ begin
if (exitcode<>0) and if (exitcode<>0) and
(erroraddr<>nil) then (erroraddr<>nil) then
begin begin
Writeln(ptext^,'No heap dump by heaptrc unit'); Writeln(ptext^,'No heap dump by memcheck unit');
Writeln(ptext^,'Exitcode = ',exitcode); Writeln(ptext^,'Exitcode = ',exitcode);
if ptext<>@stderr then if ptext<>@stderr then
begin begin
@ -2249,7 +2249,7 @@ var
ExpectedMemAvail : longint; ExpectedMemAvail : longint;
begin begin
pp:=heap_mem_root; pp:=heap_mem_root;
Writeln(ptext^,'Heap dump by heaptrc unit'); Writeln(ptext^,'Heap dump by memcheck unit');
Writeln(ptext^,getmem_cnt, ' memory blocks allocated : ',getmem_size,'/',getmem8_size); Writeln(ptext^,getmem_cnt, ' memory blocks allocated : ',getmem_size,'/',getmem8_size);
Writeln(ptext^,freemem_cnt,' memory blocks freed : ',freemem_size,'/',freemem8_size); Writeln(ptext^,freemem_cnt,' memory blocks freed : ',freemem_size,'/',freemem8_size);
Writeln(ptext^,getmem_cnt-freemem_cnt,' unfreed memory blocks : ',getmem_size-freemem_size); Writeln(ptext^,getmem_cnt-freemem_cnt,' unfreed memory blocks : ',getmem_size-freemem_size);
@ -2429,7 +2429,7 @@ begin
ioresult; ioresult;
if (exitcode<>0) and (erroraddr<>nil) then if (exitcode<>0) and (erroraddr<>nil) then
begin begin
Writeln(ptext^,'No heap dump by heaptrc unit'); Writeln(ptext^,'No heap dump by memcheck unit');
Writeln(ptext^,'Exitcode = ',exitcode); Writeln(ptext^,'Exitcode = ',exitcode);
if ptext<>@stderr then if ptext<>@stderr then
begin begin
@ -2561,6 +2561,9 @@ end.
{ {
$Log$ $Log$
Revision 1.22 2003/07/16 20:35:42 mattias
accelerated TLazXPMReader
Revision 1.21 2003/05/05 11:47:04 mazen Revision 1.21 2003/05/05 11:47:04 mazen
+ explicit override of inline assembler type to AT&T (fpc.cfg specify other?) + explicit override of inline assembler type to AT&T (fpc.cfg specify other?)

View File

@ -170,6 +170,51 @@ type
end; end;
{ TArrayNodesTree }
PArrayNode = ^TArrayNode;
TArrayNode = class
public
Parent: TArrayNode;
Value: integer;
Childs: PArrayNode;
StartValue: integer;
Capacity: integer;
Data: Pointer;
constructor Create;
destructor Destroy; override;
procedure DeleteChilds;
procedure UnbindFromParent;
function GetChildNode(ChildValue: integer;
CreateIfNotExists: boolean): TArrayNode;
procedure Expand(ValueToInclude: integer);
function FindPrevSibling: TArrayNode;
function FindNextSibling: TArrayNode;
function FindNext: TArrayNode;
function FindPrev: TArrayNode;
function FindFirstChild: TArrayNode;
function FindLastChild: TArrayNode;
function FindLastSubChild: TArrayNode;
function FindFirstSibling: TArrayNode;
function FindLastSibling: TArrayNode;
procedure ConsistencyCheck;
end;
TArrayNodesTree = class
public
Root: TArrayNode;
function FindNode(IntArray: PInteger; Count: integer): TArrayNode;
function FindData(IntArray: PInteger; Count: integer): Pointer;
function SetNode(IntArray: PInteger; Count: integer;
Data: Pointer): TArrayNode;
procedure Delete(Node: TArrayNode);
procedure Clear;
constructor Create;
destructor Destroy; override;
procedure ConsistencyCheck;
end;
{ TLazReaderXPM } { TLazReaderXPM }
{ This is a FPImage reader for xpm images. } { This is a FPImage reader for xpm images. }
@ -181,7 +226,7 @@ type
FCharsPerPixel: Integer; FCharsPerPixel: Integer;
fXHot: Integer; fXHot: Integer;
fYHot: Integer; fYHot: Integer;
FPixelToColorTree: TAvgLvlTree; FPixelToColorTree: TArrayNodesTree;
protected protected
procedure ClearPixelToColorTree; procedure ClearPixelToColorTree;
procedure InternalRead(Str: TStream; Img: TFPCustomImage); override; procedure InternalRead(Str: TStream; Img: TFPCustomImage); override;
@ -255,10 +300,10 @@ procedure CreateRawImageLineStarts(Width, Height, BitsPerPixel: cardinal;
var var
PixelCount: cardinal; PixelCount: cardinal;
BitsPerLine: cardinal; BitsPerLine: cardinal;
CurLine: Integer; CurLine: cardinal;
BytesPerLine: Integer; BytesPerLine: cardinal;
ExtraBitsPerLine: Integer; ExtraBitsPerLine: cardinal;
CurBitOffset: Cardinal; CurBitOffset: cardinal;
begin begin
// get current size // get current size
PixelCount:=Width*Height; PixelCount:=Width*Height;
@ -289,10 +334,10 @@ begin
BitsPerLine:=Width*BitsPerPixel; BitsPerLine:=Width*BitsPerPixel;
case LineEnd of case LineEnd of
rileTight: ; rileTight: ;
rileByteBoundary: BitsPerLine:=(BitsPerLine+7) and not 7; rileByteBoundary: BitsPerLine:=(BitsPerLine+7) and not cardinal(7);
rileWordBoundary: BitsPerLine:=(BitsPerLine+15) and not 15; rileWordBoundary: BitsPerLine:=(BitsPerLine+15) and not cardinal(15);
rileDWordBoundary: BitsPerLine:=(BitsPerLine+31) and not 31; rileDWordBoundary: BitsPerLine:=(BitsPerLine+31) and not cardinal(31);
rileQWordBoundary: BitsPerLine:=(BitsPerLine+63) and not 63; rileQWordBoundary: BitsPerLine:=(BitsPerLine+63) and not cardinal(63);
end; end;
Result:=BitsPerLine; Result:=BitsPerLine;
end; end;
@ -339,19 +384,19 @@ begin
1,2,4: 1,2,4:
begin begin
OneByte:=P^; OneByte:=P^;
Bits:=Word((OneByte shr (Shift+Position.Bit)) and PrecMask); Bits:=Word(cardinal(OneByte shr (Shift+Position.Bit)) and PrecMask);
end; end;
8: begin 8: begin
OneByte:=P^; OneByte:=P^;
Bits:=Word((OneByte shr Shift) and PrecMask); Bits:=Word(cardinal(OneByte shr Shift) and PrecMask);
end; end;
16: begin 16: begin
TwoBytes:=PWord(P)^; TwoBytes:=PWord(P)^;
Bits:=Word((TwoBytes shr Shift) and PrecMask); Bits:=Word(cardinal(TwoBytes shr Shift) and PrecMask);
end; end;
32: begin 32: begin
FourBytes:=PDWord(P)^; FourBytes:=PDWord(P)^;
Bits:=Word((FourBytes shr Shift) and PrecMask); Bits:=Word(cardinal(FourBytes shr Shift) and PrecMask);
end; end;
else else
Bits:=0; Bits:=0;
@ -413,7 +458,7 @@ begin
FourBytes:=PDWord(P)^; FourBytes:=PDWord(P)^;
PrecMask:=not (PrecMask shl Shift); PrecMask:=not (PrecMask shl Shift);
FourBytes:=FourBytes and PrecMask; // clear old FourBytes:=FourBytes and PrecMask; // clear old
FourBytes:=FourBytes or (Bits shl Shift); // set new FourBytes:=FourBytes or cardinal(Bits shl Shift); // set new
PDWord(P)^:=FourBytes; PDWord(P)^:=FourBytes;
//writeln('TLazIntfImage.WriteDataBits 32 Result=',HexStr(Cardinal(FourBytes),8)); //writeln('TLazIntfImage.WriteDataBits 32 Result=',HexStr(Cardinal(FourBytes),8));
end; end;
@ -641,6 +686,7 @@ end;
destructor TLazIntfImage.Destroy; destructor TLazIntfImage.Destroy;
begin begin
FreeAllData;
inherited Destroy; inherited Destroy;
end; end;
@ -853,6 +899,8 @@ begin
for x:=0 to Width-1 do for x:=0 to Width-1 do
SetInternalColor(x,y,Color); SetInternalColor(x,y,Color);
end; end;
// ToDo: mask
end; end;
{ TLazReaderXPM } { TLazReaderXPM }
@ -872,18 +920,22 @@ end;
procedure TLazReaderXPM.ClearPixelToColorTree; procedure TLazReaderXPM.ClearPixelToColorTree;
var var
Node: TAvgLvlTreeNode;
Entry: PXPMPixelToColorEntry; Entry: PXPMPixelToColorEntry;
ArrNode: TArrayNode;
begin begin
if FPixelToColorTree=nil then exit; if FPixelToColorTree<>nil then begin
Node:=FPixelToColorTree.FindLowest; ArrNode:=FPixelToColorTree.Root;
while Node<>nil do begin while ArrNode<>nil do begin
Entry:=PXPMPixelToColorEntry(Node.Data); Entry:=PXPMPixelToColorEntry(ArrNode.Data);
Dispose(Entry); if Entry<>nil then begin
Node:=FPixelToColorTree.FindSuccessor(Node); //writeln('TLazReaderXPM.ClearPixelToColorTree A ',HexStr(Cardinal(ArrNode),8),' ',HexStr(Cardinal(Entry),8));
Dispose(Entry);
end;
ArrNode:=ArrNode.FindNext;
end;
FPixelToColorTree.Free;
FPixelToColorTree:=nil;
end; end;
FPixelToColorTree.Free;
FPixelToColorTree:=nil;
end; end;
procedure TLazReaderXPM.InternalRead(Str: TStream; Img: TFPCustomImage); procedure TLazReaderXPM.InternalRead(Str: TStream; Img: TFPCustomImage);
@ -1059,68 +1111,70 @@ var
begin begin
s := copy(Src,TextStart,TextEnd-TextStart); s := copy(Src,TextStart,TextEnd-TextStart);
if s = 'transparent' then if s = 'transparent' then
Result := FPImage.clTransparent Result := FPImage.colTransparent
else if s = 'none' then else if s = 'none' then
Result := FPImage.clTransparent Result := FPImage.colTransparent
else if s = 'black' then else if s = 'black' then
result := FPImage.clBlack result := FPImage.colBlack
else if s = 'blue' then else if s = 'blue' then
Result := FPImage.clBlue Result := FPImage.colBlue
else if s = 'green' then else if s = 'green' then
Result := FPImage.clGreen Result := FPImage.colGreen
else if s = 'cyan' then else if s = 'cyan' then
Result := FPImage.clCyan Result := FPImage.colCyan
else if s = 'red' then else if s = 'red' then
Result := FPImage.clRed Result := FPImage.colRed
else if s = 'magenta' then else if s = 'magenta' then
Result := FPImage.clMagenta Result := FPImage.colMagenta
else if s = 'yellow' then else if s = 'yellow' then
Result := FPImage.clYellow Result := FPImage.colYellow
else if s = 'white' then else if s = 'white' then
Result := FPImage.clWhite Result := FPImage.colWhite
else if s = 'gray' then else if s = 'gray' then
Result := FPImage.clGray Result := FPImage.colGray
else if s = 'ltgray' then else if s = 'ltgray' then
Result := FPImage.clLtGray Result := FPImage.colLtGray
else if s = 'dkblue' then else if s = 'dkblue' then
Result := FPImage.clDkBlue Result := FPImage.colDkBlue
else if s = 'dkgreen' then else if s = 'dkgreen' then
Result := FPImage.clDkGreen Result := FPImage.colDkGreen
else if s = 'dkcyan' then else if s = 'dkcyan' then
Result := FPImage.clDkCyan Result := FPImage.colDkCyan
else if s = 'dkred' then else if s = 'dkred' then
Result := FPImage.clDkRed Result := FPImage.colDkRed
else if s = 'dkmagenta' then else if s = 'dkmagenta' then
Result := FPImage.clDkMagenta Result := FPImage.colDkMagenta
else if s = 'dkyellow' then else if s = 'dkyellow' then
Result := FPImage.clDkYellow Result := FPImage.colDkYellow
else if s = 'maroon' then else if s = 'maroon' then
Result := FPImage.clMaroon Result := FPImage.colMaroon
else if s = 'ltgreen' then else if s = 'ltgreen' then
Result := FPImage.clLtGreen Result := FPImage.colLtGreen
else if s = 'olive' then else if s = 'olive' then
Result := FPImage.clOlive Result := FPImage.colOlive
else if s = 'navy' then else if s = 'navy' then
Result := FPImage.clNavy Result := FPImage.colNavy
else if s = 'purple' then else if s = 'purple' then
Result := FPImage.clPurple Result := FPImage.colPurple
else if s = 'teal' then else if s = 'teal' then
Result := FPImage.clTeal Result := FPImage.colTeal
else if s = 'silver' then else if s = 'silver' then
Result := FPImage.clSilver Result := FPImage.colSilver
else if s = 'lime' then else if s = 'lime' then
Result := FPImage.clLime Result := FPImage.colLime
else if s = 'fuchsia' then else if s = 'fuchsia' then
Result := FPImage.clFuchsia Result := FPImage.colFuchsia
else if s = 'aqua' then else if s = 'aqua' then
Result := FPImage.clAqua Result := FPImage.colAqua
else else
Result := FPImage.clTransparent; Result := FPImage.colTransparent;
end; end;
procedure AddColor(const PixelString: string; const AColor: TFPColor); procedure AddColor(const PixelString: string; const AColor: TFPColor;
IntArray: PInteger);
var var
NewEntry: PXPMPixelToColorEntry; NewEntry: PXPMPixelToColorEntry;
i: Integer;
begin begin
{writeln('TLazReaderXPM.InternalRead.AddColor A "',PixelString,'"=', {writeln('TLazReaderXPM.InternalRead.AddColor A "',PixelString,'"=',
HexStr(Cardinal(AColor.Red),4),',', HexStr(Cardinal(AColor.Red),4),',',
@ -1130,12 +1184,15 @@ var
New(NewEntry); New(NewEntry);
NewEntry^.Pixel:=PixelString; NewEntry^.Pixel:=PixelString;
NewEntry^.Color:=AColor; NewEntry^.Color:=AColor;
// add entry to Array Tree
if FPixelToColorTree=nil then if FPixelToColorTree=nil then
FPixelToColorTree:=TAvgLvlTree.Create(@CompareXPMPixelToColorEntries); FPixelToColorTree:=TArrayNodesTree.Create;
FPixelToColorTree.Add(NewEntry); for i:=1 to length(PixelString) do
IntArray[i-1]:=ord(PixelString[i]);
FPixelToColorTree.SetNode(IntArray,length(PixelString),NewEntry);
end; end;
procedure ReadPalette; procedure ReadPalette(IntArray: PInteger);
var var
i: Integer; i: Integer;
Line: TSrcLine; Line: TSrcLine;
@ -1176,22 +1233,22 @@ var
ColorEnd:=ReadPos; ColorEnd:=ReadPos;
NewColor:=TextToColor(ColorStart,ColorEnd); NewColor:=TextToColor(ColorStart,ColorEnd);
end; end;
AddColor(PixelString,NewColor); AddColor(PixelString,NewColor,IntArray);
end; end;
end; end;
procedure ReadPixels; procedure ReadPixels(IntArray: PInteger);
var var
Entry: PXPMPixelToColorEntry; Entry: PXPMPixelToColorEntry;
y: Integer; y: Integer;
Line: TSrcLine; Line: TSrcLine;
ReadPos: Integer; ReadPos: Integer;
Node: TAvgLvlTreeNode;
x: Integer; x: Integer;
i: Integer; i: Integer;
CurColor: TFPColor; CurColor: TFPColor;
ProgressCount: Integer; ProgressCount: Integer;
ContinueReading: Boolean; ContinueReading: Boolean;
CurEntry: PXPMPixelToColorEntry;
begin begin
New(Entry); New(Entry);
SetLength(Entry^.Pixel,FCharsPerPixel); SetLength(Entry^.Pixel,FCharsPerPixel);
@ -1205,13 +1262,30 @@ var
RaiseXPMReadError('line too short',ReadPos); RaiseXPMReadError('line too short',ReadPos);
for x:=0 to FWidth-1 do begin for x:=0 to FWidth-1 do begin
for i:=1 to FCharsPerPixel do begin for i:=1 to FCharsPerPixel do begin
Entry^.Pixel[i]:=Src[ReadPos]; //Entry^.Pixel[i]:=Src[ReadPos];
IntArray[i-1]:=ord(Src[ReadPos]);
inc(ReadPos); inc(ReadPos);
end; end;
Node:=FPixelToColorTree.Find(Entry); CurEntry:=PXPMPixelToColorEntry(
if Node=nil then FPixelToColorTree.FindData(IntArray,FCharsPerPixel));
RaiseXPMReadError('pixel not found',ReadPos-FCharsPerPixel); CurColor:=CurEntry^.Color;
CurColor:=PXPMPixelToColorEntry(Node.Data)^.Color; {if CurEntry2<>CurEntry then begin
writeln('x=',x,' y=',y,' Pixel=',Entry^.Pixel,
' RefPixel=',CurEntry^.Pixel,
' Color=',
HexStr(Cardinal(CurColor.Red),4),',',
HexStr(Cardinal(CurColor.Green),4),',',
HexStr(Cardinal(CurColor.Blue),4),',',
HexStr(Cardinal(CurColor.Alpha),4));
writeln('Entry2: Pixel=',CurEntry2^.Pixel,
' RefPixel=',CurEntry2^.Pixel,
' Color=',
HexStr(Cardinal(CurEntry2^.Color.Red),4),',',
HexStr(Cardinal(CurEntry2^.Color.Green),4),',',
HexStr(Cardinal(CurEntry2^.Color.Blue),4),',',
HexStr(Cardinal(CurEntry2^.Color.Alpha),4));
end;}
{writeln('x=',x,' y=',y,' Pixel=',Entry^.Pixel, {writeln('x=',x,' y=',y,' Pixel=',Entry^.Pixel,
' RefPixel=',PXPMPixelToColorEntry(Node.Data)^.Pixel, ' RefPixel=',PXPMPixelToColorEntry(Node.Data)^.Pixel,
' Color=', ' Color=',
@ -1238,6 +1312,8 @@ var
end; end;
end; end;
var
IntArray: PInteger;
begin begin
ClearPixelToColorTree; ClearPixelToColorTree;
Src:=ReadCompleteStreamToString(Str,1024); Src:=ReadCompleteStreamToString(Str,1024);
@ -1246,8 +1322,14 @@ begin
CurLineNumber:=1; CurLineNumber:=1;
LastLineStart:=1; LastLineStart:=1;
ReadHeader; ReadHeader;
ReadPalette; GetMem(IntArray,SizeOf(Integer)*(FCharsPerPixel+1));
ReadPixels; try
ReadPalette(IntArray);
FPixelToColorTree.ConsistencyCheck;
ReadPixels(IntArray);
finally
FreeMem(IntArray);
end;
end; end;
function TLazReaderXPM.InternalCheck(Str: TStream): boolean; function TLazReaderXPM.InternalCheck(Str: TStream): boolean;
@ -1467,7 +1549,7 @@ var
if (Result.Alpha>=(alphaOpaque shr 1)) then if (Result.Alpha>=(alphaOpaque shr 1)) then
Result.Alpha:=alphaOpaque Result.Alpha:=alphaOpaque
else else
Result:=clTransparent; Result:=colTransparent;
Result.Red:=Result.Red shr FRightShiftSample; Result.Red:=Result.Red shr FRightShiftSample;
Result.Green:=Result.Green shr FRightShiftSample; Result.Green:=Result.Green shr FRightShiftSample;
Result.Blue:=Result.Blue shr FRightShiftSample; Result.Blue:=Result.Blue shr FRightShiftSample;
@ -1710,6 +1792,324 @@ begin
end; end;
end; end;
{ TArrayNode }
constructor TArrayNode.Create;
begin
//writeln('TArrayNode.Create ',Capacity,' Self=',HexStr(Cardinal(Self),8));
end;
destructor TArrayNode.Destroy;
begin
DeleteChilds;
UnbindFromParent;
inherited Destroy;
end;
procedure TArrayNode.DeleteChilds;
var
i: Integer;
begin
if Childs<>nil then begin
for i:=0 to Capacity-1 do
Childs[i].Free;
FreeMem(Childs);
Childs:=nil;
Capacity:=0;
end;
end;
procedure TArrayNode.UnbindFromParent;
begin
if Parent<>nil then begin
Parent.Childs[Value-Parent.StartValue]:=nil;
Parent:=nil;
end;
end;
function TArrayNode.GetChildNode(ChildValue: integer; CreateIfNotExists: boolean
): TArrayNode;
var
Index: Integer;
begin
Result:=nil;
Index:=ChildValue-StartValue;
if (Index<0) or (Index>=Capacity) then begin
// out of range
if not CreateIfNotExists then exit;
Expand(ChildValue);
Index:=ChildValue-StartValue;
end;
Result:=Childs[Index];
if (Result=nil) and CreateIfNotExists then begin
Result:=TArrayNode.Create;
Result.Value:=ChildValue;
Result.Parent:=Self;
Childs[Index]:=Result;
end;
end;
procedure TArrayNode.Expand(ValueToInclude: integer);
var
Index: Integer;
NewChilds: PArrayNode;
NewSize: Integer;
i: Integer;
NewStartValue: Integer;
NewCapacity: Integer;
OldSize: Integer;
begin
//writeln('TArrayNode.Expand A ',ValueToInclude,' Capacity=',Capacity,' StartValue=',StartValue);
if Childs=nil then begin
NewStartValue:=ValueToInclude;
NewCapacity:=4;
end else begin
Index:=ValueToInclude-StartValue;
if (Index>=0) and (Index<Capacity) then exit;
NewStartValue:=StartValue;
NewCapacity:=Capacity;
if NewStartValue>ValueToInclude then begin
inc(NewCapacity,NewStartValue-ValueToInclude);
NewStartValue:=ValueToInclude;
end else begin
Index:=ValueToInclude-NewStartValue;
if Index>=NewCapacity then
NewCapacity:=Index+1;
end;
// make NewCapacity a power of 2
for i:=1 to 30 do begin
if (1 shl i)>=NewCapacity then begin
NewCapacity:=1 shl i;
break;
end;
end;
end;
NewSize:=SizeOf(Pointer)*NewCapacity;
GetMem(NewChilds,NewSize);
FillChar(NewChilds^,NewSize,0);
if Childs<>nil then begin
OldSize:=SizeOf(Pointer)*Capacity;
System.Move(Childs^,NewChilds[StartValue-NewStartValue],OldSize);
FreeMem(Childs);
end;
Childs:=NewChilds;
StartValue:=NewStartValue;
Capacity:=NewCapacity;
end;
function TArrayNode.FindPrevSibling: TArrayNode;
var
i: Integer;
begin
Result:=nil;
if Parent=nil then exit;
i:=Value-Parent.StartValue-1;
while (i>=0) do begin
if Parent.Childs[i]<>nil then begin
Result:=Parent.Childs[i];
exit;
end;
dec(i);
end;
end;
function TArrayNode.FindNextSibling: TArrayNode;
var
i: Integer;
begin
Result:=nil;
if Parent=nil then exit;
i:=Value-Parent.StartValue+1;
while (i<Parent.Capacity) do begin
if Parent.Childs[i]<>nil then begin
Result:=Parent.Childs[i];
exit;
end;
inc(i);
end;
end;
function TArrayNode.FindNext: TArrayNode;
var
SiblingNode: TArrayNode;
begin
Result:=FindFirstChild;
if Result<>nil then exit;
SiblingNode:=Self;
while SiblingNode<>nil do begin
Result:=SiblingNode.FindNextSibling;
if Result<>nil then exit;
SiblingNode:=SiblingNode.Parent;
end;
end;
function TArrayNode.FindPrev: TArrayNode;
begin
Result:=FindPrevSibling;
if Result=nil then begin
Result:=Parent;
exit;
end;
Result:=Result.FindLastSubChild;
end;
function TArrayNode.FindFirstChild: TArrayNode;
var
i: Integer;
begin
Result:=nil;
if Capacity=0 then exit;
i:=0;
while i<Capacity do begin
if Childs[i]<>nil then begin
Result:=Childs[i];
exit;
end;
inc(i);
end;
end;
function TArrayNode.FindLastChild: TArrayNode;
var
i: Integer;
begin
Result:=nil;
if Capacity=0 then exit;
i:=Capacity-1;
while i>=0 do begin
if Childs[i]<>nil then begin
Result:=Childs[i];
exit;
end;
dec(i);
end;
end;
function TArrayNode.FindLastSubChild: TArrayNode;
var
ANode: TArrayNode;
begin
ANode:=Self;
while ANode<>nil do begin
Result:=ANode;
ANode:=ANode.FindLastChild;
end;
end;
function TArrayNode.FindFirstSibling: TArrayNode;
begin
if Parent=nil then
Result:=nil
else
Result:=Parent.FindFirstChild;
end;
function TArrayNode.FindLastSibling: TArrayNode;
begin
if Parent=nil then
Result:=nil
else
Result:=Parent.FindLastChild;
end;
procedure TArrayNode.ConsistencyCheck;
procedure R(const Msg: string);
begin
RaiseGDBException(Msg);
end;
var
i: Integer;
ChildNode: TArrayNode;
begin
if Childs<>nil then begin
if Capacity<=0 then R('Capacity too small');
for i:=0 to Capacity-1 do begin
ChildNode:=Childs[i];
if ChildNode<>nil then begin
if ChildNode.Value<>i+StartValue then
R('Value wrong');
if ChildNode.Parent<>Self then
R('Parent wrong');
ChildNode.ConsistencyCheck;
end;
end;
end else begin
if Capacity<>0 then R('Capacity wrong');
end;
end;
{ TArrayNodesTree }
function TArrayNodesTree.FindNode(IntArray: PInteger; Count: integer
): TArrayNode;
var
i: Integer;
begin
Result:=Root;
i:=0;
while (Result<>nil) and (i<Count) do begin
Result:=Result.GetChildNode(IntArray[i],false);
inc(i);
end;
end;
function TArrayNodesTree.FindData(IntArray: PInteger; Count: integer): Pointer;
var
ANode: TArrayNode;
begin
ANode:=FindNode(IntArray,Count);
if ANode<>nil then
Result:=ANode.Data
else
Result:=nil;
end;
function TArrayNodesTree.SetNode(IntArray: PInteger; Count: integer;
Data: Pointer): TArrayNode;
var
i: Integer;
begin
if Root=nil then
Root:=TArrayNode.Create;
Result:=Root;
for i:=0 to Count-1 do begin
//writeln('TArrayNodesTree.SetNode A ',HexStr(Cardinal(Result),8));
Result:=Result.GetChildNode(IntArray[i],true);
end;
Result.Data:=Data;
end;
procedure TArrayNodesTree.Delete(Node: TArrayNode);
begin
if Node=nil then exit;
if Node=Root then Root:=nil;
Node.Free;
end;
procedure TArrayNodesTree.Clear;
begin
Delete(Root);
end;
constructor TArrayNodesTree.Create;
begin
end;
destructor TArrayNodesTree.Destroy;
begin
Clear;
inherited Destroy;
end;
procedure TArrayNodesTree.ConsistencyCheck;
begin
if Root<>nil then
Root.ConsistencyCheck;
end;
initialization initialization
InternalInit; InternalInit;