Le 15 nov. 2014 à 18:53, Sylro 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
#include // EOF, WOULD_BLOCK
#include // multichar_output_filter
#include // 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_.componentdetail::backslashify_output_filter(0)->enable();
}
/// Disable the escaping of backslashes.
void disable_()
{
boost::iostreams::flush(bos_);
bos_.componentdetail::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!