RE: [boost] Re: Iostreams Question: Best way to output towin32debugger\outwindow ?

-----Original Message----- On Behalf Of Jonathan Turkanis Sent: Monday, February 28, 2005 3:09 PM
Brian Braatz wrote:
First off THANK YOU Johnathon Turkanis for help with "tee" earlier. That saved me a great amount of pain.
Glad to be of service ;-)
[Brian Braatz Writes:] :)
Below is part of what I am trying to use it with.
My next question is what is the best way to deal with an "output" device having a different cr\lf than another one?
Have you tried to use a newline filter:
http://www.kangaroologic.com/iostreams/libs/iostreams/doc/?path=6.2.2
[Brian Braatz Writes:] I have this sinking feeling this is like when I am standing in front of the fridge and say "Honey, WHERE IS THE MILK?"
?
I'm not familiar with the function OutputDebugString, but you might be able to do this:
struct debug_out_sink : boost::iostreams::sink { void write(const char* s, std::streamsize n) { std::string s(s, n); OutputDebugString(s.c_str()); } };
void Test_Profile() { // Note: library now uses namespace iostreams
using namespace boost::iostreams; filtering_ostream out; std::ofstream log("log.txt"); debug_out_sink dbosink; out.push(tee(log)); out.push(tee(std::cout)); out.push(newline_filter(newline::windows)); out.push(dbosink);
out << "LINE ONE" << endl << "Next line" << endl << "third line" << endl; }
Jonathan
[Brian Braatz Writes:] OutputDebugString() is a win32 function, basically when you build your app and hit the "debug" button in the IDE, it launches your app as a child process. If your app calls OutputDebugString() the text sent is marshaled across the process boundaries back to the parent process (MSVC debugger) and then it puts the string into the "debug window" in the IDE. (I point this out because it is semi-important to note that the process OutputDebugString has to go through is SLOW. I.e. just for reference, you would NOT want to call OutputDebugString() for each char) The problem with above, IF I UNDERSTAND iostreams properly, is that I just want a filter on the debug_out_sink because it needs the \r\n. Everything else needs a \n. Doesn't the above line apply the filter to everything? Do I need to weave in the filter on the debug_out_sink class? (either by "has a" or "is a")? What I am after is the "user" of debug_out_sink can just "push" it in without having to know about \r\n vs \n weirdness.

