How do I create my own ostream/streambuf?
Asked Answered
C

3

25

For educational purposes I want to create a ostream and stream buffer to do:

  1. fix endians when doing << myVar;
  2. store in a deque container instead of using std:cout or writing to a file
  3. log extra data, such as how many times I did <<, how many times I did .write, the amount of bytes I written and how many times I flush(). But I do not need all the info.

I tried overloading but failed horribly. I tried overloading write by doing

ostream& write( const char* s, streamsize n ) 

in my basic_stringstream2 class (I copied paste basic_stringstream into my cpp file and modified it) but the code kept using basic_ostream. I looked through code and it looks like I need to overload xsputn (which isn't mention on this page http://www.cplusplus.com/reference/iostream/ostream ) but what else do I need to overload? and how do I construct my class (what does it need to inherit, etc)?

Commentative answered 7/2, 2009 at 21:45 Comment(1)
Could you please provide an excerpt of the code that "kept using basic_ostream"?Basswood
V
27

The canonical approach consists in defining your own streambuf. You should have a look at:

Venipuncture answered 9/2, 2009 at 15:39 Comment(0)
B
7

For A+C) I think you should look at facets, they modify how objects are written as characters. You could store statistics here as well on how many times you streamed your objects. Check out How to format my own objects when using STL streams? for an example.

For B) You need to create your own streambuf and connect your ostream to that buffer (constructor argument). See Luc's links + Deriving new streambuf classes. In short you need to implement this for an ostream (minimum):

  • overflow (put a single char or flush buffer) (link)
  • xsputn (put a char array to buffer)(link)
  • sync (link)
Bibliofilm answered 28/8, 2009 at 7:7 Comment(1)
Most of the links in this are now dangling.Borneol
E
1

I'm not sure that what you want to do is possible. The << operators are not virtual. So you could define yourstream &operator << (yourstream &strm, int i) to do what you want with the endian conversion and counting, and it will work when your code calls it directly. But if you pass a yourstream object into a function that expects an ostream, any time that function calls <<, it will go to the original ostream version instead of yours.

As I understand it, the streams facilities have been set up so that you can "easily" define a new stream type which uses a different sort of buffer (like, say, a deque of chars), and you can very easily add support for outputting your own classes via <<. I don't think you are intended to be able to redefine the middle layer between those.

And particularly, the entire point of the << interface is to provide nicely formatted text output, while it sounds like you actually want binary output. (Otherwise the reference to "endian" makes no sense.) Even assuming there is some way of doing this I don't know, it will produce awkward binary output at best. For instance, consider the end user overload to output a point in 3D space. The end user version of << will probably do something like << '(' << x << ", " << y << ", " << z << ')'. That will look nice in a text stream, but it's a lot of wasted and completely useless characters in a binary stream, which would ideally just use << x << y << z. (And how many calls to << should those count as?)

Elin answered 9/2, 2009 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.