I'd like to provide an std::ostream
that may or may not, from the user'开发者_Python百科s point of view, encrypt its contents.
Imagine some random function that uses an std::ostream&
:
void write_stuff( std::ostream& stream ) {
os << "stuff";
}
Whether stuff
is output in cleartext or is encrypted is dependent on how the stream
argument was initialized.
I'm thinking about inheriting from std::basic_streambuf
, but I'm not sure it's the best way to go. I think the ideal scenario is some sort of filter object which is run before the contents are actually output. That way it'd be easy to chain operations, e.g. encrypting and then hex-encoding, which is a benefit that making my own basic_streambuf
does not seem to give (not easily at least).
Any advices?
Thanks.
UPDATE: I followed the strategy laid out by the accepted answer. I found this article on writing a custom streambuf
which performs XOR obfuscation to be extremely helpful as a starting point.
A streambuf
can be implemented in terms of another arbitrary streambuf
that's either passed in as an argument to the constructor or set with a special member function. And that allows you to stack streambuf
implementations like you were thinking of.
You could even make a manipulator that uses the ostream
's rdbuf
function to get the current streambuf
, call a function on your streambuf
that sets the 'stacked' streambuf
, and then calls rdbuf
again to replace the ostream
's streambuf
with your own.
aes_ctr_streambuf encrypter(key);
zlib_streambuf compressor;
::std::cout << stack_streambuf(encrypter) << stack_streambuf(compressor);
It is hard to describe in short what you have to do in order to create an I/O stream for the new source or sink. Luckily, Jonathan Turkanis and CodeRage, LLC have created very nice building blocks with exceptional documentation that can help you save hundreds of hours of research and development of new streams. The library is called Boost.Iostreams.
The second example in documentation exactly shows how to solve your problem.
Also, note that they already have an output stream with zip compression. So maybe you don't even need to write a single line of code.
Good luck!
I'm not sure that what I'm about to suggest is exactly what you need (and its too complicated to be a comment), but have you ever heard of the stream manipulators ?
#include <iostream>
#include <iomanip>
int main(int, char**)
{
int a = 10;
std::cout << "a: " << a << std::endl; //outputs: "a: 10"
std::cout << "a: " << std::hex << a << std::endl; //outputs: "a: a"
std::cout << "a: " << std::dec << a << std::endl; //outputs: "a: 10"
return EXIT_SUCCESS;
}
You may indeed use a similar pattern (this matches what you actually call a "filter" object) to somehow change the state of your custom stream object.
精彩评论