1--  Copyright 1994 Grady Booch
2--  Copyright 1998-2014 Simon Wright <simon@pushface.org>
3
4--  This package is free software; you can redistribute it and/or
5--  modify it under terms of the GNU General Public License as
6--  published by the Free Software Foundation; either version 2, or
7--  (at your option) any later version. This package is distributed in
8--  the hope that it will be useful, but WITHOUT ANY WARRANTY; without
9--  even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10--  PARTICULAR PURPOSE. See the GNU General Public License for more
11--  details. You should have received a copy of the GNU General Public
12--  License distributed with this package; see file COPYING.  If not,
13--  write to the Free Software Foundation, 59 Temple Place - Suite
14--  330, Boston, MA 02111-1307, USA.
15
16--  As a special exception, if other files instantiate generics from
17--  this unit, or you link this unit with other files to produce an
18--  executable, this unit does not by itself cause the resulting
19--  executable to be covered by the GNU General Public License.  This
20--  exception does not however invalidate any other reasons why the
21--  executable file might be covered by the GNU Public License.
22
23with System;
24
25package body BC.Containers.Deques is
26
27   procedure Process_Front (D : in out Abstract_Deque'Class) is
28   begin
29      Process (Item_At (D, 1).all);
30   end Process_Front;
31
32   procedure Process_Back (D : in out Abstract_Deque'Class) is
33   begin
34      Process (Item_At (D, Length (D)).all);
35   end Process_Back;
36
37   procedure Copy (From : Abstract_Deque'Class;
38                   To : in out Abstract_Deque'Class) is
39      Iter : Iterator'Class := New_Iterator (From);
40   begin
41      if System."/=" (From'Address, To'Address) then
42         Clear (To);
43         Reset (Iter);
44         while not Is_Done (Iter) loop
45            Append (To, Current_Item (Iter));
46            Next (Iter);
47         end loop;
48      end if;
49   end Copy;
50
51   function Are_Equal (Left, Right : Abstract_Deque'Class) return Boolean is
52   begin
53      if System."=" (Left'Address, Right'Address) then
54         return True;
55      end if;
56      if Length (Left) /= Length (Right) then
57         return False;
58      end if;
59      declare
60         Left_Iter : Iterator'Class := New_Iterator (Left);
61         Right_Iter : Iterator'Class := New_Iterator (Right);
62      begin
63         while not Is_Done (Left_Iter) and then
64           not Is_Done (Right_Iter) loop
65            if Current_Item (Left_Iter) /= Current_Item (Right_Iter) then
66               return False;
67            end if;
68            Next (Left_Iter);
69            Next (Right_Iter);
70         end loop;
71         return True;
72      end;
73   end Are_Equal;
74
75   function Available (D : in Abstract_Deque) return Natural is
76      pragma Warnings (Off, D);
77   begin
78      return Natural'Last;
79   end Available;
80
81   procedure Reset (It : in out Deque_Iterator) is
82      D : Abstract_Deque'Class
83        renames Abstract_Deque'Class (It.For_The_Container.all);
84   begin
85      if Length (D) = 0 then
86         It.Index := 0;
87      else
88         It.Index := 1;
89      end if;
90   end Reset;
91
92   procedure Next (It : in out Deque_Iterator) is
93   begin
94      It.Index := It.Index + 1;
95   end Next;
96
97   function Is_Done (It : Deque_Iterator) return Boolean is
98      D : Abstract_Deque'Class
99     renames Abstract_Deque'Class (It.For_The_Container.all);
100   begin
101      return It.Index = 0 or else It.Index > Length (D);
102   end Is_Done;
103
104   function Current_Item (It : Deque_Iterator) return Item is
105      D : Abstract_Deque'Class
106     renames Abstract_Deque'Class (It.For_The_Container.all);
107   begin
108      if Is_Done (It) then
109         raise BC.Not_Found;
110      end if;
111      return Item_At (D, It.Index).all;
112   end Current_Item;
113
114   function Current_Item_Ptr (It : Deque_Iterator) return Item_Ptr is
115      D : Abstract_Deque'Class
116     renames Abstract_Deque'Class (It.For_The_Container.all);
117   begin
118      if Is_Done (It) then
119         raise BC.Not_Found;
120      end if;
121      return Item_At (D, It.Index);
122   end Current_Item_Ptr;
123
124   procedure Delete_Item_At (It : in out Deque_Iterator) is
125      D : Abstract_Deque'Class
126        renames Abstract_Deque'Class (It.For_The_Container.all);
127   begin
128      if Is_Done (It) then
129         raise BC.Not_Found;
130      end if;
131      Remove (D, It.Index);
132   end Delete_Item_At;
133
134end BC.Containers.Deques;
135