Все фильтры, которые вы видели до сих пор — за исключением тех, которые происходят от<stdio_filter>— обрабатывают символы по одному за раз. Если вы обрабатываете несколько символов одновременно, вы часто можете уменьшить количество вызовов функций, необходимых для фильтрации последовательности символов, что приводит к более эффективному коду. Вот что такоемногофакторные фильтрыВы можете это сделать.
#include<iosfwd>// streamsize#include<boost/iostreams/categories.hpp>// tags
classmy_input_filter {
public:
typedefcharchar_type;
structcategory
: input_filter_tag,
multichar_tag
{ };
template<typenameSource>
std::streamsize read(Source& src,char* s, std::streamsize n)
{
// Read up to n filtered characters into the buffer s,// returning the number of characters read or -1 for EOF.// Use src to access the unfiltered character sequence
}
/* Other members */
};
>
Обратите внимание, что категория типа участника является<struct>конвертируемой в<input_filter_tag>и в<multichar_tag>. Это говорит библиотеке Iostream, что<my_input_filter>являетсямногохарактерным фильтромиInputFilter.. Вы могли бы достичь того же эффекта несколькими способами.Например,,
Вы также можете написать приведенный выше пример следующим образом:
#include<iosfwd>// streamsize#include<boost/iostreams/concepts.hpp>// multichar_input_filterclass my_input_filter : public multichar_input_filter {
public:
template<typename Source>
std::streamsize read(char* s, std::streamsize n);
/* Other members */
};
Здесь<multichar_input_filter>является базовым классом удобства, который обеспечивает типы членов<char_type>и<category>, а также не-оп реализации функций членов<close>и<imbue>.
#include<boost/iostreams/char_traits.hpp>// EOF, WOULD_BLOCK#include<boost/iostreams/concepts.hpp>// multichar_input_filter#include<boost/iostreams/operations.hpp>// getnamespace boost { namespace iostreams { namespace example {
class shell_comments_multichar_input_filter : public multichar_input_filter {
public:
explicit shell_comments_multichar_input_filter(char comment_char = '#')
: comment_char_(comment_char), skip_(false)
{ }
template<typename Source>
std::streamsize read(Source& src, char* s, std::streamsize n)
{
for (std::streamsize z = 0; z < n; ++z) {
int c;
while (true) {
if ((c = boost::iostreams::get(src)) == EOF)
return z != 0 ? z : -1;
elseif (c == WOULD_BLOCK)
return z;
skip_ = c == comment_char_ ?
true :
c == '\n' ?
false :
skip_;
if (!skip_)
break;
}
s[z] = c;
}
return n;
}
template<typename Source>
void close(Source&) { skip_ = false; }
private:
char comment_char_;
bool skip_;
};
} } } // End namespace boost::iostreams:example
Обратите внимание, что реализация<read>очень похожа на то, что вы получите, если поместите реализацию<shell_comments_input_filter::get>внутри<for>петли, итерирующейся от<0>до<n>. Вводные фильтры, которые называют себя рекурсивно, такие как<tab_expanding_input_filter>, гораздо труднее преобразовать в многохарактерные фильтры.
#include<iosfwd>// streamsize#include<boost/iostreams/categories.hpp>// tags
classmy_output_filter {
public:
typedefcharchar_type;
structcategory
: output_filter_tag,
multichar_tag
{ };
template<typenameSink>
std::streamsize write(Sink& dest,constchar* s, std::streamsize n)
{
// Consume up to n filtered characters from the buffer s,// writing filtered characters to dest. Return the number// of characters consumed.
}
/* Other members */
};
>
Обратите внимание, что категория типа участника является<struct>конвертируемой в<keyword>и в<multichar_tag>. Это говорит библиотеке Iostream, что<my_output_filter>являетсямногохарактерным фильтромивыходным фильтром. Как и в случае сMulti-CharacterInputFilters, вы могли бы достичь того же эффекта несколькими различными способами.Например,,
Вы также можете написать приведенный выше пример следующим образом:
#include<iosfwd>// streamsize#include<boost/iostreams/concepts.hpp>// multichar_output_filterclass my_output_filter : public multichar_output_filter {
public:
template<typename Sink>
std::streamsize write(Sink& dest, constchar* s, std::streamsize n);
/* Other members */
};
Здесь<multichar_output_filter>является базовым классом удобства, который предоставляет типы членов<char_type>и<category>, а также не-оп реализации функций членов<close>и<imbue>.
#include<boost/iostreams/char_traits.hpp>// EOF, WOULD_BLOCK#include<boost/iostreams/concepts.hpp>// multichar_output_filter#include<boost/iostreams/operations.hpp>// getnamespace boost { namespace iostreams { namespace example {
class shell_comments_multichar_output_filter : public multichar_output_filter {
public:
explicit shell_comments_multichar_output_filter(char comment_char = '#')
: comment_char_(comment_char), skip_(false)
{ }
template<typename Sink>
std::streamsize write(Sink& dest, const char* s, std::streamsize n)
{
std::streamsize z;
for (z = 0; z < n; ++z) {
int c = s[z];
skip_ = c == comment_char_ ?
true :
c == '\n' ?
false :
skip_;
if (skip_)
continue;
if (!iostreams::put(dest, c))
break;
}
return z;
}
template<typename Source>
void close(Source&) { skip_ = false; }
private:
char comment_char_;
bool skip_;
};
} } } // End namespace boost::iostreams:example
Обратите внимание, что реализация<write>очень похожа на то, что вы получите, если поместите реализацию<shell_comments_output_filter::put>внутри<for>петли, итерирующейся от<0>до<n>. Фильтры вывода, которые называют себя рекурсивными, такие как<unix2dos_output_filter>, гораздо труднее преобразовать в многохарактерные фильтры.
Статья Tutorial раздела может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.