Spec-Zone.ru › Ada 2022
Руководство по Ada (Ada 2022)

13.13.2 Потоковые атрибуты

Атрибуты Write, Read, Output и Input, связанные с типом, преобразуют значения в поток элементов и восстанавливают значения из потока.

Статическая семантика

Для каждого подтипа S элементарного типа T определён следующий атрибут представления:
S'Stream_Size

Обозначает количество битов, считываемых или записываемых в поток стандартными реализациями S'Read и S'Write. Следовательно, количество потоковых элементов, необходимых на элемент элементарного типа T, равно:
T'Stream_Size / Ada.Streams.Stream_Element'Size
Значение этого атрибута имеет тип universal_integer и является кратным Stream_Element'Size.
Stream_Size может быть задан для подтипов с помощью attribute_definition_clause; выражение такого предложения должно быть статическим, неотрицательным и кратным Stream_Element'Size.

Рекомендации по реализации

Если не указано иное, значение Stream_Size для элементарного типа должно быть равно числу битов, соответствующему минимальному числу потоковых элементов, требуемых первым подтипом типа, округлённому до ближайшего кратного размера слова, также кратного размеру потокового элемента.
Рекомендуемый уровень поддержки атрибута Stream_Size:
  • Предложение Stream_Size должно поддерживаться для дискретного или фиксированного типа T, если указанное Stream_Size кратно Stream_Element'Size и не меньше размера первого подтипа T, и не больше размера наибольшего типа того же элементарного класса (целое со знаком, целочисленное по модулю, перечисление, обычное фиксированное или десятичное фиксированное).

Статическая семантика

