I'd like to provide an std::ostream that may or may not, from the user'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.
Related
I've been using std::ofstream for writing purposes quite a bit. I open the file, do some operations based on certain conditions and close it.
Let's say that later I want to check if anything is really written into the file or not. There is not is_emtpy() kind of simple check available with std::ofstream.
One way I thought is of using the stat way which is independent of std::ofstream.
Wonder how do everyone else do it?
Standard output streams provide a tellp() method which can be used to determine the current write position. The type and meaning of the return value is implementation-defined, but for it to be useful, it must return distinct values.
#include <iostream>
#include <fstream>
int main()
{
std::ofstream out{"/tmp/test"};
auto const empty_pos = out.tellp();
std::clog.setf(std::ios_base::boolalpha);
std::clog << "At start: " << (out.tellp() != empty_pos) << '\n';
out << 'c';
std::clog << "After writing 1 char: " << (out.tellp() != empty_pos) << '\n';
}
In principle, empty_pos may be different for each stream, so a truly portable program will take that into account.
Note also that this doesn't necessarily mean that the output is visible to other programs - use std::flush if that's important.
I have read three ways to print things to the console in c++ from various sources.
Using using namespace std; and then using cout (CodeBlocks Standard)
Not using the above and using std::cout and std::endl; (C++ Primer)
Using printf (HackerRank)
Which is preferred and why?
Number 2 with amendment. (std::cout and '\n')
Why?
Because you should avoid using namespace std. Source
(Among other reasons) Because cout is typesafe and printf is not. Source
std::endl will force a flush of the output buffer to the console. Unless you specifically want this to happen use << '\n' or << "...string\n". Source
Unless you really care about speed, both cout and printf are fine. If you want faster runtimes, here are a few pointers :
Use only printf with no cout. This will give more speed than using a mixture of printf and cout or just cout.
Or use only cout but add the following at the beginning of execution
ios_base::sync_with_stdio(false);cin.tie(NULL); . There are two separate streams for printf and cout and they are synchronized by default. Lot of running time is wasted due to this synchronisation. These two lines of code will stop the synchronisation, but take care that you don't use any printf if you add these lines, otherwise printing might happen in random order.
Do not use endl unless you want to flush the output buffer. Lots of endl can make the code slower. Use cout<<'\n'; instead.
these is my debugger code that during these 10 years of c++ working helped me.
std::ostream &debugRecord (const char* fileName, int lineNum, const char* funcName)
{
std::lock_guard<std::mutex> lock(streamMutex_);
return std::cout << "Thread # " << getCurrentThreadId() << " -- "
<< "(" << fileName << ":" << lineNum << "): " << funcName << std::endl;
}
Both your first points do basically the same thing. It's better practice to use std:: instead of using namespace std; as the latter pollutes the global namespace and can cause naming conflicts.
Something not mentioned is that you can selectively expose parts of a namespace with using <namespace>::<element>; (e.g. using std::cout;). It's still better practice to be verbose with your statements, but this option still isn't as bad as exposing the entire namespace.
printf isn't as safe as cout (the stream << operators do a good job of printing what you want), you ought to avoid it while starting out.
The answer depends a lot on what you want to do. For output which largely uses default formats cout is indeed preferred because of the type safety and because it's very intuitive.
If you want to heavily format your output though I can only recommend the surprisingly versatile and straight-forward printf because manipulators in cout are a pain. True: The printf format syntax, does, let's say, take some getting used to, but it's surely worth it. Just double check the format string, listen to the warnings of your compiler, and use the proper format specifiers e.g. for size_t and other system dependent data in order to stay portable.
There is also a boost facility for combining streams and printf style formatting, see https://stackoverflow.com/a/15106194/3150802, but I have never used it. Perhaps somebody can comment on its usability?
Why does
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::fixed << std::setw(4) << std::setprecision(0);
std::cout << 4;
std::cout << 4;
}
print
" 44
(ignore the quote, it's just to get the formatting right)
and not
" 4 4
?
I thought that the iostream 'modifiers' persistent on the stream until they are explicitly changed/reset. I have a bunch of numbers I need to print with a certain prefix so that all fields have equal width; should I re-apply my modifiers every time I print one? Doesn't seem very efficient.
Unfortunately you've wandered into one of the areas of the standard that's a little archaic and seemingly without any overarching design goals.
This is undoubtedly historic as the iostreams library AFAIAA, was not originally part of the STL which is what became the standard library.
It's worth reading the notes on all std::ios_base members and the associated manipulators.
For example:
http://en.cppreference.com/w/cpp/io/ios_base/width
Some I/O functions call width(0) before returning, see std::setw (this results in this field having effect on the next I/O function only, and not on any subsequent I/O)
The exact effects this modifier has on the input and output vary between the individual I/O functions and are described at each operator<< and operator>> overload page individually.
Anticipating:
But that's just <insert expletive>!!!
A: yup.
I have a piece of code for sending data to remote side, it is acting a little like picojson, for example:
server::value::object obj;
obj["cmd"] = server::value("test");
obj["url"] = server::value(url);
...
obj["code"] = server::value(std::to_string(code));
server::value v(obj);
client.send_to_server(v.process());
As long as there is something to send, there will be a block like this.
These lines are used in so many places in my project that I'm thinking of using a function or << operator to replace it, which should be able to handle variable arguments.
A << operator version would be like:
Data d << "cmd" << "test"
<< "url" << url
<< ... << ...
<< "code" << code;
client.send_to_server(d);
Is this a good idea doing so? How to implement it?
Thanks.
I would write it differently:
d << add_value("cmd", "test")
<< add_value("url", url)
<< add_value(..., ...)
<< add_value("code", code)
;
Why? It's clearer and allows better type control.
So you create a class, say __add_value_temp which holds both the name and the value, a function add_value that creates this class, and write a << operator
Data &operator<<(Data &d, const __add_value_temp &val){
d.add(val.name,val.val);
return d;
}
Better yet - instead of __add_value_temp you can use an std::pair, and use std::make_pair instead of add_value!
Data &operator<<(Data &d, const std::pair<std::string,std::string> &val){
d.add(val.first,val.second);
return d;
}
...
Data d;
d << std::make_pair("cmd", "test")
<< std::make_pair("url", url)
<< std::make_pair(..., ...)
<< std::make_pair("code", code)
;
(last note: might be smart to write the operator<< templated on the types of the pair, so that you can pass things by reference and generally maybe avoid unneeded copying)
Designing an API like that is not a good idea, because it is extremely error-prone.
A seemingly similar idea worked fine with output streams for a simple reason: the data that you put into the stream for output is treated uniformly. Anything that you put into << as an argument becomes part of the output, apart from stream manipulators, which control how the output is to be presented.
Your API is different: odd items are treated differently from the even ones. Moreover, it is a mistake to send an odd total number of operands. If for some reason you forget to put a string code on one of the lines, all values would silently become codes on the subsequent lines. Such API is very fragile, so I would strongly recommend agains it.
I think an API that lets your users add items in pairs would work better. If your compiler is C++11 compliant, you could also use uniform initialization syntax:
Data d = {
{"cmd", server::value("test")}
, {"url", server::value(url)}
, {"code", server::value(std::to_string(code))}
};
I would like to be able write code that looks like this:
int n;
std::string s = "some string";
SomeFunction("hello world" << n << " " << s << std::endl);
Where SomeFunction() is a method of some other class. The point is that I would like to be able to construct input for certain method using operator<<, just the way one'd do when writing to standard output in C++. How can I do that?
Thanks.
Your first parameter would have to be a home-made type that overloads operator<< and builds some kind of parameter list.
Your class would probably contain an ostream and would forward the operator<< to it.
If the function takes a string rather than your mysterious string-building object, you would then need to convert your object back to a string.
You could do it aleady with ostringstream like this:
int n;
std::string s;
std::ostringstream oss;
SomeFunction( ( oss << "hello world " << n << " " << s << '\n' ).str() );
Thanks, but this solution is way too obvious. I am looking for the code to remain the same as in the sample. – Alexander Sandler 54 secs ago
A surprising bias against obvious solutions?
Your syntax just cannot be achieved (in general[1]) without the macro that you describe in the first comment. Period.
[1] In specific cases you might be able to force the issue by overloading to ostream& operator<<(std::string, myspecifictype). In practice this will give you nothing but headaches because just about every use of the << operator will subsequently result in ambiguous overload resolutions