Brian Braatz wrote:
I have this sinking feeling this is like when I am standing in front of the fridge and say "Honey, WHERE IS THE MILK?"
:-)
I'm not familiar with the function OutputDebugString,
<snip>
OutputDebugString() is a win32 function, basically when you build
<snip>
(I point this out because it is semi-important to note that the process OutputDebugString has to go through is SLOW. I.e. just for reference, you would NOT want to call OutputDebugString() for each char)
Devices are buffered by default, so unless you specify a buffer of size 0 is should be called only when you have written a big chunk of text or when you flush the stream.
The problem with above, IF I UNDERSTAND iostreams properly, is that I just want a filter on the debug_out_sink because it needs the \r\n. Everything else needs a \n.
Only data that flows through the newline filter will be affected, so if you put the newline filter after the tee everything should work in your case.
Do I need to weave in the filter on the debug_out_sink class? (either by "has a" or "is a")?
What I am after is the "user" of debug_out_sink can just "push" it in without having to know about \r\n vs \n weirdness.
More generally, if you want the line-ending conversions built in to debug_out_sink, you could use the class template compose: struct debug_out_sink_impl { /* as before */ }; debug_out_sink : compose<newline_filter, debug_out_sink_impl > { // writes to a debug_out_sink_impl , filteed by a newline_filter }; The only problem is I haven't written compose yet! The reason is that I can't figure out what the constructor arguments should be, since arguments for both components may need to be specified. The only way to merge the line-conversion with the debug_out_sink using existing library components (rather than by hand) is to use the detail class chain, like so: #include <boost/iostreams/detail/chain.hpp> #include <boost/iostreams/filter/newline_filter.hpp> struct debug_out_sink_impl : boost::iostreams::sink { void write(const char* s, std::streamsize n) { std::string str(s, n); OutputDebugStringA(str.c_str()); } }; struct debug_out_sink : boost::iostreams::detail::chain<boost::iostreams::output> { debug_out_sink () { using namespace boost::iostreams; push(newline_filter(newline::windows)); push(debug_out_sink_impl()); } }; I've included a test program at the end, which executes correctly on my machine. The class chain is a detail because I was not sure it would be useful to library users, and by documenting it I would increase the apparent size of the library. If there is no other good way to solve this sort of problem, I'll make chain public. Jonathan ------------------ #include <windows.h> #include <fstream> #include <iostream> #include <boost/iostreams/concepts.hpp> #include <boost/iostreams/detail/chain.hpp> #include <boost/iostreams/filter/newline_filter.hpp> #include <boost/iostreams/filtering_stream.hpp> struct debug_out_sink_impl : boost::iostreams::sink { void write(const char* s, std::streamsize n) { std::string str(s, n); OutputDebugStringA(str.c_str()); } }; struct debug_out_sink : boost::iostreams::detail::chain<boost::iostreams::output> { debug_out_sink () { using namespace boost::iostreams; push(newline_filter(newline::windows)); push(debug_out_sink_impl()); } }; struct tee : boost::iostreams::multichar_output_filter { tee(std::ostream& dest) : dest(dest) { } template<typename Sink> void write(Sink& snk, const char* s, std::streamsize n) { // Write to the downstream Sink boost::iostreams::write(snk, s, n); // Write to the stored ostream: dest.write(s, n); } std::ostream& dest; }; int main() { using namespace std; using namespace boost::iostreams; filtering_ostream out; std::ofstream log("C:/log.txt"); debug_out_sink dbosink; out.push(tee(log)); out.push(tee(std::cout)); out.push(dbosink); out << "LINE ONE" << endl << "Next line" << endl << "third line" << endl; }

Jonathan Turkanis wrote:
The only way to merge the line-conversion with the debug_out_sink using existing library components (rather than by hand) is to use the detail class chain, like so:
Sorry I have to correct myself again: it's not true that the only way is to use detail::chain; one could use filtering_stream or filtering_streambuf, which are wrappers for chain. However, these classes are a little more heavyweight than necessary for this purpose. Jonathan

Okay Brian, The following apparently works, but when OutputDebugString is called I don't see any output. I'm not sure if the previous version worked or not; I've run out of time for now. Jonathan struct debug_out_sink : boost::iostreams::sink { debug_out_sink () { using namespace boost::iostreams; chain_.push(newline_filter(newline::windows)); chain_.push(debug_out_sink_impl()); } void write(const char* s, std::streamsize n) { chain_.write(s, n); } boost::iostreams::detail::chain<boost::iostreams::output> chain_; };

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jonathan Turkanis Sent: Monday, February 28, 2005 6:11 PM To: boost@lists.boost.org Subject: [boost] Re: Re: Iostreams Question: Best way tooutputtowin32debugger\outwindow ?
Okay Brian,
The following apparently works, but when OutputDebugString is called I don't see any output. I'm not sure if the previous version worked or not; I've run out of time for now.
Jonathan
struct debug_out_sink : boost::iostreams::sink { debug_out_sink () { using namespace boost::iostreams; chain_.push(newline_filter(newline::windows)); chain_.push(debug_out_sink_impl()); }
void write(const char* s, std::streamsize n) { chain_.write(s, n); }
boost::iostreams::detail::chain<boost::iostreams::output> chain_; };
I didn't see most of this thread, and may be totally off-base here, but you need to use a tool that can intercept the output from OutputDebugString(), as that function assumes there's a debugger attached to its process; if there's no attached debugger, it attempts to use the Windows system debugger, which must be both installed and active. However, I like SysInternals' DebugView, both because it's well-written and easy to use, and because it's free. Very lightweight alternative to invoking a full debugger when that would be overkill. It can do kernel-mode debugging, too, which is a major plus, if you need that; got a copy running on my other machine right now. www.sysinternals.com. And if this is not to the point, or you already know all this, bear in mind that I only had this post available, and skimmed it pretty cursorily, and please just disregard my post. Reid

Reid Sweatman wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jonathan Turkanis
Okay Brian,
The following apparently works, but when OutputDebugString is called I don't see any output. I'm not sure if the previous version worked or not; I've run out of time for now.
I didn't see most of this thread, and may be totally off-base here, but you need to use a tool that can intercept the output from OutputDebugString(), as that function assumes there's a debugger attached to its process; if there's no attached debugger, it attempts to use the Windows system debugger, which must be both installed and active. However, I like SysInternals' DebugView, both because it's well-written and easy to use, and because it's free. Very lightweight alternative to invoking a full debugger when that would be overkill. It can do kernel-mode debugging, too, which is a major plus, if you need that; got a copy running on my other machine right now. www.sysinternals.com. And if this is not to the point, or you already know all this, bear in mind that I only had this post available, and skimmed it pretty cursorily, and please just disregard my post.
Thanks for the info. The main point of the thread was to show how to write a sink with a built-in line-ending filter, so the user doesn't always have to add one explicitly. Jonathan
participants (3)
-
Brian Braatz
-
Jonathan Turkanis
-
Reid Sweatman