* 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>
Session management will be enabled and the torrent files for all open
downloads will be stored in this directory. Only one instance of
rtorrent should be used with each session directory, though at the
moment no locking is done. An empty string will disable the session
directory.
rtorrent can be used per session directory. An empty string will
disable the session directory.
</para></listitem>
</varlistentry>
+60
View File
@@ -43,6 +43,7 @@
#include <rak/path.h>
#include <rak/string_manip.h>
#include <torrent/rate.h>
#include <torrent/tracker.h>
#include <torrent/data/file.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()));
}
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) \
commandDownloadSlotsItr->set_slot(slot); \
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_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_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
apply_call_download(const torrent::Object& rawArgs) {
d_multicall(const torrent::Object& rawArgs) {
const torrent::Object::list_type& args = rawArgs.as_list();
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++) {
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_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.
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"
@@ -236,7 +236,7 @@ main(int argc, char** argv) {
if (OptionParser::has_flag('n', argc, argv))
control->core()->push_log("Ignoring ~/.rtorrent.rc.");
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);
+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_STRING:
// case torrent::Object::TYPE_NONE:
{
torrent::Object tmpList(torrent::Object::TYPE_LIST);
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);
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_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)); }
+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_STRING:
case torrent::Object::TYPE_NONE:
{
torrent::Object tmpList(torrent::Object::TYPE_LIST);
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.
void
parse_command_execute(core::Download* download, torrent::Object* object) {
parse_command_execute(CommandMap::target_type target, torrent::Object* object) {
if (object->is_list()) {
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() == '$') {
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
// the code below for both cases.
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) {
first = std::find_if(first, last, std::not1(command_map_is_space()));
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
// 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
parse_command_single(const char* first) {
parse_command(NULL, first, first + std::strlen(first));
}
void
parse_command_multiple(core::Download* download, const char* first, const char* last) {
parse_command_multiple(CommandMap::target_type target, const char* first, const char* last) {
while (first != last) {
// Should we check the return value? Probably not necessary as
// 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;
}
}
void
parse_command_d_multiple(core::Download* download, const char* first) {
parse_command_multiple(download, first, first + std::strlen(first));
}
bool
parse_command_file(const std::string& path) {
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.
parse_command(NULL, buffer, buffer + getCount);
parse_command(make_target(), buffer, buffer + getCount);
getCount = 0;
}
+21 -13
View File
@@ -38,6 +38,7 @@
#define RTORRENT_RPC_PARSE_COMMANDS_H
#include <string>
#include <cstring>
#include "command_map.h"
#include "exec_file.h"
@@ -54,36 +55,43 @@ extern CommandMap commands;
extern XmlRpc xmlrpc;
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 '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 torrent::Object parse_command_single(const char* first, const char* last) { return parse_command(NULL, first, last).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); }
inline void parse_command_single(CommandMap::target_type target, const char* first) { parse_command(target, first, first + std::strlen(first)); }
inline void parse_command_multiple(CommandMap::target_type target, const char* first) { parse_command_multiple(target, first, first + std::strlen(first)); }
bool parse_command_file(const std::string& path);
const char* parse_command_name(const char* first, const char* last, std::string* dest);
inline void
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
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
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); }
+1 -1
View File
@@ -275,7 +275,7 @@ xmlrpc_to_object_target(xmlrpc_env* env, xmlrpc_value* value, int callType, void
torrent::Object result;
if (current + 1 > last) {
if (current + 1 < last) {
result = torrent::Object(torrent::Object::TYPE_LIST);
torrent::Object::list_type& listRef = result.as_list();