Version 1.3 of ais/ai-00260.txt

Unformatted version of ais/ai-00260.txt version 1.3
Other versions for file ais/ai-00260.txt

!standard 13.13.2 (31)          01-02-13 AI95-00260/00
!standard 13.13.2 (34)
!class amendment 01-02-13
!status received 01-02-13
!priority Low
!difficulty Medium
!subject How to replace S'Class'Input with custom versions
!summary
!problem
S'Class'Output writes the tag of an item with String'Output. This routine cannot be replaced, so it is not possible to write the tag in an arbitrary user-defined format (to match an external standard, for example).
A more general problem is that the dispatching accomplished by S'Class'Input cannot be duplicated in normal user code. (If it could, that mechanism could be used to eliminate the problem above by overridding the appropriate operations).
!proposal
( Ideas needed )
!discussion
A significant annoyance.
!example
!ACATS test
!appendix

From: Pascal Obry
Sent: Wednesday, January 31, 2001 3:00 PM

Hello,

I have a comment/question about an Ada feature. The current implementation
for S'Class'Output seems to be not flexible enough for some job. Let's look at
the definition for 'Class'Ouput:

<<
  29. S'Class'Output

           S'Class'Output denotes a procedure with the following
           specification:

       30.      procedure S'Class'Output(
                   Stream : access Ada.Streams.Root_Stream_Type'Class;
                   Item   : in T'Class)

       31. First writes the external tag of Item to Stream (by calling
           String'Output(Tags.External_Tag(Item'Tag) - *Note 3.9::.) and
           then dispatches to the subprogram denoted by the Output
           attribute of the specific type identified by the tag.
>>

The problem here is the way the tag is written using String'Output.

My goal was to write (on disk using streams) objects in XML. But this is not
possible because the tag is written with the string's bounds (String'Output) !
So there is some binary data dumped into the XML file !!!

Of course it is possible to write the tag myself, but then it will be just
impossible to read back the object from the disk...

To summarize:
   It is possible to stream an object to disk only in binary format.

It would be nice to be able to control the way the tag is written. I don't
have a proposal for this right now...

I have talked about this issue with my ACT support and we came to the
conclusion that it is just impossible to do what I wanted!

Please let me know if this is clear enough or if you need some more info.

****************************************************************

From: Tucker Taft
Sent: Wednesday, January 31, 2001 5:40 PM

It is definitely frustrating that the dispatching performed by
S'Class'Input cannot be duplicated by "normal" user code.  Essentially
one wants to be able to dispatch using an (internal) tag rather
than an object.  Alternatively, one wants to be able to construct
an object with default initialization given a tag.
Some kind of "magic" generic might be defined to provide this
capability, or something similar.  This definitely will require
some head-scratching.

****************************************************************

From: Pascal Obry
Sent: Saturday, March 17, 2001 2:57 PM

Hello,

Please have a look at this first proposal. I have tried to write something but
this is the very first time I do something like that. I'm not sure the wording
is correct, not talking about my english :) Can you told me if this all this
makes sense to you or if it is just not the right way to approach the
problem. I have tried to follow current AI structure.

<<
!summary

The stream input/output attributes are not flexible enough. The problem is for
the tag handling of tagged object. With the current implementation it is not
possible for example to redefine the 'Read and 'Write to have the object
streamed as an XML object. We propose a solution to solve this problem.

!problem

The problem is for the tag handling of tagged object. With the current
implementation it is not possible for example to redefine the 'Read and 'Write
to have the object streamed as an XML object. Indeed the tag is defined as a
string. It is possible to change the tag string value by using Ada.Tags
facilities. But the tag will always be a string : an unbounded object. Each
time the tagged object will be streamed the tag string value will be written
preceded by the string bound which are binary data. There is no way to avoid
these binary data to be sent. In other word, there is no way to stream an
object with a plain text representation.

!proposal

Have the possibility to set the way the 'Class'Output and 'Class'Input handle
the tag with the new attribute 'Tag_Format. Values for this attributes is of
type Ada.Tags.Tag_Output:

   type Tag_Ouput is (Constrained, Unconstrained);

