Iostreams: how can I control my (ostream) filter?
Hi! I'm trying to use Boost.Iostream to create a filter that will escape some characters (typically backslash must be backslashed). This is to conform with the syntax of an output format that requires some portions to be escaped this way. But other place must be left untouched. My problem is I don't find a means to "talk" to my filter. My first attempt used two streams: the "real" ostream and the filtered one that wraps it. Of course it failed: both streams are not synchronized, and buffers are flushed at different moments resulting in scrambled output. I don't want to flush too often (I got to keep my throughput high), so that's ruled out. My second attempt was to introduce an xalloc-based custom iomanip to enable/disable the processing in my filter. But my problem is that in my filter, I don't know how to reach the final ostream and fetch it pword, so I failed to have it work. From the syntax point of view (from the caller viewpoint) that was my favorite approach. In my third attempt, I have to boolean variable living in the caller frame, taken as a bool& by my filter's actor, and checked in its "write" function to decide whether to escape or not. This looks worrying (bool& members don't look nice), and anyway does not work nicely, again, with buffers: the asynchrony between setting/unsetting the boolean and using it breaks everything. So, what are the good options? I think I really needed something like an iomanipulator which ensures that "sequentiality" is preserved, but how should I do that? Thanks in advance! PS/ One not-good-option would be to have my filter try to "parse" what it is outputting to decide what's the current state, and whether it should escape or not. First, things become uselessly complex, and second, anyway that's not right; for instance when I'm in a string, double-quotes should be escaped, or mark the end of the string. The filter cannot know which kind of double-quote it just saw, but I know, so _I_ should change the state at that time, not it.
I have the same problem trying to escape XML : I want the filter to be enabled when writing contents and attribute values, and disabled when writing the markup. I tried the same solutions as Akim, but ended up embedding "control sequences" within the data to enable/disable the filter. From outside it's not that bad since the control sequences are wrapped into manipulators, but the implementation is simply horrible. Is there any suggestion to solve our problem ? How can we control a filter without having to sync ? Thanks ! -- View this message in context: http://boost.2283326.n4.nabble.com/Iostreams-how-can-I-control-my-ostream-fi... Sent from the Boost - Users mailing list archive at Nabble.com.
Le 15 nov. 2014 à 18:53, Sylro
I have the same problem trying to escape XML : I want the filter to be enabled when writing contents and attribute values, and disabled when writing the markup.
I tried the same solutions as Akim, but ended up embedding "control sequences" within the data to enable/disable the filter. From outside it's not that bad since the control sequences are wrapped into manipulators, but the implementation is simply horrible.
Is there any suggestion to solve our problem ? How can we control a filter without having to sync ? Thanks !
Hi Sylro,
FWIW, here is what I ended up doing. First, the
filter itself:
#pragma once
#include <iostream>
#include
Hi Akim. I see what you're trying to do : sync up to the filter, but not beyond, would be a simple solution. However boost::iostreams::flush() will always flush everything, up to the final device. For the demonstration, if you use this dummy_sink : class dummy_sink { public: typedef char char_type; struct category : public boost::iostreams::sink_tag, public boost::iostreams::flushable_tag {}; std::streamsize write(const char* s, std::streamsize n) { std::cout << "{" << std::string(s, s + n) << "}"; return n; } bool flush() { std::cout << " FLUSH "; std::cout.flush(); return true; } }; With this example : { bos_ << " [label = \""; enable_(); bos_ << "bla\\abla" << 1 << 2 << 3 << "blabla"; disable_(); bos_ << "\", shape = box"; } Then the output looks like: { [label = "} FLUSH {bla\\abla123blabla} FLUSH {", shape = box} FLUSH FLUSH FLUSH FLUSH FLUSH FLUSH FLUSH -- View this message in context: http://boost.2283326.n4.nabble.com/Iostreams-how-can-I-control-my-ostream-fi... Sent from the Boost - Users mailing list archive at Nabble.com.
Le 16 nov. 2014 à 21:06, Sylro
Hi Akim.
I see what you're trying to do : sync up to the filter, but not beyond, would be a simple solution. However boost::iostreams::flush() will always flush everything, up to the final device.
Thanks for the counter-example! I have absolutely no desire to design a protocol, as you did, but then, at this point, it seems to be the only efficient solution :(
participants (2)
-
Akim Demaille
-
Sylro