diff --git a/src/Makefile.am b/src/Makefile.am index 652eb44b..c9d45910 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,6 +15,8 @@ rtorrent_LDADD = \ rtorrent_SOURCES = \ functional.h \ main.cc \ + option_parser.cc \ + option_parser.h \ parse.cc \ parse.h \ signal_handler.cc \ diff --git a/src/core/manager.cc b/src/core/manager.cc index 2e0644ba..330d6752 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -21,7 +21,7 @@ Manager::initialize() { CurlStack::init(); torrent::initialize(); - torrent::listen_open(10000, 20000); + torrent::listen_open(m_portFirst, m_portLast); } void diff --git a/src/core/manager.h b/src/core/manager.h index 4865f335..e47639cf 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -13,11 +13,13 @@ public: typedef sigc::slot1 SlotReady; typedef sigc::slot0 SlotFailed; - DownloadList& get_download_list() { return m_downloadList; } - HashQueue& get_hash_queue() { return m_hashQueue; } - HttpQueue& get_http_queue() { return m_httpQueue; } + Manager() : m_portFirst(6890), m_portLast(6999) {} - Poll& get_poll() { return m_poll; } + DownloadList& get_download_list() { return m_downloadList; } + HashQueue& get_hash_queue() { return m_hashQueue; } + HttpQueue& get_http_queue() { return m_httpQueue; } + + Poll& get_poll() { return m_poll; } void initialize(); void cleanup(); @@ -28,6 +30,8 @@ public: void start(Download* d); void stop(Download* d); + void set_port_range(int a, int b) { m_portFirst = a; m_portLast = b; } + private: void receive_http_done(CurlGet* http); @@ -38,6 +42,9 @@ private: HashQueue m_hashQueue; HttpQueue m_httpQueue; Poll m_poll; + + int m_portFirst; + int m_portLast; }; } diff --git a/src/display/window_http_queue.cc b/src/display/window_http_queue.cc index 177c02ec..24ca3097 100644 --- a/src/display/window_http_queue.cc +++ b/src/display/window_http_queue.cc @@ -37,7 +37,7 @@ WindowHttpQueue::redraw() { } m_canvas->erase(); - m_canvas->print(0, 0, "Http [%2i]", m_container.size()); + m_canvas->print(0, 0, "Http [%i]", m_queue->size()); int pos = 10; Container::iterator itr = m_container.begin(); @@ -85,8 +85,8 @@ WindowHttpQueue::create_name(core::CurlGet* h) { n.substr(n.size() - 8) == ".TORRENT")) n = n.substr(0, n.size() - 8); - if (n.size() > 20) - n = n.substr(0, 20); + if (n.size() > 30) + n = n.substr(0, 30); return n; } diff --git a/src/main.cc b/src/main.cc index 27e15231..4765c016 100644 --- a/src/main.cc +++ b/src/main.cc @@ -20,6 +20,7 @@ #include "timer.h" #include "signal_handler.h" +#include "option_parser.h" int64_t Timer::m_cache; @@ -101,6 +102,12 @@ main(int argc, char** argv) { SignalHandler::set_handler(SIGSEGV, sigc::bind(sigc::ptr_fun(&do_panic), SIGSEGV)); SignalHandler::set_handler(SIGBUS, sigc::bind(sigc::ptr_fun(&do_panic), SIGBUS)); + OptionParser optionParser; + optionParser.insert_option('p', sigc::bind(sigc::ptr_fun(OptionParser::call_int_pair), + sigc::mem_fun(uiControl.get_core(), &core::Manager::set_port_range))); + + int firstArg = optionParser.process(argc, argv); + display::Canvas::init(); ui::DownloadList uiDownloadList(&uiControl); @@ -120,8 +127,8 @@ main(int argc, char** argv) { uiControl.get_core().initialize(); - for (int i = 1; i < argc; ++i) - uiControl.get_core().insert(argv[i]); + while (firstArg < argc) + uiControl.get_core().insert(argv[firstArg++]); uiControl.get_display().adjust_layout(); diff --git a/src/option_parser.cc b/src/option_parser.cc new file mode 100644 index 00000000..83939178 --- /dev/null +++ b/src/option_parser.cc @@ -0,0 +1,77 @@ +#include "config.h" + +#include +#include +#include +#include +#include + +#include "option_parser.h" + +void +OptionParser::insert_flag(char c, SlotFlag s) { + m_container[c].m_slot = sigc::hide(s); + m_container[c].m_useOption = false; +} + +void +OptionParser::insert_option(char c, SlotOption s) { + m_container[c].m_slot = s; + m_container[c].m_useOption = true; +} + +int +OptionParser::process(int argc, char** argv) { + int c; + std::string optString = create_optstring(); + + opterr = 0; + + while ((c = getopt(argc, argv, optString.c_str())) != -1) { + if (c == '?') { + std::stringstream s; + s << "Invalid use of option flag -" << (char)optopt; + + throw std::runtime_error(s.str()); + + } else { + call_flag(c, optarg ? optarg : ""); + } + } + + return optind; +} + +void +OptionParser::call_int_pair(const std::string& str, SlotIntPair slot) { + int a, b; + + if (sscanf(str.c_str(), "%u-%u", &a, &b) != 2) + throw std::runtime_error("Invalid argument \"" + str + "\" should be "); + + slot(a, b); +} + +std::string +OptionParser::create_optstring() { + std::string s; + + for (Container::iterator itr = m_container.begin(); itr != m_container.end(); ++itr) { + s += itr->first; + + if (itr->second.m_useOption) + s += ':'; + } + + return s; +} + +void +OptionParser::call_flag(char c, const std::string& arg) { + Container::iterator itr = m_container.find(c); + + if (itr == m_container.end()) + throw std::logic_error("OptionParser::call_flag(...) could not find the flag"); + + itr->second.m_slot(arg); +} diff --git a/src/option_parser.h b/src/option_parser.h new file mode 100644 index 00000000..425ff962 --- /dev/null +++ b/src/option_parser.h @@ -0,0 +1,39 @@ +#ifndef RTORRENT_OPTION_PARSER_H +#define RTORRENT_OPTION_PARSER_H + +#include +#include +#include + +// Throws std::runtime_error upon receiving bad input. + +class OptionParser { +public: + typedef sigc::slot0 SlotFlag; + typedef sigc::slot1 SlotOption; + typedef sigc::slot2 SlotIntPair; + + struct Node { + SlotOption m_slot; + bool m_useOption; + }; + + typedef std::map Container; + + void insert_flag(char c, SlotFlag s); + void insert_option(char c, SlotOption s); + + // Returns the index of the first non-option argument. + int process(int argc, char** argv); + + static void call_int_pair(const std::string& str, SlotIntPair slot); + +private: + std::string create_optstring(); + + void call_flag(char c, const std::string& arg); + + Container m_container; +}; + +#endif