13.13.2 Stream-Oriented Attributes
1/3
{
8652/0009}
{
AI95-00137-01}
{
AI05-0183-1}
The
type-related operational
attributes Write, Read, Output, and Input
attributes
convert values to a stream of elements and reconstruct values
from a stream.
Static Semantics
1.1/2
{
AI95-00270-01}
For every subtype S of an elementary type T,
the following representation attribute is defined:
1.2/3
S'Stream_Size
{
AI95-00270-01}
{
AI05-0194-1}
Denotes the number
of bits read from or written to a stream
by the default implementations of S'Read and S'Write occupied
in a stream by items of subtype S.
Hence, the number of stream elements required per item of elementary
type T is:
1.3/2
T'Stream_Size / Ada.Streams.Stream_Element'Size
1.4/2
The value of this
attribute is of type universal_integer and is a multiple of Stream_Element'Size.
1.5/2
Stream_Size may be
specified for first subtypes via an attribute_definition_clause;
the expression
of such a clause shall be static, nonnegative, and a multiple of Stream_Element'Size.
1.a/3
Aspect Description
for Stream_Size: Size
in bits used to represent elementary objects in a stream.
1.b/2
Discussion: Stream_Size
is a type-related attribute (see 13.1).
1.c/3
Ramification: {
AI05-0194-1}
The value of S'Stream_Size is unaffected by the
presence or absence of any attribute_definition_clauses
or aspect_specifications
specifying the Read or Write attributes of any ancestor of S. S'Stream_Size
is defined in terms of the behavior of the default implementations of
S'Read and S'Write even if those default implementations are overridden.
Implementation Advice
1.6/2
{
AI95-00270-01}
If not specified, the value of Stream_Size for
an elementary type should be the number of bits that corresponds to the
minimum number of stream elements required by the first subtype of the
type, rounded up to the nearest factor or multiple of the word size that
is also a multiple of the stream element size.
1.d/2
Implementation Advice:
If not specified, the value of Stream_Size
for an elementary type should be the number of bits that corresponds
to the minimum number of stream elements required by the first subtype
of the type, rounded up to the nearest factor or multiple of the word
size that is also a multiple of the stream element size.
1.e/2
Reason: {
AI95-00270-01}
This is Implementation Advice because we want to
allow implementations to remain compatible with their Ada 95 implementations,
which may have a different handling of the number of stream elements.
Users can always specify Stream_Size if they need a specific number of
stream elements.
1.7/2
{
AI95-00270-01}
The recommended level of support
for the Stream_Size attribute is:
1.8/2
{
AI95-00270-01}
A Stream_Size clause should be supported for a
discrete or fixed point type T if the specified Stream_Size is
a multiple of Stream_Element'Size and is no less than the size of the
first subtype of T, and no greater than the size of the largest
type of the same elementary class (signed integer, modular integer, enumeration,
ordinary fixed point, or decimal fixed point).
1.f/2
Implementation Advice:
The recommended level of support for
the Stream_Size attribute should be followed.
1.g/2
Ramification: There
are no requirements beyond supporting confirming Stream_Size clauses
for floating point and access types. Floating point and access types
usually only have a handful of defined formats, streaming anything else
makes no sense for them.
1.h/2
For discrete and fixed
point types, this may require support for sizes other than the “natural”
ones. For instance, on a typical machine with 32-bit integers and a Stream_Element'Size
of 8, setting Stream_Size to 24 must be supported. This is required as
such formats can be useful for interoperability with unusual machines,
and there is no difficulty with the implementation (drop extra bits on
output, sign extend on input).
Static Semantics
2
For every subtype S of a specific type T,
the following attributes are defined.
3
S'Write
S'Write denotes a procedure with
the following specification:
4/2
{
AI95-00441-01}
procedure S'Write(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class;
Item :
in T)
5
S'Write writes the value of Item
to Stream.
6
S'Read
S'Read denotes a procedure with
the following specification:
7/2
{
AI95-00441-01}
procedure S'Read(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class;
Item :
out T)
8
S'Read reads the value of Item from
Stream.
8.1/3
{
8652/0040}
{
AI95-00108-01}
{
AI95-00444-01}
{
AI05-0192-1}
For an untagged
derived type types,
the Write (resp. and Read) attribute is attributes are inherited according
to the rules given as
specified in 13.1 if the attribute is [specified and] available
for the parent type at the point where T is declared. For a tagged
derived type, these attributes are not inherited, but rather;
otherwise, the default implementations
of these attributes
are used. The
default implementations of Write and Read attributes execute as follows:
8.a.1/3
Proof: {
AI05-0192-1}
The inheritance rules of 13.1
say that only specified or inherited aspects are inherited; we mention
it again here as a clarification.
8.2/2
{
AI95-00444-01}
The default implementations of the Write and Read
attributes, where available, execute as follows:
9/3
{
8652/0040}
{
AI95-00108-01}
{
AI95-00195-01}
{
AI95-00251-01}
{
AI95-00270-01}
{
AI05-0139-2}
For elementary types,
Read reads (and Write writes)
the number of stream elements implied by the Stream_Size for the type
T; the representation
in terms of
those stream elements is implementation defined. For composite
types, the Write or Read attribute for each component is called in
a
canonical order
, which.
The canonical order of components is last dimension varying fastest
for an array
(unless the convention of the array
is Fortran, in which case it is first dimension varying fastest),
and positional aggregate order for a record. Bounds are not included
in the stream if
T is an array type. If
T is a discriminated
type, discriminants are included only if they have defaults. If
T
is a tagged type, the tag is not included.
For
type extensions, the Write or Read attribute for the parent type is called,
followed by the Write or Read attribute of each component of the extension
part, in canonical order. For a limited type extension, if the attribute
of the parent any
ancestor type or
any progenitor type of T is
available anywhere within the immediate scope of T, has
been directly specified and the attribute
of the parent type or any
ancestor type of the type of any
of the extension components is not available
at the freezing point of T, then which
are of a limited type has not been specified, the attribute of T shall be directly specified.
9.a/2
Implementation defined: The contents
of the stream elements read and written representation
used by the Read and Write attributes of elementary types in terms of stream elements.
9.1/3
{
AI05-0023-1}
{
AI05-0264-1}
If T is a discriminated type and its discriminants
have defaults, then S'Read first reads the discriminants from the stream
without modifying Item. S'Read then creates an object of type
T constrained by these discriminants. The value of this object
is then converted to the subtype of Item and is assigned to Item.
Finally, the Read attribute for each non-discriminant component of Item
is called in canonical order as described above. Normal default initialization
and finalization take place for the created object.
9.b
Reason: A discriminant with a default
value is treated simply as a component of the object. On the other hand,
an array bound or a discriminant without a default value, is treated
as “descriptor” or “dope” that must be provided
in order to create the object and thus is logically separate from the
regular components. Such “descriptor” data are written by
'Output and produced as part of the delivered result by the 'Input function,
but they are not written by 'Write nor read by 'Read. A tag is like a
discriminant without a default.
9.b.1/1
{
8652/0040}
{
AI95-00108-01}
For limited type extensions, we must have a definition
of 'Read and 'Write if the parent type has one, as it is possible to
make a dispatching call through the attributes. The rule is designed
to automatically do the right thing in as many cases as possible.
9.b.2/1
{
AI95-00251-01}
Similarly, a type that has a progenitor with an
available attribute must also have that attribute, for the same reason.
9.b.3/3
{
AI05-0023-1}
The semantics of S'Read for a discriminated type
with defaults involves an anonymous object so that the point of required
initialization and finalization is well-defined, especially for objects
that change shape and have controlled components. The creation of this
anonymous object often can be omitted (see the Implementation Permissions
below).
9.c/2
Ramification: {
AI95-00195-01}
For a composite object, the subprogram denoted by the Write or Read attribute
of each component is called, whether it is the default or is user-specified.
Implementations are allowed to optimize these calls (see below), presuming
the properties of the attributes are preserved.
9.2/3
{
AI95-00270-01}
{
AI05-0264-1}
Constraint_Error is raised by the predefined Write
attribute if the value of the elementary item is outside the range of
values representable using Stream_Size bits. For a signed integer type,
an enumeration type, or a fixed point type, the range is unsigned only
if the integer code for the lower bound of the first subtype is nonnegative,
and a (symmetric) signed range that covers all values of the first subtype
would require more than Stream_Size bits; otherwise, the range is signed.
10
For every subtype S'Class
of a class-wide type T'Class:
11
S'Class'Write
S'Class'Write denotes a procedure
with the following specification:
12/2
{
AI95-00441-01}
procedure S'Class'Write(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class;
Item :
in T'Class)
13
Dispatches to the subprogram denoted by
the Write attribute of the specific type identified by the tag of Item.
14
S'Class'Read
S'Class'Read denotes a procedure
with the following specification:
15/2
{
AI95-00441-01}
procedure S'Class'Read(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class;
Item :
out T'Class)
16
Dispatches to the subprogram denoted by
the Read attribute of the specific type identified by the tag of Item.
16.a
Reason: It is necessary to have class-wide
versions of Read and Write in order to avoid generic contract model violations;
in a generic, we don't necessarily know at compile time whether a given
type is specific or class-wide.
Implementation Advice
17/2
This paragraph was
deleted.{
AI95-00270-01}
If a stream element is the same size as a storage
element, then the normal in-memory representation should be used by Read
and Write for scalar objects. Otherwise, Read and Write should use the
smallest number of stream elements needed to represent all values in
the base range of the scalar type.
Static Semantics
18
For every subtype S of a specific type T,
the following attributes are defined.
19
S'Output
S'Output denotes a procedure
with the following specification:
20/2
{
AI95-00441-01}
procedure S'Output(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class;
Item :
in T)
21
S'Output writes the value of Item
to Stream, including any bounds or discriminants.
21.a
Ramification: Note that the bounds are
included even for an array type whose first subtype is constrained.
22
S'Input
S'Input denotes a function with
the following specification:
23/2
{
AI95-00441-01}
function S'Input(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class)
return T
24
S'Input reads and returns one value from
Stream, using any bounds or discriminants written by a corresponding
S'Output to determine how much to read.
25/3
{
8652/0040}
{
AI95-00108-01}
{
AI95-00444-01}
{
AI05-0192-1}
For an untagged
derived type types,
the Output (resp. and Input) attribute is attributes
of the parent type are inherited
according to the rules given as
specified in 13.1 if the attribute is [specified and] available
for the parent type at the point where T is declared. For a tagged
derived type, these attributes are not inherited, but rather;
otherwise, the default implementations of these attributes are used. The default implementations of Output and Input attributes execute as
follows: Unless
overridden by an attribute_definition_clause,
these subprograms execute as follows:
25.a/3
Proof: {
AI05-0192-1}
See the note following the inheritance rules for
the Write attribute, above.
25.1/2
{
AI95-00444-01}
The default implementations of the Output and Input
attributes, where available, execute as follows:
26
If T is an array type, S'Output first writes
the bounds, and S'Input first reads the bounds. If T has discriminants
without defaults, S'Output first writes the discriminants (using S'Write
for each), and S'Input first reads the discriminants (using S'Read for
each).
27/3
{
AI95-00195-01}
{
AI05-0023-1}
S'Output then calls S'Write to write the value of
Item to the
stream. S'Input then creates an object
of type
T, (with the bounds or
(when
without defaults) the discriminants, if any, taken from the stream
),
passes initializes
it
to with
S'Read, and returns the value of the object.
If
T has discriminants, then this object is unconstrained if and
only the discriminants have defaults. Normal
default initialization and finalization take place for this object (see
3.3.1, 7.6, and
7.6.1).
27.1/2
{
AI95-00251-01}
If T is an abstract type, then S'Input is
an abstract function.
27.a/2
Ramification: For
an abstract type T, S'Input can be called in a dispatching call,
or passed to a abstract formal subprogram. But it cannot be used in non-dispatching
contexts, because we don't allow objects of abstract types to exist.
The designation of this function as abstract has no impact on descendants
of T, as T'Input is not inherited for tagged types, but
rather recreated (and the default implementation of T'Input calls
T'Read, not the parent type's T'Input). Note that T'Input
cannot be specified in this case, as any function with the proper profile
is necessarily abstract, and specifying abstract subprograms in an attribute_definition_clause
is illegal.
28
For every subtype S'Class
of a class-wide type T'Class:
29
S'Class'Output
S'Class'Output denotes a procedure
with the following specification:
30/2
{
AI95-00441-01}
procedure S'Class'Output(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class;
Item :
in T'Class)
31/2
{
AI95-00344-01}
First writes the external tag of
Item to
Stream (by calling
String'Output(
Stream, Tags.External_Tag(
Item'Tag)
)
— see
3.9) and then dispatches to the
subprogram denoted by the Output attribute of the specific type identified
by the tag.
Tag_Error is raised if the tag of Item
identifies a type declared at an accessibility level deeper than that
of S.
31.a/2
Reason: {
AI95-00344-01}
We raise Tag_Error here for nested types as such
a type cannot be successfully read with S'Class'Input, and it doesn't
make sense to allow writing a value that cannot be read.
32
S'Class'Input
S'Class'Input denotes a function
with the following specification:
33/2
{
AI95-00441-01}
function S'Class'Input(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class)
return T'Class
34/3
{
AI95-00279-01}
{
AI95-00344-01}
{
AI05-0109-1}
First reads the external tag from
Stream and determines the corresponding
internal tag (by calling Tags.
Descendant_Tag Internal_Tag(String'Input(
Stream)
,
S'Tag)
which might raise Tag_Error —
see
3.9) and then dispatches to the subprogram
denoted by the Input attribute of the specific type identified by the
internal tag; returns that result.
If the specific
type identified by the internal tag is
not covered by T'Class or is
abstract, Constraint_Error is raised.
34.a/3
Ramification: {
AI05-0109-1}
Descendant_Tag will ensure that the tag it returns
is covered by T'Class; Tag_Error will be raised if it would not cover
T'Class.
35/3
{
AI95-00195-01}
{
AI05-0228-1}
In the default implementation
of Read and Input for a composite type, for each scalar component that
is a discriminant or
that has an implicit initial
value whose component_declaration
includes a default_expression,
a check is made that the value returned by Read for the component belongs
to its subtype.
Constraint_Error is raised if this
check fails. For other scalar components, no check is made. For each
component that is of an access type, if the implementation can detect
that the value returned by Read for the component is not a value of its
subtype, Constraint_Error is raised. If the value is not a value of its
subtype and this error is not detected, the component has an abnormal
value, and erroneous execution can result (see
13.9.1).
In the default implementation of Read for a composite type with defaulted
discriminants, if the actual parameter of Read is constrained, a check
is made that the discriminants read from the stream are equal to those
of the actual parameter. Constraint_Error is raised if this check fails.
35.a/3
Reason: {
AI05-0228-1}
The check for scalar components that have an implicit
initial value is to preserve our Language Design Principle that all objects
that have an implicit initial value do not become "deinitialized".
35.b/3
Ramification: {
AI05-0228-1}
A scalar component can have an implicit initial
value if it has a default_expression, if the component's type has the
Default_Value aspect specified, or if the component is that of an array
type that has the Default_Component_Value aspect specified.
35.c/3
To be honest: {
AI05-0228-1}
An implementation should always be able to detect
the error for a null value read into a component of a access subtype
with a null exclusion; the "if the implementation can detect"
is intended to cover non-null access values.
36/2
{
AI95-00195-01}
It is unspecified at which
point and in which order these checks are performed. In particular, if
Constraint_Error is raised due to the failure of one of these checks,
it is unspecified how many stream elements have been read from the stream.
37/1
{
8652/0045}
{
AI95-00132-01}
In the default implementation
of Read and Input for a type, End_Error is raised if the end of the stream
is reached before the reading of a value of the type is completed.
38/3
{
8652/0040}
{
AI95-00108-01}
{
AI95-00195-01}
{
AI95-00251-01}
{
AI05-0039-1}
The
stream-oriented attributes may be specified for any type via an
attribute_definition_clause.
The subprogram name given in such a clause shall
statically denote a subprogram that is not not
denote an abstract subprogram. Furthermore,
if a stream-oriented attribute is specified for an interface type by
an attribute_definition_clause,
the subprogram name given in the clause shall statically denote a null
procedure. All nonlimited types have default
implementations for these operations. An attribute_reference
for one of these attributes is illegal if the type is limited, unless
the attribute has been specified by an attribute_definition_clause or [(for a type extension)] the attribute has been specified for an ancestor
type. For an attribute_definition_clause
specifying one of these attributes, the subtype of the Item parameter
shall be the base subtype if scalar, and the first subtype otherwise.
The same rule applies to the result of the Input function.
38.a/2
This paragraph
was deleted.Reason: {
AI95-00195-01}
This is to simplify implementation.
38.a.1/2
This paragraph
was deleted.Discussion: {
8652/0040}
{
AI95-00108-01}
{
AI95-00195-01}
“Specified”
includes inherited attributes, and default implementations are never
inherited. So, for untagged limited types, the second part of the attribute_reference
rule has the same meaning as the first part. However, tagged types never
inherit attributes, so the second rule is needed so that the default
implementations for the attributes can be called when those are constructed
from a directly specified ancestor.
38.b/2
Discussion:
{
AI95-00251-01}
Stream attributes (other than Input) are always
null procedures for interface types (they have no components). We need
to allow explicit setting of the Read and Write attributes in order that
the class-wide attributes like LI'Class'Input can be made available.
(In that case, any descendant of the interface type would require available
attributes.) But we don't allow any concrete implementation because these
don't participate in extensions (unless the interface is the parent type).
If we didn't ban concrete implementations, the order of declaration of
a pair of interfaces would become significant. For example, if Int1 and
Int2 are interfaces with concrete implementations of 'Read, then the
following declarations would have different implementations for 'Read:
38.c/2
type Con1 is new Int1 and Int2 with null record;
type Con2 is new Int2 and Int1 with null record;
38.d/2
This
would violate our design principle that the order of the specification
of the interfaces in a derived_type_definition
doesn't matter.
38.e/2
Ramification:
The Input attribute cannot be specified for an interface. As it is
a function, a null procedure is impossible; a concrete function is not
possible anyway as any function returning an abstract type must be abstract.
And we don't allow specifying stream attributes to be abstract subprograms.
This has no impact, as the availability of Int'Class'Input (where Int
is a limited interface) depends on whether Int'Read (not Int'Input) is
specified. There is no reason to allow Int'Output to be specified, either,
but there is equally no reason to disallow it, so we don't have a special
rule for that.
38.f/2
Discussion: {
AI95-00195-01}
Limited types generally do not have default implementations
of the stream-oriented attributes. The rules defining when a stream-oriented
attribute is available (see below) determine when an attribute of a limited
type is in fact well defined and usable. The rules are designed to maximize
the number of cases in which the attributes are usable. For instance,
when the language provides a default implementation of an attribute for
a limited type based on a specified attribute for the parent type, we
want to be able to call that attribute.
38.g/3
Aspect Description
for Read: Procedure
to read a value from a stream for a given type.
38.h/3
Aspect Description
for Write: Procedure
to write a value to a stream for a given type.
38.i/3
Aspect Description
for Input: Function
to read a value from a stream for a given type, including any bounds
and discriminants.
38.j/3
Aspect Description
for Output: Procedure
to write a value to a stream for a given type, including any bounds and
discriminants.
39/2
{
AI95-00195-01}
A stream-oriented attribute for a subtype of a
specific type T is available at places where one of the
following conditions is true:
40/2
T is nonlimited.
41/2
The attribute_designator
is Read (resp. Write) and T is a limited record extension, and
the attribute Read (resp. Write) is available for the parent type of
T and for the types of all of the extension components.
41.a/2
Reason: In this
case, the language provides a well-defined default implementation, which
we want to be able to call.
42/2
T is a limited untagged
derived type, and the attribute was inherited for the type.
42.a/2
Reason: Attributes
are only inherited for untagged derived types, and surely we want to
be able to call inherited attributes.
43/2
The attribute_designator
is Input (resp. Output), and T is a limited type, and the attribute
Read (resp. Write) is available for T.
43.a/2
Reason: The default
implementation of Input and Output are based on Read and Write; so if
the implementation of Read or Write is good, so is the matching implementation
of Input or Output.
44/2
44.a/2
Reason: We always
want to allow calling a specified attribute. But we don't want availability
to break privacy. Therefore, only attributes whose specification can
be seen count. Yes, we defined the visibility of an attribute_definition_clause
(see 8.3).
45/2
{
AI95-00195-01}
A stream-oriented attribute for a subtype of a
class-wide type T'Class is available at places where one of the
following conditions is true:
46/2
T is nonlimited;
47/2
48/2
the corresponding attribute
of T is available, provided that if T has a partial view,
the corresponding attribute is available at the end of the visible part
where T is declared.
48.a/2
Reason: The rules
are stricter for class-wide attributes because (for the default implementation)
we must ensure that any specific attribute that might ever be dispatched
to is available. Because we require specification of attributes for extensions
of limited parent types with available attributes, we can in fact know
this. Otherwise, we would not be able to use default class-wide attributes
with limited types, a significant limitation.
49/2
49.a/2
Discussion: Stream
attributes always exist. It is illegal to call them in some cases. Having
the attributes not be defined for some limited types would seem to be
a cleaner solution, but it would lead to contract model problems for
limited private types.
49.b/2
T'Input is available
for abstract types so that T'Class'Input is available. But we
certainly don't want to allow calls that could create an object of an
abstract type. Remember that T'Class is never abstract, so the
above legality rule doesn't apply to it. We don't have to discuss whether
the attribute is specified, as it cannot be: any function returning the
type would have to be abstract, and we do not allow specifying an attribute
with an abstract subprogram.
50/3
{
AI95-00195-01}
{
AI05-0192-1}
In the parameter_and_result_profiles
for the default implementations of the
stream-oriented attributes, the subtype of the Item parameter is the
base subtype of T if T is a scalar type, and the first
subtype otherwise. The same rule applies to the result of the Input attribute.
50.a/3
Discussion: {
AI05-0192-1}
An inherited stream attribute has a profile as
determined by the rules for inheriting primitive subprograms (see 13.1
and 3.4).
51/3
{
AI95-00195-01}
{
AI05-0007-1}
For an attribute_definition_clause
specifying one of these attributes, the subtype of the Item Item parameter shall be the first subtype or
the base subtype if scalar, and the first
subtype if not scalar otherwise.
The same rule applies to the result of the Input function.
51.a/2
Reason: This is
to simplify implementation.
51.b/3
Ramification: The
view of the type at the point of the attribute_definition_clause
determines whether the first
subtype or base subtype is allowed required.
Thus, for a scalar type with a partial view (which is never scalar),
whether the first
subtype or the base subtype is allowed required is determined by whether the attribute_definition_clause
occurs before or after the full definition of the scalar type.
52/3
{
AI95-00366-01}
{
AI05-0065-1}
[A type
is said to support external streaming if Read and Write attributes
are provided for sending values of such a type between active partitions,
with Write marshalling the representation, and Read unmarshalling the
representation.] A limited type supports external streaming only if it
has available Read and Write attributes. A type with a part that is of
a non-remote an access type supports external streaming only if that access type or the
type of some part that includes the access type component, has Read and
Write attributes that have been specified via an attribute_definition_clause,
and that attribute_definition_clause
is visible. [An anonymous access type does not support external streaming.
]All other types (including remote access
types, see E.2.2) support
external streaming.
52.a/3
Ramification: A
limited type with a part that is of a non-remote an access type needs to satisfy both rules.
Erroneous Execution
53/2
{
AI95-00279-01}
{
AI95-00344-01}
If the internal tag returned
by Descendant_Tag to T'Class'Input identifies a type that is not library-level
and whose tag has not been created, or does not exist in the partition
at the time of the call, execution is erroneous.
53.a/2
Ramification: The
definition of Descendant_Tag prevents such a tag from being provided
to T'Class'Input if T is a library-level type. However, this rule is
needed for nested tagged types.
Implementation Requirements
54/1
{
8652/0040}
{
AI95-00108-01}
For every subtype S of a language-defined
nonlimited specific type T, the output generated by S'Output or
S'Write shall be readable by S'Input or S'Read, respectively. This rule
applies across partitions if the implementation conforms to the Distributed
Systems Annex.
55/3
{
AI95-00195-01}
{
AI05-0092-1}
If Constraint_Error is raised during a call to
Read because of failure of one the above checks, the implementation shall must ensure that the discriminants of the actual parameter of Read are not
modified.
Implementation Permissions
56/3
{
AI95-00195-01}
{
AI05-0092-1}
The number of calls performed by the predefined
implementation of the stream-oriented attributes on the Read and Write
operations of the stream type is unspecified. An implementation may take
advantage of this permission to perform internal buffering. However,
all the calls on the Read and Write operations of the stream type needed
to implement an explicit invocation of a stream-oriented attribute shall must take place before this invocation returns. An explicit invocation is
one appearing explicitly in the program text, possibly through a generic
instantiation (see 12.3).
56.1/3
{
AI05-0023-1}
{
AI05-0264-1}
If T is a discriminated type and its discriminants
have defaults, then in two cases an execution of the default implementation
of S'Read is not required to create an anonymous object of type T:
If the discriminant values that are read in are equal to the corresponding
discriminant values of Item, then no object of type T need
be created and Item may be used instead. If they are not equal
and Item is a constrained variable, then Constraint_Error may
be raised at that point, before any further values are read from the
stream and before the object of type T is created.
56.2/3
{
AI05-0023-1}
A default implementation of S'Input that calls
the default implementation of S'Read may create a constrained anonymous
object with discriminants that match those in the stream.
56.a/3
Implementation
Note: This allows the combined executions of S'Input and S'Read to
create one object of type T instead of two. If this option is
exercised, then:
56.b/3
The discriminants are
read from the stream by S'Input, not S'Read.
56.c/3
S'Input declares an
object of type T constrained by the discriminants read from the
stream, not an unconstrained object.
56.d/3
The discriminant values
that S'Read would normally have read from the stream are read from Item
instead.
56.e/3
The permissions of the
preceding paragraph then apply and no object of type T need be
created by the execution of S'Read.
57
41 For a definite subtype S of a type T,
only T'Write and T'Read are needed to pass an arbitrary
value of the subtype through a stream. For an indefinite subtype S of
a type T, T'Output and T'Input will normally be
needed, since T'Write and T'Read do not pass bounds, discriminants,
or tags.
58
42 User-specified attributes of S'Class
are not inherited by other class-wide types descended from S.
Examples
59
Example of user-defined
Write attribute:
60/2
{
AI95-00441-01}
procedure My_Write(
Stream :
not null access Ada.Streams.Root_Stream_Type'Class;
Item
: My_Integer'Base);
for My_Integer'Write
use My_Write;
60.a
Discussion:
Example of network input/output using input output attributes:
60.b
with Ada.Streams; use Ada.Streams;
generic
type Msg_Type(<>) is private;
package Network_IO is
-- Connect/Disconnect are used to establish the stream
procedure Connect(...);
procedure Disconnect(...);
60.c
-- Send/Receive transfer messages across the network
procedure Send(X : in Msg_Type);
function Receive return Msg_Type;
private
type Network_Stream is new Root_Stream_Type with ...
procedure Read(...); -- define Read/Write for Network_Stream
procedure Write(...);
end Network_IO;
60.d
with Ada.Streams; use Ada.Streams;
package body Network_IO is
Current_Stream : aliased Network_Stream;
. . .
procedure Connect(...) is ...;
procedure Disconnect(...) is ...;
60.e
procedure Send(X : in Msg_Type) is
begin
Msg_Type'Output(Current_Stream'Access, X);
end Send;
60.f
function Receive return Msg_Type is
begin
return Msg_Type'Input(Current_Stream'Access);
end Receive;
end Network_IO;
Inconsistencies With Ada 95
60.g/2
{
8652/0040}
{
AI95-00108-01}
Corrigendum: Clarified
how the default implementation for stream attributes is determined (eliminating
conflicting language). The new wording provides that attributes for type
extensions are created by composing the parent's attribute with those
for the extension components if any. If a program was written assuming
that the extension components were not included in the stream (as in
original Ada 95), it would fail to work in the language as corrected
by the Corrigendum.
60.h/2
{
AI95-00195-01}
Amendment Correction: Explicitly provided
a permission that the number of calls to the underlying stream Read and
Write operations may differ from the number determined by the canonical
operations. If Ada 95 code somehow depended on the number of calls to
Read or Write, it could fail with an Ada 2005 implementation. Such code
is likely to be very rare; moreover, such code is really wrong, as the
permission applies to Ada 95 as well.
Extensions to Ada 95
60.i/2
{
AI95-00270-01}
The Stream_Size attribute is
new. It allows specifying the number of bits that will be streamed for
a type. The Implementation Advice involving this also was changed; this
is not incompatible because Implementation Advice does not have to be
followed.
60.j/2
{
8652/0040}
{
AI95-00108-01}
{
AI95-00195-01}
{
AI95-00444-01}
Corrigendum: Limited types may have default
constructed attributes if all of the parent and (for extensions) extension
components have available attributes. Ada 2005 adds the notion of availability
to patch up some holes in the Corrigendum model.
Wording Changes from Ada 95
60.k/2
60.l/2
{
8652/0045}
{
AI95-00132-01}
Corrigendum: Clarified that End_Error is
raised by the default implementation of Read and Input if the end of
the stream is reached. (The result could have been abnormal without this
clarification, thus this is not an inconsistency, as the programmer could
not have depended on the previous behavior.)
60.m/2
{
AI95-00195-01}
Clarified that the default implementation of S'Input
does normal initialization on the object that it passes to S'Read.
60.n/2
{
AI95-00195-01}
Explicitly stated that what is read from a stream
when a required check fails is unspecified.
60.o/2
{
AI95-00251-01}
Defined availability and default implementations
for types with progenitors.
60.p/2
{
AI95-00279-01}
Specified that Constraint_Error is raised if the
internal tag retrieved for S'Class'Input is for some type not covered
by S'Class or is abstract. We also explicitly state that the program
is erroneous if the tag has not been created or does not currently exist
in the partition. (Ada 95 did not specify what happened in these cases;
it's very unlikely to have provided some useful result, so this is not
considered an inconsistency.)
60.q/2
{
AI95-00344-01}
Added wording to support nested type extensions.
S'Input and S'Output always raise Tag_Error for such extensions, and
such extensions were not permitted in Ada 95, so this is neither an extension
nor an incompatibility.
60.r/2
{
AI95-00366-01}
Defined supports external streaming to put
all of the rules about “good” stream attributes in one place.
This is used for distribution and for defining pragma Pure.
60.s/2
{
AI95-00441-01}
Added the not null qualifier to the first
parameter of all of the stream attributes, so that the semantics doesn't
change between Ada 95 and Ada 2005. This change is compatible, because
mode conformance is required for subprograms specified as stream attributes,
and null_exclusions
are not considered for mode conformance.
60.t/2
{
AI95-00444-01}
Improved the wording to make it clear that we don't
define the default implementations of attributes that cannot be called
(that is, aren't “available”). Also clarified when inheritance
takes place.
Incompatibilities With Ada 2005
60.u/3
{
AI05-0039-1}
Correction: Added a
requirement that stream attributes be specified by a static subprogram
name rather than a dynamic expression. Expressions cannot provide any
useful functionality because of the freezing rules, and the possibility
of them complicates implementations. Only pathological programs should
be affected.
Extensions to Ada 2005
60.v/3
{
AI05-0007-1}
Correction: Stream attributes
for scalar types can be specified with subprograms that take the first
subtype as well as the base type. This eliminates confusion about which
subtype is appropriate for attributes specified for partial views whose
full type is a scalar type. It also eliminates a common user error (forgetting
'Base).
Wording Changes from Ada 2005
60.w/3
{
AI05-0023-1}
Correction: Corrected the definition of
the default version S'Read and S'Input to be well-defined if S is a discriminated
type with defaulted discriminants and some components require initialization
and/or finalizations.
60.x/3
{
AI05-0065-1}
Correction: Defined remote access types
to support external streaming, since that is their purpose.
60.y/3
{
AI05-0109-1}
Correction: Removed a misleading phrase
which implies that Constraint_Error is raised for internal tags of the
wrong type, when Tag_Error should be raised for such tags.
60.z/3
{
AI05-0139-2}
Clarified that arrays with convention Fortran are
written in column-major order, rather then row-major order. This is necessary
in order that streaming of Fortran arrays is efficient.
60.aa/3
{
AI05-0192-1}
Correction: Clarified that the profile of
an inherited stream attribute is as defined for an inherited primitive
subprogram, while the default implementation of the same attribute might
have a different profile.
60.bb/3
{
AI05-0194-1}
Correction: Clarified that Stream_Size has
no effect on and is not effected by user-defined stream attributes.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe