C++ question, inheritance and fstreams

Started by
7 comments, last by Bregma 18 years, 1 month ago
Hi all, ok, this is something thought I could figure out easily, by looking at the header files, but I have not seen it: I wish to overload the function(s) responsible for the actual reading or writing within an fstream (be it iofstream, ifstream or ofstream) ... the main motivation is that I wish to use some of the C++ nice stuff of it's iostream library but with compressed files... I found a nice libary to read all sorts of archived files (i.e. zip, .wad, .pak, ect) and I wanted to write a quick "fstream" wrapper for it by deriving a class off of ifstream, ect that would use this nice library I found for the real reading and writing. Best Regards -kRogue
Close this Gamedev account, I have outgrown Gamedev.
Advertisement
streams do no reading or writing; they are only concerned with formatting the output and parsing a formatted input. The actual I/O happens at the streambuf level. You should therefore create a custom streambuf class, and then a shallow i/ostream-derived wrapper over it if you don't wish to manually assign streambufs to streams.

A word of warning, however; extending streambuf is not for the faint of heart, as the protected interface is rather... draconian. Also, good information on it is not exactly abundant on the Web.
no kidding,

doing some googling got me this:

[link] http://www.tacc.utexas.edu/services/userguides/pgi/pgC++_lib/stdlibug/cre_2288.htm
[/link]

which basicly said the exact same thing: play with the streambuf, but it is so, well as you say draconian, actually to me it it jsut plain, plain terrible and awful... as the creation of the streambuf happens so early on too.....

perhaps I jsut remove the small amount of code that I wrote that uses the fstream stuff.... think on it tommorrow...
Close this Gamedev account, I have outgrown Gamedev.
An easy way to create custom stream classes is to use the boost::iostreams classes.

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Hmm to Boost or not to boost? that is the question.. admittedly it makes it much easier since I would just do the pseudo code:

class myWackoSource
{
public:
typedef char char_type;
struct myWakcoSourceCategory
: seekable,
source_tag {}

typedef myWakcoSourceCategory category;

std::streamsize read(char* s, std::streamsize n)
{
// Read up to n characters from the underlying data source
// into the buffer s, returning the number of characters
// read; return -1 to indicate EOF
return (m_handle!=NULL)?NiceLibraryReadBytes(m_handle,s,n):-1;
}

stream_offset seek(stream_offset off, std::ios_base::seekdir way)
{
return (m_handle!=NULL)?NiceLibrarySeek( (int)off, way);
}

/* Other members */
myWackoSource(arguments) { m_handle=NiceLibraryCreateHandle(arguments); }
private:
handleFromNiceLibrary *m_handle;
};

and then I would just do this:

boost::iostreams::stream<myWackoSource> myFellow(arguments)

or just do:
boost::iostreams::stream_buffer<myWackoSource > buf(arguments);
std::istream realDeal(&buf);

on the other hand,

I could make my own streambuf class, lets call it myWackoStreamBuffClass, which I need to write the routines:

imbue: Imbue locale [virtual]
overflow: Put character at current position [virtual]
pbackfail: Put character back [virtual]
seekoff: Set relative position of internal position pointer [virtual]
seekpos: Set absolute position of internal position pointer [virtual]
setbuf: Set buffer [virtual]
showmanyc: Get number of characters availbale in input sequence [virtual]
sync: Synchronize stream buffer [virtual]
uflow: Get current character [virtual]
underflow: Get current character [virtual]
xsgetn: Get some characters [virtual]
xsputn: Write some characters [virtual]

then rather than deriving off of iostream

I would jsut do this: where type is i,o or io

[type]stream myStream;
myWackoStreamBuffClass myBuffer(arguments);
std::istream realDeal(&arguments)



and then call it a day... or just derived from [type]stream and do this in the contructor....

anyone have experience with using Boost? I am planning on making (what I am making) opensource to be distrubuted via sources, so if I use boost, then I'd have to add that to the source mess I distribute... don't know if I really want to do that as well, it would complicate matters even more (on top of the libraries I am using, SDL, SDL_image, physfs, SDL_mixer and SDL_sound)

[edited, as I read more on the boost library]

-kRogue


[Edited by - kRogue on March 6, 2006 2:37:06 AM]
Close this Gamedev account, I have outgrown Gamedev.
Quote:Original post by kRogue
Hmm to Boost or not to boost? that is the question..

For me, it's allways been a resounding yes. Boost rocks. It's only what, ~10MB? I don't consider any C++ development environment complete without it.
actually, i was wondering the same thing, i want to handle the fileio operations for my virtual file system, but i'd like to use fstreams so if my virtual file system library is removed it would still work.

im looking in 'class basic_ifstream'
and there is this:
typedef basic_filebuf<_Elem, _Traits> _Myfb; which looks like what i want to customize.

Not sure about how to do this :-/ my initial idea was to re-write all the file streams that extend from basic_istream.

Another major concern is if i do this, will my code work with different version of STL.
Quote:Original post by Fruny
An easy way to create custom stream classes is to use the boost::iostreams classes.


Another vote for this, it forms the backbone of GTL and is fantasically portable (one recompile later and it was working on the ARM9 processor of the GP2x!)

You said about the source mess you plan to distro I would say, dont worry about distroing Boost, just make a note of the dependancy and let them use their own local copy of it, which could be more up to date than your copy.
Quote:Original post by supagu
actually, i was wondering the same thing, i want to handle the fileio operations for my virtual file system, but i'd like to use fstreams so if my virtual file system library is removed it would still work.

im looking in 'class basic_ifstream'
and there is this:
typedef basic_filebuf<_Elem, _Traits> _Myfb; which looks like what i want to customize.

Not sure about how to do this :-/ my initial idea was to re-write all the file streams that extend from basic_istream.

Another major concern is if i do this, will my code work with different version of STL.


Um, yeah, well, the whole point of the 'standard' in the name 'standard library' is that if you write to the decade-old standard, it'l work on any implementation. IOStreams are not a part of the STL but they are a partof the standard library.

Here's my suggestion.

(1) Write your own stream buffer class by deriving from std::streambuf. The default operations of the std::basic_streambuf all do something sensible, so I would suggest starting with unbuffered output and leaving the rest alone.

(2) Implement your own overflow() member function. Just that function, nothing else.

(3) Grab std:cout and replace it's streambuf with your own (read up on the use of the rdbuf() member function).

(4) Get that working, then look at implemnting the unbuffered input fuctions.

(5) Get those working, look at implementing buffering.

(6) You're done. Go read <a href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201183951&rl=1>Langer and Kreft.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement