簡體   English   中英

無法使用 boost 精神解析大文件

[英]Can not parse large file with boost spirit

我有一個大文件。 它的代碼頁是 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());

但它的方法不會調用。 所以,我不介意用非標准代碼頁讀取內存映射文件太難了。 我做錯了什么?

你應該使用它¹,絕對。

您正在尋找的是 Spirit 的流迭代器。 它有一些預定義的( boost::spirit::istream_iterator ),但顯然你需要自定義類型,因為自定義流。

boost::spirit::istream_iterator所做的是在Multipass Iterator Adapter 中包裝一個常規迭代 基本上它的作用是消除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);

筆記:

  1. 我在瀏覽器中輸入了這個,還沒來得及檢查
  2. 您可以改用boost::iostreams::stream_buf - 也許效率更高(?)
  3. qi::space - qi::eolqi::blank ,因此可能使用boost::spirit::qi::blank_type作為船長效率更高
  4. 當心:根據您的語法結構,您可能會遇到糟糕的多遍邊緣情況。 您可能希望明確何時刷新(期望點會自動執行此操作),請參見例如


¹假設轉換做你需要他們做的事情

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM