|
From: Maciej Sobczak on 21 Nov 2006 10:11 Hi, In C++ the IOStreams library allows to vary the behaviour of the stream by decoupling formatting from data buffering and transport to the physical device, which are in turn strategies for the stream object. This means that having millions of functions like this: void foo(ostream &s) { s << "Hello"; s << someObject; s << someOtherObject; // ... } (and *there are* millions of functions like this) it is possible to reuse these functions with different stream objects, from standard console output: foo(cout); ....to file output: foo(myFile); ....to network socket output: foo(someSocketStreamConnectedSomewhere); ....to whatever else comes up to the programmer's mind. It's just the matter of providing the implementation for the stream buffer. The key point here is that the mass of code out there need not be aware of it and can be reused with new stream objects without any modifications (that's OO in action). I'm looking for something like this in Ada. The basic I/O facilities in the standard library don't seem to provide anything like this. I hoped that Ada.Streams allows this by subclassing Root_Stream_Type and providing some overriding operations, but unfortunately I cannot even find the specification of Root_Stream_Type (looks like there isn't any and this type is just a name placeholder in ARM). If the standard library does not provide the functionality that I'm looking for (and I hope that I'm still misunderstanding something here), did anybody tackle the problem by implementing some replacement IO library with the functionality similar to that of IOStreams in C++? -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/
From: gautier_niouzes on 21 Nov 2006 10:28 Perhaps you are looking for something like Unzip.Streams (here, a custom input stream) ? You can browse from... http://homepage.sunrise.ch/mysunrise/gdm/uza_html/teunzstr__adb.htm HTH, Gautier
From: Alex R. Mosteo on 21 Nov 2006 12:51 Maciej Sobczak wrote: > Hi, > > In C++ the IOStreams library allows to vary the behaviour of the stream > by decoupling formatting from data buffering and transport to the > physical device, which are in turn strategies for the stream object. > This means that having millions of functions like this: > > void foo(ostream &s) > { > s << "Hello"; > s << someObject; > s << someOtherObject; > // ... > } > > (and *there are* millions of functions like this) > > it is possible to reuse these functions with different stream objects, > from standard console output: > > foo(cout); > > ...to file output: > > foo(myFile); > > ...to network socket output: > > foo(someSocketStreamConnectedSomewhere); > > ...to whatever else comes up to the programmer's mind. It's just the > matter of providing the implementation for the stream buffer. > The key point here is that the mass of code out there need not be aware > of it and can be reused with new stream objects without any > modifications (that's OO in action). > > I'm looking for something like this in Ada. > > The basic I/O facilities in the standard library don't seem to provide > anything like this. > I hoped that Ada.Streams allows this by subclassing Root_Stream_Type and > providing some overriding operations, but unfortunately I cannot even > find the specification of Root_Stream_Type (looks like there isn't any > and this type is just a name placeholder in ARM). I think you haven't looked right. That's precisely how it's done. I have chainable streams for compression, buffering, file I/O, memory streaming, etc. And you do this just as you say: you extend Ada.Streams.Root_Stream_Type and provide the read/write subprograms. Then, you can dispatch on these or use the 'Input/'Output attributes of any type. Conversely, you can override these to provide your own stream representation of any type. (I mention calling the subprograms directly instead of the 'attributes because for some array types it's much more efficient -- at least it was with GNAT 3.15p. But, usually, you just want to use the attributes). Maybe is a compiler matter. In GNAT you can inspect the specification, but if this is done by compiler magic in your case, still you should be able to override the Read/Write subprograms in your derived stream type. The package spec is in the RM05 13.13.1. > If the standard library does not provide the functionality that I'm > looking for (and I hope that I'm still misunderstanding something here), > did anybody tackle the problem by implementing some replacement IO > library with the functionality similar to that of IOStreams in C++? If you're using GPS, go to Help -> GNAT runtime -> Ada -> Streams. You have there the spec of Root_Stream_Type. Ada 2005 adds new features for some kind of magic needed when inputting types from an stream. I have had no need for this, but you may be as well interested. It's all in the Barnes' rationale articles.
From: Dmitry A. Kazakov on 21 Nov 2006 14:02 On Tue, 21 Nov 2006 16:11:02 +0100, Maciej Sobczak wrote: > In C++ the IOStreams library allows to vary the behaviour of the stream > by decoupling formatting from data buffering and transport to the > physical device, which are in turn strategies for the stream object. > This means that having millions of functions like this: > > void foo(ostream &s) > { > s << "Hello"; > s << someObject; > s << someOtherObject; > // ... > } > > (and *there are* millions of functions like this) Alas, because it is a poor design based on ad-hoc polymorphism. All these millions are overloaded. They should be overridden, but that were impossible due to lack of multiple dispatch. > I'm looking for something like this in Ada. In Ada it is exactly same. Consider: Put (S : in out My_Root_Stream; X : String); Put (S : in out My_Root_Stream; X : SomeObject); ... An alternative design (still non-MD) is: Put (S : in out Root_Stream'Class; X : String); Put (S : in out Root_Stream'Class; X : SomeObject); ... This achieves what you want. You can implement I/O on an object type like String using some common class-wide functionality of streams and then re-use it over all possible streams. > The basic I/O facilities in the standard library don't seem to provide > anything like this. > I hoped that Ada.Streams allows this by subclassing Root_Stream_Type and > providing some overriding operations, but unfortunately I cannot even > find the specification of Root_Stream_Type (looks like there isn't any > and this type is just a name placeholder in ARM). As I said it is basically same. But Ada also offers a sort of hard-wired double dispatch through S'Read/Write, S'Input/Output attributes. See ARM 13.13.2. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
From: Maciej Sobczak on 22 Nov 2006 04:16 Alex R. Mosteo wrote: >> I'm looking for something like this in Ada. >> >> The basic I/O facilities in the standard library don't seem to provide >> anything like this. >> I hoped that Ada.Streams allows this by subclassing Root_Stream_Type and >> providing some overriding operations, but unfortunately I cannot even >> find the specification of Root_Stream_Type (looks like there isn't any >> and this type is just a name placeholder in ARM). > > I think you haven't looked right. Indeed - it's in 13.13.1. > That's precisely how it's done. > And you do this just as you say: you extend > Ada.Streams.Root_Stream_Type and provide the read/write subprograms. And I actually managed to do this. Consider the following example of custom stream that for the sake of presentation is bound to standard IO and just converts characters to uppercase when writing (the point is that if I can do *this*, I can do anything else): -- file my_streams.ads: with Ada.Streams; package My_Streams is use Ada.Streams; type My_Stream is new Root_Stream_Type with null record; procedure Read(Stream : in out My_Stream; Item : out Stream_Element_Array; Last : out Stream_Element_Offset); procedure Write(Stream : in out My_Stream; Item : in Stream_Element_Array); end My_Streams; -- file my_streams.adb: with Ada.Text_IO.Text_Streams; with Ada.Characters.Handling; package body My_Streams is use Ada.Text_IO; use Ada.Text_IO.Text_Streams; Std_Stream : Stream_Access := Stream(Current_Output); procedure Read(Stream : in out My_Stream; Item : out Stream_Element_Array; Last : out Stream_Element_Offset) is begin -- forward to standard streams: Read(Std_Stream.all, Item, Last); end Read; procedure Write(Stream : in out My_Stream; Item : in Stream_Element_Array) is Item_Uppercase : Stream_Element_Array := Item; C : Character; begin for I in Item_Uppercase'Range loop C := Character'Val(Item_Uppercase(I)); C := Ada.Characters.Handling.To_Upper(C); Item_Uppercase(I) := Stream_Element(Character'Pos(C)); end loop; -- forward to standard streams: Write(Std_Stream.all, Item_Uppercase); end Write; end My_Streams; -- file hello.adb: with Ada.Text_IO.Text_Streams; with My_Streams; procedure Hello is use Ada.Text_IO; use Ada.Text_IO.Text_Streams; use My_Streams; procedure Write_Hello(Stream : in out Stream_Access) is begin String'Write(Stream, "Hello"); end Write_Hello; S1 : Stream_Access := Stream(Current_Output); S2 : Stream_Access := new My_Stream; begin Write_Hello(S1); New_Line; Write_Hello(S2); New_Line; end Hello; The result is: $ ./hello Hello HELLO $ The point here is that the Write_Hello procedure can be reused with various streams, just like my foo functions in C++ (from initial post). Is the code above correct? Any traps or problems that I don't see at the moment? -- Maciej Sobczak : http://www.msobczak.com/ Programming : http://www.msobczak.com/prog/
|
Next
|
Last
Pages: 1 2 3 Prev: How to use associative arrays in Ada 2005? Next: Get_Line problem (GNAT bug?) |