Hosted by
|
with Ada.Unchecked_Deallocation;
package body Limited_Lists is
function Create
return List_Access is
begin
return new List;
end Create;
procedure Append
(This : access List;
Tail : access List) is
begin
This.Last.Next := Tail.First;
This.Count := This.Count + Tail.Count;
This.Last := Tail.Last;
end Append;
function Push
(This : access List)
return Item_Access
is
New_Item : Item_Access := new Item;
begin
if This.First = null
then This.First := New_Item;
else This.Last.Next := New_Item;
end if;
This.Last := New_Item;
This.Count := This.Count + 1;
return New_Item;
end Push;
function Unshift
(This : access List)
return Item_Access
is
New_Item : Item_Access := new Item;
begin
New_Item.Next := This.First;
This.First := New_Item;
if This.Last = null then This.Last := New_Item; end if;
This.Count := This.Count + 1;
return New_Item;
end Unshift;
function Pop
(This : access List)
return Item_Access
is
Not_Implemented : exception;
begin
raise Not_Implemented;
return null;
end Pop;
function Shift
(This : access List)
return Item_Access
is
Result : Item_Access := This.First;
begin
This.First := Result.Next;
if This.First = null then This.Last := null; end if;
This.Count := This.Count - 1;
return Result;
end Shift;
function Count
(This : access List)
return Natural is
begin
return This.Count;
end Count;
function Empty
(This : access List)
return Boolean is
begin
return This.First = null;
end Empty;
function Index
(This : access List)
return Natural is
begin
return This.Index;
end Index;
function First
(This : access List)
return Content_Type is
begin
return This.First.Content;
end First;
function Last
(This : access List)
return Content_Type is
begin
return This.Last.Content;
end Last;
procedure Reset
(This : access List) is
begin
This.Current := null;
This.Index := 0;
end Reset;
procedure Next
(This : access List) is
begin
This.Prev := This.Current;
if This.Current = null
then This.Current := This.First;
else This.Current := This.Current.Next;
end if;
if This.Current /= null then
This.Next := This.Current.Next;
This.Index := This.Index + 1;
else
This.Next := null;
This.Index := 0;
end if;
end Next;
function Next
(This : access List)
return Boolean is
begin
This.Prev := This.Current;
if This.Current = null
then This.Current := This.First;
else This.Current := This.Current.Next;
end if;
if This.Current /= null then
This.Next := This.Current.Next;
This.Index := This.Index + 1;
return True;
else
This.Next := null;
This.Index := 0;
return False;
end if;
end Next;
function Next_Available
(This : access List)
return Boolean is
begin
return This.Next /= null;
end Next_Available;
function Next_Content
(This : access List)
return Content_Type is
begin
return This.Next.Content;
end Next_Content;
function End_Of_List
(This : access List)
return Boolean is
begin
return This.Current = null;
end End_Of_List;
function Current
(This : access List)
return Content_Type is
begin
return This.Current.Content;
end Current;
procedure Free is new Ada.Unchecked_Deallocation(Item, Item_Access);
procedure Free is new Ada.Unchecked_Deallocation(List, List_Access);
procedure Remove_Current
(This : access List)
is
Old_Item : Item_Access := This.Current;
begin
This.Count := This.Count - 1;
This.Current := Old_Item.Next;
if This.First = Old_Item then This.First := This.Current; end if;
if This.Last = Old_Item then This.Last := This.Prev; end if;
if This.Current /= null then This.Next := This.Current.Next; end if;
if This.Prev /= null then This.Prev.Next := This.Current; end if;
Free(Old_Item);
end Remove_Current;
function Insert_Before_Current
(This : access List)
return Item_Access
is
New_Item : Item_Access := new Item;
begin
if This.Current = null then
if This.Last = null
then This.First := New_Item;
else This.Last.Next := New_Item;
end if;
This.Last := New_Item;
else
New_Item.Next := This.Current;
if This.Prev /= null then This.Prev.Next := New_Item; end if;
if This.First = This.Current then This.First := New_Item; end if;
end if;
This.Prev := New_Item;
This.Index := This.Index + 1;
This.Count := This.Count + 1;
return New_Item;
end Insert_Before_Current;
function Insert_After_Current
(This : access List)
return Item_Access
is
New_Item : Item_Access := new Item;
begin
if This.Current = null then
New_Item.Next := This.First;
This.First := New_Item;
if This.Last = null then This.Last := New_Item; end if;
else
New_Item.Next := This.Current.Next;
This.Current.Next := New_Item;
if This.Last = This.Current then This.Last := New_Item; end if;
end if;
This.Next := New_Item;
This.Count := This.Count + 1;
return New_Item;
end Insert_After_Current;
function First_Item
(This : access List)
return Item_Access is
begin
return This.First;
end First_Item;
function Last_Item
(This : access List)
return Item_Access is
begin
return This.Last;
end Last_Item;
function Current_Item
(This : access List)
return Item_Access is
begin
return This.Current;
end Current_Item;
procedure Next_Item
(This : in out Item_Access) is
begin
This := This.Next;
end Next_Item;
function Next_Item
(This : access Item)
return Item_Access is
begin
return This.Next;
end Next_Item;
function Item_Invalid
(This : in Item_Access)
return Boolean is
begin
return This = null;
end Item_Invalid;
function Item_Equals
(This : in Item_Access;
Other : in Item_Access)
return Boolean is
begin
return This = Other;
end Item_Equals;
function Item_Content
(This : access Item)
return Content_Type is
begin
return This.Content;
end Item_Content;
procedure Remove_Item
(Previous : in Item_Access;
This : in out Item_Access;
Context : access List)
is
Next : Item_Access := This.Next;
begin
Context.Count := Context.Count - 1;
if This = Context.First then
pragma Assert(Next /= null);
Context.First := Next;
end if;
if This = Context.Last then
pragma Assert(Previous /= null);
pragma Assert(Next = null);
Context.Last := Previous;
end if;
if Previous /= null then
if Previous = Context.Last
then Previous.Next := null;
else Previous.Next := Next;
end if;
end if;
Free(This);
This := Next;
end Remove_Item;
end Limited_Lists;
|