comp.lang.ada
 help / color / mirror / Atom feed
From: Adrien Plisson <aplisson-news@stochastique.net>
Subject: Re: Sending Variable Length Messages with GNAT.Sockets
Date: Mon, 09 May 2005 20:49:56 +0200
Date: 2005-05-09T20:49:56+02:00	[thread overview]
Message-ID: <427fb046$0$1421$ba620e4c@news.skynet.be> (raw)
In-Reply-To: <1115650283.330746.109740@f14g2000cwb.googlegroups.com>

markp wrote:
> Thanks John.
> 
> I still have a fundamental problem. I am working on legacy code in
> which data is defined in records (or arrays of records) which are sent
> in variable lengths. We use address, byte count to send the exact
> number of bytes. Using Streams, it seems they type has to be of
> Stream_element_Array. The only way I can see to send/receive these
> "variable" messages is to first read our message header which contains
> the number of bytes in the message. Then, create a Stream_Element_Array
> of the exact size for the next read. Then, do an unchecked conversion
> or a copy bytes routine to get the data into my data type for
> processing. Does this sound correct?

this sounds bof bof... a bit complicated...

since you seem still struggling on this, here is some help, based on 
wild guesses i made given your previous posts:

with Ada.Text_IO,
      Ada.Streams,
      Ada.Streams.Stream_IO;
procedure Main is
     -- let's assume you have this kind of records
     type Data_Record is record
         Some : Integer;
         Dummy : String (1..8);
         Fields : Float;
     end record;

     -- according to the description you gave in a previous post,
     -- your message type is implemented (simplified) this way
     type Data_Record_Array is array (1..512) of Data_Record;
     type Message is record
         -- the message header (very simplified)
         -- holds the number of actual records in the data
         Number_Of_Records : Natural;
         -- the message data
         Data : Data_Record_Array;
     end record;

     -- declaration of the custom stream attribute procedures
     procedure Message_Read( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : out Message );
     for Message'Read use Message_Read;
     procedure Message_Write( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : in Message );
     for Message'Write use Message_Write;

     -- implementation of Message'Read
     procedure Message_Read( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : out Message ) is
         Size : Natural;
     begin
         -- first read the header
         -- WARNING: on the network, the size is in bytes,
         -- not in number of records
         Natural'Read( Stream, Size );
         Msg.Number_Of_Records := Size / (Data_Record'Size / 
Ada.Streams.Stream_Element'Size);

         -- then read the data
         for I in Msg.Data'First..Msg.Data'First + Msg.Number_Of_Records 
- 1 loop
             Data_Record'Read( Stream, Msg.Data(I) );
         end loop;
     end Message_Read;

     -- implementation of Message'Write
     procedure Message_Write( Stream : access 
Ada.Streams.Root_Stream_Type'Class; Msg : in Message ) is
     begin
         -- first write the header
         -- WARNING: on the network, the size is in bytes,
         -- not in number of records
         Natural'Write( Stream, Msg.Number_Of_Records * Data_Record'Size 
/ Ada.Streams.Stream_Element'Size );

         -- then write the data
         for I in Msg.Data'First..Msg.Data'First + Msg.Number_Of_Records 
- 1 loop
             Data_Record'Write( Stream, Msg.Data(I) );
         end loop;
     end Message_Write;


     -- this is for to simplify test writing
     use Ada.Streams.Stream_IO;

begin
     -- since socket streams and file streams are identical (really, all 
streams work the same)
     -- we will use files for testing

     -- first write some stuffs to a stream
     declare
         F : File_Type;
         S : Stream_Access;
         M : Message;

     begin
         -- create a new file
         Create( F, Out_File, "test.out" );
         -- get the stream corresponding to the file
         S := Stream( F );

         -- create 5 messages
         for I in 1..5 loop
             -- fill each message with dummy data
             M.Number_Of_Records := I * 2;
             for J in 1..M.Number_Of_Records loop
                 M.Data(J) := Data_Record'(Some => J, Dummy => 
"20050509", Fields => 42.0 / Float( I ) + Float( J ));
             end loop;

             -- write the data to the stream
             Message'Write( S, M );
         end loop;

         -- close the file
         Close( F );
     end;

     -- here you can look at "test.out" and see what it contains.

     -- now read some stuffs from the stream
     declare
         F : File_Type;
         S : Stream_Access;
         M : Message;

     begin
         -- open the file
         Open( F, In_File, "test.out" );
         -- get the stream corresponding to the file
         S := Stream( F );

         -- read all messages on the stream
         loop
             Message'Read( S, M );

             -- display the content of the messages
             Ada.Text_IO.Put_Line( "Message found : " & Natural'Image( 
M.Number_Of_Records ) & " records =>" );
             for I in M.Data'First..M.Data'First + M.Number_Of_Records - 
1 loop
                 Ada.Text_IO.Put_Line( "    " & Integer'Image( 
M.Data(I).Some ) & " " & M.Data(I).Dummy & " " & Float'Image( 
M.Data(I).Fields ) );
             end loop;
         end loop;
     exception
         when End_Error =>
             -- when there are no more messages in the stream file,
             -- close it
             Close( F );
     end;
end Main;

-- 
rien




  reply	other threads:[~2005-05-09 18:49 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-05-09 10:11 Sending Variable Length Messages with GNAT.Sockets markp
2005-05-09 10:39 ` Adrien Plisson
2005-05-09 11:19   ` markp
2005-05-09 11:50     ` Adrien Plisson
2005-05-09 14:30     ` John B. Matthews
2005-05-09 14:51       ` markp
2005-05-09 18:49         ` Adrien Plisson [this message]
2005-05-09 19:16         ` Simon Wright
2005-05-10 15:08           ` markp
2005-05-10 20:34           ` Simon Wright
2005-05-11 13:19             ` Marc A. Criley
2005-05-11 17:14               ` tmoran
2005-05-11 21:05               ` Simon Wright
2005-05-12 10:24                 ` Jacob Sparre Andersen
2005-05-14 11:12                   ` Simon Wright
2005-05-09 11:19   ` Jeff C
2005-05-09 11:35     ` markp
2005-05-09 11:57     ` Adrien Plisson
replies disabled

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