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
23generic
24   type Key is private;
25   with function "=" (L, R : Key) return Boolean is <>;
26package BC.Containers.Maps is
27
28   pragma Preelaborate;
29
30   --  A map denotes a collection forming a dictionary of domain/range
31   --  pairs.
32
33   --  The parameter Key denotes the universe from which the map draws
34   --  its domain; the parameter Item denotes the universe from which
35   --  the map draws its range. The parameters Key and Item typically
36   --  represent different types, although they may may represent the
37   --  same type. Either may be a primitive type or user-defined.
38
39   type Abstract_Map is abstract new Container with private;
40
41   function Are_Equal (L, R : Abstract_Map'Class) return Boolean;
42   --  Return True if and only if both maps have the same extent and
43   --  the same key/item pairs; return False otherwise.
44   --  Can't call this "=" because of the standard one for Map.
45
46   procedure Clear (M : in out Abstract_Map)
47      is abstract;
48   --  Empty the map of all key/item pairs.
49
50   procedure Bind (M : in out Abstract_Map; K : Key; I : Item)
51      is abstract;
52   --  If the key already exists in the map, raise BC.Duplicate.
53   --  Otherwise, add the key/item pair to the map.
54
55   procedure Rebind (M : in out Abstract_Map; K : Key; I : Item)
56      is abstract;
57   --  If the key does not exist in the map, raise BC.Not_Found.
58   --  Otherwise, change the key's binding to the given value.
59
60   procedure Unbind (M : in out Abstract_Map; K : Key)
61      is abstract;
62   --  If the key does not exist in the map, raise BC.Not_Found.
63   --  Otherwise, remove the key/item binding.
64
65   function Available (M : Abstract_Map) return Natural;
66   --  Return the number of unused slots in the map.
67
68   function Extent (M : Abstract_Map) return Natural
69      is abstract;
70   --  Return the number of key/item bindings in the map.
71
72   function Is_Empty (M : Abstract_Map) return Boolean
73      is abstract;
74   --  Return True if and only if there are no key/item bindings in
75   --  the map; otherwise, return False.
76
77   function Is_Bound (M : Abstract_Map; K : Key) return Boolean
78      is abstract;
79   --  Return True if and only if there is a binding for the given key
80   --  in the map; otherwise, return False.
81
82   function Item_Of (M : Abstract_Map; K : Key) return Item
83      is abstract;
84   --  If the key does not exist in the map, raises BC.Not_Found.
85   --  Otherwise, returns a copy of the item bound to the given key.
86
87   --  Additional Iterator support
88
89   type Map_Iterator is abstract new Iterator with private;
90
91   function Current_Key (It : Map_Iterator) return Key is abstract;
92   --  Returns a copy of the current Key.
93
94   generic
95      with procedure Apply (K : Key; I : Item; OK : out Boolean);
96   procedure Visit (Using : in out Map_Iterator'Class);
97   --  Call Apply with a copy of each Key/Item pair in the Container
98   --  to which the iterator Using is bound. The iteration will
99   --  terminate early if Apply sets OK to False.
100
101   generic
102      with procedure Apply (K : Key; I : in out Item; OK : out Boolean);
103   procedure Modify (Using : in out Map_Iterator'Class);
104   --  Call Apply for each Key/Item pair in the Container to which the
105   --  iterator Using is bound. The Item is a copy, the Item is the
106   --  actual content. The iteration will terminate early if Apply
107   --  sets OK to False.
108
109private
110
111   --  Suppress "unreferenced" warnings here (GNAT 5.02). Can't use
112   --  pragma Unreferenced, because then we get warnings in child
113   --  packages.
114   pragma Warnings (Off, "=");
115
116   type Abstract_Map is abstract new Container with null record;
117
118   type Key_Ptr is access all Key;
119   for Key_Ptr'Storage_Size use 0;
120
121   --  The new subprograms for Map iteration (which allow access to
122   --  the Key as well as the Item) require the inherited
123   --  For_The_Container to in fact be in Map'Class. This must be the
124   --  case since the only way of getting a Map_Iterator is by using
125   --  one of the concrete forms' New_Iterator using eg
126   --
127   --   Iter : Map_Iterator'Class := Map_Iterator'Class (New_Iterator (M));
128   --
129   --  which fails at compilation time if M isn't actually a Map.
130   type Map_Iterator is abstract new Iterator with record
131      Bucket_Index : Natural := 0;
132      Index : Natural := 0;
133   end record;
134
135end BC.Containers.Maps;
136