Расшифровка char UTF8 ускользает в Boost Spirit - PullRequest
4 голосов
/ 10 ноября 2011

заданный вопрос: Общий список духов

Привет всем,

Я не уверен, что мойтема правильная, но тестовый код, вероятно, покажет, чего я хочу достичь.

Я пытаюсь разобрать такие вещи, как:

  • '% 40' до '@'
  • '% 3C' до '<' </li>

У меня минимальный тестовый пример ниже.Я не понимаю, почему это не работает.Возможно, я ошибаюсь, но не вижу ее.

Использование: Компилятор: gcc 4.6 Boost: текущая магистраль

Я использую следующую строку компиляции:

g++ -o main -L/usr/src/boost-trunk/stage/lib -I/usr/src/boost-trunk -g -Werror -Wall -std=c++0x -DBOOST_SPIRIT_USE_PHOENIX_V3 main.cpp

#include <iostream>
#include <string>

#define BOOST_SPIRIT_UNICODE

#include <boost/cstdint.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/phoenix/phoenix.hpp>

typedef boost::uint32_t uchar; // Unicode codepoint

namespace qi = boost::spirit::qi;

int main(int argc, char **argv) {

    // Input
    std::string input = "%3C";
    std::string::const_iterator begin = input.begin();
    std::string::const_iterator end = input.end();

    using qi::xdigit;
    using qi::_1;
    using qi::_2;
    using qi::_val;

    qi::rule<std::string::const_iterator, uchar()> pchar =
        ('%' > xdigit > xdigit) [_val = (_1 << 4) + _2];

    std::string result;
    bool r = qi::parse(begin, end, pchar, result);
    if (r && begin == end) {
        std::cout << "Output:   " << result << std::endl;
        std::cout << "Expected: < (LESS-THAN SIGN)" << std::endl;
    } else {
        std::cerr << "Error" << std::endl;
        return 1;
    }

    return 0;
}

С уважением,

Matthijs Möhlmann

1 Ответ

2 голосов
/ 10 ноября 2011

qi::xdigit не делает то, что вы думаете, он делает: он возвращает необработанный символ (т.е. '0', а не 0x00).

Вы можете использовать qi::uint_parser в своих интересах, что значительно упрощает анализ в качестве бонуса:

typedef qi::uint_parser<uchar, 16, 2, 2> xuchar;
  • не нужно полагаться на Phoenix (чтобы он работал на более старых версиях Boost)
  • получить оба символа за один раз (в противном случае вам может потребоваться добавить обильное приведение, чтобы предотвратить расширение целых знаков)

Вот фиксированный пример:

#include <iostream>
#include <string>

#define BOOST_SPIRIT_UNICODE

#include <boost/cstdint.hpp>
#include <boost/spirit/include/qi.hpp>

typedef boost::uint32_t uchar; // Unicode codepoint

namespace qi = boost::spirit::qi;

typedef qi::uint_parser<uchar, 16, 2, 2> xuchar;
const static xuchar xuchar_ = xuchar();


int main(int argc, char **argv) {

    // Input
    std::string input = "%3C";
    std::string::const_iterator begin = input.begin();
    std::string::const_iterator end = input.end();

    qi::rule<std::string::const_iterator, uchar()> pchar = '%' > xuchar_;

    uchar result;
    bool r = qi::parse(begin, end, pchar, result);

    if (r && begin == end) {
        std::cout << "Output:   " << result << std::endl;
        std::cout << "Expected: < (LESS-THAN SIGN)" << std::endl;
    } else {
        std::cerr << "Error" << std::endl;
        return 1;
    }

    return 0;
}

Выход:

Output:   60
Expected: < (LESS-THAN SIGN)

'<' действительно ASCII 60 </p>

...