comp.lang.ada
 help / color / mirror / Atom feed
* Behavior of Stream Attributes On Access Types.
@ 2002-06-10 19:38 Marin David Condic
  2002-06-11  5:33 ` R. Tim Coslet
                   ` (2 more replies)
  0 siblings, 3 replies; 19+ messages in thread
From: Marin David Condic @ 2002-06-10 19:38 UTC (permalink / raw)


I'm checking section 13.13.2 of the ARM to discover the default behavior of
the Stream 'Read, 'Write, 'Input and 'Output when they encounter an access
type. I'm not finding any clear indication of what gets put to the stream -
although there is a mention in paragraph 35 of raising Constraint_Error on
input if the value is not of its subtype. Can someone clarify the behavior?

My inclination is to think that the sensible thing would be to call the
'Read or 'Write for the thing pointed to by the access type, but this has
implications for dynamically allocated objects. Will it write/read a
(totally useless) access value?

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com






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

* Re: Behavior of Stream Attributes On Access Types.
  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-12  3:44 ` David C. Hoos, Sr.
  2 siblings, 1 reply; 19+ messages in thread
From: R. Tim Coslet @ 2002-06-11  5:33 UTC (permalink / raw)


As I understand it, the LRM simply leaves it "implementation defined".

I don't expect the value to be of any use...

I always write custom 'Read and 'Write functions for access types
specifically designed to instead read or write the "subtree" of the data
structure the access points to, instead of the value.

Of course this only works for types used to define simple "linear" and
"tree" shaped data structures. It would get much more involved for the
"general" case.

-- 
        R. Tim Coslet
        r_tim_coslet@pacbell.net

Technology, n. Domesticated natural phenomena.


> From: "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org>
> Organization: Posted on a server owned by Pace Micro Technology plc
> Newsgroups: comp.lang.ada
> Date: Mon, 10 Jun 2002 15:38:20 -0400
> Subject: Behavior of Stream Attributes On Access Types.
> 
> I'm checking section 13.13.2 of the ARM to discover the default behavior of
> the Stream 'Read, 'Write, 'Input and 'Output when they encounter an access
> type. I'm not finding any clear indication of what gets put to the stream -
> although there is a mention in paragraph 35 of raising Constraint_Error on
> input if the value is not of its subtype. Can someone clarify the behavior?
> 
> My inclination is to think that the sensible thing would be to call the
> 'Read or 'Write for the thing pointed to by the access type, but this has
> implications for dynamically allocated objects. Will it write/read a
> (totally useless) access value?
> 
> MDC
> --
> Marin David Condic
> Senior Software Engineer
> Pace Micro Technology Americas    www.pacemicro.com
> Enabling the digital revolution
> e-Mail:    marin.condic@pacemicro.com
> 
> 
> 




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

* Re: Behavior of Stream Attributes On Access Types.
  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 13:47 ` Ted Dennison
  2002-06-11 14:27   ` Marin David Condic
  2002-06-11 21:56   ` Randy Brukardt
  2002-06-12  3:44 ` David C. Hoos, Sr.
  2 siblings, 2 replies; 19+ messages in thread
From: Ted Dennison @ 2002-06-11 13:47 UTC (permalink / raw)


"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in message news:<ae2v7f$r12$1@nh.pace.co.uk>...
> My inclination is to think that the sensible thing would be to call the
> 'Read or 'Write for the thing pointed to by the access type, but this has

You can pretty much count on it *not* doing that. For instance, what
would happen in that case with a circularly-referenced structure like
a doubly-linked list?


> implications for dynamically allocated objects. Will it write/read a
> (totally useless) access value?

Pretty much. It isn't *totally* useless. It will work just fine within
the same execution (assuming you don't deallocate the memory).
However, it is next to useless.

If you want better behavior, its up to you to override 'Write and
'Read for your pointer type. Then you can code it to handle things
like circular references and deallocating the target's old value on a
'Read.


-- 
T.E.D. 
Home     -  mailto:dennison@telepath.com (Yahoo: Ted_Dennison)
Homepage -  (temporarily down)



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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-11  5:33 ` R. Tim Coslet
@ 2002-06-11 14:15   ` Marin David Condic
  0 siblings, 0 replies; 19+ messages in thread
From: Marin David Condic @ 2002-06-11 14:15 UTC (permalink / raw)


That's kind of how I've been handling it - overriding the "default" case
with my own operations to get linked data structures in and out of streams.
I was just wondering what the ARM had to say on what the "default" case is -
if I have a record with pointers to other things and just do a 'Write, what
happens? Given the nature of the beast, its hard to imagine anything
happening that would be at all useful, so I guess the answer is "Always Roll
Your Own."

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com


"R. Tim Coslet" <R_Tim_Coslet@pacbell.net> wrote in message
news:B92AD893.4284%R_Tim_Coslet@pacbell.net...
> As I understand it, the LRM simply leaves it "implementation defined".
>
> I don't expect the value to be of any use...
>
> I always write custom 'Read and 'Write functions for access types
> specifically designed to instead read or write the "subtree" of the data
> structure the access points to, instead of the value.
>
> Of course this only works for types used to define simple "linear" and
> "tree" shaped data structures. It would get much more involved for the
> "general" case.
>






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

* Re: Behavior of Stream Attributes On Access Types.
  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 13:31     ` Ted Dennison
  2002-06-11 21:56   ` Randy Brukardt
  1 sibling, 2 replies; 19+ messages in thread
From: Marin David Condic @ 2002-06-11 14:27 UTC (permalink / raw)


"Ted Dennison" <dennison@telepath.com> wrote in message
news:4519e058.0206110547.526d2369@posting.google.com...
> "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in
message news:<ae2v7f$r12$1@nh.pace.co.uk>...
> > My inclination is to think that the sensible thing would be to call the
> > 'Read or 'Write for the thing pointed to by the access type, but this
has
>
> You can pretty much count on it *not* doing that. For instance, what
> would happen in that case with a circularly-referenced structure like
> a doubly-linked list?
>
Giving it a few minutes of thought after I posted, this case occurred to me.
Initially, I was thinking about what would make sense and certainly storing
the access value is of minimal use the instant it goes out to a file or down
a wire. Hence, I thought, "Well maybe it should store the object pointed
to..." But clearly, as you point out, its an interesting opportunity to
create infinite recursion.


>
> > implications for dynamically allocated objects. Will it write/read a
> > (totally useless) access value?
>
> Pretty much. It isn't *totally* useless. It will work just fine within
> the same execution (assuming you don't deallocate the memory).
> However, it is next to useless.
>
Yeah, I just can't think of many cases where I want to write something into
a stream and not have it persist across executions or partitions or
whatever, wherein the address starts becoming a totally useless piece of
information. In the same execution? Why wouldn't I just keep referencing the
data structure I've already got? I suppose the language needs to do
*something* if it encounters an access type going into or out of a stream,
but its hard to imagine how one might make use of it.


> If you want better behavior, its up to you to override 'Write and
> 'Read for your pointer type. Then you can code it to handle things
> like circular references and deallocating the target's old value on a
> 'Read.
>
>
Basically, that's been the story. I was just wondering what the ARM had to
say about the default case & couldn't spot something explicit enough to
clear through the fog. Thanks for the help.

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com





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

* Re: Behavior of Stream Attributes On Access Types.
  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 19:39       ` Randy Brukardt
  2002-06-12 13:31     ` Ted Dennison
  1 sibling, 2 replies; 19+ messages in thread
From: Marin David Condic @ 2002-06-11 14:37 UTC (permalink / raw)


Just to make sure I'm getting this correct in my brain, try this one out for
me: I have a tagged record that does not have any access values in it, so
using the standard-issue 'Output and 'Input is just fine. I inherit from
this and add some access values, so I need to create my own 'Read and
'Write, correct? (But not 'Output and 'Input) Then, 'Output and 'Input for
that descendent should work correctly without overriding anything, right?
Further, using the base type's 'Class'Output and 'Class'Input should work
correctly by dispatching up the ladder to find my home-grown 'Read and
'Write, correct? Then, just to make it more interesting, I inherit from the
second type and add more (non-access) fields. I *must* override my own 'Read
and 'Write to include the newly added fields? Or will it dispatch to the
'Read and 'Write in the second level, then go on to call the defaults for
the newly added fields?

My brain hurts! :-)

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com


> "Ted Dennison" <dennison@telepath.com> wrote in message
> news:4519e058.0206110547.526d2369@posting.google.com...
> > If you want better behavior, its up to you to override 'Write and
> > 'Read for your pointer type. Then you can code it to handle things
> > like circular references and deallocating the target's old value on a
> > 'Read.
> >






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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-11 13:47 ` Ted Dennison
  2002-06-11 14:27   ` Marin David Condic
@ 2002-06-11 21:56   ` Randy Brukardt
  1 sibling, 0 replies; 19+ messages in thread
