* Make VariableMap handle both global and core::Download

variables. Variable now has functions for both void and
core::Download*, where the core::Download* is discarded if necessary.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@847 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2007-01-17 15:18:33 +00:00
parent d030c5401e
commit e59b5bf7b6
19 changed files with 414 additions and 133 deletions
+20
View File
@@ -294,6 +294,26 @@ on(Src s, Dest d) {
return on_t<Src, Dest>(s, d);
}
template <typename Src, typename Dest>
struct on2_t : public std::binary_function<typename Src::argument_type, typename Dest::second_argument_type, typename Dest::result_type> {
typedef typename Dest::result_type result_type;
on2_t(Src s, Dest d) : m_dest(d), m_src(s) {}
result_type operator () (typename reference_fix<typename Src::argument_type>::type first, typename reference_fix<typename Dest::second_argument_type>::type second) {
return m_dest(m_src(first), second);
}
Dest m_dest;
Src m_src;
};
template <typename Src, typename Dest>
inline on2_t<Src, Dest>
on2(Src s, Dest d) {
return on2_t<Src, Dest>(s, d);
}
// Creates a functor for accessing a member.
template <typename Class, typename Member>
struct mem_ptr_t : public std::unary_function<Class*, Member&> {
+97 -1
View File
@@ -52,6 +52,7 @@
#define RAK_FUNCTIONAL_FUN_H
#include <memory>
#include <functional>
namespace rak {
@@ -64,13 +65,21 @@ public:
};
template <typename Result, typename Arg1>
class function_base1 {
class function_base1 : public std::unary_function<Arg1, Result> {
public:
virtual ~function_base1() {}
virtual Result operator () (Arg1 arg1) = 0;
};
template <typename Result, typename Arg1, typename Arg2>
class function_base2 : public std::binary_function<Arg1, Arg2, Result> {
public:
virtual ~function_base2() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) = 0;
};
template <typename Result>
class function0 {
public:
@@ -105,6 +114,23 @@ private:
std::auto_ptr<base_type> m_base;
};
template <typename Result, typename Arg1, typename Arg2>
class function2 {
public:
typedef Result result_type;
typedef function_base2<Result, Arg1, Arg2> base_type;
bool is_valid() const { return m_base.get() != NULL; }
void set(base_type* base) { m_base = std::auto_ptr<base_type>(base); }
base_type* release() { return m_base.release(); }
Result operator () (Arg1 arg1, Arg2 arg2) { return (*m_base)(arg1, arg2); }
private:
std::auto_ptr<base_type> m_base;
};
template <typename Result>
class ptr_fn0_t : public function_base0<Result> {
public:
@@ -256,6 +282,37 @@ private:
Arg1 m_arg1;
};
template <typename Ftor>
class ftor_fn1_t : public function_base1<typename Ftor::result_type, typename Ftor::argument_type> {
public:
typedef typename Ftor::result_type result_type;
typedef typename Ftor::argument_type argument_type;
ftor_fn1_t(Ftor ftor) : m_ftor(ftor) {}
virtual ~ftor_fn1_t() {}
virtual result_type operator () (argument_type arg1) { return m_ftor(arg1); }
private:
Ftor m_ftor;
};
template <typename Ftor>
class ftor_fn2_t : public function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type> {
public:
typedef typename Ftor::result_type result_type;
typedef typename Ftor::first_argument_type first_argument_type;
typedef typename Ftor::second_argument_type second_argument_type;
ftor_fn2_t(Ftor ftor) : m_ftor(ftor) {}
virtual ~ftor_fn2_t() {}
virtual result_type operator () (first_argument_type arg1, second_argument_type arg2) { return m_ftor(arg1, arg2); }
private:
Ftor m_ftor;
};
template <typename Result>
class value_fn0_t : public function_base0<Result> {
public:
@@ -299,6 +356,22 @@ private:
src_type m_object;
};
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
class convert_fn2_t : public function_base2<Result, Arg1, Arg2> {
public:
typedef function2<SrcResult, SrcArg1, SrcArg2> src_type;
convert_fn2_t(typename src_type::base_type* object) { m_object.set(object); }
virtual ~convert_fn2_t() {}
virtual Result operator () (Arg1 arg1, Arg2 arg2) {
return m_object(arg1, arg2);
}
private:
src_type m_object;
};
template <typename Result>
inline function_base0<Result>*
ptr_fn(Result (*func)()) {
@@ -359,6 +432,18 @@ bind_ptr_fn(Result (*func)(Arg1, Arg2), const Arg1 arg1) {
return new ptr_fn1_b1_t<Result, Arg1, Arg2>(func, arg1);
}
template <typename Ftor>
inline function_base1<typename Ftor::result_type, typename Ftor::argument_type>*
ftor_fn1(Ftor ftor) {
return new ftor_fn1_t<Ftor>(ftor);
}
template <typename Ftor>
inline function_base2<typename Ftor::result_type, typename Ftor::first_argument_type, typename Ftor::second_argument_type>*
ftor_fn2(Ftor ftor) {
return new ftor_fn2_t<Ftor>(ftor);
}
template <typename Result>
inline function_base0<Result>*
value_fn(const Result& val) {
@@ -403,6 +488,17 @@ convert_fn(function_base1<SrcResult, SrcArg1>* src) {
return new convert_fn1_t<Result, Arg1, SrcResult, SrcArg1>(src);
}
template <typename Result, typename Arg1, typename Arg2, typename SrcResult, typename SrcArg1, typename SrcArg2>
inline function_base2<Result, Arg1, Arg2>*
convert_fn(function_base2<SrcResult, SrcArg1, SrcArg2>* src) {
if (equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::result)
// The pointer cast never gets done if the types are different,
// but needs to be here to pleasant the compiler.
return reinterpret_cast<typename equal_types_t<function_base2<Result, Arg1, Arg2>, function_base2<SrcResult, SrcArg1, SrcArg2> >::first_type*>(src);
else
return new convert_fn2_t<Result, Arg1, Arg2, SrcResult, SrcArg1, SrcArg2>(src);
}
}
#endif
+13 -10
View File
@@ -36,11 +36,11 @@
#include "config.h"
#include <stdexcept>
#include <sigc++/bind.h>
#include <sigc++/hide.h>
#include <sigc++/signal.h>
#include <rak/path.h>
#include <rak/functional.h>
#include <torrent/exceptions.h>
#include <torrent/rate.h>
#include <torrent/torrent.h>
@@ -68,29 +68,32 @@ Download::Download(download_type d) :
m_download.signal_chunk_failed(sigc::mem_fun(*this, &Download::receive_chunk_failed));
m_variables.insert("connection_current", new utils::VariableStringSlot(rak::mem_fn(this, &Download::connection_current),
rak::mem_fn(this, &Download::set_connection_current)));
m_variables.insert("connection_current", new utils::VariableStringSlot(NULL, NULL,
rak::ftor_fn1(std::mem_fun(&Download::connection_current)),
rak::ftor_fn2(std::mem_fun(&Download::set_connection_current))));
m_variables.insert("connection_leech", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_LEECH)));
m_variables.insert("connection_seed", new utils::VariableAny(connection_type_to_string(download_type::CONNECTION_SEED)));
// 0 - stopped
// 1 - started
m_variables.insert("state", new utils::VariableObject(bencode(), "rtorrent", "state", torrent::Object::TYPE_VALUE));
m_variables.insert("complete", new utils::VariableObject(bencode(), "rtorrent", "complete", torrent::Object::TYPE_VALUE));
m_variables.insert("state", new utils::VariableObject("rtorrent", "state", torrent::Object::TYPE_VALUE));
m_variables.insert("complete", new utils::VariableObject("rtorrent", "complete", torrent::Object::TYPE_VALUE));
// 0 - Not hashing
// 1 - Normal hashing
// 2 - Download finished, hashing
m_variables.insert("hashing", new utils::VariableObject(bencode(), "rtorrent", "hashing", torrent::Object::TYPE_VALUE));
m_variables.insert("tied_to_file", new utils::VariableObject(bencode(), "rtorrent", "tied_to_file", torrent::Object::TYPE_STRING));
m_variables.insert("hashing", new utils::VariableObject("rtorrent", "hashing", torrent::Object::TYPE_VALUE));
m_variables.insert("tied_to_file", new utils::VariableObject("rtorrent", "tied_to_file", torrent::Object::TYPE_STRING));
// The "state_changed" variable is required to be a valid unix time
// value, it indicates the last time the torrent changed its state,
// resume/pause.
m_variables.insert("state_changed", new utils::VariableObject(bencode(), "rtorrent", "state_changed", torrent::Object::TYPE_VALUE));
m_variables.insert("state_changed", new utils::VariableObject("rtorrent", "state_changed", torrent::Object::TYPE_VALUE));
m_variables.insert("directory", new utils::VariableStringSlot(rak::mem_fn(m_download.file_list(), &torrent::FileList::root_dir), rak::mem_fn(this, &Download::set_root_directory)));
m_variables.insert("directory", new utils::VariableStringSlot(NULL, NULL,
rak::ftor_fn1(rak::on(std::mem_fun(&Download::file_list), std::mem_fun(&torrent::FileList::root_dir))),
rak::ftor_fn2(std::mem_fun(&Download::set_root_directory))));
// m_variables.insert("info_hash", new utils::VariableStringSlot(rak::mem_fn(&m_download, &torrent::Download::info_hash), NULL));
@@ -113,7 +116,7 @@ Download::Download(download_type d) :
m_variables.insert("tracker_numwant", new utils::VariableValueSlot(rak::mem_fn(&m_trackerList, &tracker_list_type::numwant), rak::mem_fn(&m_trackerList, &tracker_list_type::set_numwant)));
m_variables.insert("ignore_commands", new utils::VariableObject(bencode(), "rtorrent", "ignore_commands", torrent::Object::TYPE_VALUE));
m_variables.insert("ignore_commands", new utils::VariableObject("rtorrent", "ignore_commands", torrent::Object::TYPE_VALUE));
}
Download::~Download() {
+11 -14
View File
@@ -82,14 +82,6 @@ public:
bool is_hash_failed() const { return m_hashFailed; }
void set_hash_failed(bool v) { m_hashFailed = v; }
variable_map_type* variable() { return &m_variables; }
int64_t variable_value(const std::string& key) const { return m_variables.get_value(key.c_str()); }
const std::string& variable_string(const std::string& key) const { return m_variables.get_string(key.c_str()); }
int64_t variable_value_c(const char* key) const { return m_variables.get_value(key); }
const std::string& variable_string_c(const char* key) const { return m_variables.get_string(key); }
download_type* download() { return &m_download; }
const download_type* c_download() const { return &m_download; }
@@ -109,13 +101,18 @@ public:
uint32_t priority();
void set_priority(uint32_t p);
// Helper functions for calling functions in download_type
// through sigc++.
template <typename Ret, Ret (download_type::*func)()>
void call() { (m_download.*func)(); }
// variable_map_type* variable() { return &m_variables; }
template <typename Ret, typename Arg1, Ret (download_type::*func)(Arg1)>
void call(Arg1 a1) { (m_download.*func)(a1); }
int64_t get_value(const char* key) { return m_variables.get_d_value(this, key); }
const std::string& get_string(const char* key) { return m_variables.get_d_string(this, key); }
int64_t get_std_value(const std::string& key) { return m_variables.get_d_value(this, key.c_str()); }
const std::string& get_std_string(const std::string& key) { return m_variables.get_d_string(this, key.c_str()); }
void set(const char* key, const torrent::Object& value) { return m_variables.set_d(this, key, value); }
void set_value(const char* key, int64_t value) { return m_variables.set_d_value(this, key, value); }
void set_string(const char* key, const std::string& value) { return m_variables.set_d_string(this, key, value); }
bool operator == (const std::string& str) const;
+17 -17
View File
@@ -172,27 +172,27 @@ DownloadFactory::receive_success() {
initialize_rtorrent(download, rtorrent);
// Move to 'rtorrent'.
download->variable()->set("connection_leech", m_variables.get("connection_leech"));
download->variable()->set("connection_seed", m_variables.get("connection_seed"));
download->set("connection_leech", m_variables.get("connection_leech"));
download->set("connection_seed", m_variables.get("connection_seed"));
download->variable()->set("max_uploads", control->variable()->get("max_uploads"));
download->variable()->set("min_peers", control->variable()->get("min_peers"));
download->variable()->set("max_peers", control->variable()->get("max_peers"));
download->variable()->set("tracker_numwant", control->variable()->get("tracker_numwant"));
download->set("max_uploads", control->variable()->get("max_uploads"));
download->set("min_peers", control->variable()->get("min_peers"));
download->set("max_peers", control->variable()->get("max_peers"));
download->set("tracker_numwant", control->variable()->get("tracker_numwant"));
if (download->variable()->get_value("complete") != 0) {
if (download->get_value("complete") != 0) {
if (control->variable()->get_value("min_peers_seed") >= 0)
download->variable()->set("min_peers", control->variable()->get("min_peers_seed"));
download->set("min_peers", control->variable()->get("min_peers_seed"));
if (control->variable()->get_value("max_peers_seed") >= 0)
download->variable()->set("max_peers", control->variable()->get("max_peers_seed"));
download->set("max_peers", control->variable()->get("max_peers_seed"));
}
if (!control->variable()->get_value("use_udp_trackers"))
download->enable_udp_trackers(false);
if (control->variable()->get_value("max_file_size") > 0)
download->variable()->set("max_file_size", control->variable()->get("max_file_size"));
download->set("max_file_size", control->variable()->get("max_file_size"));
// Check first if we already have these values set in the session
// torrent, so that it is safe to change the values.
@@ -204,12 +204,12 @@ DownloadFactory::receive_success() {
control->variable()->get_string("split_suffix"));
if (!rtorrent->has_key_string("directory"))
download->variable()->set("directory", m_variables.get("directory"));
download->set("directory", m_variables.get("directory"));
else
download->variable()->set("directory", rtorrent->get_key("directory"));
download->set("directory", rtorrent->get_key("directory"));
if (!m_session && m_variables.get("tied_to_file").as_value())
download->variable()->set("tied_to_file", m_uri);
download->set("tied_to_file", m_uri);
torrent::Object& resumeObject = root->has_key_map("libtorrent_resume")
? root->get_key("libtorrent_resume")
@@ -234,8 +234,8 @@ DownloadFactory::receive_success() {
if (m_session) {
// This torrent was queued for hashing or hashing when the session
// file was saved. Or it was in a started state.
if (download->variable()->get_value("hashing") != Download::variable_hashing_stopped ||
download->variable()->get_value("state") != 0)
if (download->get_value("hashing") != Download::variable_hashing_stopped ||
download->get_value("state") != 0)
m_manager->download_list()->resume(download);
} else {
@@ -284,9 +284,9 @@ DownloadFactory::initialize_rtorrent(Download* download, torrent::Object* rtorre
rtorrent->insert_key("tied_to_file", std::string());
if (rtorrent->has_key_value("priority"))
download->variable()->set("priority", rtorrent->get_key_value("priority") % 4);
download->set("priority", rtorrent->get_key_value("priority") % 4);
else
download->variable()->set("priority", (int64_t)2);
download->set("priority", (int64_t)2);
if (rtorrent->has_key_value("key")) {
download->tracker_list()->set_key(rtorrent->get_key_value("key"));
+31 -31
View File
@@ -229,7 +229,7 @@ DownloadList::close_throw(Download* download) {
download->download()->close();
if (!download->is_hash_failed() && download->variable()->get_value("hashing") != Download::variable_hashing_stopped)
if (!download->is_hash_failed() && download->get_value("hashing") != Download::variable_hashing_stopped)
throw torrent::internal_error("DownloadList::close_throw(...) called but we're going into a hashing loop.");
std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download));
@@ -243,7 +243,7 @@ DownloadList::start_normal(Download* download) {
// Clear hash failed as we're doing a manual start and want to try
// hashing again.
download->set_hash_failed(false);
download->variable()->set("state", (int64_t)1);
download->set("state", (int64_t)1);
resume(download);
}
@@ -255,12 +255,12 @@ DownloadList::start_try(Download* download) {
// Also don't start if the state is one of those that indicate we
// were manually stopped?
if (download->is_hash_failed() || download->variable()->get_value("ignore_commands") != 0)
if (download->is_hash_failed() || download->get_value("ignore_commands") != 0)
return false;
// Don't clear the hash failed as this function is used by scripts,
// etc.
download->variable()->set("state", (int64_t)1);
download->set("state", (int64_t)1);
resume(download);
return true;
@@ -270,7 +270,7 @@ void
DownloadList::stop_normal(Download* download) {
check_contains(download);
download->variable()->set("state", (int64_t)0);
download->set("state", (int64_t)0);
pause(download);
}
@@ -279,10 +279,10 @@ bool
DownloadList::stop_try(Download* download) {
check_contains(download);
if (download->variable()->get_value("ignore_commands") != 0)
if (download->get_value("ignore_commands") != 0)
return false;
download->variable()->set("state", (int64_t)0);
download->set("state", (int64_t)0);
pause(download);
return true;
@@ -308,8 +308,8 @@ DownloadList::resume(Download* download) {
if (download->is_hash_failed())
return;
if (download->variable()->get_value("hashing") == Download::variable_hashing_stopped)
download->variable()->set("hashing", Download::variable_hashing_initial);
if (download->get_value("hashing") == Download::variable_hashing_stopped)
download->set("hashing", Download::variable_hashing_initial);
std::for_each(slot_map_hash_queued().begin(), slot_map_hash_queued().end(), download_list_call(download));
return;
@@ -318,12 +318,12 @@ DownloadList::resume(Download* download) {
// This will never actually do anything due to the above hash check.
// open_throw(download);
download->variable()->set("state_changed", cachedTime.seconds());
download->set("state_changed", cachedTime.seconds());
if (download->is_done()) {
download->set_connection_type(download->variable()->get_string("connection_seed"));
download->set_connection_type(download->get_string("connection_seed"));
} else {
download->set_connection_type(download->variable()->get_string("connection_leech"));
download->set_connection_type(download->get_string("connection_leech"));
// For the moment, clear the resume data so we force hash-check
// on non-complete downloads after a crash. This shouldn't be
@@ -352,9 +352,9 @@ DownloadList::pause(Download* download) {
// Always clear hashing on pause. When a hashing request is added,
// it should have cleared the hash resume data.
if (download->variable()->get_value("hashing") != Download::variable_hashing_stopped) {
if (download->get_value("hashing") != Download::variable_hashing_stopped) {
download->download()->hash_stop();
download->variable()->set_value("hashing", Download::variable_hashing_stopped);
download->set_value("hashing", Download::variable_hashing_stopped);
std::for_each(slot_map_hash_removed().begin(), slot_map_hash_removed().end(), download_list_call(download));
}
@@ -367,7 +367,7 @@ DownloadList::pause(Download* download) {
std::for_each(slot_map_stop().begin(), slot_map_stop().end(), download_list_call(download));
download->variable()->set("state_changed", cachedTime.seconds());
download->set("state_changed", cachedTime.seconds());
// Save the state after all the slots, etc have been called so we
// include the modifications they may make.
@@ -384,7 +384,7 @@ DownloadList::check_hash(Download* download) {
try {
if (download->variable()->get_value("hashing") != Download::variable_hashing_stopped)
if (download->get_value("hashing") != Download::variable_hashing_stopped)
return;
hash_queue(download, Download::variable_hashing_rehash);
@@ -417,8 +417,8 @@ DownloadList::hash_done(Download* download) {
// confirm all the data, avoiding large BW usage on f.ex. the
// ReiserFS bug with >4GB files.
int64_t hashing = download->variable()->get_value("hashing");
download->variable()->set_value("hashing", Download::variable_hashing_stopped);
int64_t hashing = download->get_value("hashing");
download->set_value("hashing", Download::variable_hashing_stopped);
switch (hashing) {
case Download::variable_hashing_initial:
@@ -427,17 +427,17 @@ DownloadList::hash_done(Download* download) {
// If the download was previously completed but the files were
// f.ex deleted, then we clear the state and complete.
if (download->variable()->get_value("complete") && !download->is_done()) {
download->variable()->set("state", (int64_t)0);
if (download->get_value("complete") && !download->is_done()) {
download->set("state", (int64_t)0);
download->set_message("Download registered as completed, but hash check returned unfinished chunks.");
}
// Save resume data so we update time-stamps and priorities if
// they were invalid/changed while loading/hashing.
download->variable()->set("complete", (int64_t)download->is_done());
download->set("complete", (int64_t)download->is_done());
torrent::resume_save_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
if (download->variable()->get_value("state") == 1)
if (download->get_value("state") == 1)
resume(download);
break;
@@ -467,14 +467,14 @@ void
DownloadList::hash_queue(Download* download, int type) {
check_contains(download);
if (download->variable()->get_value("hashing") != Download::variable_hashing_stopped)
if (download->get_value("hashing") != Download::variable_hashing_stopped)
throw torrent::internal_error("DownloadList::hash_queue(...) hashing already queued.");
close_throw(download);
torrent::resume_clear_progress(*download->download(), download->download()->bencode()->get_key("libtorrent_resume"));
download->set_hash_failed(false);
download->variable()->set_value("hashing", type);
download->set_value("hashing", type);
if (download->is_open())
throw torrent::internal_error("DownloadList::hash_clear(...) download still open.");
@@ -503,16 +503,16 @@ void
DownloadList::confirm_finished(Download* download) {
check_contains(download);
download->variable()->set("complete", (int64_t)1);
download->set("complete", (int64_t)1);
download->set_connection_type(download->variable()->get_string("connection_seed"));
download->set_connection_type(download->get_string("connection_seed"));
download->set_priority(download->priority());
if (download->variable_value("min_peers") == control->variable()->get_value("min_peers") && control->variable()->get_value("min_peers_seed") >= 0)
download->variable()->set("min_peers", control->variable()->get("min_peers_seed"));
if (download->get_value("min_peers") == control->variable()->get_value("min_peers") && control->variable()->get_value("min_peers_seed") >= 0)
download->set("min_peers", control->variable()->get("min_peers_seed"));
if (download->variable_value("max_peers") == control->variable()->get_value("max_peers") && control->variable()->get_value("max_peers_seed") >= 0)
download->variable()->set("max_peers", control->variable()->get("max_peers_seed"));
if (download->get_value("max_peers") == control->variable()->get_value("max_peers") && control->variable()->get_value("max_peers_seed") >= 0)
download->set("max_peers", control->variable()->get("max_peers_seed"));
// Do this before the slots are called in case one of them closes
// the download.
@@ -527,7 +527,7 @@ DownloadList::confirm_finished(Download* download) {
std::for_each(slot_map_finished().begin(), slot_map_finished().end(), download_list_call(download));
if (!download->is_active() && download->variable()->get_value("state") == 1)
if (!download->is_active() && download->get_value("state") == 1)
resume(download);
}
+7 -7
View File
@@ -166,8 +166,8 @@ Manager::handshake_log(const sockaddr* sa, int msg, int err, const torrent::Hash
// Hmm... find some better place for all this.
void
Manager::delete_tied(Download* d) {
const std::string& tie = d->variable()->get_string("tied_to_file");
Manager::delete_tied(Download* download) {
const std::string& tie = download->get_string("tied_to_file");
// This should be configurable, need to wait for the variable
// thingie to be implemented.
@@ -177,7 +177,7 @@ Manager::delete_tied(Download* d) {
if (::unlink(rak::path_expand(tie).c_str()) == -1)
push_log("Could not unlink tied file: " + std::string(rak::error_number::current().c_str()));
d->variable()->set("tied_to_file", std::string());
download->set("tied_to_file", std::string());
}
Manager::Manager() :
@@ -468,7 +468,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, rak::bind2nd(std::mem_fun(&Download::variable_string), "tied_to_file")))
if (std::find_if(m_downloadList->begin(), m_downloadList->end(), rak::equal(*itr, rak::bind2nd(std::mem_fun(&Download::get_string), "tied_to_file")))
!= m_downloadList->end())
itr = paths.erase(itr);
else
@@ -504,7 +504,7 @@ Manager::receive_hashing_changed() {
continue;
bool tryQuick =
(*itr)->variable()->get_value("hashing") == Download::variable_hashing_initial &&
(*itr)->get_value("hashing") == Download::variable_hashing_initial &&
(*itr)->download()->file_list()->bitfield()->empty();
if (!tryQuick && foundHashing)
@@ -526,7 +526,7 @@ Manager::receive_hashing_changed() {
(*itr)->download()->hash_stop();
// Make sure we don't repeat the quick hashing.
(*itr)->variable()->set_value("hashing", Download::variable_hashing_rehash);
(*itr)->set_value("hashing", Download::variable_hashing_rehash);
} else {
(*itr)->download()->hash_check(false);
@@ -535,7 +535,7 @@ Manager::receive_hashing_changed() {
} catch (torrent::local_error& e) {
if (tryQuick) {
// Make sure we don't repeat the quick hashing.
(*itr)->variable()->set_value("hashing", Download::variable_hashing_rehash);
(*itr)->set_value("hashing", Download::variable_hashing_rehash);
} else {
(*itr)->set_hash_failed(true);
+5 -5
View File
@@ -70,8 +70,8 @@ public:
virtual bool operator () (Download* d1, Download* d2) const {
return
d1->variable()->get_string(m_name) == m_value &&
d2->variable()->get_string(m_name) != m_value;
d1->get_string(m_name) == m_value &&
d2->get_string(m_name) != m_value;
}
private:
@@ -85,9 +85,9 @@ public:
virtual bool operator () (Download* d1, Download* d2) const {
if (m_reverse)
return d2->variable()->get_value(m_name) < d1->variable()->get_value(m_name);
return d2->get_value(m_name) < d1->get_value(m_name);
else
return d1->variable()->get_value(m_name) < d2->variable()->get_value(m_name);
return d1->get_value(m_name) < d2->get_value(m_name);
}
private:
@@ -114,7 +114,7 @@ public:
m_name(name), m_value(v), m_inverse(inverse) {}
virtual bool operator () (Download* d1) const {
return (d1->variable()->get_value(m_name) == m_value) != m_inverse;
return (d1->get_value(m_name) == m_value) != m_inverse;
}
private:
+2 -2
View File
@@ -93,7 +93,7 @@ te_string(Return (torrent::FileList::*fptr)() const, int flags = TextElementStri
inline TextElementStringBase*
te_variable_string(const std::string& variable, int flags = TextElementStringBase::flag_normal, int attributes = Attributes::a_invalid) {
return text_element_string_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_string), variable), flags, attributes);
return text_element_string_slot(rak::bind2nd(std::mem_fun(&core::Download::get_std_string), variable), flags, attributes);
}
// Value stuff:
@@ -118,7 +118,7 @@ te_value(Return (torrent::File::*fptr)() const, int flags = TextElementValueBase
inline TextElementValueBase*
te_variable_value(const std::string& variable, int flags = TextElementValueBase::flag_normal, int attributes = Attributes::a_invalid) {
return text_element_value_slot(rak::bind2nd(std::mem_fun(&core::Download::variable_value), variable), flags, attributes);
return text_element_value_slot(rak::bind2nd(std::mem_fun(&core::Download::get_std_value), variable), flags, attributes);
}
template <typename Return>
+3 -3
View File
@@ -158,8 +158,8 @@ print_download_info(char* first, char* last, core::Download* d) {
}
first = print_buffer(first, last, " [%c%c R: %3.2f",
d->variable()->get_string("tied_to_file").empty() ? ' ' : 'T',
d->variable()->get_value("ignore_commands") == 0 ? ' ' : 'I',
d->get_string("tied_to_file").empty() ? ' ' : 'T',
d->get_value("ignore_commands") == 0 ? ' ' : 'I',
d->download()->bytes_done() > 0 ? (double)(100 * d->download()->up_rate()->total() / d->download()->bytes_done()) / 100 : 0.0);
if (d->priority() != 2)
@@ -177,7 +177,7 @@ char*
print_download_status(char* first, char* last, core::Download* d) {
if (d->is_active())
;
else if (d->variable_value("hashing") != 0)
else if (d->get_value("hashing") != 0)
first = print_buffer(first, last, "Hashing: ");
else if (!d->is_active())
first = print_buffer(first, last, "Inactive: ");
+37 -7
View File
@@ -78,6 +78,17 @@ namespace core {
path_expand(std::vector<std::string>* paths, const std::string& pattern);
}
// void
// apply_new_string(const std::string& args) {
// std::string::const_iterator split = std::find(args.begin(), args.end(), ',');
// std::string key =
// if (control->variable()->has(args))
// variables->insert("tracker_dump", new utils::VariableAny(std::string()));
// }
void
apply_hash_read_ahead(__UNUSED Control* m, int arg) {
torrent::set_hash_read_ahead(arg << 20);
@@ -122,11 +133,11 @@ apply_load_start_verbose(Control* m, const std::string& arg) {
void
apply_start_tied(Control* m) {
for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ++itr) {
if ((*itr)->variable_value("state") == 1)
if ((*itr)->get_value("state") == 1)
continue;
rak::file_stat fs;
const std::string& tiedToFile = (*itr)->variable_string("tied_to_file");
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
if (!tiedToFile.empty() && fs.update(rak::path_expand(tiedToFile)))
m->core()->download_list()->start_try(*itr);
@@ -136,11 +147,11 @@ apply_start_tied(Control* m) {
void
apply_stop_untied(Control* m) {
for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ++itr) {
if ((*itr)->variable_value("state") == 0)
if ((*itr)->get_value("state") == 0)
continue;
rak::file_stat fs;
const std::string& tiedToFile = (*itr)->variable_string("tied_to_file");
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)))
m->core()->download_list()->stop_try(*itr);
@@ -151,7 +162,7 @@ void
apply_close_untied(Control* m) {
for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ++itr) {
rak::file_stat fs;
const std::string& tiedToFile = (*itr)->variable_string("tied_to_file");
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && m->core()->download_list()->stop_try(*itr))
m->core()->download_list()->close(*itr);
@@ -162,7 +173,7 @@ void
apply_remove_untied(Control* m) {
for (core::DownloadList::iterator itr = m->core()->download_list()->begin(); itr != m->core()->download_list()->end(); ) {
rak::file_stat fs;
const std::string& tiedToFile = (*itr)->variable_string("tied_to_file");
const std::string& tiedToFile = (*itr)->get_string("tied_to_file");
if (!tiedToFile.empty() && !fs.update(rak::path_expand(tiedToFile)) && m->core()->download_list()->stop_try(*itr))
itr = m->core()->download_list()->erase(itr);
@@ -211,13 +222,30 @@ apply_stop_on_ratio(Control* m, const std::string& arg) {
if ((totalUpload >= minUpload && totalUpload * 100 >= totalDone * minRatio) || (maxRatio > 0 && totalUpload * 100 > totalDone * maxRatio)) {
m->core()->download_list()->stop_try(*itr);
(*itr)->variable()->set("ignore_commands", (int64_t)1);
(*itr)->set("ignore_commands", (int64_t)1);
}
++itr;
}
}
// void
// apply_on_finished(const std::string& arg) {
// std::string::const_iterator itr = std::find(arg.begin(), arg.end(), ',');
// std::string key = rak::trim(std::string(arg.begin(), itr));
// std::string value = rak::trim(std::string(itr != arg.end() ? itr + 1 : itr, arg.end()));
// if (key.empty())
// throw torrent::input_error("Empty key.");
// if (value.empty())
// control->core()->download_list()->slot_map_finished().erase("0_finished_" + key);
// else
// control->core()->download_list()->slot_map_finished().insert("0_finished_" + key, );
// ->process_std_single(value);
// }
void
apply_encoding_list(__UNUSED Control* m, const std::string& arg) {
torrent::encoding_list()->push_back(arg);
@@ -548,6 +576,8 @@ initialize_option_handler(Control* c) {
variables->insert("close_low_diskspace", new utils::VariableValueSlot(rak::value_fn(int64_t()), rak::bind_ptr_fn(&apply_close_low_diskspace, c)));
variables->insert("stop_on_ratio", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_stop_on_ratio, c)));
// variables->insert("on_finished", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::ptr_fn(&apply_on_finished)));
variables->insert("enable_trackers", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_enable_trackers, c)));
variables->insert("encoding_list", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_encoding_list, c)));
+2 -2
View File
@@ -283,8 +283,8 @@ DownloadList::receive_exit_input(Input type) {
if (current_view()->focus() == current_view()->end_visible())
throw torrent::input_error("No download in focus to change root directory.");
(*current_view()->focus())->variable()->set("directory", rak::trim(input->str()));
control->core()->push_log("New root directory \"" + (*current_view()->focus())->variable()->get_string("directory") + "\" for torrent.");
(*current_view()->focus())->set("directory", rak::trim(input->str()));
control->core()->push_log("New root directory \"" + (*current_view()->focus())->get_string("directory") + "\" for torrent.");
break;
case INPUT_COMMAND:
+6 -6
View File
@@ -149,7 +149,7 @@ ElementDownloadList::receive_stop_download() {
if (m_view->focus() == m_view->end_visible())
return;
if ((*m_view->focus())->variable()->get_value("state") == 1)
if ((*m_view->focus())->get_value("state") == 1)
control->core()->download_list()->stop_normal(*m_view->focus());
else
control->core()->download_list()->erase(*m_view->focus());
@@ -164,7 +164,7 @@ ElementDownloadList::receive_close_download() {
core::Download* download = *m_view->focus();
download->variable()->set("ignore_commands", (int64_t)1);
download->set("ignore_commands", (int64_t)1);
control->core()->download_list()->stop_normal(download);
control->core()->download_list()->close(download);
@@ -203,11 +203,11 @@ ElementDownloadList::receive_ignore_ratio() {
if (m_view->focus() == m_view->end_visible())
return;
if ((*m_view->focus())->variable()->get_value("ignore_commands") != 0) {
(*m_view->focus())->variable()->set("ignore_commands", (int64_t)0);
if ((*m_view->focus())->get_value("ignore_commands") != 0) {
(*m_view->focus())->set("ignore_commands", (int64_t)0);
control->core()->push_log("Torrent set to heed commands.");
} else {
(*m_view->focus())->variable()->set("ignore_commands", (int64_t)1);
(*m_view->focus())->set("ignore_commands", (int64_t)1);
control->core()->push_log("Torrent set to ignore commands.");
}
}
@@ -217,7 +217,7 @@ ElementDownloadList::receive_clear_tied() {
if (m_view->focus() == m_view->end_visible())
return;
const std::string& tiedFile = (*m_view->focus())->variable()->get_string("tied_to_file");
const std::string& tiedFile = (*m_view->focus())->get_string("tied_to_file");
if (!tiedFile.empty()) {
// Move this into core?
+20
View File
@@ -44,6 +44,26 @@ namespace utils {
const torrent::Object Variable::m_emptyObject;
// Consider throwing an exception.
const torrent::Object&
Variable::get() {
return m_emptyObject;
}
void
Variable::set(const torrent::Object& arg) {
}
const torrent::Object&
Variable::get_d(core::Download* download) {
return get();
}
void
Variable::set_d(core::Download* download, const torrent::Object& arg) {
set(arg);
}
const char*
Variable::string_to_value_unit(const char* pos, value_type* value, int base, int unit) {
char* last;
+10 -2
View File
@@ -39,6 +39,10 @@
#include <torrent/object.h>
namespace core {
class Download;
}
namespace utils {
class Variable {
@@ -52,8 +56,12 @@ public:
Variable() {}
virtual ~Variable() {}
virtual const torrent::Object& get() = 0;
virtual void set(const torrent::Object& arg) = 0;
virtual const torrent::Object& get();
virtual void set(const torrent::Object& arg);
// The default action is to throw away the 'download' argument.
virtual const torrent::Object& get_d(core::Download* download);
virtual void set_d(core::Download* download, const torrent::Object& arg);
static const char* string_to_value_unit(const char* pos, value_type* value, int base, int unit);
static bool string_to_value_unit_nothrow(const char* pos, value_type* value, int base, int unit);
+54 -7
View File
@@ -102,22 +102,22 @@ VariableBool::set(const torrent::Object& arg) {
}
const torrent::Object&
VariableObject::get() {
VariableObject::get_d(core::Download* download) {
if (m_root.empty())
return m_bencode->get_key(m_key);
return download->bencode()->get_key(m_key);
else
return m_bencode->get_key(m_root).get_key(m_key);
return download->bencode()->get_key(m_root).get_key(m_key);
}
void
VariableObject::set(const torrent::Object& arg) {
VariableObject::set_d(core::Download* download, const torrent::Object& arg) {
// Consider removing if TYPE_NONE.
torrent::Object* root;
if (m_root.empty())
root = m_bencode;
root = download->bencode();
else
root = &m_bencode->get_key(m_root);
root = &download->bencode()->get_key(m_root);
switch (m_type) {
case torrent::Object::TYPE_NONE:
@@ -200,7 +200,7 @@ VariableValueSlot::set(const torrent::Object& arg) {
const torrent::Object&
VariableStringSlot::get() {
if (!m_slotGet.is_valid())
return m_cache;
return m_cache = torrent::Object();
m_cache = m_slotGet();
@@ -224,4 +224,51 @@ VariableStringSlot::set(const torrent::Object& arg) {
}
}
const torrent::Object&
VariableStringSlot::get_d(core::Download* download) {
// Should clear the cache.
if (!m_slotGetDownload.is_valid()) {
if (!m_slotGet.is_valid())
return m_cache = torrent::Object();
m_cache = m_slotGet();
} else {
m_cache = m_slotGetDownload(download);
}
return m_cache;
}
void
VariableStringSlot::set_d(core::Download* download, const torrent::Object& arg) {
if (!m_slotSetDownload.is_valid()) {
if (!m_slotSet.is_valid())
return;
switch (arg.type()) {
case torrent::Object::TYPE_STRING:
m_slotSet(arg.as_string());
break;
case torrent::Object::TYPE_NONE:
m_slotSet(std::string());
break;
default:
throw torrent::input_error("Not a string.");
}
} else {
switch (arg.type()) {
case torrent::Object::TYPE_STRING:
m_slotSetDownload(download, arg.as_string());
break;
case torrent::Object::TYPE_NONE:
m_slotSetDownload(download, std::string());
break;
default:
throw torrent::input_error("Not a string.");
}
}
}
}
+37 -13
View File
@@ -49,6 +49,7 @@
#include <torrent/exceptions.h>
#include "variable.h"
#include "core/download.h"
namespace utils {
@@ -82,17 +83,13 @@ class VariableObject : public Variable {
public:
typedef torrent::Object::type_type Type;
VariableObject(torrent::Object* b,
const std::string& root,
const std::string& key,
Type t = torrent::Object::TYPE_NONE) :
m_bencode(b), m_root(root), m_key(key), m_type(t) {}
VariableObject(const std::string& root, const std::string& key, Type t = torrent::Object::TYPE_NONE) :
m_root(root), m_key(key), m_type(t) {}
virtual const torrent::Object& get();
virtual void set(const torrent::Object& arg);
virtual const torrent::Object& get_d(core::Download* download);
virtual void set_d(core::Download* download, const torrent::Object& arg);
private:
torrent::Object* m_bencode;
std::string m_root;
std::string m_key;
Type m_type;
@@ -169,27 +166,54 @@ private:
class VariableStringSlot : public Variable {
public:
typedef rak::function0<string_type> slot_get_type;
typedef rak::function1<void, const string_type&> slot_set_type;
typedef rak::function0<string_type> slot_get_type;
typedef rak::function1<string_type, core::Download*> slot_get_d_type;
typedef rak::function1<void, const string_type&> slot_set_type;
typedef rak::function2<void, core::Download*, const string_type&> slot_set_d_type;
template <typename SlotGet, typename SlotSet>
VariableStringSlot(SlotGet* slotGet, SlotSet* slotSet) {
m_slotGet.set(rak::convert_fn<string_type>(slotGet));
m_slotSet.set(rak::convert_fn<void, const string_type&>(slotSet));
m_slotGetDownload.set(NULL);
m_slotSetDownload.set(NULL);
}
template <typename SlotGet>
VariableStringSlot(SlotGet* slotGet, void* slotSet) {
m_slotGet.set(rak::convert_fn<string_type>(slotGet));
template <typename SlotGetDownload>
VariableStringSlot(void* slotGet, void* slotSet, SlotGetDownload* slotGetDownload, void* slotSetDownload) {
m_slotGet.set(NULL);
m_slotSet.set(NULL);
m_slotGetDownload.set(rak::convert_fn<string_type, core::Download*>(slotGetDownload));
m_slotSetDownload.set(NULL);
}
template <typename SlotGetDownload, typename SlotSetDownload>
VariableStringSlot(void* slotGet, void* slotSet, SlotGetDownload* slotGetDownload, SlotSetDownload* slotSetDownload) {
m_slotGet.set(NULL);
m_slotSet.set(NULL);
m_slotGetDownload.set(rak::convert_fn<string_type, core::Download*>(slotGetDownload));
m_slotSetDownload.set(rak::convert_fn<void, core::Download*, const string_type&>(slotSetDownload));
}
// template <typename SlotGet, typename SlotSet, typename SlotGetDownload, typename SlotSetDownload>
// VariableStringSlot(SlotGet* slotGet, SlotSet* slotSet, SlotGetDownload* slotGetDownload, SlotSetDownload* slotSetDownload) {
// m_slotGet.set(slotGet != NULL ? rak::convert_fn<string_type>(slotGet) : NULL);
// m_slotSet.set(slotSet != NULL ? rak::convert_fn<void, const string_type&>(slotSet) : NULL);
// m_slotGetDownload.set(slotGetDownload != NULL ? rak::convert_fn<string_type, core::Download*>(slotGetDownload) : NULL);
// m_slotSetDownload.set(slotSetDownload != NULL ? rak::convert_fn<void, core::Download*, const string_type&>(slotSetDownload) : NULL);
// }
virtual const torrent::Object& get();
virtual void set(const torrent::Object& arg);
virtual const torrent::Object& get_d(core::Download* download);
virtual void set_d(core::Download* download, const torrent::Object& arg);
private:
slot_get_type m_slotGet;
slot_set_type m_slotSet;
slot_get_d_type m_slotGetDownload;
slot_set_d_type m_slotSetDownload;
// Store the cache here to avoid unnessesary copying and such. This
// should not result in any unresonable memory usage since few
+22
View File
@@ -74,6 +74,16 @@ VariableMap::get(key_type key) const {
return itr->second->get();
}
const VariableMap::mapped_type&
VariableMap::get_d(core::Download* download, key_type key) const {
const_iterator itr = base_type::find(key);
if (itr == base_type::end())
throw torrent::input_error("Variable \"" + std::string(key) + "\" does not exist.");
return itr->second->get_d(download);
}
void
VariableMap::set(key_type key, const mapped_type& arg) {
iterator itr = base_type::find(key);
@@ -86,6 +96,18 @@ VariableMap::set(key_type key, const mapped_type& arg) {
itr->second->set(arg);
}
void
VariableMap::set_d(core::Download* download, key_type key, const mapped_type& arg) {
iterator itr = base_type::find(key);
// 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 \"" + std::string(key) + "\" does not exist.");
itr->second->set_d(download, arg);
}
struct variable_map_is_space : std::unary_function<char, bool> {
bool operator () (char c) const {
return std::isspace(c);
+20 -6
View File
@@ -43,6 +43,10 @@
#include <iosfwd>
#include <torrent/object.h>
namespace core {
class Download;
}
namespace torrent {
class Object;
}
@@ -78,15 +82,25 @@ public:
void insert(key_type key, Variable* v);
// Consider taking char* start and finish instead of std::string to
// avoid copying. Or make a view class.
// Consider uninlining the helper functions.
const mapped_type& get(key_type key) const;
const std::string& get_string(key_type key) const { return get(key).as_string(); }
mapped_value_type get_value(key_type key) const { return get(key).as_value(); }
const mapped_type& get_d(core::Download* download, key_type key) const;
const std::string& get_string(key_type key) const { return get(key).as_string(); }
const std::string& get_d_string(core::Download* download, key_type key) const { return get_d(download, key).as_string(); }
mapped_value_type get_value(key_type key) const { return get(key).as_value(); }
mapped_value_type get_d_value(core::Download* download, key_type key) const { return get_d(download, key).as_value(); }
void set(key_type key, const mapped_type& arg);
void set_string(key_type key, const std::string& arg) { set(key, mapped_type(arg)); }
void set_value(key_type key, mapped_value_type arg) { set(key, mapped_type(arg)); }
void set_d(core::Download* download, key_type key, const mapped_type& arg);
void set_string(key_type key, const std::string& arg) { set(key, mapped_type(arg)); }
void set_d_string(core::Download* download, key_type key, const std::string& arg) { set_d(download, key, mapped_type(arg)); }
void set_value(key_type key, mapped_value_type arg) { set(key, mapped_type(arg)); }
void set_d_value(core::Download* download, key_type key, mapped_value_type arg) { set_d(download, key, mapped_type(arg)); }
void set_std_string(const std::string& key, const std::string& arg) { set(key.c_str(), mapped_type(arg)); }