У меня есть аналогичная проблема, например How to use boost::spirit to parse UTF-8? и How to match unicode characters with boost::spirit?, но ни одна из этих проблем не решена. У меня есть std::string
с UTF-8 символов, я использовал u8_to_u32_iterator
обернуть std::string
и использовать unicode
терминалы, как это:Обработка utf-8 в Boost.Spirit с парсером utf-32
BOOST_NETWORK_INLINE void parse_headers(std::string const & input, std::vector<request_header_narrow> & container) {
using namespace boost::spirit::qi;
u8_to_u32_iterator<std::string::const_iterator> begin(input.begin()), end(input.end());
std::vector<request_header_narrow_utf8_wrapper> wrapper_container;
parse(
begin, end,
*(
+(alnum|(punct-':'))
>> lit(": ")
>> +((unicode::alnum|space|punct) - '\r' - '\n')
>> lit("\r\n")
)
>> lit("\r\n")
, wrapper_container
);
BOOST_FOREACH(request_header_narrow_utf8_wrapper header_wrapper, wrapper_container)
{
request_header_narrow header;
u32_to_u8_iterator<request_header_narrow_utf8_wrapper::string_type::iterator> name_begin(header_wrapper.name.begin()),
name_end(header_wrapper.name.end()),
value_begin(header_wrapper.value.begin()),
value_end(header_wrapper.value.end());
for(; name_begin != name_end; ++name_begin)
header.name += *name_begin;
for(; value_begin != value_end; ++value_begin)
header.value += *value_begin;
container.push_back(header);
}
}
request_header_narrow_utf8_wrapper
определяется и отображается в Fusion, как это (не возражаете недостающее пространство имен декларации):
struct request_header_narrow_utf8_wrapper
{
typedef std::basic_string<boost::uint32_t> string_type;
std::basic_string<boost::uint32_t> name, value;
};
BOOST_FUSION_ADAPT_STRUCT(
boost::network::http::request_header_narrow_utf8_wrapper,
(std::basic_string<boost::uint32_t>, name)
(std::basic_string<boost::uint32_t>, value)
)
Это прекрасно работает, но мне было интересно, может я как-то удается сделать синтаксический анализатор непосредственно присваивает ей на структуру, содержащую std::string
членов вместо того, чтобы делать для каждого цикла, с u32_to_u8_iterator
? Я думал, что один способ может сделать оболочку для std :: string, которая будет иметь оператор присваивания с boost::uint32_t
, чтобы парсер мог назначить напрямую, но есть ли другие решения?
EDIT
После прочтения некоторых еще я закончил с этим:
namespace boost { namespace spirit { namespace traits {
typedef std::basic_string<uint32_t> u32_string;
/* template <>
struct is_string<u32_string> : mpl::true_ {};*/
template <> // <typename Attrib, typename T, typename Enable>
struct assign_to_container_from_value<std::string, u32_string, void>
{
static void call(u32_string const& val, std::string& attr) {
u32_to_u8_iterator<u32_string::const_iterator> begin(val.begin()), end(val.end());
for(; begin != end; ++begin)
attr += *begin;
}
};
} // namespace traits
} // namespace spirit
} // namespace boost
и это
BOOST_NETWORK_INLINE void parse_headers(std::string const & input, std::vector<request_header_narrow> & container) {
using namespace boost::spirit::qi;
u8_to_u32_iterator<std::string::const_iterator> begin(input.begin()), end(input.end());
parse(
begin, end,
*(
as<boost::spirit::traits::u32_string>()[+(alnum|(punct-':'))]
>> lit(": ")
>> as<boost::spirit::traits::u32_string>()[+((unicode::alnum|space|punct) - '\r' - '\n')]
>> lit("\r\n")
)
>> lit("\r\n")
, container
);
}
Любые комментарии или советы, если это лучшее, что я могу получить?
Спасибо, проверим это и примем, если он решает мою проблему :) –
Извините за долгую задержку, но мне нужно дополнительное руководство - мой парсер (как в примере) всегда вызывает 'assign_to_attribute_from_value' с параметрами шаблона' char' и 'unsigned int' (что имеет смысл с тех пор), заключается в том, что из-за грамматики? Есть ли способ заставить его использовать int32_t внутри, а затем назначить целую 'u32_string' на' std :: string'? Я определенно чего-то не хватает. –
Да, это возможно, это то, что я делаю в своем ответе. Для сравнения, посмотрите на «no_wide» ветви моего игрушечного парсера JSON ([в частности «https://github.com/sehe/spirit-v2-json/blob/nowide/JSON.cpp#L48'](https:/ /github.com/sehe/spirit-v2-json/blob/nowide/JSON.cpp#L48)), если вы (хотите) иметь его другим способом. – sehe