按顺序排列第一个和最后一个迭代器位置

时间:2014-02-13 14:47:44

标签: boost-spirit boost-spirit-qi

我需要解析http-header字段:

key:value\r\n
key:value\r\n

如何解析两个迭代器的值,指示开始和结束?

1 个答案:

答案 0 :(得分:1)

我过去曾使用libcurl's CURLOPT_HEADERFUNCTION回调:

// userdata points to instance of response
size_t header_callback(void *data, size_t size, size_t nmemb, void *userdata)
{
    auto const length = size*nmemb;

    auto const b = static_cast<char const*>(data);
    auto f = b,
         e = b + length;

    std::string key, value;

    using namespace boost::spirit::qi;
    // 2.2 Basic Rules (rfc1945)
    static const auto& tspecials = " \t><@,;:\\\"/][?=}{:";
    static const rule<char const*, std::string()> token = +~char_(tspecials); // FIXME? should filter CTLs

    auto self = static_cast<webclient::response*>(userdata);
    if (phrase_parse(f, e, token >> ':' >> lexeme[*(char_ - eol)], space, key, value))
    {
        boost::trim(value);
        auto insertion = self->headers.insert({key, value});
        if (!insertion.second)
        {
            // merge list-valued header occurences (see rfc1945 4.2)
            insertion.first->second += ',';
            insertion.first->second.append(value);
        }
    }
    else
    {
        // roll with non seperated headers...
        std::string header(b, e);
        boost::trim(header);

        if (!header.empty())
        {
            auto insertion = self->headers.insert({header, "present"});
            logicErrAssert(insertion.second);
        }
    }

    return length;
}

请注意,header不区分大小写的地图:

/** http://www.faqs.org/rfcs/rfc1945.html 4.2  Message Headers
 *
 * Field names are case-insensitive.
 * Header fields can be extended over multiple lines by preceding each
 * extra line with at least one SP or HT, though this is not recommended.
 *
 * Multiple HTTP-header fields with the same field-name may be present
 * in a message if and only if the entire field-value for that header
 * field is defined as a comma-separated list [i.e., #(values)]. It
 * must be possible to combine the multiple header fields into one
 * "field-name: field-value" pair, without changing the semantics of
 * the message, by appending each subsequent field-value to the first,
 * each separated by a comma.
 */

using ::misc::text_utils::ci_lookup;
typedef ci_lookup<std::string> message_headers_t;