* Added 'f.multicall' and 't.multicall', and renamed 'call_download'

to 'd.multicall'.

* Cleanup of 'rpc/parse_commands.h'.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@961 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2007-08-20 21:29:59 +00:00
parent bac7d0ba3b
commit 0390b7ec00
10 changed files with 103 additions and 43 deletions
+2 -3
View File
@@ -438,9 +438,8 @@ Set the default download directory. Defaults to "./".
<listitem><para> <listitem><para>
Session management will be enabled and the torrent files for all open Session management will be enabled and the torrent files for all open
downloads will be stored in this directory. Only one instance of downloads will be stored in this directory. Only one instance of
rtorrent should be used with each session directory, though at the rtorrent can be used per session directory. An empty string will
moment no locking is done. An empty string will disable the session disable the session directory.
directory.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
+60
View File
@@ -43,6 +43,7 @@
#include <rak/path.h> #include <rak/path.h>
#include <rak/string_manip.h> #include <rak/string_manip.h>
#include <torrent/rate.h> #include <torrent/rate.h>
#include <torrent/tracker.h>
#include <torrent/data/file.h> #include <torrent/data/file.h>
#include <torrent/data/file_list.h> #include <torrent/data/file_list.h>
@@ -220,6 +221,62 @@ retrieve_d_hash(core::Download* download) {
return torrent::Object(rak::transform_hex(hashString->begin(), hashString->end())); return torrent::Object(rak::transform_hex(hashString->begin(), hashString->end()));
} }
torrent::Object
f_multicall(core::Download* download, const torrent::Object& rawArgs) {
const torrent::Object::list_type& args = rawArgs.as_list();
if (args.empty())
throw torrent::input_error("Too few arguments.");
// We ignore the first arg for now, but it will be used for
// selecting what files to include.
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
torrent::Object resultRaw(torrent::Object::TYPE_LIST);
torrent::Object::list_type& result = resultRaw.as_list();
for (torrent::FileList::const_iterator itr = download->file_list()->begin(), last = download->file_list()->end(); itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object(torrent::Object::TYPE_LIST))->as_list();
for (torrent::Object::list_type::const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command(rpc::make_target(*itr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
}
torrent::Object
t_multicall(core::Download* download, const torrent::Object& rawArgs) {
const torrent::Object::list_type& args = rawArgs.as_list();
if (args.empty())
throw torrent::input_error("Too few arguments.");
// We ignore the first arg for now, but it will be used for
// selecting what files to include.
// Add some pre-parsing of the commands, so we don't spend time
// parsing and searching command map for every single call.
torrent::Object resultRaw(torrent::Object::TYPE_LIST);
torrent::Object::list_type& result = resultRaw.as_list();
for (int itr = 0, last = download->tracker_list()->size(); itr != last; itr++) {
torrent::Object::list_type& row = result.insert(result.end(), torrent::Object(torrent::Object::TYPE_LIST))->as_list();
for (torrent::Object::list_type::const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string();
torrent::Tracker t = download->tracker_list()->get(itr);
row.push_back(rpc::parse_command(rpc::make_target(&t), cmd.c_str(), cmd.c_str() + cmd.size()).first);
}
}
return resultRaw;
}
#define ADD_CD_SLOT(key, function, slot, parm, doc) \ #define ADD_CD_SLOT(key, function, slot, parm, doc) \
commandDownloadSlotsItr->set_slot(slot); \ commandDownloadSlotsItr->set_slot(slot); \
rpc::commands.insert_download(key, commandDownloadSlotsItr++, &rpc::CommandDownloadSlot::function, rpc::CommandMap::flag_dont_delete, parm, doc); rpc::commands.insert_download(key, commandDownloadSlotsItr++, &rpc::CommandDownloadSlot::function, rpc::CommandMap::flag_dont_delete, parm, doc);
@@ -383,4 +440,7 @@ initialize_command_download() {
ADD_CD_STRING_BI("directory", std::mem_fun(&core::Download::set_root_directory), rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::root_dir))); ADD_CD_STRING_BI("directory", std::mem_fun(&core::Download::set_root_directory), rak::on(std::mem_fun(&core::Download::file_list), std::mem_fun(&torrent::FileList::root_dir)));
ADD_CD_VALUE_BI("priority", std::mem_fun(&core::Download::set_priority), std::mem_fun(&core::Download::priority)); ADD_CD_VALUE_BI("priority", std::mem_fun(&core::Download::set_priority), std::mem_fun(&core::Download::priority));
ADD_CD_STRING_UNI("priority_str", std::ptr_fun(&retrieve_d_priority_str)); ADD_CD_STRING_UNI("priority_str", std::ptr_fun(&retrieve_d_priority_str));
ADD_CD_SLOT_PUBLIC("f.multicall", call_list, rak::ptr_fn(&f_multicall), "i:", "")
ADD_CD_SLOT_PUBLIC("t.multicall", call_list, rak::ptr_fn(&t_multicall), "i:", "")
} }
+4 -3
View File
@@ -268,7 +268,7 @@ apply_download_list(const torrent::Object& rawArgs) {
} }
torrent::Object torrent::Object
apply_call_download(const torrent::Object& rawArgs) { d_multicall(const torrent::Object& rawArgs) {
const torrent::Object::list_type& args = rawArgs.as_list(); const torrent::Object::list_type& args = rawArgs.as_list();
if (args.empty()) if (args.empty())
@@ -306,7 +306,7 @@ apply_call_download(const torrent::Object& rawArgs) {
for (torrent::Object::list_type::const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) { for (torrent::Object::list_type::const_iterator cItr = ++args.begin(), cLast = args.end(); cItr != args.end(); cItr++) {
const std::string& cmd = cItr->as_string(); const std::string& cmd = cItr->as_string();
row.push_back(rpc::parse_command_d_single(*vItr, cmd.c_str(), cmd.c_str() + cmd.size())); row.push_back(rpc::parse_command(rpc::make_target(*vItr), cmd.c_str(), cmd.c_str() + cmd.size()).first);
} }
} }
@@ -354,5 +354,6 @@ initialize_command_events() {
ADD_COMMAND_VALUE_UN("close_low_diskspace", std::ptr_fun(&apply_close_low_diskspace)); ADD_COMMAND_VALUE_UN("close_low_diskspace", std::ptr_fun(&apply_close_low_diskspace));
ADD_COMMAND_LIST("download_list", rak::ptr_fn(&apply_download_list)); ADD_COMMAND_LIST("download_list", rak::ptr_fn(&apply_download_list));
ADD_COMMAND_LIST("call_download", rak::ptr_fn(&apply_call_download)); ADD_COMMAND_LIST("d.multicall", rak::ptr_fn(&d_multicall));
ADD_COMMAND_COPY("call_download", call_list, "i:", "");
} }
+2 -2
View File
@@ -165,7 +165,7 @@ main(int argc, char** argv) {
// torrent::ConnectionManager* are valid etc. // torrent::ConnectionManager* are valid etc.
initialize_commands(); initialize_commands();
rpc::parse_command_multiple( rpc::parse_command_multiple(rpc::make_target(),
// "set_name = $cat={$get_hostname=,:,$get_pid=}\n" // "set_name = $cat={$get_hostname=,:,$get_pid=}\n"
"set_name = \"$cat=$get_hostname=,:,$get_pid=\"\n" "set_name = \"$cat=$get_hostname=,:,$get_pid=\"\n"
@@ -236,7 +236,7 @@ main(int argc, char** argv) {
if (OptionParser::has_flag('n', argc, argv)) if (OptionParser::has_flag('n', argc, argv))
control->core()->push_log("Ignoring ~/.rtorrent.rc."); control->core()->push_log("Ignoring ~/.rtorrent.rc.");
else else
rpc::parse_command_single("try_import = ~/.rtorrent.rc"); rpc::parse_command_single(rpc::make_target(), "try_import = ~/.rtorrent.rc");
int firstArg = parse_options(control, argc, argv); int firstArg = parse_options(control, argc, argv);
+1
View File
@@ -60,6 +60,7 @@ CommandDownloadSlot::call_list(Command* rawCommand, core::Download* download, co
case torrent::Object::TYPE_VALUE: case torrent::Object::TYPE_VALUE:
case torrent::Object::TYPE_STRING: case torrent::Object::TYPE_STRING:
// case torrent::Object::TYPE_NONE:
{ {
torrent::Object tmpList(torrent::Object::TYPE_LIST); torrent::Object tmpList(torrent::Object::TYPE_LIST);
tmpList.as_list().push_back(rawArgs); tmpList.as_list().push_back(rawArgs);
+1 -1
View File
@@ -138,7 +138,7 @@ public:
void insert(key_type key, const command_map_data_type src); void insert(key_type key, const command_map_data_type src);
const mapped_type call_command(key_type key, const mapped_type& arg, target_type target = target_type((int)target_generic, NULL)); const mapped_type call_command (key_type key, const mapped_type& arg, target_type target = target_type((int)target_generic, NULL));
const mapped_type call_command_d(key_type key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)target_download, download)); } const mapped_type call_command_d(key_type key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)target_download, download)); }
const mapped_type call_command_f(key_type key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)target_file, file)); } const mapped_type call_command_f(key_type key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)target_file, file)); }
const mapped_type call_command_p(key_type key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)target_peer, peer)); } const mapped_type call_command_p(key_type key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)target_peer, peer)); }
+1
View File
@@ -59,6 +59,7 @@ CommandSlot::call_list(Command* rawCommand, const torrent::Object& rawArgs) {
case torrent::Object::TYPE_VALUE: case torrent::Object::TYPE_VALUE:
case torrent::Object::TYPE_STRING: case torrent::Object::TYPE_STRING:
case torrent::Object::TYPE_NONE:
{ {
torrent::Object tmpList(torrent::Object::TYPE_LIST); torrent::Object tmpList(torrent::Object::TYPE_LIST);
tmpList.as_list().push_back(rawArgs); tmpList.as_list().push_back(rawArgs);
+10 -20
View File
@@ -82,22 +82,22 @@ parse_count_escaped(const char* first, const char* last) {
// //
// Find a better name. // Find a better name.
void void
parse_command_execute(core::Download* download, torrent::Object* object) { parse_command_execute(CommandMap::target_type target, torrent::Object* object) {
if (object->is_list()) { if (object->is_list()) {
for (torrent::Object::list_type::iterator itr = object->as_list().begin(), last = object->as_list().end(); itr != last; itr++) for (torrent::Object::list_type::iterator itr = object->as_list().begin(), last = object->as_list().end(); itr != last; itr++)
parse_command_execute(download, &*itr); parse_command_execute(target, &*itr);
} else if (*object->as_string().c_str() == '$') { } else if (*object->as_string().c_str() == '$') {
const std::string& str = object->as_string(); const std::string& str = object->as_string();
*object = parse_command_d_single(download, str.c_str() + 1, str.c_str() + str.size()); *object = parse_command(target, str.c_str() + 1, str.c_str() + str.size()).first;
} }
} }
// Set 'download' to NULL to call the generic functions, thus reusing // Set 'download' to NULL to call the generic functions, thus reusing
// the code below for both cases. // the code below for both cases.
std::pair<torrent::Object, const char*> parse_command_type
parse_command(core::Download* download, const char* first, const char* last) { parse_command(CommandMap::target_type target, const char* first, const char* last) {
first = std::find_if(first, last, std::not1(command_map_is_space())); first = std::find_if(first, last, std::not1(command_map_is_space()));
if (first == last || *first == '#') if (first == last || *first == '#')
@@ -127,32 +127,22 @@ parse_command(core::Download* download, const char* first, const char* last) {
// Replace any strings starting with '$' with the result of the // Replace any strings starting with '$' with the result of the
// following command. // following command.
parse_command_execute(download, &args); parse_command_execute(target, &args);
return std::make_pair(commands.call_command_d(key.c_str(), download, args), first); return std::make_pair(commands.call_command(key.c_str(), args, target), first);
} }
void void
parse_command_single(const char* first) { parse_command_multiple(CommandMap::target_type target, const char* first, const char* last) {
parse_command(NULL, first, first + std::strlen(first));
}
void
parse_command_multiple(core::Download* download, const char* first, const char* last) {
while (first != last) { while (first != last) {
// Should we check the return value? Probably not necessary as // Should we check the return value? Probably not necessary as
// parse_args throws on unquoted multi-word input. // parse_args throws on unquoted multi-word input.
std::pair<torrent::Object, const char*> result = parse_command(download, first, last); parse_command_type result = parse_command(target, first, last);
first = result.second; first = result.second;
} }
} }
void
parse_command_d_multiple(core::Download* download, const char* first) {
parse_command_multiple(download, first, first + std::strlen(first));
}
bool bool
parse_command_file(const std::string& path) { parse_command_file(const std::string& path) {
std::fstream file(rak::path_expand(path).c_str(), std::ios::in); std::fstream file(rak::path_expand(path).c_str(), std::ios::in);
@@ -185,7 +175,7 @@ parse_command_file(const std::string& path) {
} }
// Would be nice to make this zero-copy. // Would be nice to make this zero-copy.
parse_command(NULL, buffer, buffer + getCount); parse_command(make_target(), buffer, buffer + getCount);
getCount = 0; getCount = 0;
} }
+21 -13
View File
@@ -38,6 +38,7 @@
#define RTORRENT_RPC_PARSE_COMMANDS_H #define RTORRENT_RPC_PARSE_COMMANDS_H
#include <string> #include <string>
#include <cstring>
#include "command_map.h" #include "command_map.h"
#include "exec_file.h" #include "exec_file.h"
@@ -54,36 +55,43 @@ extern CommandMap commands;
extern XmlRpc xmlrpc; extern XmlRpc xmlrpc;
extern ExecFile execFile; extern ExecFile execFile;
inline CommandMap::target_type make_target() { return CommandMap::target_type((int)CommandMap::target_generic, NULL); }
inline CommandMap::target_type make_target(core::Download* target) { return CommandMap::target_type((int)CommandMap::target_download, target); }
inline CommandMap::target_type make_target(torrent::File* target) { return CommandMap::target_type((int)CommandMap::target_file, target); }
inline CommandMap::target_type make_target(torrent::Peer* target) { return CommandMap::target_type((int)CommandMap::target_peer, target); }
inline CommandMap::target_type make_target(torrent::Tracker* target) { return CommandMap::target_type((int)CommandMap::target_tracker, target); }
typedef std::pair<torrent::Object, const char*> parse_command_type;
// The generic parse command function, used by the rest. At some point // The generic parse command function, used by the rest. At some point
// the 'download' parameter should be replaced by a more generic one. // the 'download' parameter should be replaced by a more generic one.
std::pair<torrent::Object, const char*> parse_command(core::Download* download, const char* first, const char* last); parse_command_type parse_command(CommandMap::target_type target, const char* first, const char* last);
void parse_command_multiple(CommandMap::target_type target, const char* first, const char* last);
void parse_command_single(const char* first); inline void parse_command_single(CommandMap::target_type target, const char* first) { parse_command(target, first, first + std::strlen(first)); }
inline torrent::Object parse_command_single(const char* first, const char* last) { return parse_command(NULL, first, last).first; } inline void parse_command_multiple(CommandMap::target_type target, const char* first) { parse_command_multiple(target, first, first + std::strlen(first)); }
inline torrent::Object parse_command_d_single(core::Download* download, const char* first, const char* last) { return parse_command(download, first, last).first; }
void parse_command_multiple(core::Download* download, const char* first, const char* last);
void parse_command_d_multiple(core::Download* download, const char* first);
inline void parse_command_d_multiple_std(core::Download* download, const std::string& cmd) { parse_command_multiple(download, cmd.c_str(), cmd.c_str() + cmd.size()); }
inline void parse_command_multiple(const char* first) { parse_command_d_multiple(NULL, first); }
bool parse_command_file(const std::string& path); bool parse_command_file(const std::string& path);
const char* parse_command_name(const char* first, const char* last, std::string* dest); const char* parse_command_name(const char* first, const char* last, std::string* dest);
inline void inline void
parse_command_single_std(const std::string& cmd) { parse_command_single_std(const std::string& cmd) {
parse_command_single(cmd.c_str(), cmd.c_str() + cmd.size()); parse_command(make_target(), cmd.c_str(), cmd.c_str() + cmd.size());
} }
inline void inline void
parse_command_d_single_std(core::Download* download, const std::string& cmd) { parse_command_d_single_std(core::Download* download, const std::string& cmd) {
parse_command_d_single(download, cmd.c_str(), cmd.c_str() + cmd.size()); parse_command(make_target(download), cmd.c_str(), cmd.c_str() + cmd.size());
} }
inline void inline void
parse_command_multiple_std(const std::string& cmd) { parse_command_multiple_std(const std::string& cmd) {
parse_command_multiple(NULL, cmd.c_str(), cmd.c_str() + cmd.size()); parse_command_multiple(make_target(), cmd.c_str(), cmd.c_str() + cmd.size());
}
inline void
parse_command_d_multiple_std(core::Download* download, const std::string& cmd) {
parse_command_multiple(make_target(download), cmd.c_str(), cmd.c_str() + cmd.size());
} }
inline torrent::Object call_command(const char* key, const torrent::Object& obj) { return commands.call_command(key, obj); } inline torrent::Object call_command(const char* key, const torrent::Object& obj) { return commands.call_command(key, obj); }
+1 -1
View File
@@ -275,7 +275,7 @@ xmlrpc_to_object_target(xmlrpc_env* env, xmlrpc_value* value, int callType, void
torrent::Object result; torrent::Object result;
if (current + 1 > last) { if (current + 1 < last) {
result = torrent::Object(torrent::Object::TYPE_LIST); result = torrent::Object(torrent::Object::TYPE_LIST);
torrent::Object::list_type& listRef = result.as_list(); torrent::Object::list_type& listRef = result.as_list();