comp.lang.ada
 help / color / mirror / Atom feed
* Using streams to convert record types
@ 1999-07-02  0:00 Robert Jordan
  1999-07-03  0:00 ` tmoran
  1999-07-03  0:00 ` Robert Dewar
  0 siblings, 2 replies; 3+ messages in thread
From: Robert Jordan @ 1999-07-02  0:00 UTC (permalink / raw)


I'm basically lazy.  I have to create code to handle roughly 300 types
of network messages (Going both ways).  I would like to use a stream
technique to convert the outgoing messages (Already defined as separate
record types) into arrays of integers for transfer to a TCP/IP handler. 
I also need to convert incoming integer data to very complex record
types (They vary in both size and organization).  The incoming data
could be defined (typed) as variant records, but my software doesn't
have to process any of it so I don't want to go to thhrough the
complexity of doing an 8000 line variant record.  I'm also loath to have
to create instantiations or unchecked conversions for every message.

Here's a little piece of code that I used to perform this type of action
with Stream_IO.

----------------------
with Ada.Streams.Stream_IO;        use Ada.Streams.Stream_IO;
with Ada.Streams;
with Ada.Text_IO;                  use Ada.Text_IO;


procedure Streamtest is

type TestArray is array(1..12) of Short_Integer;

MyArray : TestArray := (others => 0);

Myfile : Ada.Streams.Stream_IO.File_Type;

--type MyRootStream_Access is access Ada.Streams.Root_Stream_Type'Class;

MyStream : Stream_Access ;  --Hopefully Root access soon

--MyOffset : Ada.Streams.Stream_Element_Offset; -- Doesn't work

TmpString : String(1..5);

--An Enum rep clause for giggles...
type MyEnum_Type is ( Red   ,
                      Blue  ,
                      Green );
for MyEnum_Type use ( Red   => 16#0A01# ,
                      Blue  => 16#0B02# ,
                      Green => 16#0C03# );
for MyEnum_Type'Size use 16;

type MyRecord_type is
record
   Item1 : MyEnum_Type ;
   Item2 : MyEnum_Type ;
end record;
pragma Pack(MyRecord_Type);  --4 bytes (Storage_Elements)

MyRecord    : MyRecord_Type;
MyBadRecord : MyRecord_Type;

begin

MyArray := (
16#0C03#,   --Green
16#0A01#,   --Red
16#0B02#,   --Blue
16#0708#,   --Junk (Should cause an error if read and used)
16#090a#,   --and so on...
16#0b0c#,
16#0d0e#,
16#0f10#,
16#1112#,
16#1314#,
16#1516#,
16#1718#);

Create ( File => Myfile,
         Mode => Out_File,
         Name => "streamtest.bin" );

MyStream := Stream(MyFile);

TestArray'Write(MyStream, MyArray);

Close(MyFile);

--Now reconstruct a record
Open(File => MyFile,
    Mode => In_File,
    Name => "streamtest.bin");

MyStream := Stream(MyFile);

MyRecord_Type'Read(MyStream, MyRecord);
--Construct a partially bad record
MyRecord_Type'Read(MyStream, MyBadRecord);

--Known to be bad, but checked anyway
if MyBadRecord.Item2'Valid = False then
   Put_Line("MyBadRecord.Item2 was not valid");
   --Known to be good
   Put_Line("But MyBadRecord.Item1 was = "
           & MyEnum_Type'Image(MyBadRecord.Item1));
end if;

Put_Line("MyRecord.Item1 =" & MyEnum_Type'Image(MyRecord.Item1));
Close(MyFile);

--Now create a new file to prove the test conclusively
Create(File => MyFile,
       Mode => Out_File,
       Name => "streamtest_new.bin");

MyStream := Stream(MyFile);

MyRecord_Type'Write(MyStream,MyRecord);

Put_Line("MyRecord_Type'Max_Size_In_Storage_Elements = " &
         Integer'Image(MyRecord_Type'Max_Size_In_Storage_Elements) & "
Bytes");

Close(MyFile);

end StreamTest;

--unix
--od -a t streamtest.bin
--od -a t streamtest_new.bin
--Should both match up to the cut off point of writing on
--streamtest_new.bin

------------------------------
It actually works to convert a piece of an integer array to a record
using an external file without having to know or instantiate a special
function to handle the particular record data type.

What I would like to know is how I can do this same sort of thing
without having to access an external file?  Also, how would I verify the
validity of a LARGE record after reading the stream without having to
name each component and do a 'valid test (Would be bad on my worst
incoming message offendor of 400 items).

My next question comes about when trying to use S'read.  In the ADA95RM
(13.13.1) is shows an OUT Stream_Element_Offset being produced.  When I
try to use this, GNAT3.11 returns 'Unexpected parameter for "READ"
attribute'.  I looked in the GNAT SRC (I think it was the system
attribute source) and didn't see any handler for a third parameter for
the 'read stream operation.  I'm new to ADA so I probably am just using
streams incorrectly, but I'd really appreciate any code examples for
using ADA95 streams as buffers, queues, type converters,, and such.

Thanks,

Robert Jordan




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Using streams to convert record types
  1999-07-02  0:00 Using streams to convert record types Robert Jordan
  1999-07-03  0:00 ` tmoran
@ 1999-07-03  0:00 ` Robert Dewar
  1 sibling, 0 replies; 3+ messages in thread
From: Robert Dewar @ 1999-07-03  0:00 UTC (permalink / raw)


In article <377D42CD.A963EE27@boeing.com>,
  Robert Jordan <robert.l.jordan@boeing.com> wrote:
> My next question comes about when trying to use S'read.  In
> the ADA95RM (13.13.1) is shows an OUT Stream_Element_Offset
> being produced.

13.13.1 tells you about the Ada.Streams.Read procedure. This
has nothing to do with the 'Read attribute (no doubt the
internal implementation of 'Read will use the Read routine
but that is the extent of the connection!)

Read 13.13.2 for information on 'Read
(and there is indeed no 3rd parameter for the attribute, as
is clear from 13.13.2(6-7))

(the RM demands VERY careful reading. I would recommend learning
this stuff from a good text book and then reading the RM *after*
you have a basic understanding).



Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Using streams to convert record types
  1999-07-02  0:00 Using streams to convert record types Robert Jordan
@ 1999-07-03  0:00 ` tmoran
  1999-07-03  0:00 ` Robert Dewar
  1 sibling, 0 replies; 3+ messages in thread
From: tmoran @ 1999-07-03  0:00 UTC (permalink / raw)


>writing streams, then reading back, without an external file
Look at package Ada.Streams and forget about Ada.Streams.Stream_IO
You'll have to declare your own buffer type, which might be as
simple as

package My_Buffers is

  type Buffer_Type is new Ada.Streams.Root_Stream_Type with private;

  procedure Write(
    Stream : in out Buffer_Type;
    Item   : in     Ada.Streams.Stream_Element_Array);
  -- Copy from Item to buffer Stream

  procedure Read(
    Stream : in out Buffer_Type;
    Item   :    out Ada.Streams.Stream_Element_Array;
    Last   :    out Ada.Streams.Stream_Element_Offset);
  -- Copy from Stream into Item, returning Last as in Get_Line.

private
  type Buffer_Type is new Ada.Streams.Root_Stream_Type with record
    Buffer : Ada.Streams.Stream_Element_Array(1 .. 1000);
    Next_Write : Positive := 1;
    Next_Read  : Positive := 1;
  end record;
  -- Buffer(Next_Write) is where the next Stream_Element goes.
  -- Buffer(Next_Read) is where the next Stream_Element comes from,
  --  until Next_Read >= Next_Write, at which point you have run out
  --  of data and will have to return Last < Item'last
end My_Buffers;
package body My_Buffers is
..

Then instead of MyStream := Stream(MyFile);
set MyStream to an access to a buffer of Buffer_Type, so instead of
reading/writing to MyFile, the system will call your Read and Write,
which will move data to/from your buffer.




^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1999-07-03  0:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-07-02  0:00 Using streams to convert record types Robert Jordan
1999-07-03  0:00 ` tmoran
1999-07-03  0:00 ` Robert Dewar

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