From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,deffccd74319c23d X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news4.google.com!news.glorb.com!feeder.xsnews.nl!feeder.news-service.com!skynet.be!skynet.be!newspost001!tjb!not-for-mail Date: Mon, 09 May 2005 20:49:56 +0200 From: Adrien Plisson Reply-To: aplisson-news@stochastique.net User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax) X-Accept-Language: fr-be, fr, en-us, en MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: Sending Variable Length Messages with GNAT.Sockets References: <1115633512.107824.259680@g14g2000cwa.googlegroups.com> <427f3dfa$0$28058$ba620e4c@news.skynet.be> <1115637556.074009.113830@o13g2000cwo.googlegroups.com> <1115650283.330746.109740@f14g2000cwb.googlegroups.com> In-Reply-To: <1115650283.330746.109740@f14g2000cwb.googlegroups.com> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Message-ID: <427fb046$0$1421$ba620e4c@news.skynet.be> Organization: -= Belgacom Usenet Service =- NNTP-Posting-Host: ca914bf2.news.skynet.be X-Trace: 1115664455 news.skynet.be 1421 81.240.46.122:10012 X-Complaints-To: usenet-abuse@skynet.be Xref: g2news1.google.com comp.lang.ada:10980 Date: 2005-05-09T20:49:56+02:00 List-Id: 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