Reputation:
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.
Upvotes: 3
Views: 2829
Reputation: 283733
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.
Upvotes: 4
Reputation: 62333
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.
Upvotes: 0
Reputation: 76720
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).
Upvotes: 0