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.1 required=5.0 tests=AXB_XMAILER_MIMEOLE_OL_024C2, BAYES_00,MAILING_LIST_MULTI,REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,6bf481efd29cf77b X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2002-06-12 20:04:12 PST Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!skynet.be!skynet.be!freenix!enst!enst.fr!not-for-mail From: "David C. Hoos, Sr." Newsgroups: comp.lang.ada Subject: Re: Behavior of Stream Attributes On Access Types. Date: Wed, 12 Jun 2002 22:00:45 -0500 Organization: ENST, France Sender: comp.lang.ada-admin@ada.eu.org Message-ID: References: <4519e058.0206110547.526d2369@posting.google.com> Reply-To: comp.lang.ada@ada.eu.org NNTP-Posting-Host: marvin.enst.fr Mime-Version: 1.0 Content-Type: text/plain; charset="Windows-1252" Content-Transfer-Encoding: 7bit X-Trace: avanie.enst.fr 1023937451 79961 137.194.161.2 (13 Jun 2002 03:04:11 GMT) X-Complaints-To: usenet@enst.fr NNTP-Posting-Date: Thu, 13 Jun 2002 03:04:11 +0000 (UTC) Return-Path: X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2600.0000 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 Errors-To: comp.lang.ada-admin@ada.eu.org X-BeenThere: comp.lang.ada@ada.eu.org X-Mailman-Version: 2.0.8 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: comp.lang.ada mail<->news gateway List-Unsubscribe: , Errors-To: comp.lang.ada-admin@ada.eu.org X-BeenThere: comp.lang.ada@ada.eu.org Xref: archiver1.google.com comp.lang.ada:25844 Date: 2002-06-12T22:00:45-05:00 ----- Original Message ----- From: "Marin David Condic ]" Newsgroups: comp.lang.ada To: Sent: June 12, 2002 10:18 AM Subject: Re: Behavior of Stream Attributes On Access Types. > Yes. That was helpful. But I'm still curious about how it would be done with > the scenario I described because I want to understand the inheritance > issues. (I can see that it would be better to handle the access values as > you describe, but in a more "general" sense - can you describe what happens > with the 'Read and 'Write as we travel down the chain of inheritance?) I don't see any "inheritance issues." The RM is quite clear as to what happens. Each component of an aggregate is written or read in the order in which it is declared, using either default stream attribute for that component's type, unless that attribute is overridden by an attribute definition clause. If, for example, a component of a record is an array of booleans, each of those booleans will be written or read to or from the stream as an individual octet, because 'read or 'write is called for each element of the array, even if the array is packed. If that behavior is unacceptable, then you can override the default stream attributes for the Boolean array type. I have had to do a lot of that sort of thing when using streams to read and write to and from a network where the network representation is defined with components that do not begin and end on octet boundaries. Here is an example of a 31-bit component adjacent to a one-bit component: type An_Hour_Fraction is delta 3600.0 * 2.0 ** (-31) range 0.0 .. 3600.0; for An_Hour_Fraction'Small use 3600.0 * 2.0 ** (-31); for An_Hour_Fraction'Size use 31; type A_Time_Stamp_Kind is (Relative, Absolute); for A_Time_Stamp_Kind use (Relative => 0, Absolute => 1); for A_Time_Stamp_Kind'Size use 1; type A_Time_Stamp is record Seconds : An_Hour_Fraction; Kind : A_Time_Stamp_Kind; end record; for A_Time_Stamp use record Seconds at 0 range 0 .. 30; Kind at 0 range 31 .. 31; end record; for A_Time_Stamp'Size use 32; procedure Read_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out A_Time_Stamp); procedure Write_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in A_Time_Stamp); for A_Time_Stamp'Read use Read_Time_Stamp; for A_Time_Stamp'Write use Write_Time_Stamp; Here are the bodies of the read and write procedures: procedure Read_Ts is new Byte_Ordering.Read (A_Time_Stamp); procedure Read_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out A_Time_Stamp) renames Read_Ts; procedure Write_Ts is new Byte_Ordering.Write (A_Time_Stamp); procedure Write_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in A_Time_Stamp) renames Write_Ts; Here is the Byte_Ordering generic: with Ada.Streams; package Byte_Ordering is generic type Item_Type is private; procedure Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Item_type); generic type Item_Type is private; procedure Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : Item_type); end Byte_Ordering; with System; package body Byte_Ordering is type U8 is mod 2 ** 8; for U8'Size use 8; type U8_Array is array (Integer range <>) of U8; --======================= -- Private subprograms == --======================= ---------- -- Swap -- ---------- procedure Swap (The_Item : in out U8_Array) is The_Bytes : array (1 .. The_Item'Length) of U8; for The_Bytes'Address use The_Item'Address; Temp : U8; begin for B in 1 .. The_Bytes'Last / 2 loop Temp := The_Bytes (B); The_Bytes (B) := The_Bytes (The_Bytes'Last - B + 1); The_Bytes (The_Bytes'Last - B + 1) := Temp; end loop; end Swap; --====================== -- Public subprograms == --====================== ---------- -- Read -- ---------- procedure Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Item_type) is The_Bytes : U8_Array (1 .. Item_Type'Size / U8'Size); for The_Bytes'Address use Item'Address; use type System.Bit_Order; begin U8_Array'Read (Stream, The_Bytes); if System.Default_Bit_Order = System.Low_Order_First then Swap (The_Bytes); end if; end Read; ----------- -- Write -- ----------- procedure Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : Item_Type) is Item_Copy : Item_type := Item; The_Bytes : U8_Array (1 .. Item_Type'Size / U8'Size); for The_Bytes'Address use Item'Address; use type System.Bit_Order; begin if System.Default_Bit_Order = System.Low_Order_First then Swap (The_Bytes); end if; U8_Array'Write (Stream, The_Bytes); end Write; end Byte_Ordering; If stream representation is important -- e.g., when it is needed to conform to a protocol specification, or when you need to communicate between little- and big- endian architectures, then you need to declare aggregate types that begin and end on octet boundaries, and override their default stream attributes. Yes, I know that some will find fault that I used address clauses to overlay objects instead of using unchecked conversion -- but this was done in the interest of efficiency.