-- This package provides a means for iterating over the fields
-- in a line.
--
-- All operations raise "Not_Initialized" if passed an uninitialized
-- object.
--
-- All strings are returned starting at index 1.
--
generic

    with function Is_Separator (This_Character : in Character) return Boolean;
    --
    -- Specifies which characters are field separators. The beginning and
    -- the end of the string is always a field separator. For example, if
    -- the Is_Separator function recognizes '|' and '.' as field separators,
    -- then the following string contains five fields (three of which are
    -- null):
    --
    --      |a.|bcd|
    --
    -- and the following string contains three fields (one of which is null):
    --
    --      a|.bdc
    --
    -- The null string contains no fields.

package Fields is

    subtype Field is String;

    type Iterator is private; -- Is ordered.

    function Create (From_String : in String) return Iterator;
    --
    -- Parses the specified string looking for fields, and returns
    -- an initialized field iterator. If the string is null, the
    -- resulting iterator contains no fields, and "Done" is always
    -- True; otherwise the current field in the iterator is reset
    -- to the first field in the iterator before the iterator is
    -- returned.

    function Done (This_Iterator : in Iterator) return Boolean;

    procedure Reset (This_Iterator : in out Iterator);
    --
    -- Resets the current field in the iterator to the first field.
    -- If the iterator is empty, has no effect.

    function Current (This_Iterator : in Iterator) return Field;
    --
    -- Returns the current field in the iterator.
    --
    -- Raises "No_Current_Field" if already "Done".

    procedure Modify (This_Iterator : in out Iterator; New_Field : in Field);
    --
    -- Replaces the current field in the iterator with the new field.
    -- Can be called during iteration without altering iterator's position.
    --
    -- Raises "No_Current_Field" in already "Done".
    --
    -- Raises "Parse_Failure" if the new field contains a separator.

    procedure Next (This_Iterator : in out Iterator);
    --
    -- Advances the current field in the iterator to the next field.
    --
    -- Raises "No_Next_Field" if already "Done".

    subtype Field_Number is Positive; -- Fields are numbered 1..N

    function Position (In_Iterator : in Iterator) return Field_Number;
    --
    -- Returns the field number corresponding to the current field in
    -- the iterator.
    --
    -- Raises "No_Current_Field" if already "Done".

    procedure Set (This_Iterator : in out Iterator; To_Field : in Field_Number);
    --
    -- Sets the current field in the iterator to the specified field number.
    --
    -- Raises "Out_Of_Range" if the specified field number is out of range,
    -- or if the iterator is empty.

    function Field_At
                (This_Position : in Field_Number; In_Iterator : in Iterator)
                return Field;
    --
    -- Returns the field corresponding to the specified field number.
    -- Can be called during iteration without altering iterator's position.
    --
    -- Raises "Out_Of_Range" if the specified field number is out of range,
    -- or if the iterator is empty.

    function Is_Empty (This_Iterator : in Iterator) return Boolean;
    --
    -- Returns True if the specified iterator contains no fields.

    function Fields_In (This_Iterator : in Iterator) return Natural;
    --
    -- Returns the number of fields in the specified iterator.

    Not_Initialized : exception;

    Parse_Failure : exception;

    No_Current_Field : exception;
    No_Next_Field : exception;

    Out_Of_Range : exception;

private

    type Fields_Pointer is access String;

    type Iterator is
        record
            The_Fields : Fields_Pointer := null;
            Characters_In_Current_Field : Natural := 0;
            Trailing_Separator_Position : Natural := 0;
            Current_Field_Number : Natural := 0;
            Done : Boolean := True;
        end record;

end Fields;