在Boost Spirit中解码UTF8字符转义

4
问题描述:Spirit-general list

大家好,

我不确定我的主题是否正确,但是测试代码可能会显示我想要实现的内容。

我正在尝试解析以下内容:

  • '%40'转换为 '@'
  • '%3C'转换为 '<'

下面是我的最小测试案例。我不明白这为什么不起作用。可能是我犯了错误,但我看不到它。

使用的工具如下: 编译器:gcc 4.6 Boost: current trunk

我使用以下编译行:

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

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。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接