Out of
this GitHub discussion, the idea of output streams -- which has been around already for a longer time -- has been revived.
Basically, the idea is to have a class with the following synopsis, which acts as a counterpart to
sf::InputStream and can be used to save resources to custom destinations -- files, memory buffers, archives, network sockets, ...
class OutputStream
{
virtual ~OutputStream();
// return if successful (or should it be bytes written and -1 on error?)
virtual bool write(const void* data, Int64 size) = 0;
};
Now, Laurent and I have discussed a bit about the semantics of the
write() function. Here's a summary:
We should be consistent with sf::InputStream [i.e. return the bytes written, or -1 on errors].
What would the caller of write() (within SFML) do if not all bytes have been written? Call the function again with the rest of the buffer?
That. For example, we can imagine a buffered stream that rejects data if there's no more room in its internal buffer (concrete example: a stream that wraps a TCP socket).
But that means that every place that calls
OutputStream::write() must be prepared to handle that (or we write some kind of abstraction). And does it make sense to just call the function immediately again, i.e. in a loop? If an output stream fails to process all bytes at once, why would it be able to do so one microsecond later? Or how can the call site meaningfully determine how to react in such cases?
I'm just thinking that if this
bytes written return value exists purely for buffering purposes, it had better be implemented within the concrete `OutputStream` implementation itself, which knows the specific scenario (ideal buffer size, how to handle errors, etc.)
Maybe I'm also just thinking of the wrong use cases