我的文件很大。它的代码页是CP1251。我想用激发精神来解析它。当解析器遇到非标准字符时,我成功解析了它。 提升文档说:
可以使用模板code_converter如下定义内存映射文件设备的宽字符版本:
#include <boost/iostreams/code_converter.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
typedef code_converter<mapped_file_source> wmapped_file_source;
typedef code_converter<mapped_file_sink> wmapped_file_sink;
但是我应该使用它吗? 我的代码不应该有接收器。我想:我的解析器使用源代码中的迭代器,code_converter使用我给他的代码页将其转换,然后将翻译后的字符发送到解析器并对其进行解析。
所以,这是我的代码的一部分,无法正常工作:
typedef boost::iostreams::code_converter<boost::iostreams::mapped_file> wmapped_file_source;
boost::locale::generator gen;
std::locale lru = gen("ru_RU.CP1251");
wmapped_file_source mmap;
mmap.imbue(lru);
mmap.open(current_task.filename);
RhAst::RhFile rh_file(this);
bool res = phrase_parse(mmap->begin(), mmap->end(), parser, space - eol, rh_file);
我试图创建自己的语言环境对象:
class LocaleRus : public std::codecvt<wchar_t, char, std::mbstate_t>
{
public:
explicit LocaleRus(size_t r = 0) : std::codecvt <wchar_t, char, std::mbstate_t> ( r )
{
}
protected:
result do_in ( state_type&, const char* from, const char* from_end, const char*& from_next, char* to, char*, char*& to_next ) const
{
const int size = from_end - from;
//::OemToCharBuff ( from, to, size );
from_next = from + size;
to_next = to + size ;
return ok;
}
result do_out ( state_type&, const char* from, const char* from_end, const char*& from_next, char* to, char*, char*& to_next ) const
{
const int size = from_end - from;
//::CharToOemBuff ( from, to, size );
from_next = from + size;
to_next = to + size ;
return ok;
}
result do_unshift ( state_type&, char*, char*, char*& ) const { return ok; }
int do_encoding () const throw () { return 1; }
bool do_always_noconv () const throw () { return false; }
int do_length ( state_type& state, const char* from, const char* from_end, size_t max ) const
{
return std::codecvt <wchar_t, char, std::mbstate_t>::do_length ( state, from, from_end, max );
}
int do_max_length () const throw ()
{
return std::codecvt <wchar_t, char, std::mbstate_t>::do_max_length ();
}
};
并在代码中使用它:
std::locale lru(std::locale(), new LocaleRus());
但是它的方法不会调用。 因此,我不介意使用非标准代码页读取内存映射文件太难了。我该怎么办?
答案 0 :(得分:1)
您绝对应该使用¹。
您正在寻找的是Spirit的流迭代器。它有一些预定义(boost::spirit::istream_iterator
),但显然由于自定义流,您需要自定义类型。
boost::spirit::istream_iterator
的作用是在Multipass Iterator Adapter中包装常规迭代器 wrap 。基本上,它的工作是消除InputIterator的仅转发和单次使用的限制。
它通过保留回溯缓冲区来实现。
我认为您应该可以使用类似于:
boost::locale::generator gen;
std::locale lru = gen("ru_RU.CP1251");
typedef boost::iostreams::code_converter<boost::iostreams::mapped_file> wmapped_file_source;
wmapped_file_source mmap;
mmap.imbue(lru);
mmap.open(current_task.filename);
RhAst::RhFile rh_file(this);
boost::iostreams::stream<wmapped_file_source> map_source(mmap);
typedef std::istreambuf_iterator<char> base_iterator_type;
spirit::multi_pass<base_iterator_type>
first = spirit::make_default_multi_pass(base_iterator_type(map_source)),
last = spirit::make_default_multi_pass(base_iterator_type());
bool res = qi::phrase_parse(first, last, parser, qi::blank, rh_file);
注意:
boost::iostreams::stream_buf
-也许效率更高(?)qi::space - qi::eol
是qi::blank
,因此很可能使用boost::spirit::qi::blank_type
作为队长效率更高注意:根据语法的结构,您可能会遇到糟糕的多遍边缘情况。您可能需要明确何时冲洗(期望点会自动冲洗),例如
¹假设转换完成了您需要他们执行的操作