unit dleb128;

{$MODE FPC}
{$MODESWITCH DEFAULTPARAMETERS}
{$MODESWITCH OUT}
{$MODESWITCH RESULT}

interface

function EncodeLEB128(Value: Int32;  P, PEnd: Pointer): Boolean; overload;
function EncodeLEB128(Value: UInt32; P, PEnd: Pointer): Boolean; overload;
function EncodeLEB128(Value: Int64;  P, PEnd: Pointer): Boolean; overload;
function EncodeLEB128(Value: UInt64; P, PEnd: Pointer): Boolean; overload;

function DecodeLEB128(P, PEnd: Pointer; out Value: Int32):  Boolean; overload;
function DecodeLEB128(P, PEnd: Pointer; out Value: UInt32): Boolean; overload;
function DecodeLEB128(P, PEnd: Pointer; out Value: Int64):  Boolean; overload;
function DecodeLEB128(P, PEnd: Pointer; out Value: UInt64): Boolean; overload;

function LEB128Sign(P, PEnd: Pointer): PtrInt;
function LEB128IsZero(P, PEnd: Pointer): Boolean; inline;
function LEB128IsPositive(P, PEnd: Pointer): Boolean; inline;
function LEB128IsNegative(P, PEnd: Pointer): Boolean; inline;

function LEB128Compare(A, AEnd, B, BEnd: Pointer): PtrInt;

function LEB128Add(A, AEnd, B, BEnd: Pointer;
                   C, CEnd: Pointer;
                   out NewCEnd: Pointer): Boolean;
function LEB128Sub(A, AEnd, B, BEnd: Pointer;
                   C, CEnd: Pointer;
                   out NewCEnd: Pointer): Boolean;
function LEB128Mul(A, AEnd, B, BEnd: Pointer;
                   C, CEnd: Pointer;
                   out NewCEnd: Pointer): Boolean;
function LEB128Div(A, AEnd, B, BEnd: Pointer;
                   C, CEnd: Pointer;
                   out NewCEnd: Pointer): Boolean;
function LEB128Mod(A, AEnd, B, BEnd: Pointer;
                   C, CEnd: Pointer;
                   out NewCEnd: Pointer): Boolean;

implementation

function LEB128Sign(P, PEnd: Pointer): PtrInt;
begin
  if P >= PEnd then
    Exit(0);
  if (PByte(P)^ and %01000000) <> 0 then
    Exit(-1);
  while P < PEnd do begin
    if (PByte(P)^ and %01111111) <> 0 then
      Exit(1);
  end;
  Exit(0);
end;

function LEB128IsZero(P, PEnd: Pointer): Boolean;
begin
  Exit(LEB128Sign(P, PEnd) = 0);
end;

function LEB128IsPositive(P, PEnd: Pointer): Boolean;
begin
  Exit(LEB128Sign(P, PEnd) > 0);
end;

function LEB128IsNegative(P, PEnd: Pointer): Boolean;
begin
  Exit(LEB128Sign(P, PEnd) < 0);
end;


end.