'Tag_Format
   is set to Unconstrained by default. This is the current behavior. In this
   mode 'Class'Output will call String'Output on the tag string to output the
   tag. And 'Class'Input will call String'Input to read the tag. So with
   Unconstrained the tag's bounds are used. If it is set to Constrained then
   the tag will be written using String'Write (and read using String'Read). In
   this case the tag's bounds are not used.

The definition for S'Class'Input and S'Class'Output must be changed
accordingly.

!discussion

We could find some other ways to implement this feature. This is certainly the
lightest one as it requires only one new attributes on tagged record. Another
solution would have been to define two new attributes 'Read_Tag and 'Write_Tag
for reading and writing a tag value. These attributes would have the current
default and could have been overridden by users. It would have been possible to
solve the problem described here with this mechanism. Something like:

   procedure Write_Tag (S : access Streams.Root_Stream_Type'Class; O : Object);
   for Object'Write_Tag use Write_Tag;

   procedure Read_Tag (S : access Streams.Root_Stream_Type'Class; O : Object);
   for Object'Read_Tag use Read_Tag;

!example

Here is an example that show the problem. Let's say that we want to stream an
object with an XML encoding:

with Ada.Streams;

package Class is

   use Ada;

   type Object is tagged record
      V : Integer := 2;
   end record;

   procedure Write (S : access Streams.Root_Stream_Type'Class; O : Object);
   for Object'Write use Write;

   for Object'External_Tag use "<object>";

end Class;

package body Class is

   procedure Write (S : access Streams.Root_Stream_Type'Class; O : Object) is
   begin
      String'Write (S, "<v>");
      String'Write (S, Integer'Image (O.V));
      String'Write (S, "</v>");
      String'Write (S, "</object>");
   end Write;

end Class;


with Ada.Text_IO.Text_Streams;
with Class;

procedure Main is
   use Ada;

   O : Class.Object;
begin
   Class.Object'Class'Output
     (Text_IO.Text_Streams.Stream (Text_IO.Current_Output), O);
end Main;

This program output will be something like:

   ^A^@^@^@^H^@^@^@<object><v> 2</v></object>

The 8 first characters are binary representation for the tag bound. This is no
way to bypass that, so there is no way to stream an object with an XML
representation.

Using the new 'Tag_Format attributes it is possible to control the tag
output. By changing the Class spec to read:

with Ada.Streams;

package Class is

   use Ada;

   type Object is tagged record
      V : Integer := 2;
   end record;

   procedure Write (S : access Streams.Root_Stream_Type'Class; O : Object);
   for Object'Write use Write;

   for Object'External_Tag use "<object>";
   for Object'Tag_Format use Constrained;

end Class;

We now have the following output:

   <object><v> 2</v></object>
>>

I hope to hear from you soon,
Pascal.

****************************************************************

From: Pascal Obry
Sent: Sunday, March 18, 2001 3:19 PM

Please ignore my proposal as it is not working for reading the Tag. When
reading an object (by calling 'Class'Input) the Tag is not known so the string
bounds are needed !

I'll try to find something else...

****************************************************************

From: Randy Brukardt
Sent: Monday, March 19, 2001 5:20 PM

Too bad. We have an (empty) AI on this subject just waiting for a proposal.
(It seems like a problem worth solving.) Tucker pointed out that the problem
of being unable to handle the tag is really one of being unable to write a
new implementation of T'Class'Input, and *that* is caused by not having a
way to dispatch based on a (internal) tag value (or, equivalently, being
able to create a default-initialized object from a tag value). We can write
code to read the tag however you need, you can look up the tag with
Internal_Tag, but you can't write the needed dispatching and/or object
creation.

Tuck's musings suggested that perhaps a "magic" generic with this capability
would be the way to go. Perhaps you can find a solution and make a proposal
based on that idea??

****************************************************************

From: Pascal Obry
Sent: Wednesday, April 04, 2001 11:30 AM

Hello,

Here is a proposal for an Ada stream extenssion, the goal is to provide more
control on the Tag for streamed object.

<<
!summary

The stream input/output attributes are not flexible enough. The problem is for
the tag handling of tagged object. With the current implementation it is not
possible for example to redefine the 'Read and 'Write to have the object
streamed as an XML object. We propose a solution to solve this problem.

!problem

The problem is for the tag handling of tagged object. With the current
implementation it is not possible for example to redefine the 'Read and 'Write
attribute to have the object streamed as an XML object. Indeed the tag is
defined as a string. It is possible to change the tag string value by using
Ada.Tags facilities. But the tag will always be a string : an unbounded
object. Each time the tagged object will be streamed the tag string value will
be written preceded by the string bounds which are binary data. There is no way
to avoid these binary data to be sent. In other word, there is no way to
stream an object with a plain text representation.

!proposal

Have the possibility to set the way the 'Class'Output and 'Class'Input handle
the tag with the new attributes.

Two new attributes form are proposed:

   S'External_Tag'Read
     This attribute can be used to set the right function to use for reading
     the tag on a stream. This function will be called by S'Class'Input
     instead of the default one. The function prototype must be:

        function Read (S : access Streams.Root_Stream_Type'Class)
          return Ada.Tags.Tag;

   S'External_Tag'Write
     This attribute can be used to set the right function to use for writing
     the tag on a stream. This function will be called by S'Class'Output
     instead of the default one. The procedure prototype must be:

        procedure Write (S : access Streams.Root_Stream_Type'Class;
                         Tag : Ada.Tags.Tag);

The definition for S'Class'Input and S'Class'Output must be changed
accordingly.

!discussion

This proposal does not really introduce new attributes. The S'External_Tag
attribute can be composed with 'Read and 'Write. This change is upward
compatible as it does not change the semantic for streamed object when it is
not used.

!example

Here is an example that show the problem. Let's say that we want to stream an
object with an XML encoding:

with Ada.Streams;

package Class is

   use Ada;

   type Object is tagged record
      V : Integer := 2;
   end record;

   procedure Write (S : access Streams.Root_Stream_Type'Class; O : Object);
   for Object'Write use Write;

   for Object'External_Tag use "<object>";

end Class;

package body Class is

   procedure Write (S : access Streams.Root_Stream_Type'Class; O : Object) is
   begin
      String'Write (S, "<v>");
      String'Write (S, Integer'Image (O.V));
      String'Write (S, "</v>");
      String'Write (S, "</object>");
   end Write;

end Class;


with Ada.Text_IO.Text_Streams;
with Class;

procedure Main is
   use Ada;

   O : Class.Object;
begin
   Class.Object'Class'Output
     (Text_IO.Text_Streams.Stream (Text_IO.Current_Output), O);
end Main;

This program output will be something like:

   ^A^@^@^@^H^@^@^@<object><v> 2</v></object>

The 8 first characters are binary representation for the tag bound. This is no
way to bypass that, so there is no way to stream an object with an XML
representation.

Using the new 'External_Tag'Read and 'External_Tag'Write attributes it is
possible to control the tag input/output. By changing the Class spec to read:

with Ada.Streams;

package Class is

   use Ada;

   type Object is tagged record
      V : Integer := 2;
   end record;

   for Object'External_Tag use "object";

   procedure Write (S : access Streams.Root_Stream_Type'Class; O : Object);
   for Object'Write use Write;

   procedure Write (S : access Streams.Root_Stream_Type'Class;
                    Tag : Ada.Tags.Tag);
   --  Implementation not shown. This function:
   --    1) output character '<'
   --    2) output Ada.Tags.External_Tag (Tag)
   --    3) output character '>'
   for Object'External_Tag'Write use Write;

   function Read (S : access Streams.Root_Stream_Type'Class)
     return Ada.Tags.Tag;
   --  Implementation not shown. This function:
   --    1) read first character, raise Ada.Tags.Tag_Error if it is not '<'
   --    2) read the tag (let's call it Tag_String)
   --    3) check for end of tag which is '>' (raise Ada.Tags.Tag_Error if no
   --       such character on the stream)
   --    4) return Ada.Tags.Internal_Tag (Tag_String)
   for Object'External_Tag'Read use Read;

end Class;

We now have the following output:

   <object><v> 2</v></object>
>>

Let me know what you think about this proposal ? Do you need something else ?

****************************************************************

Questions? Ask the ACAA Technical Agent