Stream-Oriented Attributes
Author: JTC1/SC22/WG9/ARG, by Randall Brukardt, ARG Editor

Contents Index Search Previous Next

# 13.13.2 Stream-Oriented Attributes

1/1
The operational attributes Write, Read, Output, and Input convert values to a stream of elements and reconstruct values from a stream.

#### 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
`procedure S'Write(
Stream : 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
`procedure S'Read(
Stream : access Ada.Streams.Root_Stream_Type'Class;
Item : out T)`
8

  S'Read reads the value of Item from Stream.

8.1/1
For untagged derived types, the Write and Read attributes of the parent type are inherited as specified in 13.1; otherwise, the default implementations of these attributes are used. The default implementations of Write and Read attributes execute as follows:
9/1
For elementary types, the representation in terms of stream elements is implementation defined. For composite types, the Write or Read attribute for each component is called in canonical order, which is last dimension varying fastest for an array, 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 any ancestor type of T has been directly specified and the attribute of any ancestor type of the type of any of the extension components which are of a limited type has not been specified, the attribute of T shall be directly specified.
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
`procedure S'Class'Write(
Stream : 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
`procedure S'Class'Read(
Stream : 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.

#### Implementation Advice

17
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
`procedure S'Output(
Stream : 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.

22

S'Input
  S'Input denotes a function with the following specification:

23
`function S'Input(
Stream : 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/1
For untagged derived types, the Output and Input attributes of the parent type are inherited as specified in 13.1; otherwise, the default implementations of these attributes are used. The default implementations of Output and Input attributes 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

- S'Output then calls S'Write to write the value of Item to the stream. S'Input then creates an object (with the bounds or discriminants, if any, taken from the stream), initializes it with S'Read, and returns the value of the object.

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
`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) -- see 3.9) and then dispatches to the subprogram denoted by the Output attribute of the specific type identified by the tag.

32

S'Class'Input
  S'Class'Input denotes a function with the following specification:

33
`function S'Class'Input(
Stream : access Ada.Streams.Root_Stream_Type'Class)
return T'Class`
34

  First reads the external tag from Stream and determines the corresponding internal tag (by calling Tags.Internal_Tag(String'Input(Stream)) -- 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.

35
In the default implementation of Read and Input for a composite type, for each scalar component that is a discriminant or 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).
35.1/1
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.
36/1
The stream-oriented attributes may be specified for any type via an attribute_definition_clause. 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.

#### Implementation Requirements

36.1/1
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.
NOTES
37
31 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.
38
32 User-specified attributes of S'Class are not inherited by other class-wide types descended from S.

#### Examples

39
Example of user-defined Write attribute:
40
`procedure My_Write(
Stream : access Ada.Streams.Root_Stream_Type'Class; Item : My_Integer'Base);
for My_Integer'Write use My_Write;`

Contents Index Search Previous Next Legal