
Le 15 nov. 2014 à 18:53, Sylro <syrmonsieur@hotmail.com> a écrit :
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 <boost/iostreams/filtering_stream.hpp> #include <boost/iostreams/char_traits.hpp> // EOF, WOULD_BLOCK #include <boost/iostreams/concepts.hpp> // multichar_output_filter #include <boost/iostreams/operations.hpp> // get namespace vcsn { namespace detail { namespace io = boost::iostreams; /// Backslash backslashes. class backslashify_output_filter : public io::multichar_output_filter { public: explicit backslashify_output_filter() {} void enable() { enabled_ = true; } void disable() { enabled_ = false; } template <typename Sink> std::streamsize write(Sink& dest, const char* s, std::streamsize n) { std::streamsize z; for (z = 0; z < n; ++z) { char c = s[z]; if (enabled_ && c == '\\') if (!io::put(dest, '\\')) // FIXME: probably lost a char here. break; if (!io::put(dest, c)) break; } return z; } bool enabled_ = false; }; } } then the caller: bos_ << " [label = \""; enable_(); aut_->print_state_name(s, bos_, "text"); disable_(); boss << "\", shape = box"; where bos_ is the stream: detail::io::filtering_ostream bos_; initialized like this: dotter(const automaton_t& aut, std::ostream& out, bool dot2tex = false) : super_t(aut, out) , dot2tex_(dot2tex) { bos_.push(detail::backslashify_output_filter()); bos_.push(out); } Then, the enable/disable sequence is as follows: /// Enable the escaping of backslashes. void enable_() { boost::iostreams::flush(bos_); bos_.component<detail::backslashify_output_filter>(0)->enable(); } /// Disable the escaping of backslashes. void disable_() { boost::iostreams::flush(bos_); bos_.component<detail::backslashify_output_filter>(0)->disable(); } where the calls to flush are extremely important. I have _not_ implement flush in my filter, to avoid flushing downstream and kill the buffers: only the buffers before the filter and the filter itself are flushed, so that the effect happens when it should. Cheers!