Generic package: GNAT.Table

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.

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.Table is
 
pragma Elaborate_Body (Table);

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:

Type Summary

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)

Variables

Locked : Boolean := False;
Table expansion is permitted only if this switch is set to False. A client may set Locked to True, in which case any attempt to expand the table will cause an assertion failure. Note that while a table is locked, its address in memory remains fixed and unchanging.
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.

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

procedure Init;
This procedure allocates a new table of size Initial (freeing any previously allocated larger table). It is not necessary to call Init when a table is first instantiated (since the instantiation does the same initialization steps). However, it is harmless to do so, and Init is convenient in reestablishing a table for new use.

function Last 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;
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 (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;
pragma Inline (Increment_Last);
Adds 1 to Last (same as Set_Last (Last + 1).

procedure Decrement_Last;
pragma Inline (Decrement_Last);
Subtracts 1 from Last (same as Set_Last (Last - 1).

function Allocate (Num : Integer := 1) return Table_Index_Type;
pragma Inline (Allocate);
Adds Num to Last, and returns the old value of Last + 1. Note that this function has the possible side effect of reallocating the table. This means that a reference X.Table (X.Allocate) is incorrect, since the call to X.Allocate may modify the results of calling X.Table.
end GNAT.Table;