4.10 Image Attributes
An
image of a value is a string representing
the value in display form.
The attributes Image,
Wide_Image, and Wide_Wide_Image are available to produce the image of
a value as a String, Wide_String, or Wide_Wide_String (respectively).
User-defined images for a given type can be implemented by overriding
the default implementation of the attribute Put_Image.
Static Semantics
For every subtype S
of a type T other than universal_real or universal_fixed,
the following type-related operational attribute is defined:
S'Put_Image
S'Put_Image denotes a procedure
with the following specification:
procedure S'Put_Image
(Buffer : in out
Ada.Strings.Text_Buffers.Root_Buffer_Type'Class;
Arg : in T);
The default implementation of S'Put_Image
writes (using Wide_Wide_Put) an image of the value of Arg.
The Put_Image attribute may be specified for any
specific type T either via an
attribute_definition_clause
or via an
aspect_specification
specifying the Put_Image aspect of the type.
The Put_Image aspect is not inherited, but rather is implicitly composed
for derived types, as defined below.
The behavior of the default implementation of S'Put_Image
depends on the class of T.
For an untagged derived type, or a null extension,
the default implementation of T'Put_Image invokes the Put_Image for its
parent type on a conversion of the parameter of type T to the parent
type.
For a nonderived elementary
type, the implementation is equivalent to:
procedure Scalar_Type'Put_Image
(Buffer : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class;
Arg : in Scalar_Type) is
begin
Buffer.Wide_Wide_Put (<described below>);
end Scalar_Type'Put_Image;
where the Wide_Wide_String
value written out to the text buffer is defined as follows:
For an integer type, the image written out is the
corresponding decimal literal, without underlines, leading zeros, exponent,
or trailing spaces, but with a single leading character that is either
a minus sign or a space.
For an enumeration type, the image written out
is either the corresponding identifier in upper case or the corresponding
character literal (including the two apostrophes); neither leading nor
trailing spaces are included. For a
nongraphic character (a value
of a character type that has no enumeration literal associated with it),
the value is a corresponding language-defined name in upper case (for
example, the image of the nongraphic character identified as
nul
is
"NUL" — the quotes are not part of the image).
For a floating point type, the image written out
is a decimal real literal best approximating the value (rounded away
from zero if halfway between) with a single leading character that is
either a minus sign or a space, a single digit (that is nonzero unless
the value is zero), a decimal point, S'Digits-1 (see
3.5.8)
digits after the decimal point (but one if S'Digits is one), an upper
case E, the sign of the exponent (either + or -), and two or more digits
(with leading zeros if necessary) representing the exponent. If S'Signed_Zeros
is True, then the leading character is a minus sign for a negatively
signed zero.
For a fixed point type, the image written out is
a decimal real literal best approximating the value (rounded away from
zero if halfway between) with a single leading character that is either
a minus sign or a space, one or more digits before the decimal point
(with no redundant leading zeros), a decimal point, and S'Aft (see
3.5.10)
digits after the decimal point.
For an access type (named or anonymous), the image
written out depends on whether the value is null. If it is null,
then the image is "NULL". Otherwise the image is a
left parenthesis followed by "ACCESS", a space, and
a sequence of graphic characters, other than space or right parenthesis,
representing the location of the designated object, followed by a right
parenthesis, as in "(ACCESS FF0012AC)".
For a nonnull type extension, the default implementation
of T'Put_Image depends on whether there exists a noninterface ancestor
of T (other than T itself) for which the Put_Image aspect has been directly
specified. If so, then T'Put_Image will generate an image based on extension
aggregate syntax where the ancestor type of the extension aggregate is
the nearest ancestor type whose Put_Image aspect has been specified.
If no such ancestor exists, then the default implementation of T'Put_Image
is the same as described below for a nonderived record type.
For a specific, nonderived
composite type:
If the default implementation of Put_Image writes
components, the order in which components are written is the same canonical
order in which components of a composite type T are written out by the
default implementation of T'Write. This is also the order that is used
in determining the meaning of a positional aggregate of type T.
For an array type T, the default implementation
of T'Put_Image generates an image based on named (not positional) array
aggregate syntax (with '[' and ']' as the delimiters) using calls to
the Put_Image procedures of the index type(s) and the element type to
generate images for values of those types.
The case of a null array is handled specially,
using ranges for index bounds and "<>" as a
syntactic component-value placeholder.
For a record type (or, as indicated above, a type
extension with no noninterface ancestor specifying Put_Image), or a protected
type, the default implementation of T'Put_Image generates an image based
on named (not positional) record aggregate syntax (except that for a
protected type, the initial left parenthesis is followed by "PROTECTED
with "). Component names are displayed in upper case, following
the rules for the image of an enumeration value. Component values are
displayed via calls to the component type's Put_Image procedure.
The image written out for a record having
no components (including any interface type) is "(NULL RECORD)".
The image written out for a componentless protected type is "(PROTECTED NULL RECORD)".
In the case of a protected type T, a call to the default implementation
of T'Put_Image begins only one protected (read-only) action.
For an undiscriminated task type, the default implementation
of T'Put_Image generates an image of the form "(TASK <task_id_image>)"
where <task_id_image> is the result obtained by calling Task_Identification.Image
with the id of the given task and then passing that String to Characters.Conversions.To_Wide_Wide_String.
For a discriminated
task type, the default implementation of T'Put_Image also includes discriminant
values, as in:
"(TASK <task_id_image> with D1 => 123, D2 => 456)"
For a class-wide type, the default implementation
of T'Put_Image generates an image based on qualified expression syntax.
Wide_Wide_Put is called with Wide_Wide_Expanded_Name of Arg'Tag.
Then S'Put_Image is called, where S is the specific type identified by
Arg'Tag.
T'Put_Image is the same for both the partial view
and full view of T, if T has a partial view.
In the
parameter_and_result_profile
for the default implementation of Put_Image, the subtype of the
Arg
parameter is the base subtype of
T if
T is a scalar type,
and the first subtype otherwise. For an
aspect_specification
or
attribute_definition_clause
specifying Put_Image, the subprogram name shall denote a nonabstract
procedure whose second parameter is either of the first subtype of
T,
or as an option when
T is scalar, the base subtype of
T.
For every subtype S
of a type T, the following attributes are defined:
S'Wide_Wide_Image
S'Wide_Wide_Image denotes a function
with the following specification:
function S'Wide_Wide_Image(Arg : S'Base)
return Wide_Wide_String
S'Wide_Wide_Image calls S'Put_Image passing
Arg (which will typically store a sequence
of character values in a text buffer) and then returns the result of
retrieving the contents of that buffer with function Wide_Wide_Get. The
lower bound of the result is one. Any exception propagated by the call
of S'Put_Image is propagated.
S'Wide_Image
S'Wide_Image denotes a function
with the following specification:
function S'Wide_Image(Arg : S'Base)
return Wide_String
S'Wide_Image calls S'Put_Image passing
Arg (which will typically store a sequence
of character values in a text buffer) and then returns the result of
retrieving the contents of that buffer with function Wide_Get. The lower
bound of the result is one. Any exception propagated by the call of S'Put_Image
is propagated.
S'Image
S'Image denotes a function with
the following specification:
function S'Image(Arg : S'Base)
return String
S'Image calls S'Put_Image passing Arg
(which will typically store a sequence of character values in a text
buffer) and then returns the result of retrieving the contents of that
buffer with function Get. The lower bound of the result is one. Any exception
propagated by the call of S'Put_Image is propagated.
For a
prefix
X of a type T other than
universal_real or
universal_fixed,
the following attributes are defined:
X'Wide_Wide_Image
X'Wide_Wide_Image denotes the
result of calling function S'Wide_Wide_Image with
Arg being X,
where S is the nominal subtype of X.
X'Wide_Image
X'Wide_Image denotes the result
of calling function S'Wide_Image with
Arg being X, where S is
the nominal subtype of X.
X'Image
X'Image denotes the result of
calling function S'Image with
Arg being X, where S is the nominal
subtype of X.
Implementation Permissions
An implementation may
transform the image generated by the default implementation of S'Put_Image
for a composite subtype S in the following ways:
If S is a composite subtype, the leading character
of the image M of a component value or index value is a space,
and the immediately preceding character (if any) is an open parenthesis,
open bracket, or space, then the leading space of the image M
may be omitted.
If S is an array subtype, the low bound of the
array in each dimension equals the low bound of the corresponding index
subtype, and the array value is not a null array value, then positional
array aggregate syntax may be used.
If S is an array subtype and the given value can
be displayed using
named_array_aggregate
syntax where some
discrete_choice_list
identifies more than one index value by identifying a sequence of one
or more ranges and values separated by vertical bars, then this image
may be generated instead; this may involve the reordering of component
values.
Similarly, if S is a record subtype (or a discriminated
type) and the given value can be displayed using named component association
syntax where the length of some component_choice_list is greater than
one, then this image may be generated instead; this may involve the reordering
of component values.
Additional spaces (Wide_Wide_Characters with position
32), and calls to the New_Line operation of a text buffer, may be inserted
to improve readability of the generated image, with the spaces inserted
directly or via use of the Increase_Indent and Decrease_Indent procedures.
For a string type, implementations may produce
an image corresponding to a string literal.
For an unchecked union type, implementations may
raise Program_Error or produce some recognizable image (such as "(UNCHECKED
UNION)") that does not require reading the discriminants.
For each language-defined nonscalar type T, T'Put_Image
may be specified.
Implementation Requirements
For each language-defined
container type T (that is, each of the Vector, List, Map, Set, Tree,
and Holder types defined in the various children of Ada.Containers),
T'Put_Image shall be specified so that T'Image produces a result consistent
with array aggregate syntax (using '[' and ']' as delimiters) as follows:
Vector images shall be consistent with the default
image of an array type with the same index and component types.
Map images shall be consistent with named array
aggregate syntax, using key value images in place of discrete choice
names. For example, [Key1 => Value1, Key2 => Value2].
Set, List, and Holder images shall be consistent
with positional array aggregate syntax. List elements shall occur in
order within an image of a list. The image of an empty holder shall be
[].
Tree images (and images of subtrees of trees) shall
be consistent with positional array aggregate syntax. For example, [[1,
2], [111, 222, 333]].
For each language-defined nonscalar type T that has
a primitive language-defined Image function whose profile is type conformant
with that of T'Image (for example, Ada.Numerics.Float_Random.State has
such an Image function), T'Put_Image shall be specified so that T'Image
yields the same result as that Image function.
Implementation Advice
For each language-defined private type T, T'Image
should generate an image that would be meaningful based only on the relevant
public interfaces, as opposed to requiring knowledge of the implementation
of the private type.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe