diff --git a/configure.ac b/configure.ac index 2719fc7e..ff14d3a8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(rtorrent, 0.4.2, jaris@ifi.uio.no) +AC_INIT(rtorrent, 0.4.3, jaris@ifi.uio.no) AM_INIT_AUTOMAKE AM_CONFIG_HEADER(config.h) diff --git a/rak/functional.h b/rak/functional.h index 85d9ff2d..278c942f 100644 --- a/rak/functional.h +++ b/rak/functional.h @@ -321,14 +321,10 @@ bind1st(const Operation& op, const Type& val) { template class bind2nd_t : public std::unary_function { -protected: +public: typedef typename reference_fix::type argument_type; typedef typename reference_fix::type value_type; - Operation m_op; - value_type m_value; - -public: bind2nd_t(const Operation& op, const value_type v) : m_op(op), m_value(v) {} @@ -336,6 +332,11 @@ public: operator () (const argument_type arg) { return m_op(arg, m_value); } + +protected: + Operation m_op; + value_type m_value; + }; template diff --git a/rak/functional_fun.h b/rak/functional_fun.h index ab1fd748..8b62fc6d 100644 --- a/rak/functional_fun.h +++ b/rak/functional_fun.h @@ -180,6 +180,20 @@ private: const Arg1 m_arg1; }; +template +class ptr_fn1_t : public function_base1 { +public: + typedef Result (*Func)(Arg1); + + ptr_fn1_t(Func func) : m_func(func) {} + virtual ~ptr_fn1_t() {} + + virtual Result operator () (Arg1 arg1) { return m_func(arg1); } + +private: + Func m_func; +}; + template class ptr_fn1_b1_t : public function_base1 { public: @@ -225,6 +239,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* +ptr_fn(Result (*func)(Arg1)) { + return new ptr_fn1_t(func); +} + template function_base1* bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) { diff --git a/src/core/download.cc b/src/core/download.cc index 0c594076..b759b8c2 100644 --- a/src/core/download.cc +++ b/src/core/download.cc @@ -42,6 +42,8 @@ #include #include +#include "utils/variable_generic.h" + #include "download.h" namespace core { @@ -49,15 +51,25 @@ namespace core { Download::Download(torrent::Download d) : m_download(d), - m_chunksFailed(0), - m_connectionLeech(torrent::Download::CONNECTION_LEECH), - m_connectionSeed(torrent::Download::CONNECTION_SEED) { + m_chunksFailed(0) { m_connTrackerSucceded = m_download.signal_tracker_succeded(sigc::bind(sigc::mem_fun(*this, &Download::receive_tracker_msg), "")); m_connTrackerFailed = m_download.signal_tracker_failed(sigc::mem_fun(*this, &Download::receive_tracker_msg)); m_connStorageError = m_download.signal_storage_error(sigc::mem_fun(*this, &Download::receive_storage_error)); m_download.signal_chunk_failed(sigc::mem_fun(*this, &Download::receive_chunk_failed)); + + m_variables.insert("connection_current", new utils::VariableSlotString(rak::mem_fn(this, &Download::connection_current), + rak::mem_fn(this, &Download::set_connection_current))); + m_variables.insert("connection_leech", new utils::VariableValue(connection_type_to_string(torrent::Download::CONNECTION_LEECH))); + m_variables.insert("connection_seed", new utils::VariableValue(connection_type_to_string(torrent::Download::CONNECTION_SEED))); + m_variables.insert("directory", new utils::VariableSlotString(NULL, + rak::mem_fn(this, &Download::set_root_directory))); + m_variables.insert("tied_to_file", new utils::VariableBencode(&m_download.bencode(), "tied_to_file", torrent::Bencode::TYPE_STRING)); + + m_variables.insert("peers_min", new utils::VariableSlotValue(rak::mem_fn(&m_download, &torrent::Download::peers_min), + rak::mem_fn(&m_download, &torrent::Download::set_peers_min), + "%u")); } Download::~Download() { @@ -74,23 +86,16 @@ Download::~Download() { void Download::start() { if (is_done()) { - m_download.set_connection_type(m_connectionSeed); + m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_seed").as_string())); torrent::download_set_priority(m_download, 2); } else { - m_download.set_connection_type(m_connectionLeech); + m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_leech").as_string())); torrent::download_set_priority(m_download, 4); } m_download.start(); } -void -Download::set_root_directory(const std::string& d) { - m_download.set_root_dir(d + - (!d.empty() && *d.rbegin() != '/' ? "/" : "") + - (m_download.size_file_entries() > 1 ? m_download.name() : "")); -} - void Download::enable_udp_trackers(bool state) { for (int i = 0, last = m_download.size_trackers(); i < last; ++i) @@ -103,7 +108,7 @@ Download::enable_udp_trackers(bool state) { void Download::receive_finished() { - m_download.set_connection_type(m_connectionSeed); + m_download.set_connection_type(string_to_connection_type(m_variables.get("connection_seed").as_string())); torrent::download_set_priority(m_download, 2); } @@ -148,4 +153,15 @@ Download::receive_chunk_failed(uint32_t idx) { m_chunksFailed++; } +// Clean up. +void +Download::set_root_directory(const std::string& d) { + if (d.empty()) + m_download.set_root_dir("./" + (m_download.size_file_entries() > 1 ? m_download.name() : std::string())); + else + m_download.set_root_dir(d + + (*d.rbegin() != '/' ? "/" : "") + + (m_download.size_file_entries() > 1 ? m_download.name() : "")); +} + } diff --git a/src/core/download.h b/src/core/download.h index 8cb4591e..6b4d4327 100644 --- a/src/core/download.h +++ b/src/core/download.h @@ -41,6 +41,8 @@ #include #include +#include "utils/variable_map.h" + namespace core { class Download { @@ -55,6 +57,9 @@ public: void start(); + utils::VariableMap* variables() { return &m_variables; } + std::string variable_string(const std::string& key) { return m_variables.get_string(key); } + torrent::Download& get_download() { return m_download; } const torrent::Download& get_download() const { return m_download; } std::string get_hash() { return m_download.info_hash(); } @@ -64,18 +69,6 @@ public: uint32_t chunks_failed() const { return m_chunksFailed; } - void set_root_directory(const std::string& d); - - ConnType get_connection_current() const { return m_download.connection_type(); } - ConnType get_connection_leech() const { return m_connectionLeech; } - ConnType get_connection_seed() const { return m_connectionSeed; } - - void set_connection_leech(const std::string& name) { m_connectionLeech = string_to_connection_type(name); } - void set_connection_seed(const std::string& name) { m_connectionSeed = string_to_connection_type(name); } - - const std::string& tied_to_file() const { return m_tiedToFile; } - void set_tied_to_file(const std::string& str) { m_tiedToFile = str; } - void enable_udp_trackers(bool state); // Helper functions for calling functions in torrent::Download @@ -94,24 +87,29 @@ public: static const char* connection_type_to_string(ConnType t); private: + Download(const Download&); + void operator () (const Download&); + void receive_tracker_msg(std::string msg); void receive_storage_error(std::string msg); void receive_chunk_failed(uint32_t idx); + const char* connection_current() const { return connection_type_to_string(m_download.connection_type()); } + void set_connection_current(const std::string& t) { return m_download.set_connection_type(string_to_connection_type(t.c_str())); } + + void set_root_directory(const std::string& d); + torrent::Download m_download; std::string m_message; uint32_t m_chunksFailed; - ConnType m_connectionLeech; - ConnType m_connectionSeed; - - std::string m_tiedToFile; - sigc::connection m_connTrackerSucceded; sigc::connection m_connTrackerFailed; sigc::connection m_connStorageError; + + utils::VariableMap m_variables; }; inline bool diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index 669371eb..6d5af71f 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -42,6 +42,8 @@ #include #include +#include "utils/variable_generic.h" + #include "curl_get.h" #include "http_queue.h" #include "globals.h" @@ -60,12 +62,16 @@ DownloadFactory::DownloadFactory(const std::string& uri, Manager* m) : m_uri(uri), m_session(false), m_start(false), - m_printLog(true), - m_tiedToFile(false) { + m_printLog(true) { m_taskLoad.set_slot(rak::mem_fn(this, &DownloadFactory::receive_load)); m_taskCommit.set_slot(rak::mem_fn(this, &DownloadFactory::receive_commit)); -} + + m_variables.insert("connection_leech", new utils::VariableValue(control->variables()->get("connection_leech"))); + m_variables.insert("connection_seed", new utils::VariableValue(control->variables()->get("connection_seed"))); + m_variables.insert("directory", new utils::VariableValue(control->variables()->get("directory"))); + m_variables.insert("tied_to_file", new utils::VariableBool(false)); +} DownloadFactory::~DownloadFactory() { priority_queue_erase(&taskScheduler, &m_taskLoad); @@ -98,7 +104,7 @@ DownloadFactory::receive_load() { (*itr)->signal_done().slots().push_front(sigc::mem_fun(*this, &DownloadFactory::receive_loaded)); (*itr)->signal_failed().slots().push_front(sigc::mem_fun(*this, &DownloadFactory::receive_failed)); - m_tiedToFile = false; + m_variables.set("tied_to_file", (int64_t)false); } else { m_stream = new std::fstream(m_uri.c_str(), std::ios::in); @@ -140,6 +146,14 @@ DownloadFactory::receive_success() { return; } + // Move to 'rtorrent'. + (*itr)->variables()->set("connection_leech", m_variables.get("connection_leech")); + (*itr)->variables()->set("connection_seed", m_variables.get("connection_seed")); + (*itr)->variables()->set("directory", m_variables.get("directory")); + +// if (control->variables()->get("peers_min") +// (*itr)->variables()->set("peers_min", m_variables.get("directory")); + torrent::Bencode& bencode = (*itr)->get_bencode(); if (m_session) { @@ -147,18 +161,16 @@ DownloadFactory::receive_success() { if (bencode.get_key("rtorrent").get_key("state").as_string() == "started") m_manager->start(*itr, m_printLog); - if (bencode.get_key("rtorrent").has_key("tied") && - bencode.get_key("rtorrent").get_key("tied").is_string()) - (*itr)->set_tied_to_file(bencode.get_key("rtorrent").get_key("tied").as_string()); + // Consider adding an empty 'tied_to_file' here if not present. } else { // Remove the settings if this isn't a session torrent. //bencode.erase_key("rtorrent"); - if (m_tiedToFile) { - (*itr)->set_tied_to_file(m_uri); - bencode.get_key("rtorrent").insert_key("tied", m_uri); - } + if (m_variables.get("tied_to_file").as_value()) + (*itr)->variables()->set("tied_to_file", m_uri); + else + (*itr)->variables()->set("tied_to_file", std::string()); if (m_start) m_manager->start(*itr, m_printLog); diff --git a/src/core/download_factory.h b/src/core/download_factory.h index 688f216a..bdc6d4a0 100644 --- a/src/core/download_factory.h +++ b/src/core/download_factory.h @@ -45,6 +45,8 @@ #include #include +#include "utils/variable_map.h" + #include "http_queue.h" namespace core { @@ -65,6 +67,8 @@ public: void load(); void commit(); + utils::VariableMap* variables() { return &m_variables; } + bool get_session() const { return m_session; } void set_session(bool v) { m_session = v; } @@ -74,9 +78,6 @@ public: bool print_log() const { return m_printLog; } void set_print_log(bool v) { m_printLog = v; } - bool tied_to_file() const { return m_tiedToFile; } - void set_tied_to_file(bool v) { m_tiedToFile = v; } - void slot_finished(Slot s) { m_slotFinished = s; } private: @@ -96,7 +97,8 @@ private: bool m_session; bool m_start; bool m_printLog; - bool m_tiedToFile; + + utils::VariableMap m_variables; Slot m_slotFinished; rak::priority_item m_taskLoad; diff --git a/src/core/manager.cc b/src/core/manager.cc index ccafede6..8ef17881 100644 --- a/src/core/manager.cc +++ b/src/core/manager.cc @@ -80,10 +80,12 @@ connect_signal_storage_log(Download* d, torrent::Download::SlotString s) { // Hmm... find some better place for all this. static void delete_tied(Download* d) { + const std::string tie = d->variables()->get("tied_to_file").as_string(); + // This should be configurable, need to wait for the variable // thingie to be implemented. - if (!d->tied_to_file().empty()) - ::unlink(d->tied_to_file().c_str()); + if (!tie.empty()) + ::unlink(tie.c_str()); } Manager::Manager() : @@ -338,9 +340,10 @@ Manager::try_create_download(const std::string& uri, bool start, bool printLog, // Adding download. DownloadFactory* f = new DownloadFactory(uri, this); + f->variables()->set("tied_to_file", tied ? "yes" : "no"); + f->set_start(start); f->set_print_log(printLog); - f->set_tied_to_file(tied); f->slot_finished(sigc::bind(sigc::ptr_fun(&rak::call_delete_func), f)); f->load(); f->commit(); @@ -402,7 +405,7 @@ Manager::try_create_download_expand(const std::string& uri, bool start, bool pri if (tied) for (std::vector::iterator itr = paths.begin(); itr != paths.end(); ) if (std::find_if(m_downloadList.begin(), m_downloadList.end(), - rak::equal(*itr, std::mem_fun(&Download::tied_to_file))) != m_downloadList.end()) + rak::equal(*itr, rak::bind2nd(std::mem_fun(&Download::variable_string), "tied_to_file"))) != m_downloadList.end()) itr = paths.erase(itr); else itr++; diff --git a/src/display/window_peer_info.cc b/src/display/window_peer_info.cc index 5438c5fc..e9dbe9da 100644 --- a/src/display/window_peer_info.cc +++ b/src/display/window_peer_info.cc @@ -80,11 +80,11 @@ WindowPeerInfo::redraw() { y++; m_canvas->print(0, y++, "Connection Type: %s ( %s / %s )", - core::Download::connection_type_to_string(m_download->get_connection_current()), - core::Download::connection_type_to_string(m_download->get_connection_leech()), - core::Download::connection_type_to_string(m_download->get_connection_seed())); - m_canvas->print(0, y++, "Tied to file: %s", - m_download->tied_to_file().c_str()); + m_download->variables()->get("connection_current").as_string().c_str(), + m_download->variables()->get("connection_seed").as_string().c_str(), + m_download->variables()->get("connection_leech").as_string().c_str()); + + m_canvas->print(0, y++, "Tied to file: %s", m_download->variable_string("tied_to_file").c_str()); y++; diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc index a8872f1d..c828e08d 100644 --- a/src/option_handler_rules.cc +++ b/src/option_handler_rules.cc @@ -103,26 +103,6 @@ apply_download_max_uploads(Control* m, int arg) { m->core()->get_download_list().slot_map_insert()["1_max_uploads"] = sigc::bind(sigc::mem_fun(&core::Download::call), arg); } -void -apply_download_directory(Control* m, const std::string& arg) { - if (!arg.empty()) - m->core()->get_download_list().slot_map_insert()["1_directory"] = sigc::bind(sigc::mem_fun(&core::Download::set_root_directory), arg); - else - m->core()->get_download_list().slot_map_insert().erase("1_directory"); -} - -void -apply_connection_leech(Control* m, const std::string& arg) { - core::Download::string_to_connection_type(arg); - m->core()->get_download_list().slot_map_insert()["1_connection_leech"] = sigc::bind(sigc::mem_fun(&core::Download::set_connection_leech), arg); -} - -void -apply_connection_seed(Control* m, const std::string& arg) { - core::Download::string_to_connection_type(arg); - m->core()->get_download_list().slot_map_insert()["1_connection_seed"] = sigc::bind(sigc::mem_fun(&core::Download::set_connection_seed), arg); -} - void apply_global_download_rate(Control* m, int arg) { m->ui()->set_down_throttle(arg); @@ -134,7 +114,7 @@ apply_global_upload_rate(Control* m, int arg) { } void -apply_umask(Control* m, int arg) { +apply_umask(int arg) { umask(arg); } @@ -163,11 +143,6 @@ apply_max_open_sockets(Control* m, int arg) { torrent::set_max_open_sockets(arg); } -void -apply_ip(Control* m, const std::string& arg) { - torrent::set_local_address(arg); -} - // The arg string *must* have been checked with validate_port_range // first. void @@ -215,14 +190,13 @@ apply_stop_untied(Control* m, const std::string& arg) { core::Manager::DListItr itr = m->core()->get_download_list().begin(); while ((itr = std::find_if(itr, m->core()->get_download_list().end(), - rak::on(std::mem_fun(&core::Download::tied_to_file), std::not1(std::mem_fun_ref(&std::string::empty))))) + rak::on(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"), + std::not1(std::mem_fun_ref(&std::string::empty))))) != m->core()->get_download_list().end()) { rak::file_stat fs; - if (!fs.update((*itr)->tied_to_file())) { - (*itr)->set_tied_to_file(std::string()); - (*itr)->get_bencode().get_key("rtorrent").erase_key("tied"); - + if (!fs.update((*itr)->variable_string("tied_to_file"))) { + (*itr)->variables()->set("tied_to_file", std::string()); m->core()->stop(*itr); } @@ -235,14 +209,13 @@ apply_remove_untied(Control* m, const std::string& arg) { core::Manager::DListItr itr = m->core()->get_download_list().begin(); while ((itr = std::find_if(itr, m->core()->get_download_list().end(), - rak::on(std::mem_fun(&core::Download::tied_to_file), std::not1(std::mem_fun_ref(&std::string::empty))))) + rak::on(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"), + std::not1(std::mem_fun_ref(&std::string::empty))))) != m->core()->get_download_list().end()) { rak::file_stat fs; - if (!fs.update((*itr)->tied_to_file())) { - (*itr)->set_tied_to_file(std::string()); - (*itr)->get_bencode().get_key("rtorrent").erase_key("tied"); - + if (!fs.update((*itr)->variable_string("tied_to_file"))) { + (*itr)->variables()->set("tied_to_file", std::string()); m->core()->stop(*itr); itr = m->core()->erase(itr); @@ -294,15 +267,18 @@ initialize_option_handler(Control* c) { variables->insert("port_random", new utils::VariableValue("yes")); variables->insert("session", new utils::VariableSlotString<>(NULL, rak::mem_fn(&control->core()->get_download_store(), &core::DownloadStore::use))); + variables->insert("connection_leech", new utils::VariableValue("leech")); + variables->insert("connection_seed", new utils::VariableValue("seed")); + + variables->insert("directory", new utils::VariableValue(std::string())); + variables->insert("ip", new utils::VariableSlotString<>(NULL, rak::ptr_fn(&torrent::set_local_address))); + // Old. variables->insert("bind", new utils::VariableSlotString<>(NULL, rak::mem_fn(control->core(), &core::Manager::bind))); - - variables->insert("ip", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_ip, c))); variables->insert("port_range", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_port_range, c))); - variables->insert("directory", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_download_directory, c))); - variables->insert("max_peers", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_max_peers, c), "%i")); + variables->insert("min_peers", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_min_peers, c), "%i")); variables->insert("max_uploads", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_download_max_uploads, c), "%i")); @@ -315,10 +291,7 @@ initialize_option_handler(Control* c) { variables->insert("max_open_files", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_max_open_files, c), "%i")); variables->insert("max_open_sockets", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_max_open_sockets, c), "%i")); - variables->insert("umask", new utils::VariableSlotValue(NULL, rak::bind_ptr_fn(&apply_umask, c), "%o")); - - variables->insert("connection_leech", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_leech, c))); - variables->insert("connection_seed", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_connection_seed, c))); + variables->insert("umask", new utils::VariableSlotValue(NULL, rak::ptr_fn(&apply_umask), "%o")); variables->insert("load", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load, c))); variables->insert("load_start", new utils::VariableSlotString<>(NULL, rak::bind_ptr_fn(&apply_load_start, c))); diff --git a/src/utils/variable_generic.cc b/src/utils/variable_generic.cc index 469164ae..604fd993 100644 --- a/src/utils/variable_generic.cc +++ b/src/utils/variable_generic.cc @@ -53,4 +53,65 @@ VariableValue::set(const torrent::Bencode& arg) { m_variable = arg; } +VariableBool::~VariableBool() { +} + +const torrent::Bencode& +VariableBool::get() { + return m_variable; +} + +void +VariableBool::set(const torrent::Bencode& arg) { + if (arg.is_value()) { + m_variable = arg.as_value() ? (int64_t)1 : (int64_t)0; + + } else if (arg.is_string()) { + + if (arg.as_string() == "yes" || + arg.as_string() == "true") + m_variable = (int64_t)1; + + else if (arg.as_string() == "no" || + arg.as_string() == "false") + m_variable = (int64_t)0; + + else + throw torrent::input_error("String does not parse as a boolean."); + + } else { + throw torrent::input_error("Input is not a boolean."); + } +} + +VariableBencode::~VariableBencode() { +} + +const torrent::Bencode& +VariableBencode::get() { + return m_bencode->get_key(m_key); +} + +void +VariableBencode::set(const torrent::Bencode& arg) { + // Consider removing if TYPE_NONE. + + switch (m_type) { + case torrent::Bencode::TYPE_NONE: + m_bencode->insert_key(m_key, arg); + break; + + case torrent::Bencode::TYPE_STRING: + if (arg.get_type() == torrent::Bencode::TYPE_STRING) + m_bencode->insert_key(m_key, arg); + else + throw torrent::input_error("VariableBencode could not convert to string."); + + break; + + default: + throw torrent::input_error("VariableBencode unsupported type restriction."); + } +} + } diff --git a/src/utils/variable_generic.h b/src/utils/variable_generic.h index 040b9656..ecda2c7c 100644 --- a/src/utils/variable_generic.h +++ b/src/utils/variable_generic.h @@ -61,6 +61,36 @@ private: torrent::Bencode m_variable; }; +class VariableBool : public Variable { +public: + VariableBool(bool state) : m_variable(state ? (int64_t)1 : (int64_t)0) {} + VariableBool(const torrent::Bencode& v = torrent::Bencode((int64_t)0)) { set(v); } + virtual ~VariableBool(); + + virtual const torrent::Bencode& get(); + virtual void set(const torrent::Bencode& arg); + +private: + torrent::Bencode m_variable; +}; + +class VariableBencode : public Variable { +public: + typedef torrent::Bencode::Type Type; + + VariableBencode(torrent::Bencode* b, const std::string& key, Type t = torrent::Bencode::TYPE_NONE) : + m_bencode(b), m_key(key), m_type(t) {} + virtual ~VariableBencode(); + + virtual const torrent::Bencode& get(); + virtual void set(const torrent::Bencode& arg); + +private: + torrent::Bencode* m_bencode; + std::string m_key; + Type m_type; +}; + template class VariableSlotString : public Variable { public: diff --git a/src/utils/variable_map.cc b/src/utils/variable_map.cc index 0589a26e..6d941ae3 100644 --- a/src/utils/variable_map.cc +++ b/src/utils/variable_map.cc @@ -60,7 +60,7 @@ VariableMap::insert(const std::string& key, Variable* v) { base_type::insert(itr, value_type(key, v)); } -const torrent::Bencode& +const VariableMap::mapped_type& VariableMap::get(const std::string& key) { iterator itr = base_type::find(key); @@ -71,7 +71,7 @@ VariableMap::get(const std::string& key) { } void -VariableMap::set(const std::string& key, const torrent::Bencode& arg) { +VariableMap::set(const std::string& key, const mapped_type& arg) { iterator itr = base_type::find(key); // Later, allow the user to create new variables. Have a slot to @@ -94,7 +94,7 @@ parse_name(std::string::const_iterator first, std::string::const_iterator last, } std::string::const_iterator -parse_unknown(std::string::const_iterator first, std::string::const_iterator last, torrent::Bencode* dest) { +parse_unknown(std::string::const_iterator first, std::string::const_iterator last, VariableMap::mapped_type* dest) { if (*first == '"') { std::string::const_iterator next = std::find_if(++first, last, std::bind2nd(std::equal_to(), '"')); @@ -116,11 +116,11 @@ parse_unknown(std::string::const_iterator first, std::string::const_iterator las } std::string::const_iterator -parse_args(std::string::const_iterator first, std::string::const_iterator last, torrent::Bencode::List* dest) { +parse_args(std::string::const_iterator first, std::string::const_iterator last, VariableMap::mapped_type::List* dest) { first = std::find_if(first, last, std::not1(std::ptr_fun(&std::isspace))); while (first != last) { - dest->push_back(torrent::Bencode()); + dest->push_back(VariableMap::mapped_type()); first = parse_unknown(first, last, &dest->back()); first = std::find_if(first, last, std::not1(std::ptr_fun(&std::isspace))); @@ -148,11 +148,11 @@ VariableMap::process_command(const std::string& command) { if (pos == command.end() || *pos != '=') throw torrent::input_error("Could not find '='."); - torrent::Bencode args(torrent::Bencode::TYPE_LIST); + mapped_type args(mapped_type::TYPE_LIST); parse_args(pos + 1, command.end(), &args.as_list()); if (args.as_list().empty()) - set(key, torrent::Bencode()); + set(key, mapped_type()); else if (++args.as_list().begin() == args.as_list().end()) set(key, *args.as_list().begin()); diff --git a/src/utils/variable_map.h b/src/utils/variable_map.h index fe95e65e..cfc7ca2d 100644 --- a/src/utils/variable_map.h +++ b/src/utils/variable_map.h @@ -48,6 +48,7 @@ class Variable; class VariableMap : public std::map { public: typedef std::map base_type; + typedef torrent::Bencode mapped_type; using base_type::iterator; using base_type::value_type; @@ -59,10 +60,11 @@ public: // 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); + const mapped_type& get(const std::string& key); + std::string get_string(const std::string& key); - 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)); } + void set(const std::string& key, const mapped_type& arg); + void set_string(const std::string& key, const std::string& arg) { set(key, mapped_type(arg)); } // Temporary. void process_command(const std::string& command); @@ -72,6 +74,16 @@ private: void operator = (const VariableMap&); }; +inline std::string +VariableMap::get_string(const std::string& key) { + const mapped_type& v = get(key); + + if (v.get_type() == mapped_type::TYPE_NONE) + return std::string(); + else + return v.as_string(); +} + } #endif