paxCompiler/Sources/PAXCOMP_OFFSET.pas
Dalibor Marković 9d0de424e8
Init
Signed-off-by: Dalibor Marković <dalibor31@gmail.com>
2024-07-06 22:28:12 +02:00

299 lines
6.1 KiB
ObjectPascal

////////////////////////////////////////////////////////////////////////////
// PaxCompiler
// Site: http://www.paxcompiler.com
// Author: Alexander Baranovsky (paxscript@gmail.com)
// ========================================================================
// Copyright (c) Alexander Baranovsky, 2006-2014. All rights reserved.
// Code Version: 4.2
// ========================================================================
// Unit: PAXCOMP_SYMBOL_OFFSET.pas
// ========================================================================
////////////////////////////////////////////////////////////////////////////
{$I PaxCompiler.def}
{$O+}
unit PAXCOMP_OFFSET;
interface
uses {$I uses.def}
TypInfo,
SysUtils,
Classes,
PAXCOMP_CONSTANTS,
PAXCOMP_TYPES,
PAXCOMP_SYS;
type
TOffsetRec = class
public
Id: Integer;
Shift: Integer;
Offset: Integer;
Size: Integer;
function Clone: TOffsetRec;
procedure SaveToStream(S: TStream);
procedure LoadFromStream(S: TStream);
end;
TOffsetList = class(TTypedList)
private
Sorted: Boolean;
function GetRecord(I: Integer): TOffsetRec;
procedure SetRecord(I: Integer; value: TOffsetRec);
public
InitSize: Integer;
constructor Create;
function Add(Id, Shift, Offset, Size: Integer): TOffsetRec;
procedure Clear; override;
function Clone: TOffsetList;
function GetSize: Integer;
function GetOffset(Shift: Integer): Integer;
function HasId(Id: Integer): Boolean;
procedure SaveToStream(S: TStream);
procedure LoadFromStream(S: TStream);
function GetOffsetById(Id: Integer): Integer;
property Records[I: Integer]: TOffsetRec read GetRecord write SetRecord; default;
end;
procedure TOffsetList_Sort(Self: TOffsetList);
implementation
// TOffsetRec ------------------------------------------------------------------
function TOffsetRec.Clone: TOffsetRec;
begin
result := TOffsetRec.Create;
result.Id := Id;
result.Shift := Shift;
result.Offset := Offset;
result.Size := Size;
end;
procedure TOffsetRec.SaveToStream(S: TStream);
begin
S.Write(Shift, SizeOf(Shift));
S.Write(Offset, SizeOf(Offset));
end;
procedure TOffsetRec.LoadFromStream(S: TStream);
begin
S.Read(Shift, SizeOf(Shift));
S.Read(Offset, SizeOf(Offset));
end;
// TOffsetList -----------------------------------------------------------------
constructor TOffsetList.Create;
begin
inherited;
InitSize := 0;
Sorted := false;
end;
function TOffsetList.Add(Id, Shift, Offset, Size: Integer): TOffsetRec;
begin
result := TOffsetRec.Create;
result.Id := Id;
result.Shift := Shift;
result.Offset := Offset;
result.Size := Size;
L.Add(result);
end;
function TOffsetList.GetSize: Integer;
var
I, SZ: Integer;
begin
result := InitSize;
for I := 0 to Count - 1 do
begin
SZ := Records[I].Size;
Inc(result, SZ);
end;
end;
function BinSearch(List: TOffsetList; const Key: Integer): Integer;
var
First: Integer;
Last: Integer;
Pivot: Integer;
Found: Boolean;
begin
First := 0;
Last := List.Count - 1;
Found := False;
Result := -1;
while (First <= Last) and (not Found) do
begin
Pivot := (First + Last) div 2;
if TOffsetRec(List.L[Pivot]).Shift = Key then
begin
Found := True;
Result := Pivot;
end
else if TOffsetRec(List.L[Pivot]).Shift > Key then
Last := Pivot - 1
else
First := Pivot + 1;
end;
end;
function TOffsetList.GetOffset(Shift: Integer): Integer;
var
I: Integer;
R: TOffsetRec;
begin
result := -1;
if Shift < StdSize then
begin
result := Shift;
Exit;
end;
if Sorted then
begin
I := BinSearch(Self, Shift);
if I = -1 then
Exit;
result := Records[I].Offset;
Exit;
end;
for I := 0 to Count - 1 do
begin
R := Records[I];
if R.Shift = Shift then
begin
result := R.Offset;
Exit;
end;
end;
end;
function TOffsetList.HasId(Id: Integer): Boolean;
var
I: Integer;
R: TOffsetRec;
begin
for I := 0 to Count - 1 do
begin
R := Records[I];
if R.Id = Id then
begin
result := true;
Exit;
end;
end;
result := false;
end;
function TOffsetList.GetRecord(I: Integer): TOffsetRec;
begin
result := TOffsetRec(L[I]);
end;
procedure TOffsetList.SetRecord(I: Integer; value: TOffsetRec);
begin
L[I] := value;
end;
function TOffsetList.GetOffsetById(Id: Integer): Integer;
var
I: Integer;
begin
for I:=0 to Count - 1 do
if Records[I].Id = Id then
begin
result := Records[I].Offset;
Exit;
end;
raise Exception.Create(errInternalError);
end;
procedure TOffsetList.Clear;
begin
inherited;
InitSize := 0;
Sorted := false;
end;
function TOffsetList.Clone: TOffsetList;
var
I: Integer;
R: TOffsetRec;
begin
result := TOffsetList.Create;
for I := 0 to Count - 1 do
begin
R := Records[I].Clone;
result.L.Add(R);
end;
end;
procedure TOffsetList.SaveToStream(S: TStream);
var
I, K: Integer;
begin
K := Count;
S.Write(K, SizeOf(Integer));
for I := 0 to K - 1 do
Records[I].SaveToStream(S);
end;
procedure TOffsetList.LoadFromStream(S: TStream);
var
I, K: Integer;
R: TOffsetRec;
begin
S.Read(K, SizeOf(Integer));
for I := 0 to K - 1 do
begin
R := TOffsetRec.Create;
R.LoadFromStream(S);
L.Add(R);
end;
end;
procedure QuickSort(var List: TOffsetList; Start, Stop: Integer);
var
Left: Integer;
Right: Integer;
Mid: Integer;
Pivot: TOffsetRec;
Temp: TOffsetRec;
begin
Left := Start;
Right := Stop;
Mid := (Start + Stop) div 2;
Pivot := List[mid];
repeat
while List[Left].Shift < Pivot.Shift do Inc(Left);
while Pivot.Shift < List[Right].Shift do Dec(Right);
if Left <= Right then
begin
Temp := List[Left];
List[Left] := List[Right]; // Swops the two Strings
List[Right] := Temp;
Inc(Left);
Dec(Right);
end;
until Left > Right;
if Start < Right then QuickSort(List, Start, Right); // Uses
if Left < Stop then QuickSort(List, Left, Stop); // Recursion
end;
procedure TOffsetList_Sort(Self: TOffsetList);
begin
if Self.Count > 0 then
begin
QuickSort(Self, 0, Self.Count - 1);
Self.Sorted := true;
end;
end;
end.