From c029d90d1975e124d237605f1edb2be16bd05b5d Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Tue, 28 Feb 2017 21:50:44 +0100 Subject: Initial commit --- src/.gitignore | 4 + src/Makefile.am | 18 + src/args.cc | 281 +++++++++++ src/args.hh | 60 +++ src/buffer.cc | 119 +++++ src/buffer.hh | 30 ++ src/character.cc | 31 ++ src/character.hh | 18 + src/chunked.cc | 106 +++++ src/chunked.hh | 23 + src/common.hh | 18 + src/config.cc | 176 +++++++ src/config.hh | 33 ++ src/http.cc | 657 ++++++++++++++++++++++++++ src/http.hh | 141 ++++++ src/io.cc | 90 ++++ src/io.hh | 124 +++++ src/logger.cc | 130 ++++++ src/logger.hh | 33 ++ src/looper.cc | 287 ++++++++++++ src/looper.hh | 41 ++ src/main.cc | 187 ++++++++ src/paths.cc | 98 ++++ src/paths.hh | 18 + src/proxy.cc | 1373 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/proxy.hh | 37 ++ src/resolver.cc | 207 ++++++++ src/resolver.hh | 28 ++ src/strings.cc | 94 ++++ src/strings.hh | 24 + src/terminal.cc | 20 + src/terminal.hh | 22 + src/url.cc | 901 +++++++++++++++++++++++++++++++++++ src/url.hh | 62 +++ src/xdg.cc | 135 ++++++ src/xdg.hh | 25 + 36 files changed, 5651 insertions(+) create mode 100644 src/.gitignore create mode 100644 src/Makefile.am create mode 100644 src/args.cc create mode 100644 src/args.hh create mode 100644 src/buffer.cc create mode 100644 src/buffer.hh create mode 100644 src/character.cc create mode 100644 src/character.hh create mode 100644 src/chunked.cc create mode 100644 src/chunked.hh create mode 100644 src/common.hh create mode 100644 src/config.cc create mode 100644 src/config.hh create mode 100644 src/http.cc create mode 100644 src/http.hh create mode 100644 src/io.cc create mode 100644 src/io.hh create mode 100644 src/logger.cc create mode 100644 src/logger.hh create mode 100644 src/looper.cc create mode 100644 src/looper.hh create mode 100644 src/main.cc create mode 100644 src/paths.cc create mode 100644 src/paths.hh create mode 100644 src/proxy.cc create mode 100644 src/proxy.hh create mode 100644 src/resolver.cc create mode 100644 src/resolver.hh create mode 100644 src/strings.cc create mode 100644 src/strings.hh create mode 100644 src/terminal.cc create mode 100644 src/terminal.hh create mode 100644 src/url.cc create mode 100644 src/url.hh create mode 100644 src/xdg.cc create mode 100644 src/xdg.hh (limited to 'src') diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..7066278 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,4 @@ +/config.h +/config.h.in~ +/libtp.a +/tp diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..502c82d --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,18 @@ +MAINTAINERCLEANFILES = Makefile.in config.h.in + +AM_CXXFLAGS = @DEFINES@ + +# Remove ar: `u' modifier ignored since `D' is the default (see `U') +ARFLAGS = cr + +bin_PROGRAMS = tp +noinst_LIBRARIES = libtp.a + +tp_SOURCES = main.cc proxy.cc logger.cc resolver.cc +tp_LDADD = libtp.a @THREAD_LIBS@ +tp_CXXFLAGS = $(AM_CXXFLAGS) -DVERSION='"@VERSION@"' @THREAD_CFLAGS@ + +libtp_a_SOURCES = args.cc xdg.cc terminal.cc http.cc url.cc paths.cc \ + character.cc config.cc strings.cc io.cc looper.cc \ + buffer.cc chunked.cc +libtp_a_CXXFLAGS = $(AM_CXXFLAGS) -DSYSCONFDIR='"@SYSCONFDIR@"' diff --git a/src/args.cc b/src/args.cc new file mode 100644 index 0000000..cde77b0 --- /dev/null +++ b/src/args.cc @@ -0,0 +1,281 @@ +// -*- mode: c++; c-basic-offset: 2; -*- + +#include "common.hh" + +#include +#include +#include +#include + +#include "args.hh" +#include "character.hh" +#include "terminal.hh" + +namespace { + +class ArgsImpl : public Args { +public: + ArgsImpl() + : good_(true) { + } + void add(char short_opt, std::string const& long_opt, + std::string const& argument, std::string const& help) override { + assert(short_opt == '\0' || short_opts_.count(short_opt) == 0); + assert(long_opt.empty() || long_opts_.count(long_opt) == 0); + assert(long_opt.find('=') == std::string::npos); + auto const index = opts_.size(); + opts_.push_back(Option(short_opt, long_opt, argument, help)); + if (short_opt != '\0') { + short_opts_.insert(std::make_pair(short_opt, index)); + } + if (!long_opt.empty()) { + long_opts_.insert(std::make_pair(long_opt, index)); + } + } + + bool run(int argc, char** argv, std::ostream& out) override { + if (argc == 0) { + assert(false); + good_ = false; + return false; + } + auto start = strrchr(argv[0], '/'); + if (!start) { + start = argv[0]; + } else { + start++; + } + return run(start, argc, argv, out); + } + + bool run(std::string const& prg, int argc, char** argv, std::ostream& out) + override { + reset(); + + std::string opt; + for (int a = 1; a < argc; ++a) { + if (argv[a][0] == '-') { + if (argv[a][1] == '-') { + if (argv[a][2] == '\0') { + for (++a; a < argc; ++a) { + args_.push_back(argv[a]); + } + return good_; + } + size_t len = 2; + while (argv[a][len] && argv[a][len] != '=') ++len; + opt.assign(argv[a] + 2, len - 2); + auto i = long_opts_.find(opt); + if (i == long_opts_.end()) { + out << prg << ": unrecognized option '--" << opt << "'\n"; + good_ = false; + continue; + } + if (argv[a][len] == '=') { + if (opts_[i->second].argument.empty()) { + out << prg << ": option '--" << opt << "'" + << " doesn't allow an argument\n"; + good_ = false; + continue; + } else { + opts_[i->second].value = argv[a] + len + 1; + opts_[i->second].is_set = true; + } + } else { + if (opts_[i->second].argument.empty()) { + opts_[i->second].is_set = true; + } else if (a + 1 == argc) { + out << prg << ": option '--" << opt << "'" + << " requires an argument\n"; + good_ = false; + continue; + } else { + opts_[i->second].value = argv[++a]; + opts_[i->second].is_set = true; + } + } + } else { + for (auto opt = argv[a] + 1; *opt; ++opt) { + auto i = short_opts_.find(*opt); + if (i == short_opts_.end()) { + out << prg << ": invalid option -- '" << *opt << "'\n"; + good_ = false; + continue; + } + if (opts_[i->second].argument.empty()) { + opts_[i->second].is_set = true; + } else if (a + 1 == argc) { + out << prg << ": option requires an argument " + << " -- '" << *opt << "'\n"; + good_ = false; + continue; + } else { + opts_[i->second].value = argv[++a]; + opts_[i->second].is_set = true; + } + } + } + } else { + args_.push_back(argv[a]); + } + } + + return good_; + } + bool good() const override { + return good_; + } + + bool is_set(char short_opt) const override { + auto i = short_opts_.find(short_opt); + if (i == short_opts_.end()) return false; + return opts_[i->second].is_set; + } + bool is_set(std::string const& long_opt) const override { + auto i = long_opts_.find(long_opt); + if (i == long_opts_.end()) return false; + return opts_[i->second].is_set; + } + char const* arg(char short_opt, char const* fallback) const override { + auto i = short_opts_.find(short_opt); + if (i == short_opts_.end()) return fallback; + if (!opts_[i->second].is_set) return fallback; + if (opts_[i->second].argument.empty()) return fallback; + return opts_[i->second].value.c_str(); + } + char const* arg(std::string const& long_opt, + char const* fallback) const override { + auto i = long_opts_.find(long_opt); + if (i == long_opts_.end()) return fallback; + if (!opts_[i->second].is_set) return fallback; + if (opts_[i->second].argument.empty()) return fallback; + return opts_[i->second].value.c_str(); + } + + std::vector const& arguments() const override { + return args_; + } + + void print_help(std::ostream& out) const override { + print_help(out, Terminal::size().width); + } + + void print_help(std::ostream& out, size_t width) const override { + size_t left = 0; + for (auto const& opt : opts_) { + size_t l = 0; + if (!opt.long_opt.empty()) { + l += 6 + opt.long_opt.size(); + } else if (opt.short_opt != '\0') { + l += 2; + } else { + continue; + } + if (!opt.argument.empty()) { + l += 1 + opt.argument.size(); + } + if (l > left) left = l; + } + + size_t const need = 2 + 2 + left; + if (need + 10 > width) { + width = need + 10; + } + size_t const right = width - need; + + for (auto const& opt : opts_) { + size_t i = 0; + if (!opt.long_opt.empty()) { + if (opt.short_opt != '\0') { + out << " -" << opt.short_opt << ", "; + } else { + out << " "; + } + out << "--" << opt.long_opt; + i += 8 + opt.long_opt.size(); + } else if (opt.short_opt != '\0') { + out << " -" << opt.short_opt; + i += 4; + } else { + continue; + } + if (!opt.argument.empty()) { + out << '=' << opt.argument; + i += 1 + opt.argument.size(); + } + pad(out, need - i); + if (opt.help.size() < right) { + out << opt.help << '\n'; + } else { + i = right; + while (i > 0 && !Character::isseparator(opt.help, i)) --i; + if (i == 0) i = right; + out << opt.help.substr(0, i) << '\n'; + while (true) { + while (i < opt.help.size() && Character::isspace(opt.help, i)) ++i; + if (i == opt.help.size()) break; + size_t j = right - 2; + pad(out, width - j); + if (i + j >= opt.help.size()) { + out << opt.help.substr(i) << '\n'; + break; + } + while (j > 0 && !Character::isseparator(opt.help, i + j)) --j; + if (j == 0) j = right - 2; + out << opt.help.substr(i, j) << '\n'; + i += j; + } + } + } + } + +private: + struct Option { + char const short_opt; + std::string const long_opt; + std::string const argument; + std::string const help; + + bool is_set; + std::string value; + + Option(char short_opt, std::string const& long_opt, + std::string const& argument, std::string const& help) + : short_opt(short_opt), long_opt(long_opt), argument(argument), + help(help), is_set(false) { + } + }; + bool good_; + std::unordered_map short_opts_; + std::unordered_map long_opts_; + std::vector