!standard 13.13.1(1) 18-12-04 AI12-0293-1/02 !standard 13.13.1(9) !standard 13.13.1(9.1/1) !class Amendment 18-10-14 !status Amendment 1-2012 18-11-27 !status ARG Approved 8-0-0 18-10-22 !status work item 18-10-14 !status received 18-10-05 !priority Low !difficulty Easy !subject Add predefined FIFO_Streams packages !summary A group of 3 predefined child units of Ada.Streams are provided in order to provide capabilities which are useful on their own and, more specifically, in relation to AI12-0020-1. !problem With user-defined Image attributes as defined in AI12-0020-1, many users may have a common need for similar streaming-related functionality: a stream type which simply acts as a FIFO buffer and has operations for keeping track of the number of unread elements in the buffer and for efficiently emptying the buffer. A similar need appears in many other cases. One common example is storing and retrieving Ada objects in an existing API (for example, the Windows Clipboard and the Windows Registry). !proposal Rather than having each user address these needs in their own way, a group of predefined child units of Ada.Streams are provided. !wording Add after 13.13.1(1): The library package Ada.Streams has the following definition: Add after 13.13.1(9) (the end of the static semantics section): In addition, three packages provide stream implementations which do not make use of any file operations. These three packages provide the same operations, with Streams.FIFO_Streams providing an abstract interface, and two child packages providing implementations of that interface. The difference is that for Streams.FIFO_Streams.Bounded, the maximum storage is bounded. The library package Ada.Streams.FIFO_Streams has the following definition: package Ada.Streams.FIFO_Streams with Pure, Nonblocking is type FIFO_Stream is abstract new Root_Stream_Type with private; function Element_Count (Stream : FIFO_Stream) return Stream_Element_Count is abstract; procedure Clear (Stream : in out FIFO_Stream) is abstract; private ... -- not specified by the language end Ada.Streams.FIFO_Streams; The library package Ada.Streams.FIFO_Streams.Unbounded has the following definition: package Ada.Streams.FIFO_Streams.Unbounded with Prelaborated, Nonblocking is type Stream_Type is new FIFO_Stream with private with Default_Initial_Condition => Element_Count (Stream_Type) = 0; overriding procedure Read ( Stream : in out Stream_Type; Item : out Stream_Element_Array; Last : out Stream_Element_Offset) with Post => (declare Num_Read : constant Stream_Element_Count := Stream_Element_Count'Min (Element_Count(Stream)'Old, Item'Length); begin Last = Num_Read + Item'First - 1 and Element_Count (Stream) = Element_Count (Stream)'Old - Num_Read); AARM Discussion: Num_Read is the number of elements read; this is the minimum of Item'Length and the number of available elements. Last then is determined by that, and the Element_Count decreases by the number of elements read. overriding procedure Write ( Stream : in out Stream_Type; Item : in Stream_Element_Array) with Post => Element_Count (Stream) = Element_Count (Stream)'Old + Item'Length; overriding function Element_Count (Stream : Stream_Type) return Stream_Element_Count; overriding procedure Clear (Stream : in out Stream_Type) with Post => Element_Count (Stream) = 0; private ... -- not specified by the language end Ada.Streams.FIFO_Streams.Unbounded; The library package Ada.Streams.FIFO_Streams.Bounded has the following definition: package Ada.Streams.FIFO_Streams.Bounded with Pure, Nonblocking is type Stream_Type (Max_Elements : Stream_Element_Count) is new FIFO_Stream with private with Default_Initial_Condition => Element_Count (Stream_Type) = 0; overriding procedure Read ( Stream : in out Stream_Type; Item : out Stream_Element_Array; Last : out Stream_Element_Offset) with Post => (declare Num_Read : constant Stream_Element_Count := Stream_Element_Count'Min (Element_Count(Stream)'Old, Item'Length); begin Last = Num_Read + Item'First - 1 and Element_Count (Stream) = Element_Count (Stream)'Old - Num_Read); overriding procedure Write ( Stream : in out Stream_Type; Item : in Stream_Element_Array) with Pre => Element_Count (Stream) + Item'Length <= Stream.Max_Elements or else (raise Constraint_Error), Post => Element_Count (Stream) = Element_Count (Stream)'Old + Item'Length; overriding function Element_Count (Stream : Stream_Type) return Stream_Element_Count with Post => Element_Count'Result <= Stream.Max_Elements; overriding procedure Clear (Stream : in out Stream_Type) with Post => Element_Count (Stream) = 0; private ... -- not specified by the language end Ada.Streams.FIFO_Streams.Bounded; The Element_Count functions return the number of stream elements that are available for reading from the given stream. The Read and Write procedures behave as described for package Ada.Streams above. Stream elements are read in FIFO (first-in, first-out) order; stream elements are available for reading immediately after they are written. The Clear procedures remove any available stream elements from the given stream. ==== Add after 13.13.1(9.1/1): Implementation Advice Streams.FIFO_Streams.Bounded.Stream_Type objects should be implemented without implicit pointers or dynamic allocation. AARM Reason: The Streams.FIFO_Streams.Bounded package is provided in orde to make available an alternative to the Streaams.FIFO_Streams.Unbounded package which gives more predictable memory usage. !discussion None yet. !corrigendum 13.13.1(1) @dinsa The abstract type Root_Stream_Type is the root type of the class of stream types. The types in this class represent different kinds of streams. A new stream type is defined by extending the root type (or some other stream type), overriding the Read and Write operations, and optionally defining additional primitive subprograms, according to the requirements of the particular kind of stream. The predefined stream-oriented attributes like T'Read and T'Write make dispatching calls on the Read and Write procedures of the Root_Stream_Type. (User-defined T'Read and T'Write attributes can also make such calls, or can call the Read and Write attributes of other types.) @dinst The library package Ada.Streams has the following definition: !corrigendum 13.13.1(9) @dinsa The Write operation appends Item to the specified stream. @dinss In addition, three packages provide stream implementations which do not make use of any file operations. These three packages provide the same operations, with Streams.FIFO_Streams providing an abstract interface, and two child packages providing implementations of that interface. The difference is that for Streams.FIFO_Streams.Bounded, the maximum storage is bounded. The library package Ada.Streams.FIFO_Streams has the following definition: @xcode<@b Ada.Streams.FIFO_Streams @b Pure, Nonblocking @b> @xcode< @b FIFO_Stream @b Root_Stream_Type @b;> @xcode< @b Element_Count (Stream : FIFO_Stream) @b Stream_Element_Count @b;> @xcode< @b Clear (Stream : @b FIFO_Stream) @b;> @xcode<@b ... -- @ft<@i> @b Ada.Streams.FIFO_Streams;> The library package Ada.Streams.FIFO_Streams.Unbounded has the following definition: @xcode<@b Ada.Streams.FIFO_Streams.Unbounded @b Prelaborated, Nonblocking @b> @xcode< @b Stream_Type @b FIFO_Stream @b @b Default_Initial_Condition =@> Element_Count (Stream_Type) = 0;> @xcode< @b @b Read ( Stream : @b Stream_Type; Item : @b Stream_Element_Array; Last : @b Stream_Element_Offset) @b Post =@> (@b Num_Read : @b Stream_Element_Count := Stream_Element_Count'Min (Element_Count(Stream)'Old, Item'Length); @b Last = Num_Read + Item'First - 1 @b Element_Count (Stream) = Element_Count (Stream)'Old - Num_Read);> @xcode< @b @b Write ( Stream : @b Stream_Type; Item : @b Stream_Element_Array) @b Post =@> Element_Count (Stream) = Element_Count (Stream)'Old + Item'Length;> @xcode< @b @b Element_Count (Stream : Stream_Type) @b Stream_Element_Count;> @xcode< @b @b Clear (Stream : @b Stream_Type) @b Post =@> Element_Count (Stream) = 0;> @xcode<@b ... -- @ft<@i> @b Ada.Streams.FIFO_Streams.Unbounded;> The library package Ada.Streams.FIFO_Streams.Bounded has the following definition: @xcode<@b Ada.Streams.FIFO_Streams.Bounded @b Pure, Nonblocking @b> @xcode< @b Stream_Type (Max_Elements : Stream_Element_Count) @b FIFO_Stream @b @b Default_Initial_Condition =@> Element_Count (Stream_Type) = 0;> @xcode< @b @b Read ( Stream : @b Stream_Type; Item : @b Stream_Element_Array; Last : @b Stream_Element_Offset) @b Post =@> (@b Num_Read : @b Stream_Element_Count := Stream_Element_Count'Min (Element_Count(Stream)'Old, Item'Length); @b Last = Num_Read + Item'First - 1 @b Element_Count (Stream) = Element_Count (Stream)'Old - Num_Read);> @xcode< @b @b Write ( Stream : @b Stream_Type; Item : @b Stream_Element_Array) @b Pre =@> Element_Count (Stream) + Item'Length <= Stream.Max_Elements @b (@b Constraint_Error), Post =@> Element_Count (Stream) = Element_Count (Stream)'Old + Item'Length;> @xcode< @b @b Element_Count (Stream : Stream_Type) @b Stream_Element_Count @b Post =@> Element_Count'Result <= Stream.Max_Elements;> @xcode< @b @b Clear (Stream : @b Stream_Type) @b Post =@> Element_Count (Stream) = 0;> @xcode<@b ... -- @ft<@i> @b Ada.Streams.FIFO_Streams.Bounded;> The Element_Count functions return the number of stream elements that are available for reading from the given stream. The Read and Write procedures behave as described for package Ada.Streams above. Stream elements are read in FIFO (first-in, first-out) order; stream elements are available for reading immediately after they are written. The Clear procedures remove any available stream elements from the given stream. !corrigendum 13.13.1(9.1/1) @dinsa If Stream_Element'Size is not a multiple of System.Storage_Unit, then the components of Stream_Element_Array need not be aliased. @dinst @s8<@i> Streams.FIFO_Streams.Bounded.Stream_Type objects should be implemented without implicit pointers or dynamic allocation. !ASIS No changed needed. !ACATS test ACATS C-Tests are needed to check that the new packages are supported. !appendix From: Steve Baird Sent: Friday, October 5, 2018 5:02 PM The attached is a new version of this AI, incorporating the feedback from the Lisbon meeting. It is actually 2 AIs (one of them hasn't been assigned a number yet) because part of that Lisbon feedback was the suggestion that the AI should be split into two parts. The other AI just defines some new predefined units, Ada.Streams.FIFO_Streams and a couple of child units thereof. [This is version /01 of that split AI - Editor.] As usual, thanks to Randy for some helpful preliminary review. Also as usual, don't blame him for any flaws. **************************************************************** From: Randy Brukardt Sent: Tuesday, December 4, 2018 11:52 PM For the record: I've made various editorial changes to this AI based on conversation with Tucker. To summarize: (1) We usually start package definitions with "The library package Blah.Blah has the following definition:" This clause defines Ada.Streams and it doesn't include those words or any alternative (the RM does use several other wordings, in particular that the package "exists"; this one seems more formal). So, fix that for all four of these packages (including the original one): Add after 13.13.1(1): The library package Ada.Streams has the following definition: And introduce each new package separately: The library package Ada.Streams.FIFO_Streams has the following definition: The library package Ada.Streams.FIFO_Streams.Unbounded has the following definition: The library package Ada.Streams.FIFO_Streams.Bounded has the following definition: (2) The description of the difference between the Unbounded and Bounded packages is found in a comment (see next item). That's weird; we usually use introductory text for that. So the introductory text for these units should discuss the differences between them. In addition, three packages provide stream implementations which do not make use of any file operations. These three packages provide the same operations, with Streams.FIFO_Streams providing an abstract interface, and two child packages providing implementations of that interface. The difference is that for Streams.FIFO_Streams.Bounded, the maximum storage is bounded. (3) The large comment at the start of Ada.Streams.FIFO_Streams.Bounded is unnecessary. The part about the difference is covered above, and the part about not allowing dynamic allocation is given as Implementation Advice. Thus it is deleted. (4) I noted that one of the comments in the Post condition as provided by Tucker was in the wrong place (the first comment belongs to the declaration expression). Tucker replied that he thought that these comments belong in AARM notes, so I moved them there. (5) "is" typically is on the same line as the aspects for a package, assuming those aspects are short (which is the case for Boolean aspects like Pure and Nonblocking). **************************************************************** From: Randy Brukardt Sent: Wednesday, December 5, 2018 1:01 AM Got one more: (6) "The Read and Write procedures behave as described in section 13.13.1." But we put these packages into 13.13.1! This could be interpreted as a recursive reference. It would be better to say "The Read and Write procedures behave as described for package Ada.Streams above." P.S. It's not a "section", it’s a "subclause". Grumble. ****************************************************************