DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400 Tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400 Tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ B T

⟦6d1f8f981⟧ TextFile

    Length: 33048 (0x8118)
    Types: TextFile
    Names: »B«

Derivation

└─⟦85b835f43⟧ Bits:30000549 8mm tape, Rational 1000, Xlib rev 6.00
    └─ ⟦0c20f784e⟧ »DATA« 
        └─⟦1abbe589f⟧ 
            └─⟦059497ac5⟧ 
                └─⟦this⟧ 

TextFile

with Unchecked_Deallocation;

with Xlbt_Arithmetic;  
use Xlbt_Arithmetic;

package body Xlbip_String_Map_Generic is
------------------------------------------------------------------------------
-- X Library String to Other type map generic
--
-- Xlbp_String_Map_Generic - Map from an Ada string value to some other value
------------------------------------------------------------------------------
-- Copyright 1989 - 1991 by Rational, Santa Clara, California.
--
--                  All Rights Reserved.
--
-- Permission to use, copy, modify, and distribute this software and its
-- documentation for any purpose and without fee is hereby granted,
-- provided that the above copyright notice(s) appear in all copies and that
-- both that copyright notice(s) and this permission notice appear in
-- supporting documentation, and that the name of Rational not be used in
-- advertising or publicity pertaining to distribution of the software
-- without specific, written prior permission.
--
-- Rational disclaims all warranties with regard to this software, including
-- all implied warranties of merchantability and fitness, in no event shall
-- Rational be liable for any special, indirect or consequential damages or
-- any damages whatsoever resulting from loss of use, data or profits, whether
-- in an action of contract, negligence or other tortious action, arising out
-- of or in connection with the use or performance of this software.
------------------------------------------------------------------------------
-- *****************************************************************************
-- * Date      - /Name/ Comment
-- *
-- * 24-OCT-90 - /DRK/ Changed Hash to accept the null string.
-- * 21-JAN-91 - /GEB/ Add the Find_Ptr, Insert_Ptr, and Key_Ptr routines.
-- *****************************************************************************

--\f

----Elements are simply pairs of string Keys and Range_Type values.

    type Elem_Rec is  
        record  
            Hash : S_Long  := 0;  
            Next : Element := null;  
            Rt   : Range_Type;  
            Key  : String_Pointer;  
        end record;

----Maps are simply a table of Element linked lists.

    type Element_Array is  
       array (S_Long range 0 .. S_Long (Hash_Size) - 1) of Element;

    type Map_Rec is  
        record  
            Count : S_Natural     := 0;  
            Table : Element_Array := (others => null);  
        end record;


    procedure Free_String_Pointer is  
       new Unchecked_Deallocation (String,  
                                   String_Pointer);

    procedure Free_Element is new Unchecked_Deallocation (Elem_Rec,  
                                                          Element);

    procedure Free_Map_Internal is new Unchecked_Deallocation (Map_Rec,  
                                                               Map);

--\f

    function Hash (Key : String) return S_Long is
------------------------------------------------------------------------------
--  Key - Specifies the string to hash
--
-- Returns a hash value for the indicated string.
------------------------------------------------------------------------------
        Xl : U_Char_Array (S_Long (Key'First) .. S_Long (Key'Last));  
    begin

