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=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,d025526ebe32e523,start X-Google-Attributes: gid103376,public From: Robert Jordan Subject: Using streams to convert record types Date: 1999/07/02 Message-ID: <377D42CD.A963EE27@boeing.com>#1/1 X-Deja-AN: 496601650 Content-Transfer-Encoding: 7bit Sender: nntp@news.boeing.com (Boeing NNTP News Access) X-Nntp-Posting-Host: e897317.knt.boeing.com Organization: The Boeing Company Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 Newsgroups: comp.lang.ada Date: 1999-07-02T00:00:00+00:00 List-Id: 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