#include "apps.h" #include "trygvis/sensor/io.h" #include #include namespace trygvis { namespace apps { using namespace std; using namespace trygvis::sensor; using namespace trygvis::sensor::io; using boost::tokenizer; namespace po = boost::program_options; class sample_tee final : public app, public SampleConsumer { private: using clock = std::chrono::steady_clock; using timestamp = std::chrono::time_point; sample_format_type output_format = sample_format_type::KEY_VALUE; sample_format_type file_output_format = sample_format_type::KEY_VALUE; string file_name; sample_output_stream_options options = {}; KeyDictionary dict; shared_ptr out; unique_ptr out_writer; ofstream file; timestamp next_flush; public: sample_tee() : app("sample-to-file") {} ~sample_tee() override = default; void add_options(po::options_description_easy_init &options) override { options("output-format", po::value(&output_format)->default_value(output_format)); options("file-output-format", po::value(&file_output_format)->default_value(file_output_format)); options("file", po::value(&file_name)); } int main(app_execution &execution) override { if (file_name.size() == 0) { cerr << "Missing required argument --file" << endl; return EXIT_FAILURE; } cerr << "Writing samples to " << file_name << endl; const int buffer_size = 1024; char buffer[buffer_size]; out = shared_ptr(&cout, noop_deleter); out_writer = std::move(open_sample_writer(out, dict, output_format, options)); next_flush = clock::now(); auto parser = open_sample_stream_parser(shared_ptr(this, noop_deleter), dict); auto in = shared_ptr(&cin, noop_deleter); in->rdbuf(nullptr); while (!in->eof()) { in->read(buffer, buffer_size); auto gcount = static_cast(in->gcount()); out->write(buffer, gcount); mutable_buffers_1 b = boost::asio::buffer(buffer, gcount); parser->process(b); } file.flush(); file.close(); return EXIT_SUCCESS; }; protected: void onSample(const SampleRecord &sample) override { out_writer->onSample(sample); file.open(file_name, ios_base::out | ios_base::app); if (file.good()) { shared_ptr output(&file, noop_deleter); auto file_writer = std::move(open_sample_writer(output, dict, file_output_format, options)); file_writer->onSample(sample); } auto now = clock::now(); if(now >= next_flush) { file.flush(); next_flush = now + chrono::seconds(3); cerr << "flush" << endl; } } }; } } int main(int argc, const char *argv[]) { using namespace trygvis::apps; return real_main(new sample_tee(), argc, argv); }