unit mqueue;

{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}

interface

type
 P_TAILQ_HEAD=^TAILQ_HEAD;
 TAILQ_HEAD=packed record
  tqh_first:Pointer;
  tqh_last :PPointer;
 end;

 P_TAILQ_ENTRY=^TAILQ_ENTRY;
 TAILQ_ENTRY=packed record
  tqe_next:Pointer;
  tqe_prev:PPointer;
 end;

 P_LIST_HEAD=^LIST_HEAD;
 LIST_HEAD=packed record
  lh_first:Pointer;
 end;

 P_LIST_ENTRY=^LIST_ENTRY;
 LIST_ENTRY=packed record
  le_next:Pointer;
  le_prev:PPointer;
 end;

 P_STAILQ_HEAD=^STAILQ_HEAD;
 STAILQ_HEAD=packed record
  stqh_first:Pointer;
  stqh_last :PPointer;
 end;

 P_STAILQ_ENTRY=^STAILQ_ENTRY;
 STAILQ_ENTRY=packed record
  stqe_next:Pointer;
 end;

 P_SLIST_HEAD=^SLIST_HEAD;
 SLIST_HEAD=packed record
  slh_first:Pointer;
 end;

 P_SLIST_ENTRY=^SLIST_ENTRY;
 SLIST_ENTRY=packed record
  sle_next:Pointer;
 end;

procedure TAILQ_INIT         (head:Pointer); inline;
function  TAILQ_EMPTY        (head:Pointer):Boolean; inline;
function  TAILQ_FIRST        (head:Pointer):Pointer; inline;
function  TAILQ_LAST         (head:Pointer):Pointer; inline;
function  TAILQ_NEXT         (elm,field:Pointer):Pointer; inline;
function  TAILQ_PREV         (elm,field:Pointer):Pointer; inline;
procedure TAILQ_INSERT_HEAD  (head,elm,field:Pointer); inline;
procedure TAILQ_INSERT_TAIL  (head,elm,field:Pointer); inline;
procedure TAILQ_INSERT_AFTER (head,listelm,elm,field:Pointer); inline;
procedure TAILQ_INSERT_BEFORE(listelm,elm,field:Pointer); inline;
procedure TAILQ_REMOVE       (head,elm,field:Pointer); inline;
procedure TAILQ_CONCAT       (head1,head2,field:Pointer); inline;

procedure LIST_INIT        (head:Pointer); inline;
function  LIST_EMPTY       (head:Pointer):Boolean; inline;
function  LIST_FIRST       (head:Pointer):Pointer; inline;
function  LIST_NEXT        (elm,field:Pointer):Pointer; inline;
procedure LIST_INSERT_HEAD (head,elm,field:Pointer); inline;
procedure LIST_REMOVE      (elm,field:Pointer); inline;

procedure STAILQ_INIT        (head:Pointer); inline;
function  STAILQ_EMPTY       (head:Pointer):Boolean; inline;
function  STAILQ_FIRST       (head:Pointer):Pointer; inline;
function  STAILQ_LAST        (head,field:Pointer):Pointer; inline;
function  STAILQ_NEXT        (elm,field:Pointer):Pointer; inline;
procedure STAILQ_INSERT_AFTER(head,tqelm,elm,field:Pointer); inline;
procedure STAILQ_INSERT_HEAD (head,elm,field:Pointer); inline;
procedure STAILQ_INSERT_TAIL (head,elm,field:Pointer); inline;
procedure STAILQ_REMOVE_AFTER(head,elm,field:Pointer); inline;
procedure STAILQ_REMOVE_HEAD (head,field:Pointer); inline;
procedure STAILQ_REMOVE      (head,elm,field:Pointer); inline;

procedure SLIST_INIT        (head:Pointer); inline;
function  SLIST_EMPTY       (head:Pointer):Boolean; inline;
function  SLIST_FIRST       (head:Pointer):Pointer; inline;
function  SLIST_NEXT        (elm,field:Pointer):Pointer; inline;
procedure SLIST_INSERT_AFTER(slistelm,elm,field:Pointer); inline;
procedure SLIST_INSERT_HEAD (head,elm,field:Pointer); inline;
procedure SLIST_REMOVE_AFTER(elm,field:Pointer); inline;
procedure SLIST_REMOVE_HEAD (head,field:Pointer); inline;
procedure SLIST_REMOVE      (head,elm,field:Pointer); inline;

implementation

procedure TAILQ_INIT(head:Pointer); inline;
begin
 P_TAILQ_HEAD(head)^.tqh_first:=nil;
 P_TAILQ_HEAD(head)^.tqh_last :=@P_TAILQ_HEAD(head)^.tqh_first;
