Hosted by
|
with Ada.Text_IO;
with Primes; use Primes;
package body Limited_Hash_Tables is
Table_Full : exception;
procedure Put_Internal
(This : access Hash_Table;
Pair : in Pair_Access)
is
Start : Positive;
Index : Natural;
Test : Pair_Access;
begin
Start := Hash(Pair.Key, This.Size);
Index := Start;
loop
Test := This.Pairs(Index);
exit when Test = null;
if Equal(Test.Key, Pair.Key) then raise Key_Exists; end if;
Index := Index - 1;
if Index = 0 then Index := This.Size; end if;
if Index = Start then raise Table_Full; end if;
end loop;
This.Count := This.Count + 1;
This.Pairs(Index) := Pair;
end Put_Internal;
function Full
(This : access Hash_Table)
return Boolean
is
Result : Boolean :=
This.Count >= This.Size - 2 or else
This.Count * 100 > This.Size * Max_Fill_Percentage;
begin
return Result;
end Full;
function Copy
(This : access Hash_Table;
Size : in Positive)
return Hash_Table_Access
is
New_Table : Hash_Table_Access := new Hash_Table(Size);
Index : Natural := 0;
Pair : Pair_Access;
begin
loop
Get_Next(This, Index, Pair);
exit when Index = 0;
Put_Internal(New_Table, Pair);
end loop;
return New_Table;
end Copy;
function Double_Size
(N : in Positive)
return Positive is
begin
return Next_Prime(N * 2 - 1);
end Double_Size;
procedure Grow
(This : in out Hash_Table_Access)
is
begin
This := Copy(This, Double_Size(This.Size));
end Grow;
function Create
(Size : in Positive := Default_Start_Size)
return Hash_Table_Access is
begin
return new Hash_Table(Size);
end Create;
procedure Put
(This : in out Hash_Table_Access;
Pair : in Pair_Access) is
begin
if Full(This) then Grow(This); end if;
Put_Internal(This, Pair);
end Put;
procedure Get_Index
(This : access Hash_Table;
Key : in Key_Type;
Index : out Positive;
Found : out Boolean)
is
Start : Positive;
Test : Pair_Access;
begin
Found := False;
Start := Hash(Key, This.Size);
Index := Start;
loop
Test := This.Pairs(Index);
if Test = null then return; end if;
exit when Equal(Test.Key, Key);
if Index = 1
then Index := This.Size;
else Index := Index - 1;
end if;
if Index = Start then return; end if;
end loop;
Found := True;
end Get_Index;
function Get_Index
(This : access Hash_Table;
Key : in Key_Type)
return Positive
is
Index : Natural;
Found : Boolean;
begin
Get_Index(This, Key, Index, Found);
if not Found then raise Key_Not_Found; end if;
return Index;
end Get_Index;
function Get_Pair
(This : access Hash_Table;
Index : in Positive)
return Pair_Access is
begin
return This.Pairs(Index);
end Get_Pair;
pragma Inline(Get_Pair);
function Get_Key
(This : access Hash_Table;
Index : in Positive)
return Key_Type is
begin
return This.Pairs(Index).Key;
end Get_Key;
pragma Inline(Get_Key);
function Get_Item
(This : access Hash_Table;
Index : in Positive)
return Item_Type is
begin
return This.Pairs(Index).Item;
end Get_Item;
pragma Inline(Get_Item);
procedure Next
(This : access Hash_Table;
Index : in out Natural) is
begin
loop
Index := Index + 1;
if Index > This.Size then
Index := 0;
return;
end if;
exit when This.Pairs(Index) /= null;
end loop;
end Next;
procedure Get_Next
(This : access Hash_Table;
Index : in out Natural;
Pair : out Pair_Access) is
begin
Next(This, Index);
if Index = 0 then return; end if;
Pair := Get_Pair(This, Index);
end Get_Next;
procedure Print_Usage
(This : access Hash_Table) is
begin
for Index in This.Pairs'Range loop
if This.Pairs(Index) = null
then Ada.Text_IO.Put('-');
else Ada.Text_IO.Put('#');
end if;
end loop;
Ada.Text_IO.New_Line;
end Print_Usage;
end Limited_Hash_Tables;
|