From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: Stream_Element_Array
Date: Thu, 15 Sep 2011 22:48:24 +0200
Date: 2011-09-15T22:48:24+02:00 [thread overview]
Message-ID: <vd7r3qy6mkdn.1hap5hmaa0pkx$.dlg@40tude.net> (raw)
In-Reply-To: fd1c420f-f5c0-4a1f-ba8d-15eb6a2c7696@en1g2000vbb.googlegroups.com
On Thu, 15 Sep 2011 11:58:21 -0700 (PDT), Alexander Korolev wrote:
> On Sep 15, 12:20�pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Wed, 14 Sep 2011 14:29:41 -0700 (PDT), Alexander Korolev wrote:
>>> "In your case the other end is not the memory but the wire"
>>> I am not sure I undestand you complitly. What's wrong, at least for
>>> now, to build \ construct in memory the Buffer (Stream_Element_Array)
>>> with full command (according the format I posted) inside and after
>>> that send it over any stream (including GNAT.Serial, Socket etc)
>>> derived from Root_Stream_Type. Basicly, I don't need even a Type -
>>> I am using it just get Unsigned_16 serialized into Stream Elements.
>>
>> Yes, but in most cases it does not work so straightforwardly. You usually
>> need headers, checksums etc. The point is that you have more layers of the
>> protocol than just raw values over stream of octets. This is why you use
>> stream rather as a transport for packets/messages and often more upper
>> levels too (state machine etc). The idea is to always encapsulate each
>> level into a data type. It saves much time later.
>>
>>> That's it. It's kind of hadcrafting. I also can override My_Type'Write
>>> attribute and send to Serial port ... Your approach is to create a new
>>> stream actully, which will take into account the PROTOCOL specifics.
>>> Absolutly agree with that. But what is wrong with manual approach I am
>>> implementing.
>>
>> It is not wrong, it is just might not work because protocols are more
>> complex (layered) than this simple model.
>
> 1. Can not disagree again - layers, state machines is "must" part.
> 2. So far got some interim results with serialization of the Type
> in Volatile Stream. The Last set to 3? It looks I am getting
> there but no confidence so far.
Volatile Stream has a bug in its implementation. Last is actually "Next".
Anyway, here is how I do such stuff:
with Volatile_Streams; use Volatile_Streams;
with Ada.Streams; use Ada.Streams;
with Interfaces; use Interfaces;
package Frame_Streams is
Protocol_Error : exception;
--
-- Implements frame I/O layer over the stream transport.
-- In this case the transport is memory-resident stream.
--
type Frame_Stream (Size : Stream_Element_Count) is
tagged limited private;
-- Send frame, Data is the frame body
procedure Send
( Stream : in out Frame_Stream;
Data : Stream_Element_Array
);
-- Receive frame, Data is the frame body, Last its last item
-- Protocol_Error is propagated upon protocol errors
procedure Receive
( Stream : in out Frame_Stream;
Data : out Stream_Element_Array;
Last : out Stream_Element_Offset
);
private
Max_Frame_Size : constant := 256;
type Frame_Stream (Size : Stream_Element_Count) is
new Memory_Resident_Stream (Size) with
record
Output : Stream_Element_Array (1..Max_Frame_Size);
end record;
end Frame_Streams;
package body Frame_Streams is
procedure Send
( Stream : in out Frame_Stream;
Data : Stream_Element_Array
) is
Sum : Unsigned_8 := 0;
begin
if Data'Length + 4 > Stream.Output'Length then
raise Constraint_Error with "Packet is too large";
end if;
Stream.Output (1) := 0;
Stream.Output (2) := Stream_Element'Val (Data'Length / 256);
Stream.Output (3) := Stream_Element'Val (Data'Length mod 256);
Stream.Output (4..3 + Data'Length) := Data;
for Index in Stream_Element_Offset
range 2..3 + Data'Length
loop
Sum := Sum + Stream_Element'Pos (Stream.Output (Index));
end loop;
Stream.Output (4 + Data'Length) := Stream_Element'Val (Sum);
Stream.Write (Stream.Output (1..4 + Data'Length));
end Send;
procedure Receive
( Stream : in out Frame_Stream;
Data : out Stream_Element_Array;
Last : out Stream_Element_Offset
) is
Length : Stream_Element_Offset;
Sum : Unsigned_8;
Input : Stream_Element_Array (1..2);
begin
Stream.Read (Input (1..1), Last);
if Last /= 2 then
raise Protocol_Error with "Frame header expected";
elsif Input (1) /= 0 then
raise Protocol_Error with "Wrong leading byte";
end if;
Stream.Read (Input (1..2), Last);
Length := Stream_Element'Pos (Input (1)) * 256
+ Stream_Element'Pos (Input (2));
if Last /= 3 then
raise Protocol_Error with "Unexpected end of stream";
elsif Length > Data'Length then
raise Protocol_Error with "Frame is too large";
end if;
Sum := Stream_Element'Pos (Input (1))
+ Stream_Element'Pos (Input (2));
Stream.Read (Data (Data'First..Data'First + Length - 1), Last);
if Last /= Data'First + Length then
raise Protocol_Error with "Unexpected end of stream";
end if;
Stream.Read (Input (1..1), Last);
if Last /= 2 then
raise Protocol_Error with "Unexpected end of stream";
end if;
Last := Data'First + Length - 1;
for Index in Data'First..Last loop
Sum := Sum + Stream_Element'Pos (Data (Index));
end loop;
if Sum /= Stream_Element'Pos (Input (1)) then
raise Protocol_Error with "Checksum error";
end if;
end Receive;
end Frame_Streams;
To be used as follows:
with Ada.Text_IO; use Ada.Text_IO;
with Frame_Streams; use Frame_Streams;
procedure Put (Data : Stream_Element_Array) is
begin
for Index in Data'Range loop
Put (Stream_Element'Image (Data (Index)));
Put (' ');
end loop;
end Put;
S : aliased Frame_Stream (1024);
Buffer : Stream_Element_Array (1..4);
Last : Stream_Element_Offset;
begin
S.Send ((1, 2, 3, 4));
Put_Line ("Written:" & Stream_Element_Count'Image (S.Extent));
S.Receive (Buffer, Last);
Put_Line ("Read:");
Put (Buffer (1..Last));
end;
Note that is in its turn is frame I/O layer. Upon it you will have another
layer and so on up to the application layer.
P.S. It is a bit simplified, if there are many transports layers, the frame
layer would take the actual transport as a discriminant (access to
Root_Stream'Class) or a generic parameter. In your case it would be an
overkill.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
next prev parent reply other threads:[~2011-09-15 20:48 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-14 3:13 Stream_Element_Array Alexander Korolev
2011-09-14 5:29 ` Stream_Element_Array Per Sandberg
2011-09-14 8:34 ` Stream_Element_Array Alexander Korolev
2011-09-14 8:31 ` Stream_Element_Array Simon Wright
2011-09-14 9:09 ` Stream_Element_Array Alexander Korolev
2011-09-14 9:40 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-14 9:41 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-14 10:18 ` Stream_Element_Array Simon Wright
2011-09-14 12:42 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-14 16:20 ` Stream_Element_Array Simon Wright
2011-09-14 19:53 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-14 10:53 ` Stream_Element_Array Simon Wright
2011-09-14 12:48 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-14 14:48 ` Stream_Element_Array Alexander Korolev
2011-09-14 15:08 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-14 17:16 ` Stream_Element_Array Alexander Korolev
2011-09-14 20:13 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-14 21:29 ` Stream_Element_Array Alexander Korolev
2011-09-15 8:20 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-15 18:58 ` Stream_Element_Array Alexander Korolev
2011-09-15 20:48 ` Dmitry A. Kazakov [this message]
2011-09-16 0:20 ` Stream_Element_Array Alexander Korolev
2011-09-15 19:15 ` Stream_Element_Array Alexander Korolev
2011-09-15 20:11 ` Stream_Element_Array Simon Wright
2011-09-15 20:34 ` Stream_Element_Array Alexander Korolev
2011-09-15 21:42 ` Stream_Element_Array Simon Wright
2011-09-15 21:50 ` Stream_Element_Array Simon Wright
2011-09-16 0:01 ` Stream_Element_Array Alexander Korolev
2011-09-16 0:18 ` Stream_Element_Array Adam Beneschan
2011-09-16 7:22 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-16 10:21 ` Stream_Element_Array Simon Wright
2011-09-16 12:13 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-16 17:20 ` Stream_Element_Array Simon Wright
2011-09-16 19:32 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-16 22:18 ` Stream_Element_Array Simon Wright
2011-09-17 8:18 ` Stream_Element_Array Dmitry A. Kazakov
2011-09-19 23:22 ` Stream_Element_Array Randy Brukardt
2011-09-15 21:28 ` Stream_Element_Array Alexander Korolev
2011-09-15 2:33 ` Stream_Element_Array Alexander Korolev
2011-09-19 23:11 ` Stream_Element_Array Randy Brukardt
2011-09-14 12:19 ` Stream_Element_Array Gautier write-only
2011-09-16 11:17 ` Stream_Element_Array anon
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox