comp.lang.ada
 help / color / mirror / Atom feed
From: lutz@iks-jena.de (Lutz Donnerhacke)
Subject: Ada.Streams.Read Length Paramenter is not IN?
Date: Tue, 7 Aug 2001 09:02:29 +0000 (UTC)
Date: 2001-08-07T09:02:29+00:00	[thread overview]
Message-ID: <slrn9mvbej.hs.lutz@taranis.iks-jena.de> (raw)

Writing a very small 'Filedescriptor_Stream' package (to eliminate the libc,
dealing with sockets, and---of course---learning), I run into semantic
problems with 'Ada.Streams.Read':

procedure Read(
  Stream : in out XXX_Stream_Type;
  Item   :    out Stream_Element_Array;
  Last   :    out Stream_Element_Offset);

The RM says:
  The Read operation transfers Item'Length stream elements from the
  specified stream to fill the array Item. The index of the last stream
  element transferred is returned in Last. Last is less than Item'Last only
  if the end of the stream is reached.

I can not read an arbitary amount of data due to possible blocking or
confusing situation where the corresponding site has to close the transfer
in order to process the input. (Quite contrary to interactive)

I can not read each Storage_Element seperatly, due to massive system
performance decrease.

OTOH each T'Read or T'Input procedure exactly knows how many
Storage_Elements are needed to fullfill the request. Why is this information
not given to the Stream.Read procedure?

BTW: Do I understand the procedure semantics correctly, if I return Item and
     Last := Item'Last generally. But in the case of EOF returning Item
     larger than normally and set Item'Last to the last valid element.
     Would it be not simpler to have the following procedure?
       procedure Read(
         Stream : in out XXX_Stream_Type;
	 Data   :    out Stream_Element_Array;
	 Needed : in     Stream_Element_Offset;
	 EOT    :    out Boolean);

Please do not quote the source unless you really want to comment it.
\f
-------------------- filedescriptor_stream.ads --------------------
with Interfaces.C, Ada.Streams;

package Filedescriptor_Stream is
   type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;   
   
   type Filedescriptor_Stream_Type is new Ada.Streams.Root_Stream_Type
     with private;
   
   function Stream(fd : Interfaces.C.int) return Stream_Access;
   
   Device_Error : exception;
   
   procedure Read(
     Stream : in out Filedescriptor_Stream_Type;
     Item   :    out Ada.Streams.Stream_Element_Array;
     Last   :    out Ada.Streams.Stream_Element_Offset);
      
   procedure Write(
     Stream : in out Filedescriptor_Stream_Type;
     Item   : in     Ada.Streams.Stream_Element_Array);
   
private
   type Filedescriptor_Stream_Type is new Ada.Streams.Root_Stream_Type
     with record fd : Interfaces.C.int; end record;
end Filedescriptor_Stream;
-------------------- filedescriptor_stream.ads --------------------
\f
-------------------- filedescriptor_stream.adb --------------------
with Interfaces.C, Ada.Streams;
use Interfaces.C, Ada.Streams;

package body Filedescriptor_Stream is
   function Stream(fd : int) return Stream_Access is
      res : Stream_Access := new Filedescriptor_Stream_Type;
   begin
      Filedescriptor_Stream_Type(res.all).fd := fd;
      return res;
   end Stream;
   
   function Read(Stream : in Filedescriptor_Stream_Type)
     return Stream_Element_Array;
   type void_p is access all Stream_Element;
   for void_p'Size use 32;
   

   function c_write(fd : int; buff : void_p; len : size_t) return int;
   function c_read(fd : int; buff : void_p; len : size_t) return int;
   pragma Import(C, c_write, "write");
   pragma Import(C, c_read, "read");
   
   function Read(Stream : in Filedescriptor_Stream_Type)
     return Stream_Element_Array is
      data : aliased Stream_Element_Array (0 .. 0);
   begin
      if 1 = c_read (Stream.fd, data(0)'Unrestricted_Access, 1) then
         return data; --  & Read (Stream);
      else
         return data;
      end if;      
   end Read;
   
   procedure Read(
     Stream : in out Filedescriptor_Stream_Type;
     Item   :    out Stream_Element_Array;
     Last   :    out Stream_Element_Offset) is
   begin
      Item := Read (Stream);
      Last := Item'Last;
   end Read;
      
   procedure Write(
     Stream : in out Filedescriptor_Stream_Type;
     Item   : in     Stream_Element_Array) is
      pos : Stream_Element_Offset := Item'First;
      len : size_t := Item'Length;
      res : int;
   begin
      while len > 0 loop
         res := c_write(Stream.fd, Item(pos)'Unrestricted_Access, len);
         if res = -1 then raise Device_Error; end if;
         len := len - size_t(res);
         pos := pos + Stream_Element_Offset(res);
      end loop;
   end Write;
   
end Filedescriptor_Stream;
-------------------- filedescriptor_stream.adb --------------------
\f
----------------------- test_fd_stream.adb ------------------------
with Filedescriptor_Stream;
use Filedescriptor_Stream;

procedure Test_Fd_Stream is
   sout : Stream_Access := Stream (1);
begin
   String'Write(sout, "a =" & Integer'Image(a) & ASCII.LF);
   String'Write(sout, "b =" & Integer'Image(b) & ASCII.LF);
   String'Write(sout, "c =" & Integer'Image(c) & ASCII.LF);
end Test_Fd_Stream;
----------------------- test_fd_stream.adb ------------------------



             reply	other threads:[~2001-08-07  9:02 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-08-07  9:02 Lutz Donnerhacke [this message]
2001-08-07 18:39 ` Ada.Streams.Read Length Paramenter is not IN? Ted Dennison
2001-08-07 20:18   ` Lutz Donnerhacke
2001-08-07 19:48 ` tmoran
2001-08-07 20:21   ` Lutz Donnerhacke
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox