* Ada.Streams examples @ 1999-03-10 0:00 Tom Moran 1999-03-10 0:00 ` dennison 1999-03-10 0:00 ` Steve Quinlan 0 siblings, 2 replies; 16+ messages in thread From: Tom Moran @ 1999-03-10 0:00 UTC (permalink / raw) Could someone please point me to a text or tutorial or something on using Ada.Streams - in particular overriding the default 'Read etc. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 Ada.Streams examples Tom Moran @ 1999-03-10 0:00 ` dennison 1999-03-10 0:00 ` Tom Moran 1999-03-10 0:00 ` Rex Reges 1999-03-10 0:00 ` Steve Quinlan 1 sibling, 2 replies; 16+ messages in thread From: dennison @ 1999-03-10 0:00 UTC (permalink / raw) In article <36e61db4.50430543@news.pacbell.net>, tmoran@bix.com (Tom Moran) wrote: > Could someone please point me to a text or tutorial or something on > using Ada.Streams - in particular overriding the default 'Read etc. > Cohen's latest edition of Ada as a Second Language goes over it. Basicly, you just declare a read routine with the following spec: procedure Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Instance ); where "Instance" is your type, in the same package spec that the type ("Instance in the above case) is declared. Then, after the full declaration of the type you put the following line: for Instance'Read use Read; For the body of Read, you can call the 'Read method for the relevant field types yourself. Another option is to read in a properly sized Ada.Streams.Stream_Element_Array using the stream's Read method then use Unchecked_Conversion to convert the array type(s) you need. For instance: Bytes_Per_Element : constant := (Ada.Streams.Stream_Element'Size + 7) / 8; Bytes_Per_Instance : constant Natural := (Instance'Size + 7) / 8; Elements_Per_Header : constant Ada.Streams.Stream_Element_Offset := Ada.Streams.Stream_Element_Offset( (Bytes_Per_Instance + (Bytes_Per_Element - 1)) / Bytes_Per_Element); subtype Header_Array is Ada.Streams.Stream_Element_Array (1 .. Elements_Per_Header); function To_Instance is new Unchecked_Conversion (Source => Header_Array, Target => Instance); procedure Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Instance ) is Trash : Ada.Streams.Stream_Element_Offset; Item_Elements : Header_Array; begin Ada.Streams.Read (Stream => Stream.all, Item => Item_Elements, Last => Trash ); Item := To_Instance (Item_Elements); end Read; A wise developer would probably check "Trash". But in my case I happen to know (because I wrote them) that the streams used for this call will raise exceptions rather than return a different Last than Item_Elements'Last. If there's anything else you are curious about, just ask. T.E.D. -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 ` dennison @ 1999-03-10 0:00 ` Tom Moran 1999-03-10 0:00 ` dennison 1999-03-11 0:00 ` Richard D Riehle 1999-03-10 0:00 ` Rex Reges 1 sibling, 2 replies; 16+ messages in thread From: Tom Moran @ 1999-03-10 0:00 UTC (permalink / raw) I'll take a look at Cohen (my son took my copy away to college). Barnes example is pretty minimal. I never would have figured this stuff out just from the RM. In addition to my questions, I'd like a good place to send others. I want to do an S'Read routine for a large array. I really don't want to iteratively call Element'Read for each element. Is there an alternative to the usual Unchecked_Conversion, overlaying, etc to get the data into my array? If the array were in a Sequential_IO file I could just do a single Read and the correct number of bytes would be copied to the array - like an implicit Unchecked_Conversion. What exactly is the use of S'Class'Read? If I don't define my own, the default dispatches to appropriate S'Read routines - mine or the default ones. If I do define my own S'Class'Read does that let me do other than dispatching if I want (like other procedures that take a classwide parameter)? Does RM 13.13.2(38) mean that my S'Class'Read will not be called for objects whose class is Son_Of_S? ie, does S'Class only apply "horizontally" to a single generation? The RM implies that an object's stream representation should be similar to its in-memory representation (a generalization from 13.13.2(17)). If I have an object which has a standard external representation (a Windows bmp bitmap, for instance) but a slightly different Ada representation in my program (discriminants, say), is it better to convert the object on Write to the "standard" external form, or to write it out as an Ada object as close as possible to its internal, Ada, memory form? This is not addressed in AQS - anybody have any experience with these choices? ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 ` Tom Moran @ 1999-03-10 0:00 ` dennison 1999-03-10 0:00 ` Tom Moran 1999-03-11 0:00 ` Richard D Riehle 1 sibling, 1 reply; 16+ messages in thread From: dennison @ 1999-03-10 0:00 UTC (permalink / raw) In article <36e6cd2c.3377267@news.pacbell.net>, tmoran@bix.com (Tom Moran) wrote: > I'll take a look at Cohen (my son took my copy away to college). Cool! You must be very proud of him. :-) > I want to do an S'Read routine for a large array. I really don't > want to iteratively call Element'Read for each element. Is there an > alternative to the usual Unchecked_Conversion, overlaying, etc to get > the data into my array? If the array were in a Sequential_IO file I Not that I've discovered. But in this context I don't see anything wrong with Unchecked_Conversion. Converting types is what its there for. > The RM implies that an object's stream representation should be > similar to its in-memory representation (a generalization from > 13.13.2(17)). If I have an object which has a standard external Not only is that just implementation advice, but it also starts with the word "If". > representation (a Windows bmp bitmap, for instance) but a slightly > different Ada representation in my program (discriminants, say), is it > better to convert the object on Write to the "standard" external form, > or to write it out as an Ada object as close as possible to its > internal, Ada, memory form? This is not addressed in AQS - anybody > have any experience with these choices? It depends on what you want to do. If you want to be able to write a bmp to any stream, not just a file, then you should probably put the conversion in the 'Write. If you will always write bmp's to the same type of stream, and never want to put other non-bmp information in those same stream objects, then it might make sense to create your own "bmp stream". If neither really holds, I'd go with the one that seems the better abstraction in your environment. Now lets say you have a screen bitmap stored memory. You want to write this to disk as a BMP file. I see three options: o Create a 'Write procedure for that bitmap type which converts the bitmap to a bmp and does one massive Write call for the stream. The problem with this approach is that if anyone ever wants to do a 'Write on a bitmap for any reason, the'll get a BMP. You can't overload it to get a JPG or GIF or a straight memory dump (which is what they might be expecting). o Create a new stream that converts Write data into GIF format, and saves it to a file. The problem here is that the input data *must* be a bitmap of our specified format, or this stream will produce garbage. There's no real way in the language to enforce this. Also, we can't count on getting all the data in one big Write call. This may be OK for BMP, but for a compressing scheme like GIF it complicates matters. o Create a Write_BMP and Read_BMP routine that take in files and bitmaps as parameters, and forget about streams. Random objects cannot now be placed an a "BMP" file. The strength of streams IMHO is the ability to do I/O on hetrogenious data. In our example I don't think that's a loss, so the last option is probably the way to go. T.E.D. -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 ` dennison @ 1999-03-10 0:00 ` Tom Moran 1999-03-11 0:00 ` dennison 0 siblings, 1 reply; 16+ messages in thread From: Tom Moran @ 1999-03-10 0:00 UTC (permalink / raw) > o Create a 'Write procedure for that bitmap type which converts the bitmap >to a bmp and does one massive Write call for the stream. The problem with >this approach is that if anyone ever wants to do a 'Write on a bitmap for any >reason, the'll get a BMP. You can't overload it to get a JPG or GIF or a >straight memory dump (which is what they might be expecting). Someone could presumably do type GIFED_Bitmap is new BMP with null record; for GIFED_Bitmap'Write use Convert_To_GIF_And_Write; Then internally a GIFED_Bitmap is the same as my BMP, and my routines all work on it, but when the user writes it he gets his Convert_To_GIF_And_Write instead of my BMP'Write. No? > o Create a Write_BMP and Read_BMP routine that take in files and bitmaps as >parameters, and forget about streams. But with the BMP'Write I separate the file from the conversion, so the result of the conversion could be handed to a called C routine, say. That seems to me a pretty strong argument for BMP'Write instead of BMP_Write. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 ` Tom Moran @ 1999-03-11 0:00 ` dennison 1999-03-17 0:00 ` Tom Moran 0 siblings, 1 reply; 16+ messages in thread From: dennison @ 1999-03-11 0:00 UTC (permalink / raw) In article <36e6fe8d.16020474@news.pacbell.net>, tmoran@bix.com (Tom Moran) wrote: > > o Create a 'Write procedure for that bitmap type which converts the bitmap > >to a bmp and does one massive Write call for the stream. The problem with > >this approach is that if anyone ever wants to do a 'Write on a bitmap for any > >reason, the'll get a BMP. You can't overload it to get a JPG or GIF or a > >straight memory dump (which is what they might be expecting). > Someone could presumably do > type GIFED_Bitmap is new BMP with null record; > for GIFED_Bitmap'Write use Convert_To_GIF_And_Write; > Then internally a GIFED_Bitmap is the same as my BMP, and my routines > all work on it, but when the user writes it he gets his > Convert_To_GIF_And_Write instead of my BMP'Write. > No? Well, yes. But those are still different types, not the same type. I can think of several other objections, but they all really boil down to...YUK! > > o Create a Write_BMP and Read_BMP routine that take in files and bitmaps as > >parameters, and forget about streams. > But with the BMP'Write I separate the file from the conversion, so > the result of the conversion could be handed to a called C routine, > say. That seems to me a pretty strong argument for BMP'Write instead > of BMP_Write. That is true. If there are several different sources you might want to route your output to other than just disk files, that is a point in the favor of using 'Write for the conversion. But note that in the case you give the C routine will have to be able to handle the data in the way 'Write will give it. If you write both 'Write and the stream's Write (which internally interfaces to the C) then you should be ok. You still have the problem of some goober comming along and trying to do an Integer'Write to your BMP stream, but perhaps that's not a big deal in your application. T.E.D. -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-11 0:00 ` dennison @ 1999-03-17 0:00 ` Tom Moran 0 siblings, 0 replies; 16+ messages in thread From: Tom Moran @ 1999-03-17 0:00 UTC (permalink / raw) >> Someone could presumably do >> type GIFED_Bitmap is new BMP with null record; >> for GIFED_Bitmap'Write use Convert_To_GIF_And_Write; >> Then internally a GIFED_Bitmap is the same as my BMP, and my routines >> all work on it, but when the user writes it he gets his >> Convert_To_GIF_And_Write instead of my BMP'Write. > I can think of several other objections, but they all really boil down to...YUK! He could certainly write his own Write_As_Gif(X : in BMP) and call it directly. Or I could make an abstract 'Write (or could I?) for BMP and a higher level type External_Form_Is_BMP is new BMP with null record; with a 'Write that generates .bmp, and he could make instead type External_Form_Is_GIF is new BMP with null record; etc. I guess I don't react YUK. A multiplatform GIF image seems to me legitimately a higher abstraction level than a Windows DIBitmap/.bmp file. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 ` Tom Moran 1999-03-10 0:00 ` dennison @ 1999-03-11 0:00 ` Richard D Riehle 1999-03-11 0:00 ` Steve Quinlan 1 sibling, 1 reply; 16+ messages in thread From: Richard D Riehle @ 1999-03-11 0:00 UTC (permalink / raw) There is an interesting example of how to use Streams in the GNAT compiler for Ada.Exceptions. I post a fragment from my book, Object Technology in Ada that steals liberally from the GNAT package. In the package specification for Ada.Exceptions the designer includes a context clause for Ada.Streams. The limited private type Exception_Occurrence has the full definiton as limited record. type Exception_Occurrence (Max_Length : Nat := SSL.Exception_Msg_Max) is limited record Id : Exception_Id; Msg_Length : Natural; Msg : String (1 .. Max_Length); end record; Elsewhere in the private part of the specification, two procedures are declared to provide Read and Write for Exception_Occurrence. It should be noted that 'Input and 'Output cannot be written for a limited private type since assignment is not available. It is possible to write those functions for Exception_Occurrence_Access which is already defined in the Ada.Exceptions package. For this discussion, it should be enough to cover Read and Write. procedure Exception_Occurrence_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Exception_Occurrence); procedure Exception_Occurrence_Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in Exception_Occurrence); for Exception_Occurrence'Read use Exception_Occurrence_Read; for Exception_Occurrence'Write use Exception_Occurrence_Write; Note that Exception_Occurrence is a record. Therfore, it is necessary to create Read and Write operations for it since none currently exist. Also, the creation of Read and Write procedures is not the same as overloading existing subprograms. You create a procedure with a name and the associate it with an attribute of 'Read or 'Write through a representation specification. Implementing code for Execption_Occurrence_Read and Execption_Occurrence_Write looks like this. procedure Exception_Occurrence_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Exception_Occurrence) is Name : String := String'Input(Stream); Len : Natural := Natural'Input(Stream); Msg : String := String'Input(Stream); begin Item.Id := Exception_Id (Internal_Exception (Name)); if Msg'Length /= Len then raise Data_Error; end if; -- Silently truncate message if it does not fit Item.Msg_Length := Natural'Min (Len, Item.Max_Length); Item.Msg (1 .. Item.Msg_Length) := Msg (1 .. Item.Msg_Length); end Exception_Occurrence_Read; The reader should notice that the implementation of the Read operation takes advantage of the "Input attribute already available for Standard types. Now we show the code for implementing the 'Write. It is even easier that the code for the 'Read. procedure Exception_Occurrence_Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in Exception_Occurrence) is begin String'Output (Stream, Exception_Name (Item.Id)); Natural'Output (Stream, Item.Msg_Length); String'Output (Stream, Item.Msg (1 .. Item.Msg_Length)); end Exception_Occurrence_Write; Hope this is helpful, Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-11 0:00 ` Richard D Riehle @ 1999-03-11 0:00 ` Steve Quinlan 1999-03-11 0:00 ` Richard D Riehle 0 siblings, 1 reply; 16+ messages in thread From: Steve Quinlan @ 1999-03-11 0:00 UTC (permalink / raw) Richard D Riehle wrote: > Note that Exception_Occurrence is a record. Therfore, it is necessary to create Read and Write operations for it > since none currently exist. Why would there not be read and write operations available? Those attributes are supported for composite types, aren't they? ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-11 0:00 ` Steve Quinlan @ 1999-03-11 0:00 ` Richard D Riehle 1999-03-11 0:00 ` Steve Quinlan 0 siblings, 1 reply; 16+ messages in thread From: Richard D Riehle @ 1999-03-11 0:00 UTC (permalink / raw) In article <36E7EFCF.82A87270@nospam.lmco.com>, Steve Quinlan <steven.quinlan@nospam.lmco.com> wrote: >Richard D Riehle wrote: > >> Note that Exception_Occurrence is a record. Therfore, it is necessary to create Read and Write operations for it >> since none currently exist. > >Why would there not be read and write operations available? Those attributes are supported for composite types, aren't >they? > Perhaps I should have said, it is possible to override the Read and Write operations so they behave exactly as you want them to. In fact, the procedures Read and Write, in package Ada.Streams, are abstract so they must be overridden. Note: we are not talking of Ada.Streams.Stream_IO. We are talking about the parent package Ada.Streams (LRM 13.13.1). Notice how useful this is in Ada.Exceptions from the GNAT compiler. Richard ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-11 0:00 ` Richard D Riehle @ 1999-03-11 0:00 ` Steve Quinlan 1999-03-12 0:00 ` Richard D Riehle 0 siblings, 1 reply; 16+ messages in thread From: Steve Quinlan @ 1999-03-11 0:00 UTC (permalink / raw) Richard D Riehle wrote: > Perhaps I should have said, it is possible to override the Read and Write > operations so they behave exactly as you want them to. In fact, the > procedures Read and Write, in package Ada.Streams, are abstract so they > must be overridden. Note: we are not talking of Ada.Streams.Stream_IO. > We are talking about the parent package Ada.Streams (LRM 13.13.1). > Notice how useful this is in Ada.Exceptions from the GNAT compiler. > > Richard OK, that's clearer. I understand that when you define a new stream type derived from root_stream_class you have to implement the read and write procedures that override Ada.Streams. But what GNAT did was to override the 'read and 'write attributes. ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-11 0:00 ` Steve Quinlan @ 1999-03-12 0:00 ` Richard D Riehle 0 siblings, 0 replies; 16+ messages in thread From: Richard D Riehle @ 1999-03-12 0:00 UTC (permalink / raw) In article <36E82E5B.6C1B4050@nospam.lmco.com>, Steve Quinlan <steven.quinlan@nospam.lmco.com> wrote: > OK, that's clearer. I understand that when you define a new stream type >derived from root_stream_class you have to implement the read and write >procedures that override Ada.Streams. But what GNAT did was to override the >'read and 'write attributes. That is exactly right. Notice how the overriding was done. First the author coded an procedure specification, procedure Exception_Occurrence_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Exception_Occurrence); The she/he attached that procedure to the 'Read attribute. for Exception_Occurrence'Read use Exception_Occurrence_Read; This means that there is now a special version of 'Read for Exception_Occurrence. This is important because the author wanted 'Read to behave in a very special way. The final code for implementing the procedure looks like this, procedure Exception_Occurrence_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Exception_Occurrence) is Name : String := String'Input(Stream); Len : Natural := Natural'Input(Stream); Msg : String := String'Input(Stream); begin Item.Id := Exception_Id (Internal_Exception (Name)); if Msg'Length /= Len then raise Data_Error; end if; -- Silently truncate message if it does not fit Item.Msg_Length := Natural'Min (Len, Item.Max_Length); Item.Msg (1 .. Item.Msg_Length) := Msg (1 .. Item.Msg_Length); end Exception_Occurrence_Read; This version will behave as one would expect for the data type. This one reason why Ada.Streams is important: so the designer can create well-behaved 'Read and 'Write attributes for composite data types. Imagine, for example, that you wanted a 'Read and 'Write for a full data structure such as a stack. You would certainly want to code your own version of those attributes. It would be a far more complex procedure than the ones we have looked at so far. But it would be possible if you wanted to take the trouble. As another simpler example, we override the abstract Read for a brand new type, with Ada.Streams; package Stream_05 is type My_Stream is tagged record Id : Natural := 0; end record; procedure My_Stream_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out My_Stream); for My_Stream'Read use My_Stream_Read; -- also override Write for a complete implementation end Stream_05; The coding of My_Stream_Read is left as an excercise. You may follow the pattern shown in the Exception_Occurrence example. Now we create a little test program. with Stream_05; -- 1 with Ada.Streams.Stream_IO; -- 2 use Ada; -- 3 procedure Test_Stream_05 is -- 4 The_Stream : Streams.Stream_IO.Stream_Access; -- 5 Data : Stream_05.My_Stream; -- 6 Class_Data : Stream_IO.My_Stream'Class := Data; -- 7 begin -- 8 -- First version for overriding Read -- 9 Data := Stream_05.My_Stream'Input(The_Stream); -- 10 -- Second version of using the Read -- 11 Stream_05.My_Stream'Read(The_Stream, Data); -- 12 -- Third version of using the Read -- 13 Class_Data := Stream_05. -- 14 My_Stream'Class'Input(The_Stream); -- 15 end Test_Stream_05; -- 16 The first version, on line 10, shows how we can use this with the 'Input statement. The version on line 12 shows how we use it with a 'Read statement. The version on lines 14-15 show how to call it with a 'Class'Input. Note that the 'Class'Input version reads the tag and is dispatching. The rules for each type of call are clearly spelled out in ALRM 13.13.2. Congratualtions to whoever wrote that section of the ALRM. They did a good job of explaining the mechanism. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 ` dennison 1999-03-10 0:00 ` Tom Moran @ 1999-03-10 0:00 ` Rex Reges 1999-03-10 0:00 ` dennison 1 sibling, 1 reply; 16+ messages in thread From: Rex Reges @ 1999-03-10 0:00 UTC (permalink / raw) dennison@telepath.com wrote: > In article <36e61db4.50430543@news.pacbell.net>, > tmoran@bix.com (Tom Moran) wrote: > > Could someone please point me to a text or tutorial or something on > > using Ada.Streams - in particular overriding the default 'Read etc. > > > > Cohen's latest edition of Ada as a Second Language goes over it. > > Basicly, you just declare a read routine with the following spec: > > procedure Read > (Stream : access Ada.Streams.Root_Stream_Type'Class; > Item : out Instance > ); > > where "Instance" is your type, in the same package spec that the type > ("Instance in the above case) is declared. Then, after the full declaration > of the type you put the following line: > > for Instance'Read use Read; > > For the body of Read, you can call the 'Read method for the relevant field > types yourself. > > Another option is to read in a properly sized Ada.Streams.Stream_Element_Array > using the stream's Read method then use Unchecked_Conversion to convert the > array type(s) you need. For instance: > > Bytes_Per_Element : constant := (Ada.Streams.Stream_Element'Size + 7) / 8; > Bytes_Per_Instance : constant Natural := (Instance'Size + 7) / 8; > > Elements_Per_Header : constant Ada.Streams.Stream_Element_Offset := > Ada.Streams.Stream_Element_Offset( > (Bytes_Per_Instance + (Bytes_Per_Element - 1)) / Bytes_Per_Element); > subtype Header_Array is Ada.Streams.Stream_Element_Array (1 .. > Elements_Per_Header); > > function To_Instance is new Unchecked_Conversion > (Source => Header_Array, > Target => Instance); > > procedure Read > (Stream : access Ada.Streams.Root_Stream_Type'Class; > Item : out Instance > ) is > > Trash : Ada.Streams.Stream_Element_Offset; > Item_Elements : Header_Array; > begin > > Ada.Streams.Read > (Stream => Stream.all, > Item => Item_Elements, > Last => Trash > ); > > Item := To_Instance (Item_Elements); > > end Read; > > A wise developer would probably check "Trash". But in my case I happen to > know (because I wrote them) that the streams used for this call will raise > exceptions rather than return a different Last than Item_Elements'Last. > > If there's anything else you are curious about, just ask. > > T.E.D. Stream_IO solved the File IO difficulties that were in Ada 83. In Ada 83, the elements put into a file were of some discriminated record. This made it necessary to have a huge structure to define all the possible things that one might want to put in the file. Stream_IO allows one to stuff any number of items of varying type into a file as long as the user keeps track of this information when the file is to be read again. I would like to use Streams to create a similar package to Stream_IO, but write to a memory object. If I have a "storage container", how can I fill it with objects of varying types? How would I use Streams to do this? Say I have container defined as follows: subtype Storage_Container is Streams.Stream_Element_Array ; type Medium_Storage_Container is Storage_Container( 0..511) ; I'ld like to be able to code something like this: Parcel : Medium_Storage_Container ; Parcel_Access : Container_Access ; Parcel_Access := Start_Packing( Container => Parcel ); String'Write ( Parcel_Access, "Dear Sir, The items you ordered." ); Integer'Write( Parcel_Access, 2 ); Gadget'Write ( Parcel_Access, New_Gadget ); Widget'Write ( Parcel_Access, New_Widget ); Stop_Packing( Container => Parcel ); The final step is to hand this Parcel off to a delivery service for shipping. The delivery service doesn't care what's in the parcel, only what the size and destination are. I'm sure it must be easy to code this using Streams, but even with the ARM and the Barnes book, I don't have a clear picture of what I need to do. Rex Reges ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 ` Rex Reges @ 1999-03-10 0:00 ` dennison [not found] ` <36E7036B.EADEEA80@Boeing.com> 0 siblings, 1 reply; 16+ messages in thread From: dennison @ 1999-03-10 0:00 UTC (permalink / raw) In article <36E6C291.F97766CB@Boeing.com>, Rex Reges <Rex.R.Reges@Boeing.com> wrote: > I would like to use Streams to create a similar package to Stream_IO, but write > to a memory object. If I have a "storage container", how can I fill it with > objects of varying types? How would I use Streams to do this? > I can probably give some advice here, as I have just written code to do that. But first, I'll need requirements clarification. IAW: How do you want to use it? Does it need to support concurrent 'Writes from multiple tasks? Does it need to support concurrent 'Writes with 'Reads? Should it act just like a file, where written items start at the first element and continue filling up the available space until it is exhausted? Or should it act like a circular buffer where 'Read's will free up space that may be used for later 'Writes? T.E.D. -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 16+ messages in thread
[parent not found: <36E7036B.EADEEA80@Boeing.com>]
* Re: Ada.Streams examples [not found] ` <36E7036B.EADEEA80@Boeing.com> @ 1999-03-11 0:00 ` dennison 0 siblings, 0 replies; 16+ messages in thread From: dennison @ 1999-03-11 0:00 UTC (permalink / raw) In article <36E7036B.EADEEA80@Boeing.com>, Rex Reges <Rex.R.Reges@Boeing.com> wrote: > A container can be accessed by a single task at a time (only one packer at a > time). However, two or more containers could be in the process of being filled > at the same time, but only one task is allowed to do this work for any one > container. The honor system will be used, so a guard task isn't necessary. > > When the container is filled, then an exception should be raised. The choice > then is to either use two containers or to use a bigger container. Good. You are making things very easy for yourself. I needed something more like a pipe, so it was considerably more difficult for me. All you'd have to do in this case is create a simple buffer (an Ada.Stream.Stream_Element_Array), and keep track of the read and write pointers in the Stream's tagged type. I'd put a pointer to the buffer in the stream type, and add a constructor procedure to allocate the array with a given size and a destructor procedure to deallocate it: private type Buffer_Ptr is access all Ada.Streams.Stream_Element_Array; type Stream is new Ada.Streams.Root_Stream_Type with record Head : Index := 1; Tail : Index := 1; Elements : Buffer_Ptr; end record; All you'd have to do after that is: o override "Write" to copy the given stream elements into the buffer at the write pointer, and update the write pointer. o override "Read" to copy the requested amount of stream elements from the buffer at the read pointer, and update the read pointer. If you wanted to get really sexy, I suppose you could implement "Open" calls to prevent Reads from streams that are opened for Writes and the like. T.E.D. -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: Ada.Streams examples 1999-03-10 0:00 Ada.Streams examples Tom Moran 1999-03-10 0:00 ` dennison @ 1999-03-10 0:00 ` Steve Quinlan 1 sibling, 0 replies; 16+ messages in thread From: Steve Quinlan @ 1999-03-10 0:00 UTC (permalink / raw) Tom Moran wrote: > Could someone please point me to a text or tutorial or something on > using Ada.Streams - in particular overriding the default 'Read etc. If you're asking the mechanics of how to accomplish the override (vs. how to implement it), the general concept is you define a subprogram something like this for type foo; procedure Foo_Write ( Stream access Root_Stream_Type'class; Item in Foo) is --- code here end Foo_Write; for Foo'Write use Foo_Write; As far as what to put into Foo_Write, you can do whatever you like -- implement it using the stream attributes of components of Foo, re-ordering them or adding things or whatever. You could also define your own way to convert Foo into an array of Stream Elements, and update the Stream using the overriden Write procedure from Ada.Streams, which given an array of stream elements will write it to the stream (and similarly for reading Foo). There is a limited example of this in the Barnes book 'Programming in Ada95'. ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~1999-03-17 0:00 UTC | newest] Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1999-03-10 0:00 Ada.Streams examples Tom Moran 1999-03-10 0:00 ` dennison 1999-03-10 0:00 ` Tom Moran 1999-03-10 0:00 ` dennison 1999-03-10 0:00 ` Tom Moran 1999-03-11 0:00 ` dennison 1999-03-17 0:00 ` Tom Moran 1999-03-11 0:00 ` Richard D Riehle 1999-03-11 0:00 ` Steve Quinlan 1999-03-11 0:00 ` Richard D Riehle 1999-03-11 0:00 ` Steve Quinlan 1999-03-12 0:00 ` Richard D Riehle 1999-03-10 0:00 ` Rex Reges 1999-03-10 0:00 ` dennison [not found] ` <36E7036B.EADEEA80@Boeing.com> 1999-03-11 0:00 ` dennison 1999-03-10 0:00 ` Steve Quinlan
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox