Spec-Zone.ru › Ada 2012
Справочник по Ada 2012

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 может быть задан для подтипов с помощью определения атрибутов; выражение в таком пункте должно быть статическим, неотрицательным и кратным 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) наследуется в соответствии с правилами, указанными в 13.1, если атрибут указан и доступен для родительского типа в момент объявления T. Для меченного производного типа эти атрибуты не наследуются, а используются стандартные реализации.
Стандартные реализации атрибутов Write и Read, если они доступны, выполняются следующим образом:
Для элементарных типов Read считывает (и Write записывает) количество потоковых элементов, подразумеваемых Stream_Size для типа T; представление этих потоковых элементов определяется реализацией. Для составных типов атрибут Write или Read для каждого компонента вызывается в каноническом порядке, где последняя размерность изменяется быстрее для массива (если соглашение об массиве не Fortran, в этом случае самая быстро меняющаяся - первая размерность), и позиционный агрегатный порядок для записи. Границы не включаются в поток, если T - тип массива. Если T - дискриминированный тип, дискриминанты включаются только если у них есть значения по умолчанию. Если T - помеченный тип, метка не включается. Для расширений типов вызывается атрибут Write или Read родительского типа, за которым следуют атрибуты Write или Read каждого компонента расширяемой части в каноническом порядке. Для ограниченного расширения типа, если атрибут родительского типа или любого предкового типа T доступен где-либо в непосредственной области видимости T, а атрибут родительского типа или тип любого из компонентов расширения недоступен в точке замораживания T, то атрибут T должен быть непосредственно указан.
Если 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) наследуется в соответствии с правилами, указанными в 13.1, если атрибут указан и доступен для родительского типа в момент объявления T. Для меченного производного типа эти атрибуты не наследуются, а используются стандартные реализации.
Стандартные реализации атрибутов 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 возникает, если конец потока достигнут до завершения чтения значения типа.
Атрибуты, ориентированные на поток, могут быть определены для любого типа с помощью 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, и attribute_definition_clause виден.
Атрибут, ориентированный на поток, для подтипа типа класса T'Class доступен в местах, где выполняется одно из следующих условий:
  • T неограничен;
  • атрибут был определён с помощью attribute_definition_clause, и attribute_definition_clause виден; или
  • соответствующий атрибут 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, определяющего один из этих атрибутов, подтип параметра Item должен быть первым подтипом или базовым подтипом, если скалярным, и первым подтипом, если нет.
Тип считается поддерживающим внешнюю передачу данных потоком, если для него предусмотрены атрибуты 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 соответственно. Это правило применяется в различных разделах, если реализация соответствует Приложению о распределённых системах.
Если Constraint_Error возникает во время вызова Read из-за сбоя одной из вышеперечисленных проверок, реализация должна гарантировать, что дискриминанты фактического параметра Read не изменятся.

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

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

Примеры

Пример пользовательского атрибута Write:
процедура My_Write(
Stream : не null доступ Ada.Streams.Root_Stream_Type'Class;
Item : My_Integer'Base);
для My_Integer'Write используется My_Write;


Spec-Zone.ru

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