読者です 読者をやめる 読者になる 読者になる

堕(惰)プログラマ開発記録

タイトル変えようかなとも思ってるけれど,思い浮かばない

駆け出しBoost.Spirit.Qi

C++ Boost

Boost.SpiritがBoost Advent Calendar 2011 - PARTAKEで取り上げられそうなので,ちょっと予習がてらBoost.Spirit.Qi,弄ってみました.

とりあえずHTTPレスポンスのパーサを.

#include <map>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/foreach.hpp>

typedef std::map<std::string,std::string> header_type;

bool read(
  std::string const &response,
  std::string &http_version,
  int &status_code,
  std::string &status_message,
  header_type &response_header
  )
{
  namespace qi = boost::spirit::qi;
  std::string::const_iterator it = response.begin();
  auto header_rule = 
    "HTTP/" >> +(qi::char_ - " ") >> " " >> qi::int_ >> " " >> +(qi::char_ - "\r\n") >> ("\r\n") //一行目
    >> *(+(qi::char_ - ": ") >> ": " >> +(qi::char_ - "\r\n") >> "\r\n") //二行目をmapに
    >> *("\r\n") >> *qi::eol; //改行が残ってたら全部スルー
  
  bool r = qi::parse(it,response.end(),header_rule,http_version,status_code,status_message,response_header);
  if (it != response.end()) return false;

  return r;
}

int main()
{
  std::string http_version,status_message;
  int status_code;
  header_type header;

  const std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8; charset=\"utf-8\"\r\nContent-Length: 256\r\n\r\n";
  read(response,http_version,status_code,status_message,header);
  
  std::pair<std::string,std::string> p;
  std::cout << "  HTTP Version: " << http_version << "\n";
  std::cout << "   Status Code: " << status_code << "\n";
  std::cout << "Status Message: " << status_message << "\n";

  std::cout << "\n<Response Header>\n";
  BOOST_FOREACH(p,header) std::cout << p.first << ": " << p.second << "\n";
  std::cout << std::flush;
  
  return 0;
}

こんな感じで実行すると,一応readからtrueが帰ってきて各情報は出力されます.
autoになってますが,header_ruleにパース設定が入ってるようです.const std::string responseと比べてもこのまんまで,とても解りやすいのではないかと思いました.

コンパイル時に私のPCでは20秒ほどかかるのが難点ですが….