Safe_IO


Doing IO in Ada may result in exceptions being raised. For simple programs
it can become quite bothersome to sorrund each IO with an exception
handler. Designing the code to handle exceptions, without localizing the
handling of exceptions, can be confusing - and result in exceptions not
being handled, and the program ending with error.
The safe_io package receives any type with put&get operations and provides
new put&get operations which handle all exceptions. The input routine,
retries until successful input. The output routine simply produces an
error message to the user, when an expcetion happens during output (this
is, of course, rarer than invalid input).
This relieves the programmer from worrying about IO exceptions, while keep
the program from ending wiht error.

The design of Safe_Io makes use of a "signature package" called
IO_Pacakge. This package ties together a type (which can be any type
mathicing "limited private"), a put and a get routine. This is the
parameter Safe_Io expects.

The Try_Safe_Io program is an example of the steps reuqired in order to
instnatiate a generic that works with a signature package generic
parameter (aka "formal package parameter").


-- Purpose:   Protects againts exceptions during input/output
--            Useful for programming exercises that should be safe from
--            exceptions, but in which you do not want to bother with
--            error sophisticated handling.
-- Generic Parameters:            
--         * Item type & Put/Get operations - using the IO_Package signature
--         * Messaeg - error message to disply when exception occurs.
-- Exported Routines:
--         * Put - Outputs an item. Exceptions will cause an error message
--                 No retry is done when excpetion occurs.
--         * Get - Gets an Item. If exception occurs, a message is displayed
--                 and the input is retired. Routine exits only after
--                 successful input.  
------------------------------------------------------------------------------
-- Programmed by Ehud Lamm (C)
------------------------------------------------------------------------------

with IO_Package;
generic
   with package IO is new IO_Package(<>);
   Message:String:="Exception occured during IO";
package Safe_Io is

   procedure Put(I:in IO.Item);
   procedure Get(I:out IO.Item);
   
end;


--------------------------------------------------------------------------------


-- Purpose:   Safe io implementation
------------------------------------------------------------------------------
-- Programmed by Ehud Lamm (C)
------------------------------------------------------------------------------

with Ada.Text_Io;
use  Ada.Text_Io;

package body Safe_Io is

   ---------
   -- Get --
   ---------

   procedure Get (I:out IO.Item) is
      Success:Boolean:=FALSE;
  begin
      loop
         begin
            IO.get(I);
            Success:=True;
         exception
            when Others=>
               put(Message);
               put_line("(retry)");
               Skip_Line;
         end;
         exit when Success;
      end loop;      
   end Get;

   ---------
   -- Put --
   ---------

   procedure Put (I:in IO.Item) is
   begin
      IO.Put(I);
   exception
      when Others => 
            put(Message);
            put_line("(no retry on output)");
   end Put;

end Safe_Io;


--------------------------------------------------------------------------------


-- Purpose:   Signature package suplying put and get.
--            For use with the Safe_Io package.
------------------------------------------------------------------------------
-- Programmed by Ehud Lamm (C)
------------------------------------------------------------------------------
generic 
   type Item is limited private;
   with procedure Put(I:in Item) is <>;
   with procedure Get(I:out Item) is <>;
package IO_Package is
end;


--------------------------------------------------------------------------------


-- Purpose:   Example of use for Safe_Io pacakge.
-- Explanation:
--    Safe_Io uses a signature package as a generic parameter.
--    This means that before instantiating Safe_Io we have to create an
--    instance of Io_Package. This ensure that we have all the required 
--    elements for Safe_Io.
--    Since Integer_Io put and get routines have default parameters, and
--    thus do not agree with the generic parameter declarations in 
--    Io_Package, we wrap them with routines that hide the defaults.
--    Notice the order of instantiation, as numbered below.
------------------------------------------------------------------------------
-- Programmed by Ehud Lamm (C)
------------------------------------------------------------------------------

with Safe_Io;
with Io_Package;
with Ada.Text_Io;

procedure Try_Safe_Io is

   package Pos_Io is new Ada.Text_Io.Integer_Io(Positive);        --1
   
   -- Kludge because of defaulted paramters:
   procedure Put(I:in Positive)  is begin Pos_Io.Put(I); end;
   procedure Get(I:out Positive) is begin Pos_Io.Get(I); end;
   
   package IO_Interface is new Io_Package(Positive);              --2
   
   package Safe_Pos_Io is new Safe_Io(Io_Interface);              --3
   
   P:Positive;
begin
   Safe_Pos_Io.Get(P);
   Safe_Pos_Io.Put(P);
end;

Contributed by: Ehud Lamm
Contributed on: February 16, 2000
License: Public Domain

Back