end;

function TAILQ_EMPTY(head:Pointer):Boolean; inline;
begin
 Result:=P_TAILQ_HEAD(head)^.tqh_first=nil;
end;

function TAILQ_FIRST(head:Pointer):Pointer; inline;
begin
 Result:=P_TAILQ_HEAD(head)^.tqh_first;
end;

function TAILQ_LAST(head:Pointer):Pointer; inline;
begin
 Result:=P_TAILQ_HEAD(P_TAILQ_HEAD(head)^.tqh_last)^.tqh_last^;
end;

function TAILQ_NEXT(elm,field:Pointer):Pointer; inline;
begin
 Result:=P_TAILQ_ENTRY(field)^.tqe_next;
end;

function TAILQ_PREV(elm,field:Pointer):Pointer; inline;
begin
 Result:=P_TAILQ_HEAD(P_TAILQ_ENTRY(field)^.tqe_prev)^.tqh_last^;
end;

procedure TAILQ_INSERT_HEAD(head,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 P_TAILQ_ENTRY(field)^.tqe_next:=P_TAILQ_HEAD(head)^.tqh_first;
 if (P_TAILQ_ENTRY(field)^.tqe_next<>nil) then
 begin
  offset:=ptruint(field-elm);
  P_TAILQ_ENTRY(P_TAILQ_HEAD(head)^.tqh_first+offset)^.tqe_prev:=@P_TAILQ_ENTRY(field)^.tqe_next;
 end else
 begin
  P_TAILQ_HEAD(head)^.tqh_last:=@P_TAILQ_ENTRY(field)^.tqe_next;
 end;
 P_TAILQ_HEAD(head)^.tqh_first:=elm;
 P_TAILQ_ENTRY(field)^.tqe_prev:=@P_TAILQ_HEAD(head)^.tqh_first;
end;

procedure TAILQ_INSERT_TAIL(head,elm,field:Pointer); inline;
begin
 P_TAILQ_ENTRY(field)^.tqe_next:=nil;
 P_TAILQ_ENTRY(field)^.tqe_prev:=P_TAILQ_HEAD(head)^.tqh_last;
 P_TAILQ_HEAD(head)^.tqh_last^:=elm;
 P_TAILQ_HEAD(head)^.tqh_last:=@P_TAILQ_ENTRY(field)^.tqe_next;
end;

procedure TAILQ_INSERT_AFTER(head,listelm,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 offset:=ptruint(field-elm);
 P_TAILQ_ENTRY(field)^.tqe_next:=P_TAILQ_ENTRY(listelm+offset)^.tqe_next;
 if (P_TAILQ_ENTRY(field)^.tqe_next<>nil) then
 begin
  P_TAILQ_ENTRY(P_TAILQ_ENTRY(field)^.tqe_next+offset)^.tqe_prev:=@P_TAILQ_ENTRY(field)^.tqe_next;
 end else
 begin
  P_TAILQ_HEAD(head)^.tqh_last:=@P_TAILQ_ENTRY(field)^.tqe_next;
 end;
 P_TAILQ_ENTRY(listelm+offset)^.tqe_next:=(elm);
 P_TAILQ_ENTRY(field)^.tqe_prev:=@P_TAILQ_ENTRY(listelm+offset)^.tqe_next;
end;

procedure TAILQ_INSERT_BEFORE(listelm,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 offset:=ptruint(field-elm);
 P_TAILQ_ENTRY(field)^.tqe_prev:=P_TAILQ_ENTRY(listelm+offset)^.tqe_prev;
 P_TAILQ_ENTRY(field)^.tqe_next:=listelm;
 P_TAILQ_ENTRY(listelm+offset)^.tqe_prev^:=elm;
 P_TAILQ_ENTRY(listelm+offset)^.tqe_prev:=@P_TAILQ_ENTRY(field)^.tqe_next;
end;

procedure TAILQ_REMOVE(head,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 if (P_TAILQ_ENTRY(field)^.tqe_next<>nil) then
 begin
  offset:=ptruint(field-elm);
  P_TAILQ_ENTRY(P_TAILQ_ENTRY(field)^.tqe_next+offset)^.tqe_prev:=P_TAILQ_ENTRY(field)^.tqe_prev;
 end else
 begin
  P_TAILQ_HEAD(head)^.tqh_last:=P_TAILQ_ENTRY(field)^.tqe_prev;
 end;
 P_TAILQ_ENTRY(field)^.tqe_prev^:=P_TAILQ_ENTRY(field)^.tqe_next;
end;

procedure TAILQ_CONCAT(head1,head2,field:Pointer); inline;
begin
 if (P_TAILQ_HEAD(head2)^.tqh_first<>nil) then
 begin
  P_TAILQ_HEAD(head1)^.tqh_last^:=P_TAILQ_HEAD(head2)^.tqh_first;
  P_TAILQ_ENTRY(P_TAILQ_HEAD(head2)^.tqh_first+ptruint(field))^.tqe_prev:=P_TAILQ_HEAD(head1)^.tqh_last;
  P_TAILQ_HEAD(head1)^.tqh_last:=P_TAILQ_HEAD(head2)^.tqh_last;
  TAILQ_INIT(head2);
 end;
end;

//

procedure LIST_INIT(head:Pointer); inline;
begin
 P_LIST_HEAD(head)^.lh_first:=nil;
end;

function LIST_EMPTY(head:Pointer):Boolean; inline;
begin
 Result:=P_LIST_HEAD(head)^.lh_first=nil;
end;

function LIST_FIRST(head:Pointer):Pointer; inline;
begin
 Result:=P_LIST_HEAD(head)^.lh_first;
end;

function LIST_NEXT(elm,field:Pointer):Pointer; inline;
begin
 Result:=P_LIST_ENTRY(field)^.le_next;
end;

procedure LIST_INSERT_HEAD(head,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 P_LIST_ENTRY(field)^.le_next:=P_LIST_HEAD(head)^.lh_first;
 if (P_LIST_ENTRY(field)^.le_next<>nil) then
 begin
  offset:=ptruint(field-elm);
  P_LIST_ENTRY(P_LIST_HEAD(head)^.lh_first+offset)^.le_prev:=@P_LIST_ENTRY(field)^.le_next;
 end;
 P_LIST_HEAD(head)^.lh_first:=elm;
 P_LIST_ENTRY(field)^.le_prev:=head;
end;

procedure LIST_REMOVE(elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 if (P_LIST_ENTRY(field)^.le_next<>nil) then
 begin
  offset:=ptruint(field-elm);
  P_LIST_ENTRY(P_LIST_ENTRY(field)^.le_next+offset)^.le_prev:=P_LIST_ENTRY(field)^.le_prev;
 end;
 P_LIST_ENTRY(field)^.le_prev^:=P_LIST_ENTRY(field)^.le_next;
end;

//

procedure STAILQ_INIT(head:Pointer); inline;
begin
 P_STAILQ_HEAD(head)^.stqh_first:=nil;
 P_STAILQ_HEAD(head)^.stqh_last :=@P_STAILQ_HEAD(head)^.stqh_first;
end;

function STAILQ_EMPTY(head:Pointer):Boolean; inline;
begin
 Result:=P_STAILQ_HEAD(head)^.stqh_first=nil;
end;

function STAILQ_FIRST(head:Pointer):Pointer; inline;
begin
 Result:=P_STAILQ_HEAD(head)^.stqh_first;
end;

function STAILQ_LAST(head,field:Pointer):Pointer; inline;
begin
 if (P_STAILQ_HEAD(head)^.stqh_first=nil) then
 begin
  Result:=nil;
 end else
 begin
  Result:=Pointer(P_STAILQ_HEAD(head)^.stqh_last)-ptruint(@P_STAILQ_ENTRY(field)^.stqe_next);
 end;
end;

function STAILQ_NEXT(elm,field:Pointer):Pointer; inline;
begin
 Result:=P_STAILQ_ENTRY(field)^.stqe_next;
end;

procedure STAILQ_INSERT_AFTER(head,tqelm,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 offset:=ptruint(field-elm);
 P_STAILQ_ENTRY(field)^.stqe_next:=P_STAILQ_ENTRY(tqelm+offset)^.stqe_next;
 if (P_STAILQ_ENTRY(field)^.stqe_next=nil) then
 begin
  P_STAILQ_HEAD(head)^.stqh_last:=@P_STAILQ_ENTRY(field)^.stqe_next;
 end;
 P_STAILQ_ENTRY(tqelm+offset)^.stqe_next:=elm;
end;

procedure STAILQ_INSERT_HEAD(head,elm,field:Pointer); inline;
begin
 P_STAILQ_ENTRY(field)^.stqe_next:=P_STAILQ_HEAD(head)^.stqh_first;
 if (P_STAILQ_HEAD(head)^.stqh_first=nil) then
 begin
  P_STAILQ_HEAD(head)^.stqh_last:=@P_STAILQ_ENTRY(field)^.stqe_next;
 end;
 P_STAILQ_HEAD(head)^.stqh_first:=elm;
end;

procedure STAILQ_INSERT_TAIL(head,elm,field:Pointer); inline;
begin
 P_STAILQ_ENTRY(field)^.stqe_next:=nil;
 P_STAILQ_HEAD(head)^.stqh_last^:=elm;
 P_STAILQ_HEAD(head)^.stqh_last:=@P_STAILQ_ENTRY(field)^.stqe_next;
end;

procedure STAILQ_REMOVE_AFTER(head,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 offset:=ptruint(field-elm);
 P_STAILQ_ENTRY(field)^.stqe_next:=P_STAILQ_ENTRY(P_STAILQ_ENTRY(field)^.stqe_next+offset)^.stqe_next;
 if (P_STAILQ_ENTRY(field)^.stqe_next=nil) then
 begin
  P_STAILQ_HEAD(head)^.stqh_last:=@P_STAILQ_ENTRY(field)^.stqe_next;
 end;
end;

procedure STAILQ_REMOVE_HEAD(head,field:Pointer); inline;
begin
 P_STAILQ_HEAD(head)^.stqh_first:=P_STAILQ_ENTRY(P_STAILQ_HEAD(head)^.stqh_first+ptruint(field))^.stqe_next;
 if (P_STAILQ_HEAD(head)^.stqh_first=nil) then
 begin
  P_STAILQ_HEAD(head)^.stqh_last:=@P_STAILQ_HEAD(head)^.stqh_first;
 end;
end;

procedure STAILQ_REMOVE(head,elm,field:Pointer); inline;
var
 offset:ptruint;
 curelm:Pointer;
begin
 offset:=ptruint(field-elm);
 if (P_STAILQ_HEAD(head)^.stqh_first=elm) then
 begin
  STAILQ_REMOVE_HEAD(head,Pointer(offset));
 end else
 begin
  curelm:=P_STAILQ_HEAD(head)^.stqh_first;
  while (P_STAILQ_ENTRY(curelm+offset)^.stqe_next<>elm) do
  begin
   curelm:=P_STAILQ_ENTRY(curelm+offset)^.stqe_next;
  end;
  STAILQ_REMOVE_AFTER(head,curelm,curelm+offset);
 end;
end;

//

procedure SLIST_INIT(head:Pointer); inline;
begin
 P_SLIST_HEAD(head)^.slh_first:=nil;
end;

function SLIST_EMPTY(head:Pointer):Boolean; inline;
begin
 Result:=P_SLIST_HEAD(head)^.slh_first=nil;
end;

function SLIST_FIRST(head:Pointer):Pointer; inline;
begin
 Result:=P_SLIST_HEAD(head)^.slh_first;
end;

function SLIST_NEXT(elm,field:Pointer):Pointer; inline;
begin
 Result:=P_SLIST_ENTRY(field)^.sle_next;
end;

procedure SLIST_INSERT_AFTER(slistelm,elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 offset:=ptruint(field-elm);
 P_SLIST_ENTRY(field)^.sle_next:=P_SLIST_ENTRY(slistelm+offset)^.sle_next;
 P_SLIST_ENTRY(slistelm+offset)^.sle_next:=elm;
end;

procedure SLIST_INSERT_HEAD(head,elm,field:Pointer); inline;
begin
 P_SLIST_ENTRY(field)^.sle_next:=P_SLIST_HEAD(head)^.slh_first;
 P_SLIST_HEAD(head)^.slh_first:=elm;
end;

procedure SLIST_REMOVE_AFTER(elm,field:Pointer); inline;
var
 offset:ptruint;
begin
 offset:=ptruint(field-elm);
 P_SLIST_ENTRY(field)^.sle_next:=P_SLIST_ENTRY(P_SLIST_ENTRY(field)^.sle_next+offset)^.sle_next;
end;

procedure SLIST_REMOVE_HEAD(head,field:Pointer); inline;
begin
 P_SLIST_HEAD(head)^.slh_first:=P_SLIST_ENTRY(P_SLIST_HEAD(head)^.slh_first+ptruint(field))^.sle_next;
end;

procedure SLIST_REMOVE(head,elm,field:Pointer); inline;
var
 offset:ptruint;
 curelm:Pointer;
begin
 offset:=ptruint(field-elm);
 if (P_SLIST_HEAD(head)^.slh_first=elm) then
 begin
  SLIST_REMOVE_HEAD(head,Pointer(offset));
 end else
 begin
  curelm:=P_SLIST_HEAD(head)^.slh_first;
  while (P_SLIST_ENTRY(curelm+offset)^.sle_next<>elm) do
  begin
   curelm:=P_SLIST_ENTRY(curelm+offset)^.sle_next;
  end;
  SLIST_REMOVE_AFTER(curelm,curelm+offset);
 end;
end;


end.

