/*!
  \file
  \brief monitor ログからのタイミングデータ除去

  monitor 形式のログファイルから、送受信されたデータを取り出す。

  使用例
  \verbatim
% ./stripTimingData mConnection_0.log
-> mConnection_0_recv.txt, mConnection_0_send.txt が生成される。
   それぞれ、受信データ、送信データ、が格納されている。 \endverbatim

  \author Satofumi KAMIMURA

  $Id: stripTimingData.cpp 590 2009-02-17 10:11:40Z satofumi $
*/

#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>

using namespace boost;
using namespace boost::algorithm;
using namespace std;


namespace
{
  void printUsage(const char* program_name)
  {
    cout << "usage:" << endl
         << "\t" << program_name << " <log file>" << endl;
  }


  void checkFileCreated(ofstream& fout, const string& file)
  {
    if (! fout.is_open()) {
      perror(file.c_str());
      exit(1);
    }
  }
}


int main(int argc, char *argv[])
{
  if (argc < 2) {
    printUsage(argv[0]);
    exit(1);
  }
  const char* logfile = argv[1];


  // 出力ファイル名の作成
  filesystem::path file_path(logfile);
  string basename = file_path.leaf();
  string basename_body = basename.substr(0, basename.rfind("."));

  string send_file = basename_body + "_send.txt";
  string recv_file = basename_body + "_recv.txt";

  ofstream send_fout(send_file.c_str());
  checkFileCreated(send_fout, send_file);

  ofstream recv_fout(recv_file.c_str());
  checkFileCreated(recv_fout, recv_file);

  // 送受信データの生成
  ifstream fin(logfile);
  if (! fin.is_open()) {
    perror(logfile);
    exit(1);
  }

  string line;
  vector<char> buffer;
  while (getline(fin, line)) {

    // コメントのある行のみ処理する
    size_t comment_first = line.rfind("#");
    if (comment_first == string::npos) {
      continue;
    }
    string comment = line.substr(comment_first);

    // send, recv のとき以外は、処理を行わない
    if (comment.compare("# recv()") && comment.compare("# send()")) {
      continue;
    }

    vector<string> tokens;
    split(tokens, line, boost::is_any_of(", "));
    if (tokens.size() != 4) {
      continue;
    }
    size_t data_size = atoi(tokens[1].c_str());
    if (buffer.size() < data_size) {
      buffer.resize(data_size);
    }
    fin.read(&buffer[0], data_size);

    // データの格納
    if (comment[2] == 'r') {
      recv_fout.write(&buffer[0], data_size);
    } else {
      send_fout.write(&buffer[0], data_size);
    }

    // 改行の読み飛ばし
    char ch;
    fin.read(&ch, 1);
  }
  return 0;
}
