Продолжение темы, начатой еще в сентябре. Предыдущие части саги: один, два, три.
В результате переосмысления того, что получилось на прошлой неделе, некоторого упрощения использованных концепций, набитых шишек и внезапно обнаруженных подводных камней (один из которых чуть было не пустил еще недостроенное суденышко на дно), получилось переписать пример, показанный в третьей части саги, вот таким образом:
struct cache_control_value_t { using directive_t = std::pair< std::string, restinio::optional_t<std::string> >; using directive_container_t = std::map< std::string, restinio::optional_t<std::string> >; directive_container_t m_directives; static auto make_parser() { using namespace restinio::http_field_parser; using namespace restinio::http_field_parser::rfc; return produce< cache_control_value_t >( one_or_more_of_producer< directive_container_t >( produce< directive_t >( token_producer() >> to_lower() >> &directive_t::first, maybe( symbol('='), alternatives( token_producer() >> &directive_t::second, quoted_string_producer() >> &directive_t::second ) ) ) ) >> &cache_control_value_t::m_directives ); } static std::pair< bool, cache_control_value_t > try_parse( string_view_t what ) { using namespace restinio::http_field_parser; return try_parse_field_value( what, make_parser() ); } }; |
Напомню, что этот код решает проблему парсинга и получения значения из HTTP-поля Cache-Control, которое в RFC специфицируется следующим образом:
Cache-Control = 1#cache-directive
cache-directive = token [ "=" ( token / quoted-string ) ]
где запись 1#element означает вот такое:
1#element => *( "," OWS ) element *( OWS "," [ OWS element ] )
Собственно, в методе make_parser идет декларативное описание и того, что мы должны получить в результате парсинга, и самой структуры парсера: