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 ` Robert Dewar
  1999-07-03  0:00 ` tmoran
  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

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 ` Robert Dewar
1999-07-03  0:00 ` tmoran

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