Asuro/src/include/lists.pas
Kieron Morris 64b3c9a7ba Apache License
Added the apache license to all source files, accounting for authors. Also added a license.md containing the apache license + contributors.md listing all contributors.
2021-06-22 21:31:17 +01:00

354 lines
9.3 KiB
ObjectPascal

// Copyright 2021 Kieron Morris
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
{
Include->Lists - Linked List Data Structures & Helpers.
@author(Kieron Morris <kjm@kieronmorris.me>)
}
unit lists;
interface
uses
console,
lmemorymanager,
util,
tracer;
type
{ Managed Linked List }
PLinkedList = ^TLinkedList;
TLinkedList = record
Previous : PLinkedList;
Data : void;
Next : PLinkedList;
end;
PLinkedListBase = ^TLinkedListBase;
TLinkedListBase = record
Count : uint32;
Head : PLinkedList;
ElementSize : uint32;
end;
{ String Linked List }
procedure STRLL_Add(LinkedList : PLinkedListBase; str : pchar);
function STRLL_Get(LinkedList : PLinkedListBase; idx : uint32) : pchar;
function STRLL_New : PLinkedListBase;
function STRLL_Size(LinkedList : PLinkedListBase) : uint32;
procedure STRLL_Delete(LinkedList : PLinkedListBase; idx : uint32);
procedure STRLL_Free(LinkedList : PLinkedListBase);
procedure STRLL_Clear(LinkedList : PLinkedListBase);
function STRLL_FromString(str : pchar; delimter : char) : PLinkedListBase;
{ Managed Linked List }
function LL_New(ElementSize : uint32) : PLinkedListBase;
function LL_Add(LinkedList : PLinkedListBase) : Void;
function LL_Delete(LinkedList : PLinkedListBase; idx : uint32) : boolean;
function LL_Size(LinkedList : PLinkedListBase) : uint32;
function LL_Insert(LinkedList : PLinkedListBase; idx : uint32) : Void;
function LL_Get(LinkedList : PLinkedListBase; idx : uint32) : Void;
procedure LL_Free(LinkedList : PLinkedListBase);
function LL_FromString(str : pchar; delimter : char) : PLinkedListBase;
implementation
uses
strings;
{ Managed Linked List }
function LL_New(ElementSize : uint32) : PLinkedListBase;
begin
LL_New:= PLinkedListBase(kalloc(sizeof(TLinkedListBase)));
LL_New^.ElementSize:= ElementSize;
LL_New^.Count:= 0;
LL_New^.Head:= nil;
end;
function LL_Add(LinkedList : PLinkedListBase) : Void;
var
Element : PLinkedList;
Base : PLinkedList;
Count : uint32;
begin
if LinkedList^.Head = nil then begin
Element:= PLinkedList(kalloc(sizeof(TLinkedList)));
Element^.Previous:= nil;
Element^.Next:= nil;
Element^.Data:= kalloc(LinkedList^.ElementSize);
memset(uint32(Element^.Data), 0, LinkedList^.ElementSize);
LinkedList^.Head:= Element;
LinkedList^.Count:= LinkedList^.Count + 1;
LL_Add:= Element^.Data;
end else begin
Base:= LinkedList^.Head;
Count:= 1;
While Base^.Next <> nil do begin
Base:= Base^.Next;
Count:= Count + 1;
end;
Element:= PLinkedList(kalloc(sizeof(TLinkedList)));
Base^.Next:= Element;
Element^.Previous:= Base;
Element^.Next:= nil;
Element^.Data:= kalloc(LinkedList^.ElementSize);
memset(uint32(Element^.Data), 0, LinkedList^.ElementSize);
LinkedList^.Count:= LinkedList^.Count + 1;
LL_Add:= Element^.Data;
end;
end;
function LL_Delete(LinkedList : PLinkedListBase; idx : uint32) : boolean;
var
Prev, Next : PLinkedList;
Base : PLinkedList;
i : uint32;
begin
Base:= LinkedList^.Head;
i:= 0;
while (i < idx) and (Base <> nil) do begin
i:= i + 1;
Base:= Base^.Next;
end;
if Base = nil then begin
LL_Delete:= false;
exit;
end;
Prev:= Base^.Previous;
Next:= Base^.Next;
if Prev = nil then begin
LinkedList^.Head:= Next;
end else begin
Prev^.Next:= Next;
end;
if Next <> nil then begin
Next^.Previous:= Prev;
end;
LinkedList^.Count:= LinkedList^.Count - 1;
kfree(void(Base^.Data));
kfree(void(Base));
LL_Delete:= True;
end;
function LL_Size(LinkedList : PLinkedListBase) : uint32;
begin
LL_Size:= LinkedList^.Count;
end;
function LL_Insert(LinkedList : PLinkedListBase; idx : uint32) : void;
var
i : uint32;
Base : PLinkedList;
Prev, Next : PLinkedList;
Element : PLinkedList;
begin
LL_Insert:= nil;
if idx > LinkedList^.Count then exit;
Base:= LinkedList^.Head;
i:=0;
while (i < idx) and (Base <> nil) do begin
i:= i + 1;
Base:= Base^.Next;
end;
if i = 0 then begin
Element:= PLinkedList(kalloc(sizeof(TLinkedList)));
Element^.Data:= kalloc(LinkedList^.ElementSize);
memset(uint32(Element^.Data), 0, LinkedList^.ElementSize);
Element^.Next:= LinkedList^.Head;
Element^.Previous:= nil;
LinkedList^.Head:= Element;
LinkedList^.Count:= LinkedList^.Count + 1;
LL_Insert:= Element^.Data;
end else begin
if Base = nil then exit;
Prev:= Base^.Previous;
Next:= Base;
Element:= PLinkedList(kalloc(sizeof(TLinkedList)));
Element^.Data:= kalloc(LinkedList^.ElementSize);
memset(uint32(Element^.Data), 0, LinkedList^.ElementSize);
Element^.Previous:= Prev;
Element^.Next:= Next;
if Prev = nil then begin
LinkedList^.Head:= Element;
end else begin
Prev^.Next:= Element;
end;
if Next <> nil then begin
Next^.Previous:= Element;
end;
LinkedList^.Count:= LinkedList^.Count + 1;
LL_Insert:= Element^.Data;
end;
end;
function LL_Get(LinkedList : PLinkedListBase; idx : uint32) : void;
var
i : uint32;
Base : PLinkedList;
begin
LL_Get:= nil;
if idx >= LinkedList^.Count then exit;
Base:= LinkedList^.Head;
i:=0;
while (i < idx) and (Base <> nil) do begin
i:= i + 1;
Base:= Base^.Next;
end;
if Base = nil then exit;
LL_Get:= Base^.Data;
end;
procedure LL_Free(LinkedList : PLinkedListBase);
begin
while LL_Size(LinkedList) > 0 do begin
LL_Delete(LinkedList, 0);
end;
kfree(void(LinkedList));
end;
function LL_FromString(str : pchar; delimter : char) : PLinkedListBase;
var
list : PLinkedListBase;
i : uint32 = 0;
out_str : pchar;
elm : puint32;
head : pchar;
tail : pchar;
size : uint32;
null_delim : boolean;
begin
list := LL_New(sizeof(uint32));
LL_FromString:= list;
head:= str;
tail:= head;
null_delim:= false;
while not null_delim do begin
if (head^ = delimter) or (head^ = char(0)) then begin
if head^ = char(0) then null_delim:= true;
size:= uint32(head) - uint32(tail);
if size > 0 then begin
elm:= puint32(LL_Add(list));
out_str:= stringNew(size + 1); //maybe
memcpy(uint32(tail), uint32(out_str), size);
elm^:= uint32(out_str);
end;
tail:= head+1;
end;
inc(head);
end;
end;
{ String Linked List }
procedure STRLL_Add(LinkedList : PLinkedListBase; str : pchar);
var
ptr : puint32;
begin
ptr:= puint32(LL_Add(LinkedList));
ptr^:= uint32(str);
end;
function STRLL_Get(LinkedList : PLinkedListBase; idx : uint32) : pchar;
var
ptr : puint32;
begin
ptr:= puint32(LL_Get(LinkedList, idx));
STRLL_Get:= nil;
if ptr <> nil then begin
STRLL_Get:= pchar(ptr^);
end;
end;
function STRLL_New : PLinkedListBase;
begin
STRLL_New:= LL_New(sizeof(uint32));
end;
function STRLL_Size(LinkedList : PLinkedListBase) : uint32;
begin
STRLL_Size:= LL_Size(LinkedList);
end;
procedure STRLL_Delete(LinkedList : PLinkedListBase; idx : uint32);
var
ptr : pchar;
begin
tracer.push_trace('lists.STRLL_Delete (Don''t add static strings)');
ptr:= STRLL_get(LinkedList, idx);
kfree(void(ptr));
LL_Delete(LinkedList, idx);
end;
procedure STRLL_Free(LinkedList : PLinkedListBase);
begin
STRLL_Clear(LinkedList);
LL_Free(LinkedList);
end;
procedure STRLL_Clear(LinkedList : PLinkedListBase);
begin
while STRLL_Size(LinkedList) > 0 do STRLL_Delete(LinkedList, 0);
end;
function STRLL_FromString(str : pchar; delimter : char) : PLinkedListBase;
var
list : PLinkedListBase;
i : uint32 = 0;
out_str : pchar;
elm : puint32;
head : pchar;
tail : pchar;
size : uint32;
null_delim : boolean;
begin
list := LL_New(sizeof(uint32));
STRLL_FromString:= list;
head:= str;
tail:= head;
null_delim:= false;
while not null_delim do begin
if (head^ = delimter) or (head^ = char(0)) then begin
if head^ = char(0) then null_delim:= true;
size:= uint32(head) - uint32(tail);
if size > 0 then begin
elm:= puint32(LL_Add(list));
out_str:= stringNew(size + 1); //maybe
memcpy(uint32(tail), uint32(out_str), size);
elm^:= uint32(out_str);
end;
tail:= head+1;
end;
inc(head);
end;
end;
end.