comp.lang.ada
 help / color / mirror / Atom feed
From: "David C. Hoos, Sr." <david.c.hoos.sr@ada95.com>
Subject: Re: Behavior of Stream Attributes On Access Types.
Date: Wed, 12 Jun 2002 22:00:45 -0500
Date: 2002-06-12T22:00:45-05:00	[thread overview]
Message-ID: <mailman.1023937450.3797.comp.lang.ada@ada.eu.org> (raw)
In-Reply-To: ae7oo4$7ob$1@nh.pace.co.uk


----- Original Message -----
From: "Marin David Condic ]" <dont.bother.mcondic.auntie.spam@[acm.org>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada.eu.org>
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.







  reply	other threads:[~2002-06-13  3:00 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-06-10 19:38 Behavior of Stream Attributes On Access Types Marin David Condic
2002-06-11  5:33 ` R. Tim Coslet
2002-06-11 14:15   ` Marin David Condic
2002-06-11 13:47 ` Ted Dennison
2002-06-11 14:27   ` Marin David Condic
2002-06-11 14:37     ` Marin David Condic
2002-06-12 14:19       ` David C. Hoos
2002-06-12 15:18         ` Marin David Condic
2002-06-13  3:00           ` David C. Hoos, Sr. [this message]
2002-06-14 18:27           ` Simon Wright
2002-06-14 18:53             ` Marin David Condic
2002-06-15 14:56               ` Simon Wright
2002-06-16  2:27                 ` Randy Brukardt
2002-06-17 14:31                   ` Marin David Condic
2002-06-18 19:30                     ` Randy Brukardt
2002-06-12 19:39       ` Randy Brukardt
2002-06-12 13:31     ` Ted Dennison
2002-06-11 21:56   ` Randy Brukardt
2002-06-12  3:44 ` David C. Hoos, Sr.
replies disabled

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