// -*- mode: c++; c-basic-offset: 2; -*- #include "common.hh" #include #include #include #include "args.hh" #include "gui_attrtext.hh" #include "gui_htmlattrtext.hh" #include "gui_plainattrtext.hh" #include "looper.hh" #include "protocols.hh" namespace { std::ostream* g_out; bool g_use_html; class Receiver : public Protocols::Listener { public: Receiver(Looper* looper) : looper_(looper) { } void text(Protocols*, size_t, std::string const&, std::unique_ptr&& text) { if (g_out) { if (g_use_html) { *g_out << "" << static_cast(text.get())->html() << "" << std::endl; } else { *g_out << text->text() << std::endl; } } looper_->quit(); } void content(Protocols*, size_t, std::string const&, std::ostream*) { looper_->quit(); } private: Looper* looper_; }; bool run(std::istream& in, std::ostream& out, bool html, bool content) { g_use_html = html; std::unique_ptr looper(Looper::create()); std::unique_ptr receiver(new Receiver(looper.get())); std::unique_ptr protocols( Protocols::create(1, 65536, 1, looper.get(), receiver.get())); char buffer[8192]; std::string data; in.read(buffer, 8192); data.append(buffer, in.gcount()); protocols->add(42, data.data(), data.size()); while (in.good()) { in.read(buffer, 8192); if (in.gcount() == 0) break; data.append(buffer, in.gcount()); protocols->update(42, data.data(), data.size()); } if (content) { protocols->content(42, &out); } else { g_out = &out; protocols->text(42); } looper->run(); protocols.reset(); g_out = nullptr; return true; } } // namespace // static AttributedText* AttributedText::create() { if (g_use_html) return HtmlAttributedText::create(); return PlainAttributedText::create(); } int main(int argc, char** argv) { std::unique_ptr args(Args::create()); args->add('H', "html", "generate HTML output"); args->add('C', "content", "print content if possible"); args->add('h', "help", "display this text and exit."); if (!args->run(argc, argv)) { std::cerr << "Try `protocol --help` for usage." << std::endl; return EXIT_FAILURE; } if (args->is_set('h')) { std::cout << "Usage: `protocol [OPTIONS...] [INPUT]`\n" << "Runs protocols on INPUT or STDIN and prints result.\n" << '\n'; args->print_help(); return EXIT_SUCCESS; } switch (args->arguments().size()) { case 0: return run(std::cin, std::cout, args->is_set('H'), args->is_set('C')); case 1: { std::ifstream in(args->arguments().front()); if (!in.good()) { std::cerr << "Unable to open " << args->arguments().front() << " for reading." << std::endl; return EXIT_FAILURE; } return run(in, std::cout, args->is_set('H'), args->is_set('C')); } default: std::cerr << "Too many arguments.\n" << "Try `protocol --help` for usage." << std::endl; return EXIT_FAILURE; } }