1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . F O R M A L _ V E C T O R S --
9 -- Copyright (C) 2004-2013, Free Software Foundation, Inc. --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 3, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. --
22 -- As a special exception under Section 7 of GPL version 3, you are granted --
23 -- additional permissions described in the GCC Runtime Library Exception, --
24 -- version 3.1, as published by the Free Software Foundation. --
26 -- You should have received a copy of the GNU General Public License and --
27 -- a copy of the GCC Runtime Library Exception along with this program; --
28 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
29 -- <http://www.gnu.org/licenses/>. --
30 ------------------------------------------------------------------------------
32 -- This spec is derived from package Ada.Containers.Bounded_Vectors in the Ada
33 -- 2012 RM. The modifications are to facilitate formal proofs by making it
34 -- easier to express properties.
36 -- The modifications are:
38 -- A parameter for the container is added to every function reading the
39 -- content of a container: Element, Next, Query_Element, Previous, Iterate,
40 -- Has_Element, Reverse_Iterate. This change is motivated by the need
41 -- to have cursors which are valid on different containers (typically a
42 -- container C and its previous version C'Old) for expressing properties,
43 -- which is not possible if cursors encapsulate an access to the underlying
46 -- There are two new functions:
48 -- function Left (Container : Vector; Position : Cursor) return Vector;
49 -- function Right (Container : Vector; Position : Cursor) return Vector;
51 -- Left returns a container containing all elements preceding Position
52 -- (excluded) in Container. Right returns a container containing all
53 -- elements following Position (included) in Container. These two new
54 -- functions are useful to express invariant properties in loops which
55 -- iterate over containers. Left returns the part of the container already
56 -- scanned and Right the part not scanned yet.
62 type Index_Type
is range <>;
63 type Element_Type
is private;
65 with function "=" (Left
, Right
: Element_Type
) return Boolean is <>;
67 package Ada
.Containers
.Formal_Vectors
is
70 subtype Extended_Index
is Index_Type
'Base
71 range Index_Type
'First - 1 ..
72 Index_Type
'Min (Index_Type
'Base'Last - 1, Index_Type'Last) + 1;
74 No_Index : constant Extended_Index := Extended_Index'First;
76 type Vector (Capacity : Count_Type) is private;
78 type Cursor is private;
79 pragma Preelaborable_Initialization (Cursor);
81 Empty_Vector : constant Vector;
83 No_Element : constant Cursor;
85 function "=" (Left, Right : Vector) return Boolean;
88 (New_Item : Element_Type;
89 Length : Count_Type) return Vector;
91 function "&" (Left, Right : Vector) return Vector;
93 function "&" (Left : Vector; Right : Element_Type) return Vector;
95 function "&" (Left : Element_Type; Right : Vector) return Vector;
97 function "&" (Left, Right : Element_Type) return Vector;
99 function Capacity (Container : Vector) return Count_Type;
101 procedure Reserve_Capacity
102 (Container : in out Vector;
103 Capacity : Count_Type)
105 Pre => Capacity <= Container.Capacity;
107 function Length (Container : Vector) return Count_Type;
110 (Container : in out Vector;
111 New_Length : Count_Type)
113 Pre => New_Length <= Length (Container);
115 function Is_Empty (Container : Vector) return Boolean;
117 procedure Clear (Container : in out Vector);
119 procedure Assign (Target : in out Vector; Source : Vector) with
120 Pre => Length (Source) <= Target.Capacity;
124 Capacity : Count_Type := 0) return Vector
126 Pre => Length (Source) <= Capacity;
130 Index : Extended_Index) return Cursor;
132 function To_Index (Position : Cursor) return Extended_Index;
136 Index : Index_Type) return Element_Type
138 Pre => First_Index (Container) <= Index
139 and then Index <= Last_Index (Container);
143 Position : Cursor) return Element_Type
145 Pre => Has_Element (Container, Position);
147 procedure Replace_Element
148 (Container : in out Vector;
150 New_Item : Element_Type)
152 Pre => First_Index (Container) <= Index
153 and then Index <= Last_Index (Container);
155 procedure Replace_Element
156 (Container : in out Vector;
158 New_Item : Element_Type)
160 Pre => Has_Element (Container, Position);
162 procedure Move (Target : in out Vector; Source : in out Vector) with
163 Pre => Length (Source) <= Target.Capacity;
166 (Container : in out Vector;
167 Before : Extended_Index;
170 Pre => First_Index (Container) <= Before
171 and then Before <= Last_Index (Container) + 1
172 and then Length (Container) < Container.Capacity;
175 (Container : in out Vector;
179 Pre => Length (Container) < Container.Capacity
180 and then (Has_Element (Container, Before)
181 or else Before = No_Element);
184 (Container : in out Vector;
187 Position : out Cursor)
189 Pre => Length (Container) < Container.Capacity
190 and then (Has_Element (Container, Before)
191 or else Before = No_Element);
194 (Container : in out Vector;
195 Before : Extended_Index;
196 New_Item : Element_Type;
197 Count : Count_Type := 1)
199 Pre => First_Index (Container) <= Before
200 and then Before <= Last_Index (Container) + 1
201 and then Length (Container) + Count <= Container.Capacity;
204 (Container : in out Vector;
206 New_Item : Element_Type;
207 Count : Count_Type := 1)
209 Pre => Length (Container) + Count <= Container.Capacity
210 and then (Has_Element (Container, Before)
211 or else Before = No_Element);
214 (Container : in out Vector;
216 New_Item : Element_Type;
217 Position : out Cursor;
218 Count : Count_Type := 1)
220 Pre => Length (Container) + Count <= Container.Capacity
221 and then (Has_Element (Container, Before)
222 or else Before = No_Element);
225 (Container : in out Vector;
228 Pre => Length (Container) < Container.Capacity;
231 (Container : in out Vector;
232 New_Item : Element_Type;
233 Count : Count_Type := 1)
235 Pre => Length (Container) + Count <= Container.Capacity;
238 (Container : in out Vector;
241 Pre => Length (Container) < Container.Capacity;
244 (Container : in out Vector;
245 New_Item : Element_Type;
246 Count : Count_Type := 1)
248 Pre => Length (Container) + Count <= Container.Capacity;
251 (Container : in out Vector;
252 Index : Extended_Index;
253 Count : Count_Type := 1)
255 Pre => First_Index (Container) <= Index
256 and then Index <= Last_Index (Container) + 1;
259 (Container : in out Vector;
260 Position : in out Cursor;
261 Count : Count_Type := 1)
263 Pre => Has_Element (Container, Position);
265 procedure Delete_First
266 (Container : in out Vector;
267 Count : Count_Type := 1);
269 procedure Delete_Last
270 (Container : in out Vector;
271 Count : Count_Type := 1);
273 procedure Reverse_Elements (Container : in out Vector);
275 procedure Swap (Container : in out Vector; I, J : Index_Type) with
276 Pre => First_Index (Container) <= I and then I <= Last_Index (Container)
277 and then First_Index (Container) <= J
278 and then J <= Last_Index (Container);
280 procedure Swap (Container : in out Vector; I, J : Cursor) with
281 Pre => Has_Element (Container, I) and then Has_Element (Container, J);
283 function First_Index (Container : Vector) return Index_Type;
285 function First (Container : Vector) return Cursor;
287 function First_Element (Container : Vector) return Element_Type with
288 Pre => not Is_Empty (Container);
290 function Last_Index (Container : Vector) return Extended_Index;
292 function Last (Container : Vector) return Cursor;
294 function Last_Element (Container : Vector) return Element_Type with
295 Pre => not Is_Empty (Container);
297 function Next (Container : Vector; Position : Cursor) return Cursor with
298 Pre => Has_Element (Container, Position) or else Position = No_Element;
300 procedure Next (Container : Vector; Position : in out Cursor) with
301 Pre => Has_Element (Container, Position) or else Position = No_Element;
303 function Previous (Container : Vector; Position : Cursor) return Cursor with
304 Pre => Has_Element (Container, Position) or else Position = No_Element;
306 procedure Previous (Container : Vector; Position : in out Cursor) with
307 Pre => Has_Element (Container, Position) or else Position = No_Element;
312 Index : Index_Type := Index_Type'First) return Extended_Index;
317 Position : Cursor := No_Element) return Cursor
319 Pre => Has_Element (Container, Position) or else Position = No_Element;
321 function Reverse_Find_Index
324 Index : Index_Type := Index_Type'Last) return Extended_Index;
326 function Reverse_Find
329 Position : Cursor := No_Element) return Cursor
331 Pre => Has_Element (Container, Position) or else Position = No_Element;
335 Item : Element_Type) return Boolean;
337 function Has_Element (Container : Vector; Position : Cursor) return Boolean;
340 with function "<" (Left, Right : Element_Type) return Boolean is <>;
341 package Generic_Sorting is
343 function Is_Sorted (Container : Vector) return Boolean;
345 procedure Sort (Container : in out Vector);
347 procedure Merge (Target : in out Vector; Source : in out Vector);
351 function Left (Container : Vector; Position : Cursor) return Vector with
352 Pre => Has_Element (Container, Position) or else Position = No_Element;
354 function Right (Container : Vector; Position : Cursor) return Vector with
355 Pre => Has_Element (Container, Position) or else Position = No_Element;
359 pragma Inline (First_Index);
360 pragma Inline (Last_Index);
361 pragma Inline (Element);
362 pragma Inline (First_Element);
363 pragma Inline (Last_Element);
364 pragma Inline (Replace_Element);
365 pragma Inline (Contains);
366 pragma Inline (Next);
367 pragma Inline (Previous);
369 type Elements_Array is array (Count_Type range <>) of Element_Type;
370 function "=" (L, R : Elements_Array) return Boolean is abstract;
372 type Vector (Capacity : Count_Type) is record
373 Elements : Elements_Array (1 .. Capacity);
374 Last : Extended_Index := No_Index;
377 type Cursor is record
378 Valid : Boolean := True;
379 Index : Index_Type := Index_Type'First;
382 Empty_Vector : constant Vector := (Capacity => 0, others => <>);
384 No_Element : constant Cursor := (Valid => False, Index => Index_Type'First);
386 end Ada.Containers.Formal_Vectors;