----Convert the characters in the string into a series of numeric values.

        if Exact_Case_Match then  
            for I in Key'Range loop  
                Xl (S_Natural (I)) := Character'Pos (Key (I));  
            end loop;  
        else  
            for I in Key'Range loop  
                if Key (I) in  
                   Character'Val (Standard.Character'Pos ('a')) ..  
                      Character'Val (Standard.Character'Pos ('z')) then  
                    Xl (S_Natural (I)) := Character'Pos (Key (I)) -  
                                             (Standard.Character'Pos ('a') -  
                                              Standard.Character'Pos ('A'));  
                else  
                    Xl (S_Natural (I)) := Character'Pos (Key (I));  
                end if;  
            end loop;  
        end if;

----Take the string of numeric values and turn them into a hash code.

        case Key'Length is  
            when 0 =>  
                return 0;  
            when 1 =>  
                return S_Long (Xl (Xl'First));  
            when 2 =>  
                return S_Long (Xl (Xl'First)) * 128  
                           + S_Long (Xl (Xl'Last));  
            when 3 =>  
                return S_Long (Xl (Xl'First)) * 128 ** 2  
                           + S_Long (Xl (Xl'First + 1)) * 128  
                           + S_Long (Xl (Xl'Last));  
            when 4 =>  
                return S_Long (Xl (Xl'First)) * 128 ** 3  
                           + S_Long (Xl (Xl'First + 1)) * 128 ** 2  
                           + S_Long (Xl (Xl'First + 2)) * 128  
                           + S_Long (Xl (Xl'Last));  
            when others =>  
                declare  
                    I : S_Natural := Xl'First;  
                    H : S_Long    := 0;  
                begin  
                    while I + 3 <= Xl'Last loop  
                        if S_Long'Last - 2 ** 28 < H then
                            ----Prevent overflow on long strings.
                            H := H / 3;  
                        end if;  
                        H := H + S_Long (Xl (I)) * 128 ** 3  
                                 + S_Long (Xl (I + 1)) * 128 ** 2  
                                 + S_Long (Xl (I + 2)) * 128  
                                 + S_Long (Xl (I + 3));  
                        I := I + 4;  
                    end loop;  
                    for J in I .. Xl'Last loop  
                        H := H + S_Long (Xl (J));  
                    end loop;  
                    return H;  
                end;  
        end case;

    end Hash;

--\f

    function Equal (A : String; B : String) return Boolean is
------------------------------------------------------------------------------
--  A   - Specifies the first string
--  B   - Specifies the second string
--
-- Returns TRUE if A = B when both are upper case.  B is assumed to be
-- upper case already.
------------------------------------------------------------------------------
        Ai : Index := A'First;  
        Bi : Index := B'First;  
    begin

----The lengths must be the same.

        if A'Length /= B'Length then  
            return False;  
        end if;

----Check for any differences.

        for I in Index range 1 .. A'Length loop  
            if A (Ai + I - 1) /= B (Bi + I - 1) then  
                if (A (Ai + I - 1) not in  
                    Character'Val (Standard.Character'Pos ('a')) ..  
                       Character'Val (Standard.Character'Pos ('z')) or else  
                    Character'Val (Character'Pos (A (Ai + I - 1)) -  
                                   (Standard.Character'Pos ('a') -  
                                    Standard.Character'Pos ('A')))  
                     /= B (Bi + I - 1)) then  
                    return False;  
                end if;  
            end if;  
        end loop;

----They are the same.

        return True;

    end Equal;

--\f

    procedure Lookup (H    :        S_Long;  
                      Key  :        String;  
                      Prev : out    Element;  
                      Elem : in out Element) is
------------------------------------------------------------------------------
--  H       - Specifies the hash value for the Key
--  Key     - Specifies the key we are looking for
--  Prev    - Receives the last element in the initial Elem list or else the
--              Element whose .Next is Elem.
--  Elem    - Receives NULL or else the Element that matches the Key/H values;
--              initially is the M.Table(H) value
------------------------------------------------------------------------------
        El : Element := Elem;  
    begin

----Initially there is no Prev vaue.

        Prev := null;

----Loop over all of the chained elements looking for matching H/Key values.

        while El /= null loop  
            if El.Hash = H then  
                if Exact_Case_Match then  
                    if El.Key.all = Key then  
                        Elem := El;  
                        return;  
                    end if;  
                else  
                    if Equal (Key, El.Key.all) then  
                        Elem := El;  
                        return;  
                    end if;  
                end if;  
            end if;  
            Prev := El;  
            El   := El.Next;  
        end loop;

----Nothing was found.  Return null.

        Elem := null;

    end Lookup;

--\f

    procedure New_Map (M : out Map) is
------------------------------------------------------------------------------
--  M   - Receives a new Map.
--
-- Called to create and initialize a new Map.  The Map Is_Empty.
------------------------------------------------------------------------------
    begin

        M := new Map_Rec;

    end New_Map;

--\f

    procedure Free_Map (M : in out Map) is
------------------------------------------------------------------------------
--  M   - Specifies the existing Map to deallocate.
--
-- Called to destroy an existing Map.  Map may have a None_Map value.  All map
-- entries are destroyed.  The Range_Type values contained in the map are
-- merely dropped and are not deallocated or manipulated in any way.
------------------------------------------------------------------------------
        Elem1 : Element;  
        Elem2 : Element;  
    begin

----Don't free a non-existend map.

        if M = null then  
            return;  
        end if;

----Free any existing table entries.

        if M.Count > 0 then  
            for I in M.Table'Range loop  
                Elem1 := M.Table (I);

----Free elements on this chain; including the Key strings.

                while Elem1 /= null loop  
                    Elem2 := Elem1.Next;  
                    Free_String_Pointer (Elem1.Key);  
                    Free_Element (Elem1);  
                    Elem1 := Elem2;  
                end loop;

            end loop;  
        end if;

----Free the map itself.

        Free_Map_Internal (M);

    end Free_Map;

--\f

    function Is_Empty (M : in Map) return Boolean is
------------------------------------------------------------------------------
--  M   - Specifies the map
--
-- Returns TRUE if the map is completely empty.
------------------------------------------------------------------------------
    begin

        return M.Count = 0;

    end Is_Empty;

--\f

    function Cardinality (M : in Map) return S_Natural is
------------------------------------------------------------------------------
--  M   - Specifies the map
--
-- Returns the number of entries in the map.
------------------------------------------------------------------------------
    begin

        return M.Count;

    end Cardinality;

--\f

    procedure Find (M      : in     Map;  
                    Key    : in     String;  
                    Rt     : in out Range_Type;  
                    Status : out    Boolean) is
------------------------------------------------------------------------------
--  M      - Specifies the map to use
--  Key    - Specifies the string value to use for the lookup
--  Rt     - Receives the Range_Type value from the map or is unchanged
--  Status - Receives TRUE if the Key was found and FALSE if not
--
-- Called to perform a lookup within the map.  If the Key string is found
-- within the map then the associated Range_Type value is returned and
-- Status is set to TRUE.  If the Key string is not found then Status is
-- set to FALSE and the Rt parameter remains unchanged.  (Beware of
-- uninitialized locals being passed to Find; they will often be the cause
-- of Constraint_Errors.)
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key);  
        Prev : Element;  
        Elem : Element := M.Table (H rem S_Long (Hash_Size));  
    begin

----Lookup the entry in the table with this hash value.

        Lookup (H, Key, Prev, Elem);  
        if Elem /= null then  
            Rt     := Elem.Rt;  
            Status := True;  
            return;  
        end if;

----We did not find the Key in the map.

        Status := False;

    end Find;

--\f

    procedure Find (M      : in     Map;  
                    Key    : in     String;  
                    Ptr    : in out String_Pointer;  
                    Rt     : in out Range_Type;  
                    Status : out    Boolean) is
------------------------------------------------------------------------------
--  M       - Specifies the map to use
--  Key     - Specifies the string value to use for the lookup
--  Ptr     - Receives the string pointer from the map or is unchanged
--  Rt      - Receives the Range_Type value from the map or is unchanged
--  Status  - Receives TRUE if the Key was found and FALSE if not
--
-- Called to perform a lookup within the map.  If the Key string is found
-- within the map then the associated Range_Type value is returned and
-- Status is set to TRUE.  If the Key string is not found then Status is
-- set to FALSE and the Rt parameter remains unchanged.  (Beware of
-- uninitialized locals being passed to Find; they will often be the cause
-- of Constraint_Errors.)  Do not free the Ptr value returned by a successful
-- lookup.  It is shared by the map and deallocating it will cause
-- unpredicatble program behavior.
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key);  
        Prev : Element;  
        Elem : Element := M.Table (H rem S_Long (Hash_Size));  
    begin

----Lookup the entry in the table with this hash value.

        Lookup (H, Key, Prev, Elem);  
        if Elem /= null then  
            Rt     := Elem.Rt;  
            Ptr    := Elem.Key;  
            Status := True;  
            return;  
        end if;

----We did not find the Key in the map.

        Status := False;

    end Find;


--\f

    procedure Find_Ptr (M      : in     Map;  
                        Key    : in out String_Pointer;  
                        Rt     : in out Range_Type;  
                        Status : out    Boolean) is
------------------------------------------------------------------------------
--  M      - Specifies the map to use
--  Key    - Specifies the string value to use for the lookup
--  Rt     - Receives the Range_Type value from the map or is unchanged
--  Status - Receives TRUE if the Key was found and FALSE if not
--
-- Called to perform a lookup within the map.  If the Key string is found
-- within the map then the associated Range_Type value is returned and
-- Status is set to TRUE.  If the Key string is not found then Status is
-- set to FALSE and the Rt parameter remains unchanged.  (Beware of
-- uninitialized locals being passed to Find; they will often be the cause
-- of Constraint_Errors.)
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key.all);  
        Prev : Element;  
        Elem : Element := M.Table (H rem S_Long (Hash_Size));  
    begin

----Lookup the entry in the table with this hash value.

        Lookup (H, Key.all, Prev, Elem);  
        if Elem /= null then  
            Rt     := Elem.Rt;  
            Key    := Elem.Key;  
            Status := True;  
            return;  
        end if;

----We did not find the Key in the map.

        Status := False;

    end Find_Ptr;

--\f

    function Locate (M   : in Map;  
                     Key : in String) return Range_Type is
------------------------------------------------------------------------------
--  M       - Specifies the map to use
--  Key     - Specifies the string value to use for the lookup
--
-- Called to perform a lookup within the map.  If the Key string is found
-- within the map then the associated Range_Type value is returned.
-- If the Key string is not found then Missing_Entry is raised.
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key);  
        Prev : Element;  
        Elem : Element := M.Table (H rem S_Long (Hash_Size));  
    begin

----Lookup the entry in the table with this hash value.

        Lookup (H, Key, Prev, Elem);  
        if Elem /= null then  
            return Elem.Rt;  
        end if;

----We did not find the Key in the map.

        raise Missing_Entry;

    end Locate;

--\f

    procedure Insert (M       : in Map;  
                      Key     : in String;  
                      Rt      : in Range_Type;  
                      Dups_Ok : in Boolean := False) is
------------------------------------------------------------------------------
--  M       - Specifies the map to use
--  Key     - Specifies the string value to use for the insertion
--  Rt      - Specifies the Range_Type value to be placed into the map
--  Dups_Ok - Specifies TRUE if the new entry is allowed to replace an
--              existing entry.
--
-- Called to insert a new Range_Type value into the map.  If Dups_Ok => FALSE
-- then a pre-existing map entry with the same Key value will cause
-- Duplicate_Entry to be raised.
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key);  
        Prev : Element;  
        Elem : Element := M.Table (H rem S_Long (Hash_Size));  
    begin

----Lookup the entry in the table with this hash value.  Replace any existing
--  entry if that is ok.

        Lookup (H, Key, Prev, Elem);  
        if Elem /= null then  
            if Dups_Ok then  
                Elem.Rt := Rt;  
                return;  
            else  
                raise Duplicate_Entry;  
            end if;  
        end if;

----Create a new map element and put it into the map.

        declare  
            New_Elem : Elem_Rec;  
        begin  
            New_Elem.Hash := H;  
            New_Elem.Key  := new String'(Key);  
            New_Elem.Rt   := Rt;  
            Elem          := new Elem_Rec'(New_Elem);  
        end;  
        H           := H rem S_Long (Hash_Size);  
        Elem.Next   := M.Table (H);  
        M.Table (H) := Elem;  
        M.Count     := M.Count + 1;

----If not matching on case of characters then make the Key string upper case.

        if not Exact_Case_Match then  
            for I in Elem.Key'Range loop  
                if Elem.Key (I) in  
                   Character'Val (Standard.Character'Pos ('a')) ..  
                      Character'Val (Standard.Character'Pos ('z')) then  
                    Elem.Key (I) :=  
                       Character'Val  
                          (Character'Pos (Elem.Key (I)) -  
                           (Standard.Character'Pos ('a') -  
                            Standard.Character'Pos ('A')));  
                end if;  
            end loop;  
        end if;

    end Insert;

--\f

    procedure Insert_Ptr (M       : in Map;  
                          Key     : in String_Pointer;  
                          Rt      : in Range_Type;  
                          Dups_Ok : in Boolean := False) is
------------------------------------------------------------------------------
--  M       - Specifies the map to use
--  Key     - Specifies the string value to use for the insertion
--  Rt      - Specifies the Range_Type value to be placed into the map
--  Dups_Ok - Specifies TRUE if the new entry is allowed to replace an
--              existing entry.
--
-- Called to insert a new Range_Type value into the map.  If Dups_Ok => FALSE
-- then a pre-existing map entry with the same Key value will cause
-- Duplicate_Entry to be raised.
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key.all);  
        Prev : Element;  
        Elem : Element := M.Table (H rem S_Long (Hash_Size));  
    begin

----Lookup the entry in the table with this hash value.  Replace any existing
--  entry if that is ok.

        Lookup (H, Key.all, Prev, Elem);  
        if Elem /= null then  
            if Dups_Ok then  
                Free_String_Pointer (Elem.Key);  
                Elem.Key := Key;  
                Elem.Rt  := Rt;  
                return;  
            else  
                raise Duplicate_Entry;  
            end if;  
        end if;

----Create a new map element and put it into the map.

        declare  
            New_Elem : Elem_Rec;  
        begin  
            New_Elem.Hash := H;  
            New_Elem.Key  := Key;  
            New_Elem.Rt   := Rt;  
            Elem          := new Elem_Rec'(New_Elem);  
        end;  
        H           := H rem S_Long (Hash_Size);  
        Elem.Next   := M.Table (H);  
        M.Table (H) := Elem;  
        M.Count     := M.Count + 1;

----If not matching on case of characters then make the Key string upper case.

        if not Exact_Case_Match then  
            for I in Elem.Key'Range loop  
                if Elem.Key (I) in  
                   Character'Val (Standard.Character'Pos ('a')) ..  
                      Character'Val (Standard.Character'Pos ('z')) then  
                    Elem.Key (I) :=  
                       Character'Val  
                          (Character'Pos (Elem.Key (I)) -  
                           (Standard.Character'Pos ('a') -  
                            Standard.Character'Pos ('A')));  
                end if;  
            end loop;  
        end if;

    end Insert_Ptr;

--\f

    procedure Delete (M          : in Map;  
                      Key        : in String;  
                      Missing_Ok : in Boolean := False) is
------------------------------------------------------------------------------
--  M           - Specifies the map to use
--  Key         - Specifies the string value to use for the lookup
--  Missing_Ok  - Specifies TRUE if the entry need not exist
--
-- Called to delete an existing Range_Type value from the map.  Raises
-- Missing_Entry if no matching Key entry is found unless Missing_Ok => TRUE.
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key);  
        H2   : S_Long  := H rem S_Long (Hash_Size);  
        Prev : Element;  
        Elem : Element := M.Table (H2);  
    begin

----Lookup the entry in the table with this hash value and delete it.

        Lookup (H, Key, Prev, Elem);  
        if Elem /= null then  
            if Prev = null then  
                M.Table (H2) := Elem.Next;  
            else  
                Prev.Next := Elem.Next;  
            end if;  
            Free_String_Pointer (Elem.Key);  
            Free_Element (Elem);  
            M.Count := M.Count - 1;  
            return;  
        end if;

----We did not find the Key in the map.

        if Missing_Ok then  
            return;  
        else  
            raise Missing_Entry;  
        end if;

    end Delete;

--\f

    procedure Remove (M      : in     Map;  
                      Key    : in     String;  
                      Rt     : in out Range_Type;  
                      Status : out    Boolean) is
------------------------------------------------------------------------------
--  M      - Specifies the map to use
--  Key    - Specifies the string value to use for the lookup
--  Rt     - Receives the Range_Type value from the map or is unchanged
--  Status - Receives TRUE if the Key was found and FALSE if not
--
-- Called to lookup and remove an entry within the map.  If the Key string is
-- found -- within the map then the associated Range_Type value is returned and
-- Status is set to TRUE.  If the Key string is not found then Status is
-- set to FALSE and the Rt parameter remains unchanged.  (Beware of
-- uninitialized locals being passed to Find; they will often be the cause
-- of Constraint_Errors.)
------------------------------------------------------------------------------
        H    : S_Long  := Hash (Key);  
        H2   : S_Long  := H rem S_Long (Hash_Size);  
        Prev : Element;  
        Elem : Element := M.Table (H2);  
    begin

----Lookup the entry in the table with this hash value and delete it.

        Lookup (H, Key, Prev, Elem);  
        if Elem /= null then  
            if Prev = null then  
                M.Table (H2) := Elem.Next;  
            else  
                Prev.Next := Elem.Next;  
            end if;  
            Rt := Elem.Rt;  
            Free_String_Pointer (Elem.Key);  
            Free_Element (Elem);  
            M.Count := M.Count - 1;  
            Status  := True;  
            return;  
        end if;

----We did not find the Key in the map.

        Status := False;

    end Remove;

--\f

    procedure Initialize (M : in     Map;  
                          I : in out Iter) is

------------------------------------------------------------------------------
--  M   - Specifies the map
--  I   - Receives the new iteration value
--
-- Called to initialize an iterator for a particular map.  Iterators are
-- used in this fashion:
--      declare
--          I  : Iter;
--          M  : Map;
--          Rt : Range_Type;
--      begin
--          Initialize (M, I);
--          while not Done (I) loop
--              Rt := Value (I);
--              .... Code using the Rt value ....
--              Next (I);
--          end loop;
--      end;
-- Iterators are affected by changes to the map.  Deletions can cause
-- dereferencing of null pointers.  Insertions are benign and new map entries
-- may or may not appear as Values in the iteration depending upon the
-- state of the Iter when the Insert is performed and also depending upon the
-- value of the Key string.
--
-- The iterator will advance through all entries within the map and the
-- processing order of the entries is determined by the hash value of the
-- Key strings and may or may not have any externally sensible ordering.
------------------------------------------------------------------------------
    begin

----Search for any element whatsoever.

        I.M := M;  
        for Ind in S_Long range 0 .. S_Long (Hash_Size) - 1 loop  
            if M.Table (Ind) /= null then  
                I.Elem  := M.Table (Ind);  
                I.Index := Ind;  
                return;  
            end if;  
        end loop;

----Map is empty.  Finish the initialization.

        I.Elem  := null;  
        I.Index := S_Long (Hash_Size);

    end Initialize;

--\f

    procedure Initialize (M   : in     Map;  
                          I   : in out Iter;  
                          Rng : in     Range_Type) is
------------------------------------------------------------------------------
--  M   - Specifies the map
--  I   - Receives the new iteration value
--  Rng - Specifies the Range_Type value that we are iterating upon
--
-- Just like the other Initialize procedure except that the first value
-- returned by this iterator will have a Range_Type value equal to Rng
-- if Done(I) != TRUE.
------------------------------------------------------------------------------
    begin

----Search for any element whatsoever.

        I.M := M;  
        for Ind in S_Long range 0 .. S_Long (Hash_Size) - 1 loop  
            if M.Table (Ind) /= null then  
                I.Elem := I.M.Table (Ind);  
                loop  
                    if I.Elem.Rt = Rng then  
                        I.Index := Ind;  
                        return;  
                    end if;  
                    if I.Elem.Next = null then  
                        exit;  
                    end if;  
                    I.Elem := I.Elem.Next;  
                end loop;  
            end if;  
        end loop;

----Map is empty.  Finish the initialization.

        I.Elem  := null;  
        I.Index := S_Long (Hash_Size);

    end Initialize;

--\f

    function Done (I : in Iter) return Boolean is
------------------------------------------------------------------------------
--  I   - Specifies the iterator to check
--
-- Returns TRUE when there are no more map entries to iterate through.
------------------------------------------------------------------------------
    begin

----If we have an element waiting then we are not done.

        if I.Elem /= null then  
            return False;  
        end if;

----We must be done.

        return True;

    end Done;

--\f

    function Value (I : in Iter) return Range_Type is
------------------------------------------------------------------------------
--  I   - Specifies the iterator to check
--
-- Returns the Range_Type value associated with the current value of the
-- map iterator.  Raises Missing_Entry if Done(I) = TRUE.
------------------------------------------------------------------------------
    begin

        if I.Elem = null then  
            raise Missing_Entry;  
        end if;  
        return I.Elem.Rt;

    end Value;

--\f

    function Key (I : in Iter) return String is
------------------------------------------------------------------------------
--  I   - Specifies the iterator to check
--
-- Returns the string key associated with the current value of the
-- map iterator.  Raises Missing_Entry if Done(I) = TRUE.
------------------------------------------------------------------------------
    begin

        if I.Elem = null then  
            raise Missing_Entry;  
        end if;  
        return I.Elem.Key.all;

    end Key;

--\f

    function Key_Ptr (I : in Iter) return String_Pointer is
------------------------------------------------------------------------------
--  I   - Specifies the iterator to check
--
-- Returns the string key associated with the current value of the
-- map iterator.  Raises Missing_Entry if Done(I) = TRUE.
------------------------------------------------------------------------------
    begin

        if I.Elem = null then  
            raise Missing_Entry;  
        end if;  
        return I.Elem.Key;

    end Key_Ptr;

--\f

    procedure Next (I : in out Iter) is
------------------------------------------------------------------------------
--  I   - Specifies the iterator
--
-- Advances the map iterator by one entry.  Raises Missing_Entry if
-- Done(I) = TRUE already.  Done(I) = TRUE will be true when this routine
-- returns if there are no more entries to be processed.
------------------------------------------------------------------------------
    begin

----Locate the next element.

        if I.Elem = null then  
            raise Missing_Entry;  
        end if;  
        if I.Elem.Next /= null then  
            I.Elem := I.Elem.Next;  
            return;  
        end if;  
        for Ind in I.Index + 1 .. S_Long (Hash_Size) - 1 loop  
            if I.M.Table (Ind) /= null then  
                I.Elem  := I.M.Table (Ind);  
                I.Index := Ind;  
                return;  
            end if;  
        end loop;

----Nothing Next; we are Done.

        I.Elem := null;

    end Next;

--\f

    procedure Next (I   : in out Iter;  
                    Rng : in     Range_Type) is
------------------------------------------------------------------------------
--  I   - Specifies the iterator
--  Rng - Specifies the Range_Type value that we are iterating upon
--
-- Advances the map iterator by N entries.  Stops advancing the iterator when
-- the next entry with a Range_Type entry equal to Rng is found or when
-- the last entry in the map has been passed over.  Raises Missing_Entry if
-- Done(I) = TRUE already.  Done(I) = TRUE will be true when this routine
-- returns and there are no more entries to be processed.
------------------------------------------------------------------------------
    begin

----Locate the next element.

        if I.Elem = null then  
            raise Missing_Entry;  
        end if;  
        if I.Elem.Next /= null then  
            loop  
                I.Elem := I.Elem.Next;  
                if I.Elem.Rt = Rng then  
                    return;  
                end if;  
                if I.Elem.Next = null then  
                    exit;  
                end if;  
            end loop;  
        end if;  
        for Ind in I.Index + 1 .. S_Long (Hash_Size) - 1 loop  
            if I.M.Table (Ind) /= null then  
                I.Elem := I.M.Table (Ind);  
                loop  
                    if I.Elem.Rt = Rng then  
                        I.Index := Ind;  
                        return;  
                    end if;  
                    if I.Elem.Next = null then  
                        exit;  
                    end if;  
                    I.Elem := I.Elem.Next;  
                end loop;  
            end if;  
        end loop;

----Nothing Next; we are Done.

        I.Elem := null;

    end Next;

--\f

end Xlbip_String_Map_Generic;