Generic package: GNAT.Dynamic_Tables

Description

Note controlled types are not supported by this package. In particular the type provided for Table_Component_Type may not be a controlled type. Table_Component_Type and Table_Index_Type specify the type of the array, Table_Low_Bound is the lower bound. Index_type must be an integer type. The effect is roughly to declare:

Header

generic
   type Table_Component_Type is private;
   type Table_Index_Type     is range <>;

   Table_Low_Bound : Table_Index_Type;
   Table_Initial   : Positive;
   Table_Increment : Natural;

package GNAT.Dynamic_Tables is
 

Type Summary

Instance
Primitive Operations:  Allocate, Decrement_Last, Increment_Last, Init, Last, Release, Set_Last
Table_Private
Table_Ptr
Table_Type

Constants and Named Numbers

First : constant Table_Index_Type := Table_Low_Bound;
Export First as synonym for Low_Bound (parallel with use of Last)

Other Items:

type Table_Type is
  array (Table_Index_Type range <>) of Table_Component_Type;
Note: we do not make the table components aliased, since this would restrict the use of table for discriminated types. If it is necessary to take the access of a table element, use Unrestricted_Access.

subtype Big_Table_Type is
  Table_Type (Table_Low_Bound .. Table_Index_Type'Last);
We work with pointers to a bogus array type that is constrained with the maximum possible range bound. This means that the pointer is a thin pointer, which is more efficient. Since subscript checks in any case must be on the logical, rather than physical bounds, safety is not compromised by this approach.

type Table_Ptr is access all Big_Table_Type;
The table is actually represented as a pointer to allow reallocation.

type Table_Private is private;
table private data that is not exported in Instance.

type Instance is record
   Table : aliased Table_Ptr := null;
--  The table itself. The lower bound is the value of Low_Bound.
--  Logically the upper bound is the current value of Last (although
--  the actual size of the allocated table may be larger than this).
--  The program may only access and modify Table entries in the
--  range First .. Last.

   P : Table_Private;
end record;

procedure Init (T : in out Instance);
This procedure allocates a new table of size Initial (freeing any previously allocated larger table). Init must be called before using the table. Init is convenient in reestablishing a table for new use.

function Last (T : in Instance) return Table_Index_Type;
pragma Inline (Last);
Returns the current value of the last used entry in the table, which can then be used as a subscript for Table. Note that the only way to modify Last is to call the Set_Last procedure. Last must always be used to determine the logically last entry.

procedure Release (T : in out Instance);
Storage is allocated in chunks according to the values given in the Initial and Increment parameters. A call to Release releases all storage that is allocated, but is not logically part of the current array value. Current array values are not affected by this call.

procedure Set_Last (T : in out Instance; New_Val : Table_Index_Type);
pragma Inline (Set_Last);
This procedure sets Last to the indicated value. If necessary the table is reallocated to accomodate the new value (i.e. on return the allocated table has an upper bound of at least Last). If Set_Last reduces the size of the table, then logically entries are removed from the table. If Set_Last increases the size of the table, then new entries are logically added to the table.

procedure Increment_Last (T : in out Instance);
pragma Inline (Increment_Last);
Adds 1 to Last (same as Set_Last (Last + 1).

procedure Decrement_Last (T : in out Instance);
pragma Inline (Decrement_Last);
Subtracts 1 from Last (same as Set_Last (Last - 1).

procedure Allocate (T   : in out Instance;
                    Num : Integer := 1);
pragma Inline (Allocate);
Adds Num to Last.

private

   --  Implementation-defined ...
end GNAT.Dynamic_Tables;