Для каждого подтипа S определённого типа T определены следующие атрибуты.
S'Write
S'Write обозначает процедуру со следующим описанием:
procedure S'Write(
Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in T)
S'Write записывает значение Item в Stream.
S'Read
S'Read обозначает процедуру со следующим описанием:
procedure S'Read(
Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : out T)
S'Read считывает значение Item из Stream.
Этот абзац был удалён.
Стандартные реализации атрибутов Write и Read, где доступны, выполняются следующим образом:
Для непроизводных элементарных типов Read считывает (а Write записывает) количество потоковых элементов, заданных Stream_Size для типа T; представление этих потоковых элементов определяется реализацией. Для непроизводных составных типов атрибут Write или Read для каждого компонента (за исключением, если таковые имеются, тех, которые не являются компонентами номинального типа объекта) вызывается в каноническом порядке, при котором последняя размерность изменяется быстрее всего для массива (если соглашение массива не Fortran, в этом случае изменяется быстрее всего первая размерность), и порядковый порядок агрегатов для записи. Границы не включаются в поток, если T — это массивный тип. Если T — это тип с дискриминантами, дискриминанты включаются только если они имеют значения по умолчанию. Если T — это тип с меткой, метка не включается.
Для расширений типов вызывается атрибут Write или Read родительского типа, за которым следуют атрибуты Write или Read каждого компонента расширяющей части в каноническом порядке. Для расширения ограниченного типа, если атрибут родительского типа или любого родительского типа T доступен где-либо в непосредственной области видимости T, а атрибут родительского типа или тип любого из компонентов расширения недоступен на точке замораживания T, то атрибут T должен быть задан напрямую. Для немеченых производных типов атрибут Write (соответственно, Read) вызывает соответствующий атрибут родительского типа, если атрибут доступен для родительского типа.
Если T — тип с дискриминантами, а его дискриминанты имеют значения по умолчанию, то S'Read сначала считывает дискриминанты из потока, не изменяя Item. S'Read затем создаёт объект типа T, ограниченный этими дискриминантами. Значение этого объекта затем преобразуется в подтип Item и присваивается Item. Наконец, атрибут Read для каждого недискриминантного компонента Item вызывается в каноническом порядке, как описано выше. Обычная инициализация по умолчанию и завершение выполняются для созданного объекта.
Constraint_Error поднимается предопределённым атрибутом Write, если значение элементарного элемента находится за пределами диапазона значений, представимых с помощью Stream_Size битов. Для типа целого со знаком, типа перечисления или типа с фиксированной точкой диапазон является беззнаковым только в том случае, если целочисленное представление нижней границы первого подтипа неотрицательно, а (симметричный) диапазон со знаком, охватывающий все значения первого подтипа, потребовал бы более Stream_Size битов; в противном случае диапазон со знаком.
Для каждого подтипа S'Class класса широкого типа T'Class:
S'Class'Write
S'Class'Write обозначает процедуру со следующим описанием:
procedure S'Class'Write(
Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in T'Class)
Выполняет диспетчеризацию к подпрограмме, обозначаемой атрибутом Write определённого типа, идентифицированного меткой Item.
S'Class'Read
S'Class'Read обозначает процедуру со следующим описанием:
procedure S'Class'Read(
Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : out T'Class)
Выполняет диспетчеризацию к подпрограмме, обозначаемой атрибутом Read определённого типа, идентифицированного меткой Item.
Параграф 17 был удалён.

Статическая семантика

Для каждого подтипа S определённого типа T определены следующие атрибуты.
S'Output
S'Output обозначает процедуру со следующим описанием:
procedure S'Output(
Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in T)
S'Output записывает значение Item в Stream, включая любые границы или дискриминанты.
S'Input
S'Input обозначает функцию со следующим описанием:
function S'Input(
Stream : not null access Ada.Streams.Root_Stream_Type'Class)
return T
S'Input считывает и возвращает одно значение из Stream, используя любые границы или дискриминанты, записанные соответствующим S'Output, чтобы определить, сколько считывать.
Для немеченого производного типа стандартная реализация атрибута Output (соответственно, Input) вызывает соответствующий атрибут родительского типа, если атрибут доступен для родительского типа. Для любого другого типа стандартные реализации атрибутов Output и Input, где доступны, выполняются следующим образом:
  • Если T — это массивный тип, S'Output сначала записывает границы, а S'Input сначала считывает границы. Если T имеет дискриминанты без значений по умолчанию, S'Output сначала записывает дискриминанты (используя атрибут Write типа дискриминанта для каждого), а S'Input сначала считывает дискриминанты (используя атрибут Read типа дискриминанта для каждого).
  • Затем S'Output вызывает S'Write, чтобы записать значение Item в поток. Затем S'Input создаёт объект типа T, с границами или (когда без значений по умолчанию) дискриминантами, если таковые имеются, извлечёнными из потока, передаёт его в S'Read и возвращает значение объекта. Если T имеет дискриминанты, этот объект является неограниченным тогда и только тогда, когда дискриминанты имеют значения по умолчанию. Обычная инициализация по умолчанию и завершение выполняются для этого объекта (см. 3.3.1, 7.6 и 7.6.1).
Если T — абстрактный тип, то S'Input — абстрактная функция.
Для каждого подтипа S'Class класса широкого типа T'Class:
S'Class'Output

S'Class'Output обозначает процедуру со следующим описанием:
procedure S'Class'Output(
Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in T'Class)
Сначала записывает внешний тег Item в Stream (вызывая String'Output(Stream, Tags.External_Tag(Item'Tag)) — см. 3.9), а затем пересылает в подпрограмму, обозначенную атрибутом Output конкретного типа, идентифицированного тегом. Tag_Error генерируется, если тег Item идентифицирует тип, объявленный на уровне доступности глубже, чем у S.
S'Class'Input
S'Class'Input обозначает функцию со следующей спецификацией:
function S'Class'Input(
Stream : not null access Ada.Streams.Root_Stream_Type'Class)
return T'Class
Сначала считывает внешний тег из Stream и определяет соответствующий внутренний тег (вызывая Tags.Descendant_Tag(String'Input(Stream), S'Tag), который может генерировать Tag_Error — см. 3.9), а затем пересылает в подпрограмму, обозначенную атрибутом Input конкретного типа, идентифицированного внутренним тегом; возвращает этот результат. Если конкретный тип, идентифицированный внутренним тегом, является абстрактным, генерируется Constraint_Error.
В реализации по умолчанию Read и Input для составного типа для каждого скалярного компонента, являющегося дискриминантом или имеющего неявное начальное значение, проверяется, принадлежит ли значение, возвращённое Read для компонента, его подтипу. Constraint_Error генерируется, если эта проверка не пройдена. Для других скалярных компонентов проверка не выполняется. Для каждого компонента типа доступа, если реализация может определить, что значение, возвращённое Read для компонента, не является значением его подтипа, генерируется Constraint_Error. Если значение не является значением его подтипа и эта ошибка не обнаружена, компонент имеет аномальное значение, и может произойти ошибочное выполнение (см. 13.9.1). В реализации по умолчанию Read для составного типа с дискриминантами по умолчанию, если фактический параметр Read ограничен, проверяется, совпадают ли дискриминанты, прочитанные из потока, с дискриминантами фактического параметра. Constraint_Error генерируется, если эта проверка не пройдена.
Не определено, в какой момент и в каком порядке выполняются эти проверки. В частности, если Constraint_Error генерируется из-за неудачи одной из этих проверок, не определено, сколько элементов потока было прочитано из потока.
В реализации по умолчанию Read и Input для типа, End_Error генерируется, если конец потока достигается до завершения чтения значения типа.
Аспект Nonblocking статически равен True, а аспект Global равен null для реализаций по умолчанию атрибутов потокового типа для элементарных типов. Для реализаций по умолчанию атрибутов потокового типа для составных типов значение аспекта Nonblocking равно значению первого подтипа, а аспект Global по умолчанию равен значению первого подтипа. Реализация по умолчанию атрибута потокового типа, у которого аспект Nonblocking статически равен True, считается областью без блокировок. Аспект Dispatching (см. H.7.1) равен Read(Stream) для реализаций по умолчанию атрибутов потокового типа Read, Read'Class, Input и Input'Class; аспект Dispatching равен Write(Stream) для реализаций по умолчанию атрибутов потокового типа Write, Write'Class, Output и Output'Class.
Атрибуты потокового типа могут быть указаны для любого типа с помощью attribute_definition_clause. В качестве альтернативы, каждый из конкретных атрибутов потокового типа может быть указан с помощью aspect_specification для любого type_declaration, причём имя аспекта совпадает с соответствующим именем атрибута. Каждый из атрибутов потокового типа для всего класса типов может быть указан с помощью aspect_specification для помеченного типа T с использованием имени атрибута потокового типа, за которым следует 'Class; такие аспекты всего класса не применяются к другим потомкам T. Если не указано явно, реализация по умолчанию атрибута потокового типа неявно создаётся для неограниченного типа и для определённых ограниченных типов, как определено выше.
Имя подпрограммы, указанное в attribute_definition_clause или aspect_specification, должно статически обозначать подпрограмму, которая не является абстрактной. Кроме того, если конкретный атрибут потокового типа указан для типа интерфейса, имя подпрограммы, указанное в attribute_definition_clause или aspect_specification, должно статически обозначать пустую процедуру.
Атрибут потокового типа для подтипа конкретного типа T доступен в тех местах, где выполняется одно из следующих условий:
  • T не ограничен.
  • Оператор attribute_designator равен Read (соответственно Write) и T является ограниченным расширением записи, и атрибут Read (соответственно Write) доступен для родительского типа T и для типов всех компонентов расширения.
  • T является ограниченным неупорядоченным производным типом, и атрибут доступен для родительского типа.
  • Оператор attribute_designator равен Input (соответственно Output), и T является ограниченным типом, и атрибут Read (соответственно Write) доступен для T.
  • Атрибут был указан с помощью attribute_definition_clause или aspect_specification, и attribute_definition_clause или aspect_specification видимы.
Атрибут потокового типа для подтипа типа всего класса T'Class доступен в тех местах, где выполняется одно из следующих условий:
  • T не ограничен;
  • атрибут был указан с помощью attribute_definition_clause или aspect_specification, и attribute_definition_clause или aspect_specification виден; или
  • соответствующий атрибут T доступен, при условии, что если T имеет частичный вид, соответствующий атрибут доступен в конце видимой части, где T объявлен.
Ссылка attribute_reference на один из атрибутов потокового типа недопустима, если атрибут не доступен в месте ссылки attribute_reference. Кроме того, ссылка attribute_reference на T'Input недопустима, если T является абстрактным типом. В дополнение к местам, где обычно применяются правила допустимости (см. 12.3), эти правила также применяются в частях с умолчанием экземпляра генерического блока.
Если атрибут не доступен для родительского типа, если таковой имеется, для неупорядоченного типа, содержащего задачу, защищённый блок или явно ограниченную часть записи, реализация по умолчанию каждого из атрибутов Read, Write, Input и Output генерирует Program_Error и не выполняет никаких других действий.
В parameter_and_result_profile для реализаций по умолчанию атрибутов потокового типа подтип параметра Item является базовым подтипом T, если T является скалярным типом, и в противном случае — первым подтипом. То же правило применяется к результату атрибута Input.
Для attribute_definition_clause или aspect_specification, указывающего один из этих атрибутов, подтип параметра Item должен быть первым подтипом или базовым подтипом, если скалярный, и первым подтипом, если не скалярный. То же правило применяется к результату функции Input.
Тип называется поддерживающим внешнюю потоковую передачу, если для него предоставляются атрибуты Read и Write для отправки значений такого типа между активными разделами, причём Write упаковывает представление, а Read распаковывает представление. Ограниченный тип поддерживает внешнюю потоковую передачу только в том случае, если для него доступны атрибуты Read и Write. Тип с частью, являющейся типом доступа, не являющимся удалённым, поддерживает внешнюю потоковую передачу только в том случае, если этот тип доступа или тип какой-либо части, включающей компонент типа доступа, имеет атрибуты Read и Write, указанные с помощью attribute_definition_clause, и этот attribute_definition_clause видим. Анонимный тип доступа не поддерживает внешнюю потоковую передачу. Все остальные типы (включая типы удалённого доступа, см. E.2.2) поддерживают внешнюю потоковую передачу.

Ошибочное выполнение

Если внутренний тег, возвращённый Descendant_Tag для T'Class'Input, идентифицирует тип, который не является библиотечным и тег которого не был создан или не существует в разделе на момент вызова, выполнение является ошибочным.

Требования к реализации

Для каждого подтипа S языка-определённого неограниченного конкретного типа T, вывод, генерируемый S'Output или S'Write, должен быть читаем S'Input или S'Read, соответственно. Это правило распространяется на разделы, если реализация соответствует приложению к распределённым системам.
Если при вызове Read из-за сбоя одного из вышеперечисленных проверок возникает исключение Constraint_Error, реализация должна гарантировать, что дискриминанты фактического параметра Read не изменятся.

Разрешения реализации

Количество вызовов, выполняемых предварительно определенной реализацией потоковых атрибутов для операций Read и Write типа потока, не определено. Реализация может использовать это разрешение для внутренней буферизации. Однако все вызовы операций Read и Write типа потока, используемые для реализации явного вызова потокового атрибута, должны произойти до возврата этого вызова. Явный вызов — это вызов, явно присутствующий в тексте программы, возможно, через обобщенное экземплярирование (см. 12.3).
Если T — тип с дискриминантами, а его дискриминанты имеют значения по умолчанию, то в двух случаях выполнение стандартной реализации S'Read не требует создания анонимного объекта типа T: Если значения дискриминантов, которые считываются, равны соответствующим значениям дискриминантов Item, то создание нового объекта типа T может быть пропущено, и вместо него может быть использован Item. Если они не равны, и Item — ограниченная переменная, то в этот момент может быть поднято исключение Constraint_Error, прежде чем будут считаны какие-либо другие значения из потока и прежде чем будет создан объект типа T.
Стандартная реализация S'Input, которая вызывает стандартную реализацию S'Read, может создать ограниченный анонимный объект с дискриминантами, соответствующими дискриминантам в потоке.
ПРИМЕЧАНИЕ 1 Для определенного подтипа S типа T необходимы только T'Write и T'Read для передачи произвольного значения подтипа через поток. Для неопределенного подтипа S типа T обычно потребуются T'Output и T'Input, так как T'Write и T'Read не передают границы, дискриминанты или теги.
ПРИМЕЧАНИЕ 2 Пользовательские атрибуты S'Class не наследуются другими типами класса, произошедшими от S.

Примеры

Пример пользовательского атрибута Write:
procedure My_Write(
Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : My_Integer'Base);
for My_Integer'Write use My_Write;


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API