From: Randy Brukardt @ 2002-06-11 21:56 UTC (permalink / raw)


Ted Dennison wrote in message
<4519e058.0206110547.526d2369@posting.google.com>...
>"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote
in message news:<ae2v7f$r12$1@nh.pace.co.uk>...
>> My inclination is to think that the sensible thing would be to call
the
>> 'Read or 'Write for the thing pointed to by the access type, but this
has
>
>You can pretty much count on it *not* doing that. For instance, what
>would happen in that case with a circularly-referenced structure like
>a doubly-linked list?
>
>
>> implications for dynamically allocated objects. Will it write/read a
>> (totally useless) access value?
>
>Pretty much. It isn't *totally* useless. It will work just fine within
>the same execution (assuming you don't deallocate the memory).
>However, it is next to useless.


There is one more thing you can do with it: test it for nullness.
Although that is not guarenteed to work, it would be an unusual system
indeed where it did not. This can be very useful. The Janus/Ada compiler
uses this to store and reconstruct linked lists: (Note that Janus/Ada,
as an Ada 83 app., doesn't use the stream attributes themselves but a
very similar implementation specific package)

              type Data;
              type Ptr is access Data;
              type Data is record
                  ...
                  Next : Ptr;
              end record;

              List : Ptr;


              procedure Write_List (To : Stream_Access) is
                   Walk : Ptr := List;
              begin
                   Ptr'Write (To, Walk);
                   while Walk /= null loop
                         Data'Write (To, Walk.all);
                         Walk := Walk.Next;
                   end loop;
              end Write_List;

              procedure Read_List (From : Stream_Access) is
                   Work : Ptr;
              begin
                   Ptr'Read (From, Work);
                   if Work /= null then
                        List := new Data;
                        Work := List;
                   else
                        List := null;
                        return; -- Nothing to read.
                   end if;
                   loop
                          Data'Read (From, Work.all);
                          if Work.Next = null then
                                return;
                          else
                                Work.Next := new Data;
                                Work := Work.Next;
                         end;
                   end loop;
             end Read_List;

(There's probably a simpler way to read the list, but you get the
idea...)

               Randy.






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

* Re: Behavior of Stream Attributes On Access Types.
  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 13:47 ` Ted Dennison
@ 2002-06-12  3:44 ` David C. Hoos, Sr.
  2 siblings, 0 replies; 19+ messages in thread
From: David C. Hoos, Sr. @ 2002-06-12  3:44 UTC (permalink / raw)



----- 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 10, 2002 2:38 PM
Subject: Behavior of Stream Attributes On Access Types.


> I'm checking section 13.13.2 of the ARM to discover the default behavior of
> the Stream 'Read, 'Write, 'Input and 'Output when they encounter an access
> type. I'm not finding any clear indication of what gets put to the stream -
> although there is a mention in paragraph 35 of raising Constraint_Error on
> input if the value is not of its subtype. Can someone clarify the behavior?
>
> My inclination is to think that the sensible thing would be to call the
> 'Read or 'Write for the thing pointed to by the access type, but this has
> implications for dynamically allocated objects. Will it write/read a
> (totally useless) access value?
>
Here is an example of how I do this in a number of ADT packages I have
developed.

The complete file with appropriate copyright notice, and ratioonale, etc.,
is available at
ftp.ada95.com/pub/access_object_stream_attributes.tgz or
ftp.ada95.com/pub/access_object_stream_attributes.tar.gz

with Ada.Streams.Stream_IO;
with Ada.Text_IO;
with Ada.Unchecked_Deallocation;
procedure Test_Access_Object_Stream_Attributes
is
   type Node;

   type Node_Access is access all Node;

   procedure Node_Access_Read
      (Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   :    out Node_Access);

   procedure Node_Access_Write
      (Stream : access Ada.Streams.Root_Stream_Type'Class;
       Item   : in     Node_Access);

   type Node is record
      Item : Integer;
      Next : Node_Access;
   end record;

   for Node_Access'Read use Node_Access_Read;

   for Node_Access'Write use Node_Access_Write;

   procedure Node_Access_Read
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   :    out Node_Access)
   is
      Is_Non_Null : Boolean;
   begin
      Boolean'Read (Stream, Is_Non_Null);
      if Is_Non_Null then
         Item := new Node'(Node'Input (Stream));
      else
         Item := null;
      end if;
   end Node_Access_Read;

   procedure Node_Access_Write
     (Stream : access Ada.Streams.Root_Stream_Type'Class;
      Item   : in     Node_Access)
   is
   begin
      Boolean'Write (Stream, Item /= null);
      if Item /= null then
         Node'Output (Stream, Item.all);
      end if;
   end Node_Access_Write;

   --   NOTE:  Since the Read procedure is an allocator, it is the
   --   responsibility of the caller to deallocate the memory.
   --   To this end, a Deallocate procedure is provided.
   procedure Deallocate (Item : in out Node_Access)
   is
      procedure Free is new Ada.Unchecked_Deallocation
        (Object => Node,
         Name   => Node_Access);
   begin
      if Item.Next /= null then
         -- Not a leaf node; first deallocate node's children,
         -- then deallocate this node
         Deallocate (Item.Next);
         Deallocate (Item);
      else
         -- Leaf node; free the storage
         Free (Item);
      end if;
   end Deallocate;

   Head : Node_Access;
   Tail : Node_Access;
   Next : Node_Access;

   File   : Ada.Streams.Stream_IO.File_Type;
   Stream : Ada.Streams.Stream_IO.Stream_Access;

