diff --git a/rak/functional_fun.h b/rak/functional_fun.h index 56e06646..ab1fd748 100644 --- a/rak/functional_fun.h +++ b/rak/functional_fun.h @@ -180,6 +180,21 @@ private: const Arg1 m_arg1; }; +template +class ptr_fn1_b1_t : public function_base1 { +public: + typedef Result (*Func)(Arg1, Arg2); + + ptr_fn1_b1_t(Func func, const Arg1 arg1) : m_func(func), m_arg1(arg1) {} + virtual ~ptr_fn1_b1_t() {} + + virtual Result operator () (Arg2 arg2) { return m_func(m_arg1, arg2); } + +private: + Func m_func; + Arg1 m_arg1; +}; + template function_base0* mem_fn(Object* object, Result (Object::*func)()) { @@ -210,6 +225,12 @@ bind_mem_fn(Object* object, Result (Object::*func)(Arg1), const Arg1 arg1) { return new mem_fn0_b1_t(object, func, arg1); } +template +function_base1* +bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) { + return new ptr_fn1_b1_t(func, arg1); +} + } #endif diff --git a/src/Makefile.am b/src/Makefile.am index de95b820..0d2b631f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,8 +26,6 @@ rtorrent_SOURCES = \ main.cc \ option_file.cc \ option_file.h \ - option_handler.cc \ - option_handler.h \ option_handler_rules.cc \ option_handler_rules.h \ option_parser.cc \ diff --git a/src/control.cc b/src/control.cc index da300a3e..f2f79059 100644 --- a/src/control.cc +++ b/src/control.cc @@ -45,9 +45,9 @@ #include "input/manager.h" #include "input/input_event.h" #include "ui/root.h" +#include "utils/variable_map.h" #include "command_scheduler.h" -#include "option_handler.h" #include "control.h" @@ -61,7 +61,7 @@ Control::Control() : m_inputStdin(new input::InputEvent(STDIN_FILENO)), m_commandScheduler(new CommandScheduler()), - m_optionHandler(new OptionHandler()), + m_variables(new utils::VariableMap()), m_tick(0) { @@ -69,7 +69,7 @@ Control::Control() : m_taskShutdown.set_slot(rak::mem_fn(this, &Control::receive_shutdown)); - m_commandScheduler->set_slot_command(rak::mem_fn(m_optionHandler, &OptionHandler::process_command)); + m_commandScheduler->set_slot_command(rak::mem_fn(m_variables, &utils::VariableMap::process_command)); m_commandScheduler->set_slot_error_message(rak::mem_fn(m_core, &core::Manager::push_log)); } @@ -78,7 +78,7 @@ Control::~Control() { delete m_input; delete m_commandScheduler; - delete m_optionHandler; + delete m_variables; delete m_ui; delete m_display; diff --git a/src/control.h b/src/control.h index 386dec2e..58e320e6 100644 --- a/src/control.h +++ b/src/control.h @@ -59,7 +59,10 @@ namespace input { class Manager; } -class OptionHandler; +namespace utils { + class VariableMap; +} + class CommandScheduler; class Control { @@ -82,7 +85,7 @@ public: input::InputEvent* input_stdin() { return m_inputStdin; } CommandScheduler* command_scheduler() { return m_commandScheduler; } - OptionHandler* option_handler() { return m_optionHandler; } + utils::VariableMap* variables() { return m_variables; } uint64_t tick() const { return m_tick; } void inc_tick() { m_tick++; } @@ -100,7 +103,7 @@ private: input::InputEvent* m_inputStdin; CommandScheduler* m_commandScheduler; - OptionHandler* m_optionHandler; + utils::VariableMap* m_variables; uint64_t m_tick; diff --git a/src/core/manager.cc b/src/core/manager.cc index 3dac59bd..364d015c 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -276,6 +276,18 @@ Manager::listen_open() { } } +void +Manager::bind(const std::string& addr) { + if (torrent::listen_port() != 0) { + torrent::listen_close(); + torrent::set_bind_address(addr); + listen_open(); + + } else { + torrent::set_bind_address(addr); + } +} + void Manager::initialize_bencode(Download* d) { torrent::Bencode& bencode = d->get_bencode(); diff --git a/src/core/manager.h b/src/core/manager.h index 1ebc72e6..53ed56dc 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -81,6 +81,8 @@ public: void listen_open(); + void bind(const std::string& addr); + void shutdown(bool force); DListItr insert(std::istream* s, bool printLog = true); diff --git a/src/main.cc b/src/main.cc index 438a046a..dc19839f 100644 --- a/src/main.cc +++ b/src/main.cc @@ -63,12 +63,12 @@ #include "input/bindings.h" #include "utils/directory.h" +#include "utils/variable_map.h" #include "control.h" #include "globals.h" #include "signal_handler.h" #include "option_file.h" -#include "option_handler.h" #include "option_handler_rules.h" #include "option_parser.h" #include "command_scheduler.h" @@ -91,20 +91,20 @@ is_resized() { } int -parse_options(Control* c, OptionHandler* optionHandler, int argc, char** argv) { +parse_options(Control* c, utils::VariableMap* optionHandler, int argc, char** argv) { try { OptionParser optionParser; // Converted. optionParser.insert_flag('h', sigc::ptr_fun(&print_help)); - optionParser.insert_option('b', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "bind")); - optionParser.insert_option('d', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "directory")); - optionParser.insert_option('i', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "ip")); - optionParser.insert_option('p', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "port_range")); - optionParser.insert_option('s', sigc::bind<0>(sigc::mem_fun(*optionHandler, &OptionHandler::process), "session")); + optionParser.insert_option('b', sigc::bind<0>(sigc::mem_fun(*optionHandler, &utils::VariableMap::set_string), "bind")); + optionParser.insert_option('d', sigc::bind<0>(sigc::mem_fun(*optionHandler, &utils::VariableMap::set_string), "directory")); + optionParser.insert_option('i', sigc::bind<0>(sigc::mem_fun(*optionHandler, &utils::VariableMap::set_string), "ip")); + optionParser.insert_option('p', sigc::bind<0>(sigc::mem_fun(*optionHandler, &utils::VariableMap::set_string), "port_range")); + optionParser.insert_option('s', sigc::bind<0>(sigc::mem_fun(*optionHandler, &utils::VariableMap::set_string), "session")); - optionParser.insert_option_list('o', sigc::mem_fun(*optionHandler, &OptionHandler::process)); + optionParser.insert_option_list('o', sigc::mem_fun(*optionHandler, &utils::VariableMap::set_string)); return optionParser.process(argc, argv); @@ -175,12 +175,12 @@ main(int argc, char** argv) { control.core()->initialize_first(); OptionFile optionFile; - optionFile.slot_option(sigc::mem_fun(control.option_handler(), &OptionHandler::process)); + optionFile.slot_option(sigc::mem_fun(control.variables(), &utils::VariableMap::set)); if (getenv("HOME") && !optionFile.process_file(getenv("HOME") + std::string("/.rtorrent.rc"))) control.core()->get_log_important().push_front("Could not load \"~/.rtorrent.rc\"."); - int firstArg = parse_options(&control, control.option_handler(), argc, argv); + int firstArg = parse_options(&control, control.variables(), argc, argv); control.initialize(); diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index 61d7ac09..46abf5c5 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -52,6 +52,8 @@ #include "core/manager.h" #include "ui/root.h" #include "utils/directory.h" +#include "utils/variable_generic.h" +#include "utils/variable_map.h" #include "control.h" #include "option_handler_rules.h" @@ -160,18 +162,6 @@ apply_max_open_sockets(Control* m, int arg) { torrent::set_max_open_sockets(arg); } -void -apply_bind(Control* m, const std::string& arg) { - if (torrent::listen_port() != 0) { - torrent::listen_close(); - torrent::set_bind_address(arg); - m->core()->listen_open(); - - } else { - torrent::set_bind_address(arg); - } -} - void apply_ip(Control* m, const std::string& arg) { torrent::set_local_address(arg); @@ -309,43 +299,44 @@ apply_schedule_remove(Control* m, const std::string& arg) { void initialize_option_handler(Control* c) { - c->option_handler()->insert("max_peers", new OptionHandlerInt(c, &apply_download_max_peers)); - c->option_handler()->insert("min_peers", new OptionHandlerInt(c, &apply_download_min_peers)); - c->option_handler()->insert("max_uploads", new OptionHandlerInt(c, &apply_download_max_uploads)); + c->variables()->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(c->core(), &core::Manager::bind))); - c->option_handler()->insert("download_rate", new OptionHandlerInt(c, &apply_global_download_rate)); - c->option_handler()->insert("upload_rate", new OptionHandlerInt(c, &apply_global_upload_rate)); + c->variables()->insert("ip", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_ip, c))); + c->variables()->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c))); + c->variables()->insert("port_random", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_random, c))); - c->option_handler()->insert("bind", new OptionHandlerString(c, &apply_bind)); - c->option_handler()->insert("ip", new OptionHandlerString(c, &apply_ip)); - c->option_handler()->insert("port_range", new OptionHandlerString(c, &apply_port_range)); - c->option_handler()->insert("port_random", new OptionHandlerString(c, &apply_port_random)); + c->variables()->insert("check_hash", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_check_hash, c))); + c->variables()->insert("directory", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_download_directory, c))); - c->option_handler()->insert("check_hash", new OptionHandlerString(c, &apply_check_hash)); - c->option_handler()->insert("directory", new OptionHandlerString(c, &apply_download_directory)); + c->variables()->insert("max_peers", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_max_peers, c), "%i")); + c->variables()->insert("min_peers", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_min_peers, c), "%i")); + c->variables()->insert("max_uploads", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_max_uploads, c), "%i")); - c->option_handler()->insert("hash_read_ahead", new OptionHandlerInt(c, &apply_hash_read_ahead)); - c->option_handler()->insert("hash_interval", new OptionHandlerInt(c, &apply_hash_interval)); - c->option_handler()->insert("hash_max_tries", new OptionHandlerInt(c, &apply_hash_max_tries)); - c->option_handler()->insert("max_open_files", new OptionHandlerInt(c, &apply_max_open_files)); - c->option_handler()->insert("max_open_sockets", new OptionHandlerInt(c, &apply_max_open_sockets)); + c->variables()->insert("download_rate", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_global_download_rate, c), "%i")); + c->variables()->insert("upload_rate", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_global_upload_rate, c), "%i")); - c->option_handler()->insert("umask", new OptionHandlerOctal(c, &apply_umask)); + c->variables()->insert("hash_read_ahead", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_hash_read_ahead, c), "%i")); + c->variables()->insert("hash_interval", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_hash_interval, c), "%i")); + c->variables()->insert("hash_max_tries", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_hash_max_tries, c), "%i")); + c->variables()->insert("max_open_files", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_max_open_files, c), "%i")); + c->variables()->insert("max_open_sockets", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_max_open_sockets, c), "%i")); - c->option_handler()->insert("connection_leech", new OptionHandlerString(c, &apply_connection_leech)); - c->option_handler()->insert("connection_seed", new OptionHandlerString(c, &apply_connection_seed)); + c->variables()->insert("umask", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_umask, c), "%o")); - c->option_handler()->insert("load", new OptionHandlerString(c, &apply_load)); - c->option_handler()->insert("load_start", new OptionHandlerString(c, &apply_load_start)); - c->option_handler()->insert("stop_untied", new OptionHandlerString(c, &apply_stop_untied)); - c->option_handler()->insert("remove_untied", new OptionHandlerString(c, &apply_remove_untied)); + c->variables()->insert("connection_leech", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_leech, c))); + c->variables()->insert("connection_seed", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_seed, c))); - c->option_handler()->insert("session", new OptionHandlerString(c, &apply_session_directory)); - c->option_handler()->insert("encoding_list", new OptionHandlerString(c, &apply_encoding_list)); - c->option_handler()->insert("tracker_dump", new OptionHandlerString(c, &apply_tracker_dump)); - c->option_handler()->insert("use_udp_trackers", new OptionHandlerString(c, &apply_use_udp_trackers)); + c->variables()->insert("load", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load, c))); + c->variables()->insert("load_start", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load_start, c))); + c->variables()->insert("stop_untied", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_stop_untied, c))); + c->variables()->insert("remove_untied", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_remove_untied, c))); - c->option_handler()->insert("http_proxy", new OptionHandlerString(c, &apply_http_proxy)); - c->option_handler()->insert("schedule", new OptionHandlerString(c, &apply_schedule)); - c->option_handler()->insert("schedule_remove", new OptionHandlerString(c, &apply_schedule_remove)); + c->variables()->insert("session", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_session_directory, c))); + c->variables()->insert("encoding_list", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_encoding_list, c))); + c->variables()->insert("tracker_dump", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_tracker_dump, c))); + c->variables()->insert("use_udp_trackers", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_use_udp_trackers, c))); + + c->variables()->insert("http_proxy", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_http_proxy, c))); + c->variables()->insert("schedule", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_schedule, c))); + c->variables()->insert("schedule_remove", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_schedule_remove, c))); } diff --git a/src/option_handler_rules.h b/src/option_handler_rules.h index 7f2c7256..6afc072e 100644 --- a/src/option_handler_rules.h +++ b/src/option_handler_rules.h @@ -38,16 +38,15 @@ #define RTORRENT_OPTION_HANDLER_RULES_H #include +#include #include #include -#include "option_handler.h" - class Control; void initialize_option_handler(Control* c); -class OptionHandlerInt : public OptionHandlerBase { +class OptionHandlerInt { public: typedef void (*Apply)(Control*, int); @@ -61,7 +60,7 @@ private: Apply m_apply; }; -class OptionHandlerOctal : public OptionHandlerBase { +class OptionHandlerOctal { public: typedef void (*Apply)(Control*, int); @@ -75,7 +74,7 @@ private: Apply m_apply; }; -class OptionHandlerString : public OptionHandlerBase { +class OptionHandlerString { public: typedef void (*Apply)(Control*, const std::string&); diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 107ad7ab..7c966faa 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -3,6 +3,11 @@ noinst_LIBRARIES = libsub_utils.a libsub_utils_a_SOURCES = \ directory.cc \ directory.h \ - list_focus.h + list_focus.h \ + variable.h \ + variable_generic.cc \ + variable_generic.h \ + variable_map.cc \ + variable_map.h INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) diff --git a/src/utils/variable.h b/src/utils/variable.h new file mode 100644 index 00000000..c9798316 --- /dev/null +++ b/src/utils/variable.h @@ -0,0 +1,61 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2006, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#ifndef RTORRENT_UTILS_VARIABLE_H +#define RTORRENT_UTILS_VARIABLE_H + +namespace torrent { + class Bencode; +} + +namespace utils { + +class Variable { +public: + Variable() {} + virtual ~Variable() {} + + virtual const torrent::Bencode& get() = 0; + virtual void set(const torrent::Bencode& arg) = 0; + +protected: + Variable(const Variable&); + void operator = (const Variable&); +}; + +} + +#endif diff --git a/src/utils/variable_generic.cc b/src/utils/variable_generic.cc new file mode 100644 index 00000000..f417e70d --- /dev/null +++ b/src/utils/variable_generic.cc @@ -0,0 +1,56 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2006, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#include "config.h" + +#include "variable_generic.h" + +namespace utils { + +// VariableString::~VariableString() { +// } + +// std::string +// VariableString::get() { +// return m_variable; +// } + +// void +// VariableString::set(const std::string& arg) { +// m_variable = arg; +// } + +} diff --git a/src/utils/variable_generic.h b/src/utils/variable_generic.h new file mode 100644 index 00000000..74c49ccf --- /dev/null +++ b/src/utils/variable_generic.h @@ -0,0 +1,160 @@ +// rTorrent - BitTorrent client +// Copyright (C) 2006, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#ifndef RTORRENT_UTILS_VARIABLE_GENERIC_H +#define RTORRENT_UTILS_VARIABLE_GENERIC_H + +#include +#include +#include +#include +#include +#include + +#include "variable.h" + +namespace utils { + +// class VariableS : public Variable { +// public: +// VariableString(const std::string& v = "") : m_variable(v) {} +// virtual ~VariableString(); + +// virtual const torrent::Bencode& get(); +// virtual void set(const torrent::Bencode& arg); + +// private: +// std::string m_variable; +// }; + +// VariableSlot? +template +class VariableSlotString : public Variable { +public: + typedef rak::function0 SlotGet; + typedef rak::function1 SlotSet; + + VariableSlotString(typename SlotGet::base_type* slotGet, typename SlotSet::base_type* slotSet) { + m_slotGet.set(slotGet); + m_slotSet.set(slotSet); + } + + virtual ~VariableSlotString() {} + + virtual const torrent::Bencode& get() { + m_cache = m_slotGet(); + + if (!m_cache.is_string()) + throw torrent::internal_error("VariableSlotString::get() got wrong type."); + + return m_cache; + } + + virtual void set(const torrent::Bencode& arg) { + if (!arg.is_string()) + throw torrent::internal_error("VariableSlotString::set(...) got wrong type."); + + m_slotSet(arg.as_string()); + } + +private: + SlotGet m_slotGet; + SlotSet m_slotSet; + + // Store the cache here to avoid unnessesary copying and such. This + // should not result in any unresonable memory usage since few + // strings will be very large. + torrent::Bencode m_cache; +}; + +template +class VariableSlotValue : public Variable { +public: + typedef rak::function0 SlotGet; + typedef rak::function1 SlotSet; + + VariableSlotValue(typename SlotGet::base_type* slotGet, + typename SlotSet::base_type* slotSet, + const char* pattern) { + m_slotGet.set(slotGet); + m_slotSet.set(slotSet); + m_pattern = pattern; + } + + virtual ~VariableSlotValue() {} + + virtual const torrent::Bencode& get() { + m_cache = m_slotGet(); + + // Need this? + if (!m_cache.is_value()) + throw torrent::internal_error("VariableSlotValue::get() got wrong type."); + + return m_cache; + } + + virtual void set(const torrent::Bencode& arg) { + if (arg.is_string()) { + Set v; + + if (std::sscanf(arg.as_string().c_str(), m_pattern, &v) != 1) + throw torrent::input_error("Not a value."); + + m_slotSet(v); + + } else if (arg.is_value()) { + m_slotSet(arg.as_value()); + + } else { + throw torrent::input_error("Not a value"); + } + } + +private: + SlotGet m_slotGet; + SlotSet m_slotSet; + + const char* m_pattern; + + // Store the cache here to avoid unnessesary copying and such. This + // should not result in any unresonable memory usage since few + // strings will be very large. + torrent::Bencode m_cache; +}; + +} + +#endif diff --git a/src/option_handler.cc b/src/utils/variable_map.cc similarity index 56% rename from src/option_handler.cc rename to src/utils/variable_map.cc index 0fee34ce..6ecd285a 100644 --- a/src/option_handler.cc +++ b/src/utils/variable_map.cc @@ -1,5 +1,5 @@ // rTorrent - BitTorrent client -// Copyright (C) 2005-2006, Jari Sundell +// Copyright (C) 2006, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -36,60 +36,62 @@ #include "config.h" -#include -#include -#include +#include +#include #include +#include -#include "option_handler.h" +#include "variable.h" +#include "variable_map.h" -void -OptionHandler::insert(const std::string& key, OptionHandlerBase* opt) { - iterator itr = find(key); +namespace utils { - if (itr == end()) { - Base::insert(value_type(key, opt)); - } else { - delete itr->second; - itr->second = opt; - } +VariableMap::~VariableMap() { + std::for_each(base_type::begin(), base_type::end(), rak::on(rak::mem_ptr_ref(&value_type::second), rak::call_delete())); } void -OptionHandler::erase(const std::string& key) { - iterator itr = find(key); +VariableMap::insert(const std::string& key, Variable* v) { + iterator itr = base_type::find(key); - if (itr == end()) - return; + if (itr != base_type::end()) + throw torrent::internal_error("VariableMap::insert(...) tried to insert an already existing key."); - delete itr->second; - Base::erase(itr); + base_type::insert(itr, value_type(key, v)); +} + +const torrent::Bencode& +VariableMap::get(const std::string& key) { + iterator itr = base_type::find(key); + + if (itr == base_type::end()) + throw torrent::input_error("Variable \"" + key + "\" does not exist."); + + return itr->second->get(); } void -OptionHandler::clear() { - for (iterator itr = begin(), last = end(); itr != last; ++itr) - delete itr->second; +VariableMap::set(const std::string& key, const torrent::Bencode& arg) { + iterator itr = base_type::find(key); - Base::clear(); + // Later, allow the user to create new variables. Have a slot to + // register that thing. + if (itr == base_type::end()) + throw torrent::input_error("Variable \"" + key + "\" does not exist."); + + itr->second->set(arg); } void -OptionHandler::process(const std::string& key, const std::string& arg) const { - const_iterator itr = find(key); - - if (itr == end()) - throw torrent::input_error("Could not find option key \"" + key + "\"."); - - itr->second->process(key, arg); -} - -void -OptionHandler::process_command(const std::string& command) const { +VariableMap::process_command(const std::string& command) { std::string::size_type pos = command.find('='); if (pos == std::string::npos) throw torrent::input_error("Option handler could not find '=' in command."); - process(command.substr(0, pos), command.substr(pos + 1, std::string::npos)); + // Do sscanf, check for integer. Later move and make it smarter. + + set(command.substr(0, pos), torrent::Bencode(command.substr(pos + 1, std::string::npos))); +} + } diff --git a/src/option_handler.h b/src/utils/variable_map.h similarity index 55% rename from src/option_handler.h rename to src/utils/variable_map.h index cba59c13..fe95e65e 100644 --- a/src/option_handler.h +++ b/src/utils/variable_map.h @@ -1,5 +1,5 @@ // rTorrent - BitTorrent client -// Copyright (C) 2005-2006, Jari Sundell +// Copyright (C) 2006, Jari Sundell // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -34,54 +34,44 @@ // Skomakerveien 33 // 3185 Skoppum, NORWAY -#ifndef RTORRENT_OPTION_HANDLER_H -#define RTORRENT_OPTION_HANDLER_H +#ifndef RTORRENT_UTILS_VARIABLE_MAP_H +#define RTORRENT_UTILS_VARIABLE_MAP_H #include #include +#include -// No members with dtor's allowed. -struct OptionHandlerBase { - virtual ~OptionHandlerBase() {} +namespace utils { - virtual void process(const std::string& key, const std::string& arg) = 0; -}; +class Variable; -class OptionHandler : private std::map { +class VariableMap : public std::map { public: - typedef std::map Base; - typedef Base::value_type value_type; - typedef Base::size_type size_type; + typedef std::map base_type; - typedef Base::iterator iterator; - typedef Base::reverse_iterator reverse_iterator; - typedef Base::const_iterator const_iterator; - typedef Base::const_reverse_iterator const_reverse_iterator; + using base_type::iterator; + using base_type::value_type; - using Base::empty; - using Base::size; + VariableMap() {} + ~VariableMap(); - using Base::begin; - using Base::end; - using Base::rbegin; - using Base::rend; + void insert(const std::string& key, Variable* v); - using Base::find; + // Consider taking char* start and finish instead of std::string to + // avoid copying. Or make a view class. + const torrent::Bencode& get(const std::string& key); - OptionHandler() {} - ~OptionHandler() { clear(); } - - // We take over ownership of opt. - void insert(const std::string& key, OptionHandlerBase* opt); - void erase(const std::string& key); - - void clear(); - - // The caller must catch torrent::input_error in case of bad input. - void process(const std::string& key, const std::string& arg) const; + void set(const std::string& key, const torrent::Bencode& arg); + void set_string(const std::string& key, const std::string& arg) { set(key, torrent::Bencode(arg)); } // Temporary. - void process_command(const std::string& command) const; + void process_command(const std::string& command); + +private: + VariableMap(const VariableMap&); + void operator = (const VariableMap&); }; +} + #endif