views:

54

answers:

4

I work on an open source portable C++ image compression library. Currently, my API works by exchanging pointers to byte arrays with image data. I would like to support some kind of streaming mode for better performance and memory consumption.

For this, I would like to know if there is an interface or abstract base class (part of the C++ standard libraries) that I can use as an interface to a stream of input bytes, similar to Java's InputStream, or C# Stream. It could be as simple as this:

 class inputstream 
 {
      public:
      virtual void readbytes(char*, size_t count) = 0;
 };

I could define an interface like this myself, but then I require everybody to implement some kind of adapter to interface to my code, and my flavor of IO error handling, and I would like to avoid that.

Ideally this interface or base class would be already implemented by some existing C++ standard libraries for reading files. If it is not a base class, it should be totally abstract so my users can connect to whatever bytestream they have (platform specific, socket, whatever). I have browsed around in iostream but found nothing that fits the bill. It should be as light weight as possible: Error handling should be defined, but there's no need for seeking the stream.

If there is no such thing (which I fear), is there something like an existing best practice? Like a function pointer with a standard signature, and a contract for error handling? If there are creative solutions that would work in C as well, I am also interested.

Edit: the key thing is that base class's read() method(s) are virtual.

A: 

Look at stringstream. It does what you need

Jay
A: 

You can use the plain std::ifstream, which is nothing more than a "stream of bytes". Byte extraction is by default byte per byte, and can be used in a kazillion number of different ways:

#include <fstream>
    using std::ifstream;

int main()
{
    ifstream stream;
    stream.open("example.jpg", ifstream::binary ); // open raw binary stream
    if( !stream ) // check if stream is ready to be read
        throw runtime_error( "Failed to open file..." );

    char byteBuffer;

    while( stream >> byteBuffer ) // read all bytes until read/extraction fails
    {
        // do something with the byte
    }
    stream.close();

    return 0;
}

I hope this helps. I understand not every platform has a byte-size char, but I'm sure there's some trick that allows you to use a byte-element iostream object (default is char or wchar_t for the wide classes).

rubenvb
The issue is that the read() method on std::ifstream and std::fstream are not virtual. At least not in my implementation (VC++), nor have I found documentation that these methods should be virtual. In my scenario, my client code needs to be able to override this.
jdv
Then use composition: make a stream member that you access through your own class interface (that can be virtual if you want). Why would the read function need to be changed? A std::fstream provides pretty much anything one could want. Wrapper functions are easily written I think.
rubenvb
How do you use an `fstream` to read data that's in memory or coming in through a network connection rather than on disk?
Ben Voigt
A: 

std::fstream sounds like it fits the bill, despite your feeling of its lack of appropriateness, perfectly to me. Sure it has a seek but its not exactly heavy code.

Goz
The issue is that the read() method on std::ifstream and std::fstream are not virtual. At least not in my implementation (VC++), nor have I found documentation that these methods should be virtual. In my scenario, my client code needs to be able to override this.
jdv
+1  A: 

If your library accepts a std::istream then it will work with files, memory buffers, and user-defined streams.

Your source of confusion seems to be that istream doesn't have any virtual members to override and customize. This is because istream delegates all customizable functionality to std::streambuf, which is where you'll find the virtual members.

If you wanted to expose the compression results as a stream, you'd want to derive from streambuf. Conversely, you could accept an istream to read from and an ostream to store compressed results into.

By accepting an istream, your client can supply an istream constructed on any streambuf, either the library provided stringbuf or filebuf or a custom version.

Since you don't want to work with textual data but byte streams, perhaps using the streambuf directly would be better than using istream to wrap it.

Ben Voigt
Aaaaah. So that's the missing piece in the puzzle. Thanks a lot.
jdv