begin
   -- Link together a few nodes
   for N in 1 .. 10 loop
      if N = 1 then
         Tail := new Node;
         Head := Tail;
      else
         Tail.Next := new Node;
         Tail := Tail.Next;
      end if;
      Tail.Item := N;
   end loop;

   -- Verify the list
   Ada.Text_IO.Put_Line ("Original populated list:");
   Next := Head;
   while next  /= null loop
      Ada.Text_IO.Put_Line (Next.Item'Img);
      Next := Next.Next;
   end loop;

   -- Write the list to a stream file

   -- Create the file
   Ada.Streams.Stream_IO.Create
     (File => File,
      Mode => Ada.Streams.Stream_IO.Out_File,
      Name => "nodes.dat");

   -- Associate a stream with the file
   Stream := Ada.Streams.Stream_IO.Stream (File);

   -- Write the list
   Node_Access'Output (Stream, Head);

   -- Close the file
   Ada.Streams.Stream_IO.Close (File);

   -- Destroy the list
   Deallocate (Head);

   -- Verify the list
   Ada.Text_IO.Put_Line
     ("List after deallocation (should be empty):");
   Next := Head;
   while next  /= null loop
      Ada.Text_IO.Put_Line (Next.Item'Img);
      Next := Next.Next;
   end loop;

   -- Read the list from a stream file

   -- Open the file
   Ada.Streams.Stream_IO.Open
     (File => File,
      Mode => Ada.Streams.Stream_IO.In_File,
      Name => "nodes.dat");

   -- Associate a stream with the file
   Stream := Ada.Streams.Stream_IO.Stream (File);

   -- Read the list
   Head := Node_Access'Input (Stream);

   -- Close the file
   Ada.Streams.Stream_IO.Close (File);

   -- Verify the list
   Ada.Text_IO.Put_Line
     ("List after reading file:");
   Next := Head;
   while next  /= null loop
      Ada.Text_IO.Put_Line (Next.Item'Img);
      Next := Next.Next;
   end loop;

end Test_Access_Object_Stream_Attributes;









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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-11 14:27   ` Marin David Condic
  2002-06-11 14:37     ` Marin David Condic
@ 2002-06-12 13:31     ` Ted Dennison
  1 sibling, 0 replies; 19+ messages in thread
From: Ted Dennison @ 2002-06-12 13:31 UTC (permalink / raw)


"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in message news:<ae51cc$9ok$1@nh.pace.co.uk>...
> Yeah, I just can't think of many cases where I want to write something into
> a stream and not have it persist across executions or partitions or
> whatever, wherein the address starts becoming a totally useless piece of
> information. In the same execution? Why wouldn't I just keep referencing the
> data structure I've already got? I suppose the language needs to do

For the language-defined streams, which are files, it would indeed be
pretty pointless. However, in the past I've created stream types that
lived in RAM and acted as buffers. For those, it could be useful
(wasn't in my case, but it could be for someone).


-- 
T.E.D. 
Home     -  mailto:dennison@telepath.com (Yahoo: Ted_Dennison)
Homepage -  (temporarily down)



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

* Re: Behavior of Stream Attributes On Access Types.
  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-12 19:39       ` Randy Brukardt
  1 sibling, 1 reply; 19+ messages in thread
From: David C. Hoos @ 2002-06-12 14:19 UTC (permalink / raw)



----- 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: Tuesday, June 11, 2002 9:37 AM
Subject: Re: Behavior of Stream Attributes On Access Types.


> Just to make sure I'm getting this correct in my brain, try this one out
for
> me: I have a tagged record that does not have any access values in it, so
> using the standard-issue 'Output and 'Input is just fine. I inherit from
> this and add some access values, so I need to create my own 'Read and
> 'Write, correct? (But not 'Output and 'Input) Then, 'Output and 'Input for
> that descendent should work correctly without overriding anything, right?
> Further, using the base type's 'Class'Output and 'Class'Input should work
> correctly by dispatching up the ladder to find my home-grown 'Read and
> 'Write, correct? Then, just to make it more interesting, I inherit from
the
> second type and add more (non-access) fields. I *must* override my own
'Read
> and 'Write to include the newly added fields? Or will it dispatch to the
> 'Read and 'Write in the second level, then go on to call the defaults for
> the newly added fields?
>
You only need to add read and write for the _access_ types.
'Output and 'Input are never overridden, as they always use
'Read and 'Write.

The only other cases for which I have had to override the standard
stream attributes is when there are machine endianess issues in
network representation of data.

Did you look at my example of how I do it?






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

* Re: Behavior of Stream Attributes On Access Types.
  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.
  2002-06-14 18:27           ` Simon Wright
  0 siblings, 2 replies; 19+ messages in thread
From: Marin David Condic @ 2002-06-12 15:18 UTC (permalink / raw)


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?)

Here's some code snippets to illustrate the questions I have...

package Level_1 is
    type L1 is tagged record
        A : Integer ;
    end record ;
    --
    --  Here I have L1'Read, L1'Write, L1'Input, L1'Output
    --  and L1'Class'Read L1'Class'Write L1'Class'Input L1'Class'Output
    --
end Level_1 ;

package Level_1.Level_2 is
    type L2 is new Level_1.L1 with record
        B : Some_Access_Type := null ;
    end record ;
    --
    --  Now I have to define my own 'Read and 'Write
    --
    procedure My_Read ....
    for L2'Read use My_Read...
    procedure My_Write .....
    for L2'Write use My_Write...
    --
    --  Here I now have for free L2'Input, L2'Output
    --  Further L1'Class'Read L1'Class'Write L1'Class'Input L1'Class'Output
    --  will dispatch to My_Read and My_Write if an L2 parameter is passed?
    --
end Level_1.Level_2 ;

package Level_1.Level_2.Level_3 is
    type L3 is new Level_2.L2 with record
        C : Integer ;
    end record ;
    --
    --  Now must I define my own 'Read and 'Write???
    --
    procedure My_Read ....
    for L3'Read use My_Read...
    procedure My_Write .....
    for L3'Write use My_Write...
    --
    --  Or will a call to L1'Class'Write hit the "My_Write" from
    --  Level_2 to output the access type, then call the default
    --  'Write for the new "C" field?
    --
end Level_1.Level_2.Level_3 ;

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com


"David C. Hoos" <david.c.hoos.sr@ada95.com> wrote in message
news:mailman.1023891618.16755.comp.lang.ada@ada.eu.org...
>
> Did you look at my example of how I do it?
>
>
>





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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-11 14:37     ` Marin David Condic
  2002-06-12 14:19       ` David C. Hoos
@ 2002-06-12 19:39       ` Randy Brukardt
  1 sibling, 0 replies; 19+ messages in thread
From: Randy Brukardt @ 2002-06-12 19:39 UTC (permalink / raw)


Marin David Condic wrote in message ...

...

>Then, just to make it more interesting, I inherit from the
>second type and add more (non-access) fields. I *must* override my own
'Read
>and 'Write to include the newly added fields? Or will it dispatch to
the
>'Read and 'Write in the second level, then go on to call the defaults
for
>the newly added fields?

The Ada 95 standard doesn't address this. The Technical Corrigendum
does, and requires that the default implementation is calls the parent
type's 'Read and 'Write. So you are not required to override. But be
sure that your compiler is implementing the TC (tests for this area have
only recently been added to the ACATS, so it is not unlikely that
compilers don't follow the TC in this area).

          Randy Brukardt.






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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-12 15:18         ` Marin David Condic
@ 2002-06-13  3:00           ` David C. Hoos, Sr.
  2002-06-14 18:27           ` Simon Wright
  1 sibling, 0 replies; 19+ messages in thread
From: David C. Hoos, Sr. @ 2002-06-13  3:00 UTC (permalink / raw)



----- 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.







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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-12 15:18         ` Marin David Condic
  2002-06-13  3:00           ` David C. Hoos, Sr.
@ 2002-06-14 18:27           ` Simon Wright
  2002-06-14 18:53             ` Marin David Condic
  1 sibling, 1 reply; 19+ messages in thread
From: Simon Wright @ 2002-06-14 18:27 UTC (permalink / raw)


"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> writes:

> package Level_1 is
>     type L1 is tagged record
>         A : Integer ;
>     end record ;
>     --
>     --  Here I have L1'Read, L1'Write, L1'Input, L1'Output
>     --  and L1'Class'Read L1'Class'Write L1'Class'Input L1'Class'Output
>     --
> end Level_1 ;
> 
> package Level_1.Level_2 is
>     type L2 is new Level_1.L1 with record
>         B : Some_Access_Type := null ;
>     end record ;
>     --
>     --  Now I have to define my own 'Read and 'Write

I think this is where the mistake occurs.

At the point where you declared Some_Access_Type, declare

  procedure My_Read
    (Stream : access Ada.Streams.Root_Stream_Type'Class;
     Obj : Some_Access_Type);
  for Some_Access_Type'Read use My_Read;

and also for My_Write, and all magically happens ..



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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-14 18:27           ` Simon Wright
@ 2002-06-14 18:53             ` Marin David Condic
  2002-06-15 14:56               ` Simon Wright
  0 siblings, 1 reply; 19+ messages in thread
From: Marin David Condic @ 2002-06-14 18:53 UTC (permalink / raw)


Nope. Not a "mistake" - except maybe stylistically. I have evolved a very
specific question here that seems to be getting misunderstood. I don't want
to know how to override the default 'Read and 'Write for an access type. (I
know *how* to do that - but not necessarily what the "default" behavior is.
From other posts, I suspect just the pointer value is written.) What I want
to know is what happens as you go up the food-chain on tagged records once
you override the default 'Read and 'Write.

I posted this elsewhere:

"A" is a tagged type for which I accept the standard issue 'Write. "B" Is a
descendend of "A" that adds a new field and for which I create my own 'Write
for the type "B" - not for the field. "C" is a descendent of "B" that adds a
new field. What happens when I call: "A'Class'Write (C_Object);"? Does the
field added in "C" get written out with the standard issue 'Write or does
the food-chain stop at the point where I overrode the 'Write? What happens
if I call "C'Write (C_Object);" - assuming I didn't create my own
user-defined "C'Write"?

Hope this clarifies what it is I'm not understanding. Thanks for any help
you can give.

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com


"Simon Wright" <simon@pushface.org> wrote in message
news:x7vhek5sokk.fsf@pushface.org...
>
> I think this is where the mistake occurs.
>
> At the point where you declared Some_Access_Type, declare
>
>   procedure My_Read
>     (Stream : access Ada.Streams.Root_Stream_Type'Class;
>      Obj : Some_Access_Type);
>   for Some_Access_Type'Read use My_Read;
>
> and also for My_Write, and all magically happens ..





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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-14 18:53             ` Marin David Condic
@ 2002-06-15 14:56               ` Simon Wright
  2002-06-16  2:27                 ` Randy Brukardt
  0 siblings, 1 reply; 19+ messages in thread
From: Simon Wright @ 2002-06-15 14:56 UTC (permalink / raw)


"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> writes:

> Nope. Not a "mistake" - except maybe stylistically. I have evolved a
> very specific question here that seems to be getting
> misunderstood. I don't want to know how to override the default
> 'Read and 'Write for an access type. (I know *how* to do that - but
> not necessarily what the "default" behavior is.  From other posts, I
> suspect just the pointer value is written.) What I want to know is
> what happens as you go up the food-chain on tagged records once you
> override the default 'Read and 'Write.

Oh, sorry; I guess what we're all failing to grasp is why you would
want to do that.

Since the only contribution I would be able to make would be to try it
and see, I'll shut up ..



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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-15 14:56               ` Simon Wright
@ 2002-06-16  2:27                 ` Randy Brukardt
  2002-06-17 14:31                   ` Marin David Condic
  0 siblings, 1 reply; 19+ messages in thread
From: Randy Brukardt @ 2002-06-16  2:27 UTC (permalink / raw)


Simon Wright wrote in message ...
>"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> writes:
>
>> Nope. Not a "mistake" - except maybe stylistically. I have evolved a
>> very specific question here that seems to be getting
>> misunderstood. I don't want to know how to override the default
>> 'Read and 'Write for an access type. (I know *how* to do that - but
>> not necessarily what the "default" behavior is.  From other posts, I
>> suspect just the pointer value is written.) What I want to know is
>> what happens as you go up the food-chain on tagged records once you
>> override the default 'Read and 'Write.
>
>Oh, sorry; I guess what we're all failing to grasp is why you would
>want to do that.
>
>Since the only contribution I would be able to make would be to try it
>and see, I'll shut up ..

And I answered that question (in terms of the Corrigendum and the
original Ada 95 standard) several days ago (Wednesday to be exact). Here
it is again if you all missed it:

"The Ada 95 standard doesn't address this. The Technical Corrigendum
does, and requires that the default implementation is calls the parent
type's 'Read and 'Write. So you are not required to override. But be
sure that your compiler is implementing the TC (tests for this area have
only recently been added to the ACATS, so it is not unlikely that
compilers don't follow the TC in this area)."

To expand a bit further, the TC requires that the default implementation
calls the parent type's 'Read and 'Write, along with the 'Read and
'Writes for any extension components. So you don't have to do anything
special, and you should get what you expect. But, again, be sure that
your compiler implements the TC before depending on this! (If it doesn't
implement the TC, it could do just about anything; the original Ada 95
standard is very confused when it comes to streams and stream
attributes).

            Randy Brukardt.







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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-16  2:27                 ` Randy Brukardt
@ 2002-06-17 14:31                   ` Marin David Condic
  2002-06-18 19:30                     ` Randy Brukardt
  0 siblings, 1 reply; 19+ messages in thread
From: Marin David Condic @ 2002-06-17 14:31 UTC (permalink / raw)


O.K. *THAT* is the part I was looking for. (I don't think this was in your
original answer.) Type A uses the default 'Write. Type B descending from A
overrides 'Write to do its own thing. Type C descending from B and adding
new fields NEED NOT override 'Write - it will first call type B's 'Write and
then will call 'Write for any new fields added. At least that is the
behavior that *SHOULD* be there, correct? (If it doesn't call the 'Write for
the additional fields, you'd be stuck having to override it.)

It is a confusing issue & I'm glad I now have a good answer. As you indicate
that it may not be this way in all compilers, I guess one needs to test it
out & verify that it works. Too bad - I could see it being a serious
portability issue in that one might easily write code as I described above.
I suppose that from a stylistic perspective it would be better to override
the 'Read and 'Write for the individual fields, but I could easily imagine a
situation where the reason for overriding them is to control representation
of the overall record. (Suppose I need to make sure that some fields aren't
padded within the record - then subsequent extensions to it I might not care
because I'm happy with the default behavior.)

Thanks for the info.

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com


"Randy Brukardt" <randy@rrsoftware.com> wrote in message
news:ugnu54b8nr87aa@corp.supernews.com...
>
> To expand a bit further, the TC requires that the default implementation
> calls the parent type's 'Read and 'Write, along with the 'Read and
> 'Writes for any extension components. So you don't have to do anything
> special, and you should get what you expect. But, again, be sure that
> your compiler implements the TC before depending on this! (If it doesn't
> implement the TC, it could do just about anything; the original Ada 95
> standard is very confused when it comes to streams and stream
> attributes).
>
>             Randy Brukardt.
>
>
>
>





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

* Re: Behavior of Stream Attributes On Access Types.
  2002-06-17 14:31                   ` Marin David Condic
@ 2002-06-18 19:30                     ` Randy Brukardt
  0 siblings, 0 replies; 19+ messages in thread
From: Randy Brukardt @ 2002-06-18 19:30 UTC (permalink / raw)


Marin David Condic wrote in message ...
>O.K. *THAT* is the part I was looking for. (I don't think this was in
your
>original answer.) Type A uses the default 'Write. Type B descending
from A
>overrides 'Write to do its own thing. Type C descending from B and
adding
>new fields NEED NOT override 'Write - it will first call type B's
'Write and
>then will call 'Write for any new fields added. At least that is the
>behavior that *SHOULD* be there, correct? (If it doesn't call the
'Write for
>the additional fields, you'd be stuck having to override it.)


Right, that is what the behavior SHOULD be. But if the compiler doesn't
implement the TC and hasn't been tested against the latest ACATS test
suite, then it very well may not. The tests for this were added to the
ACATS in December, and don't become required until July 1st, so even a
recently tested compiler could get this wrong and still pass conformity
assessment.

Of course, an Ada 0y compiler will have to get this right -- but you may
not want to wait that long. :-)

          Randy.







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

end of thread, other threads:[~2002-06-18 19:30 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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.
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.

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