File : double_linked_list_mixin.ads



with Matchs;

generic
   type Base (<>) is abstract tagged limited private;
   type S    (<>) is abstract new Base with private;
package Double_Linked_List_Mixin is
   type T is abstract new S with private;
   type T_Class is access all T'Class;
   
   type Double_Linked_List is limited private;
   
   --  raised if an element is inserted twice
   Multiple_Inserted_Element : exception;
   --  raised if a deletions after the last element is requested
   Delete_After_List         : exception;

   type Direction is (Front, Rear);

   --  Basic actions
   function  Is_Empty     (Head : in     Double_Linked_List) return Boolean;
   procedure Add_Front    (Head  : in out Double_Linked_List;
                           Elem  : in     T_Class);
   procedure Add_Rear     (Head  : in out Double_Linked_List;
                           Elem  : in     T_Class);
   procedure Delete_Front (Head  : in out Double_Linked_List);
   procedure Delete_Rear  (Head  : in out Double_Linked_List);
   
   --  Explicit Iterator
   type Iterator is private;
   function  Get_Front_Iterator (Head  : Double_Linked_List) return Iterator;
   function  Get_Rear_Iterator  (Head  : Double_Linked_List) return Iterator;
   function  Is_Done            (Iter  : Iterator)           return Boolean;
   function  Get                (Iter  : Iterator)           return T_Class;
   procedure Advance    (Iter  : in out Iterator);
   procedure Set_Done   (Iter  : in out Iterator);
   procedure Turn       (Iter  : in out Iterator);
   
   procedure Add_Before (Iter : in     Iterator;
                         Elem : in     T_Class);
   procedure Add_After  (Iter : in     Iterator;
                         Elem : in     T_Class);
   procedure Delete     (Iter : in out Iterator);

   --  Adds before the element with matches the condition.
   --  If no match occurs the element is added at the end.
   generic
      with function Is_Match  (Elem : in     Base) return Boolean;
   procedure Add_Before_First (Head : in out Double_Linked_List;
                               Elem : in     T_Class);
   generic
      with function Is_Match (Elem : in     Base) return Boolean;
   procedure Add_Before_Last (Head : in out Double_Linked_List;
                              Elem : in     T_Class);

   --  Adds after the element with matches the condition.
   --  If no match occurs the element is added at the end.
   generic
      with function Is_Match (Elem : in     Base) return Boolean;
   procedure Add_After_First (Head : in out Double_Linked_List;
                              Elem : in     T_Class);
   generic
      with function Is_Match (Elem : in     Base) return Boolean;
   procedure Add_After_Last  (Head : in out Double_Linked_List;
                              Elem : in     T_Class);
   
   --  Find a specific element -- null if nothing found.
   generic
      with function Is_Match (Curr : in Iterator)  return Matchs.Match_Type;
   function Find_First       (Head : in Double_Linked_List) return Iterator;
   generic
      with function Is_Match (Curr : in Iterator)  return Matchs.Match_Type;
   function Find_Last        (Head : in Double_Linked_List) return Iterator;
   
   --  Find the next specific element -- null if nothing found.
   generic
      with function Is_Match (Curr : in Iterator) return Matchs.Match_Type;
   function Find_Next (Iter : in Iterator) return Iterator;
   
   --  Basic generic internal iterator
   generic
      with function Is_Match   (Elem : in     Base) return Matchs.Match_Type;
      with procedure On_Item   (Elem : in out Base;
                                Done :    out Boolean);
   procedure For_First_Matches (Head : in     Double_Linked_List);
   generic
      with function Is_Match  (Elem : in     Base) return Matchs.Match_Type;
      with procedure On_Item  (Elem : in out Base;
                               Done :    out Boolean);
   procedure For_Last_Matches (Head : in     Double_Linked_List);
   
   --  More efficient implementation if matching is not necessary.
   generic
      with procedure On_Item (Elem : in out Base;
                              Done :    out Boolean);
   procedure For_First_All   (Head : in     Double_Linked_List);
   generic
      with procedure On_Item (Elem : in out Base;
                              Done :    out Boolean);
   procedure For_Last_All    (Head : in     Double_Linked_List);

   --  Delete all matching elements from the list
   --  (not the elements themselfs!)
   generic
      with function Is_Match      (Elem : in Base) return Matchs.Match_Type;
   procedure Delete_First_Matches (Head : in out Double_Linked_List);
   generic
      with function Is_Match      (Elem : in Base) return Matchs.Match_Type;
   procedure Delete_Last_Matches  (Head : in out Double_Linked_List);

   --  Delete the first element from the list
   --  (not the elements themself!)
   generic
      with function Is_Match    (Elem : in Base) return Boolean;
   procedure Delete_First_Match (Head : in out Double_Linked_List);
   generic
      with function Is_Match   (Elem : in Base) return Boolean;
   procedure Delete_Last_Match (Head : in out Double_Linked_List);

private
   type T is abstract new S with
      record
         Next : T_Class := null;
         Prev : T_Class := null;
      end record;
   
   type Double_Linked_List is limited
      record
         Start : T_Class := null;
      end record;

   type Double_Linked_List_Access is access all Double_Linked_List;

   type Iterator is
      record
         L : Double_Linked_List_Access := null;
         P : T_Class                   := null;
         D : Direction                 := Front;
      end record;

end Double_Linked_List_Mixin;