* Moved hash and torrent size checking to initialize so it will be

caught when loading a torrent.

* Added VariableMap to core::Download and started moving various
settings.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@624 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2006-01-19 17:13:25 +00:00
parent e8cd37ea3a
commit 52636178d1
14 changed files with 242 additions and 114 deletions
+1 -1
View File
@@ -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)
+6 -5
View File
@@ -321,14 +321,10 @@ bind1st(const Operation& op, const Type& val) {
template <typename Operation>
class bind2nd_t : public std::unary_function<typename Operation::first_argument_type,
typename Operation::result_type> {
protected:
public:
typedef typename reference_fix<typename Operation::first_argument_type>::type argument_type;
typedef typename reference_fix<typename Operation::second_argument_type>::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 <typename Operation, typename Type>
+20
View File
@@ -180,6 +180,20 @@ private:
const Arg1 m_arg1;
};
template <typename Result, typename Arg1>
class ptr_fn1_t : public function_base1<Result, Arg1> {
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 <typename Result, typename Arg1, typename Arg2>
class ptr_fn1_b1_t : public function_base1<Result, Arg2> {
public:
@@ -225,6 +239,12 @@ bind_mem_fn(Object* object, Result (Object::*func)(Arg1), const Arg1 arg1) {
return new mem_fn0_b1_t<Object, Result, Arg1>(object, func, arg1);
}
template <typename Result, typename Arg1>
function_base1<Result, Arg1>*
ptr_fn(Result (*func)(Arg1)) {
return new ptr_fn1_t<Result, Arg1>(func);
}
template <typename Result, typename Arg1, typename Arg2>
function_base1<Result, Arg2>*
bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) {
+29 -13
View File
@@ -42,6 +42,8 @@
#include <sigc++/signal.h>
#include <torrent/exceptions.h>
#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<const char*, const std::string&>(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<std::string, const std::string&>(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<uint32_t, uint32_t>(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() : ""));
}
}
+15 -17
View File
@@ -41,6 +41,8 @@
#include <torrent/download.h>
#include <torrent/torrent.h>
#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
+23 -11
View File
@@ -42,6 +42,8 @@
#include <torrent/bencode.h>
#include <torrent/exceptions.h>
#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);
+6 -4
View File
@@ -45,6 +45,8 @@
#include <sigc++/slot.h>
#include <rak/priority_queue_default.h>
#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;
+7 -4
View File
@@ -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<core::DownloadFactory>), 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<std::string>::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++;
+5 -5
View File
@@ -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++;
+17 -44
View File
@@ -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<void, uint32_t, &torrent::Download::set_uploads_max>), 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<int, int>(NULL, rak::bind_ptr_fn(&apply_download_max_peers, c), "%i"));
variables->insert("min_peers", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_download_min_peers, c), "%i"));
variables->insert("max_uploads", new utils::VariableSlotValue<int, int>(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<int, int>(NULL, rak::bind_ptr_fn(&apply_max_open_files, c), "%i"));
variables->insert("max_open_sockets", new utils::VariableSlotValue<int, int>(NULL, rak::bind_ptr_fn(&apply_max_open_sockets, c), "%i"));
variables->insert("umask", new utils::VariableSlotValue<int, int>(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<int, int>(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)));
+61
View File
@@ -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.");
}
}
}
+30
View File
@@ -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 <typename Get = std::string, typename Set = const std::string&>
class VariableSlotString : public Variable {
public:
+7 -7
View File
@@ -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<char>(), '"'));
@@ -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());
+15 -3
View File
@@ -48,6 +48,7 @@ class Variable;
class VariableMap : public std::map<std::string, Variable*> {
public:
typedef std::map<std::string, Variable*> 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