diff --git a/src/command_download.cc b/src/command_download.cc index 22568928..e4cec1a0 100644 --- a/src/command_download.cc +++ b/src/command_download.cc @@ -202,11 +202,11 @@ retrieve_d_priority_str(core::Download* download) { #define ADD_CD_SLOT(key, function, slot, parm, doc) \ commandDownloadSlotsItr->set_slot(slot); \ - rpc::commands.insert(key, commandDownloadSlotsItr++, NULL, &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); #define ADD_CD_SLOT_PUBLIC(key, function, slot, parm, doc) \ commandDownloadSlotsItr->set_slot(slot); \ - rpc::commands.insert(key, commandDownloadSlotsItr++, NULL, &rpc::CommandDownloadSlot::function, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); + rpc::commands.insert_download(key, commandDownloadSlotsItr++, &rpc::CommandDownloadSlot::function, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); #define ADD_CD_VOID(key, slot) \ ADD_CD_SLOT_PUBLIC("get_d_" key, call_unknown, rpc::object_d_fn(slot), "i:", "") @@ -278,6 +278,8 @@ initialize_command_download() { ADD_CD_F_VOID("erase", rak::make_mem_fun(control->core()->download_list(), &core::DownloadList::erase_ptr)); ADD_CD_F_VOID("check_hash", rak::make_mem_fun(control->core()->download_list(), &core::DownloadList::check_hash)); + ADD_CD_F_VOID("update_priorities", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::update_priorities))); + ADD_CD_VALUE_UNI("is_open", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_open))); ADD_CD_VALUE_UNI("is_active", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_active))); ADD_CD_VALUE_UNI("is_hash_checked", rak::on(std::mem_fun(&core::Download::download), std::mem_fun(&torrent::Download::is_hash_checked))); diff --git a/src/command_file.cc b/src/command_file.cc index 0d356d9e..aa354c93 100644 --- a/src/command_file.cc +++ b/src/command_file.cc @@ -53,6 +53,13 @@ #include "control.h" #include "command_helpers.h" +void +apply_f_set_priority(torrent::File* file, uint32_t value) { + if (value > torrent::PRIORITY_HIGH) + throw torrent::input_error("Invalid value."); + + file->set_priority((torrent::priority_t)value); +} #define ADD_CF_SLOT(key, function, slot, parm, doc) \ commandFileSlotsItr->set_slot(slot); \ @@ -91,11 +98,11 @@ #define ADD_CF_VALUE_UNI(key, get) \ ADD_CF_SLOT_PUBLIC("get_f_" key, call_unknown, rpc::object_void_f_fn(get), "i:", "") -/* #define ADD_CF_VALUE_BI(key, set, get) \ ADD_CF_SLOT_PUBLIC("set_f_" key, call_value, rpc::object_value_f_fn(set), "i:i", "") \ ADD_CF_SLOT_PUBLIC("get_f_" key, call_unknown, rpc::object_void_f_fn(get), "i:", "") +/* #define ADD_CF_VALUE_MEM_BI(key, target, set, get) \ ADD_CF_VALUE_BI(key, rak::on2(std::mem_fun(target), std::mem_fun(set)), rak::on(std::mem_fun(target), std::mem_fun(get))); @@ -122,8 +129,7 @@ initialize_command_file() { ADD_CF_VALUE_UNI("range_first", std::mem_fun(&torrent::File::range_first)); ADD_CF_VALUE_UNI("range_second", std::mem_fun(&torrent::File::range_second)); - // Priority needs to be protected... - ADD_CF_VALUE_UNI("priority", std::mem_fun(&torrent::File::priority)); + ADD_CF_VALUE_BI("priority", std::ptr_fun(&apply_f_set_priority), std::mem_fun(&torrent::File::priority)); ADD_CF_STRING_UNI("frozen_path", std::mem_fun(&torrent::File::frozen_path)); ADD_CF_VALUE_UNI("match_depth_prev", std::mem_fun(&torrent::File::match_depth_prev)); diff --git a/src/command_helpers.cc b/src/command_helpers.cc index 3f5dc9e8..1dad4c46 100644 --- a/src/command_helpers.cc +++ b/src/command_helpers.cc @@ -93,9 +93,9 @@ add_variable(const char* getKey, const char* setKey, const char* defaultSetKey, rpc::CommandVariable* variable = commandVariablesItr++; variable->set_variable(defaultObject); - rpc::commands.insert(getKey, variable, getSlot, NULL, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, "i:", ""); - rpc::commands.insert(setKey, variable, setSlot, NULL, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, "i:", ""); + rpc::commands.insert_generic(getKey, variable, getSlot, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, "i:", ""); + rpc::commands.insert_generic(setKey, variable, setSlot, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, "i:", ""); if (defaultSetKey) - rpc::commands.insert(defaultSetKey, variable, setSlot, NULL, rpc::CommandMap::flag_dont_delete, "i:", ""); + rpc::commands.insert_generic(defaultSetKey, variable, setSlot, rpc::CommandMap::flag_dont_delete, "i:", ""); } diff --git a/src/command_helpers.h b/src/command_helpers.h index 5790a58c..a2adb295 100644 --- a/src/command_helpers.h +++ b/src/command_helpers.h @@ -82,17 +82,17 @@ add_variable("get_" key, "set_" key, key, &rpc::CommandVariable::get_string, &rp #define ADD_COMMAND_SLOT(key, function, slot, parm, doc) \ commandSlotsItr->set_slot(slot); \ - rpc::commands.insert(key, commandSlotsItr++, &rpc::CommandSlot::function, NULL, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); + rpc::commands.insert_generic(key, commandSlotsItr++, &rpc::CommandSlot::function, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); #define ADD_COMMAND_SLOT_PRIVATE(key, function, slot) \ commandSlotsItr->set_slot(slot); \ - rpc::commands.insert(key, commandSlotsItr++, &rpc::CommandSlot::function, NULL, rpc::CommandMap::flag_dont_delete, NULL, NULL); + rpc::commands.insert_generic(key, commandSlotsItr++, &rpc::CommandSlot::function, rpc::CommandMap::flag_dont_delete, NULL, NULL); #define ADD_COMMAND_COPY(key, function, parm, doc) \ - rpc::commands.insert(key, (commandSlotsItr - 1), &rpc::CommandSlot::function, NULL, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); + rpc::commands.insert_generic(key, (commandSlotsItr - 1), &rpc::CommandSlot::function, rpc::CommandMap::flag_dont_delete | rpc::CommandMap::flag_public_xmlrpc, parm, doc); #define ADD_COMMAND_COPY_PRIVATE(key, function) \ - rpc::commands.insert(key, (commandSlotsItr - 1), &rpc::CommandSlot::function, NULL, rpc::CommandMap::flag_dont_delete, NULL, NULL); + rpc::commands.insert_generic(key, (commandSlotsItr - 1), &rpc::CommandSlot::function, rpc::CommandMap::flag_dont_delete, NULL, NULL); #define ADD_COMMAND_VALUE_TRI(key, set, get) \ ADD_COMMAND_SLOT_PRIVATE(key, call_value, rpc::object_value_fn(set)) \ diff --git a/src/rpc/command_map.cc b/src/rpc/command_map.cc index 52756797..1e4461b9 100644 --- a/src/rpc/command_map.cc +++ b/src/rpc/command_map.cc @@ -71,19 +71,27 @@ CommandMap::insert(key_type key, Command* variable, int flags, const char* parm, } void -CommandMap::insert(key_type key, Command* variable, generic_slot genericSlot, download_slot downloadSlot, int flags, - const char* parm, const char* doc) { +CommandMap::insert_generic(key_type key, Command* variable, generic_slot targetSlot, int flags, const char* parm, const char* doc) { iterator itr = insert(key, variable, flags, parm, doc); - itr->second.m_genericSlot = genericSlot; - itr->second.m_downloadSlot = downloadSlot; + itr->second.m_target = target_generic; + itr->second.m_genericSlot = targetSlot; } void -CommandMap::insert_file(key_type key, Command* variable, file_slot fileSlot, int flags, const char* parm, const char* doc) { +CommandMap::insert_download(key_type key, Command* variable, download_slot targetSlot, int flags, const char* parm, const char* doc) { iterator itr = insert(key, variable, flags, parm, doc); - itr->second.m_fileSlot = fileSlot; + itr->second.m_target = target_download; + itr->second.m_downloadSlot = targetSlot; +} + +void +CommandMap::insert_file(key_type key, Command* variable, file_slot targetSlot, int flags, const char* parm, const char* doc) { + iterator itr = insert(key, variable, flags, parm, doc); + + itr->second.m_target = target_file; + itr->second.m_fileSlot = targetSlot; } void @@ -95,61 +103,33 @@ CommandMap::insert(key_type key, const command_map_data_type src) { itr = base_type::insert(itr, value_type(key, command_map_data_type(src.m_variable, src.m_flags | flag_dont_delete, src.m_parm, src.m_doc))); - itr->second.m_genericSlot = src.m_genericSlot; - itr->second.m_downloadSlot = src.m_downloadSlot; - itr->second.m_fileSlot = src.m_fileSlot; -} + itr->second.m_target = src.m_target; -// These should really be handled by a single function. An type enum -// passed with the object would work, and the switch would probably be -// optimized away as the type difference is not reflected in the -// member function pointer call. - -const CommandMap::mapped_type -CommandMap::call_command(key_type key, const mapped_type& arg) { - const_iterator itr = base_type::find(key); - - if (itr == base_type::end()) - throw torrent::input_error("Command \"" + std::string(key) + "\" does not exist."); - - if (itr->second.m_genericSlot == NULL) - throw torrent::input_error("Command does not have a generic slot."); - - return itr->second.m_genericSlot(itr->second.m_variable, arg); -} - -const CommandMap::mapped_type -CommandMap::call_command_d(key_type key, core::Download* download, const mapped_type& arg) { - const_iterator itr = base_type::find(key); - - if (itr == base_type::end()) - throw torrent::input_error("Command \"" + std::string(key) + "\" does not exist."); - - if (itr->second.m_downloadSlot == NULL || download == NULL) { - if (itr->second.m_genericSlot == NULL) - throw torrent::input_error("Command does not have a generic slot."); - - return itr->second.m_genericSlot(itr->second.m_variable, arg); + switch (itr->second.m_target) { + case target_generic: itr->second.m_genericSlot = src.m_genericSlot; break; + case target_download: itr->second.m_downloadSlot = src.m_downloadSlot; break; + case target_file: itr->second.m_fileSlot = src.m_fileSlot; break; + default: throw torrent::internal_error("CommandMap::insert(...) Invalid target."); } - - return itr->second.m_downloadSlot(itr->second.m_variable, download, arg); } const CommandMap::mapped_type -CommandMap::call_command_f(key_type key, torrent::File* file, const mapped_type& arg) { +CommandMap::call_command(key_type key, const mapped_type& arg, target_type target) { const_iterator itr = base_type::find(key); if (itr == base_type::end()) throw torrent::input_error("Command \"" + std::string(key) + "\" does not exist."); - if (itr->second.m_fileSlot == NULL || file == NULL) { - if (itr->second.m_genericSlot == NULL) - throw torrent::input_error("Command does not have a generic slot."); + if ((itr->second.m_target != target.first && itr->second.m_target != target_generic) || + (itr->second.m_target != target_generic && target.second == NULL)) + throw torrent::input_error("Command type mis-match."); - return itr->second.m_genericSlot(itr->second.m_variable, arg); + switch (itr->second.m_target) { + case target_generic: return itr->second.m_genericSlot(itr->second.m_variable, arg); + case target_download: return itr->second.m_downloadSlot(itr->second.m_variable, (core::Download*)target.second, arg); + case target_file: return itr->second.m_fileSlot(itr->second.m_variable, (torrent::File*)target.second, arg); + default: throw torrent::internal_error("CommandMap::call_command(...) Invalid target."); } - - return itr->second.m_fileSlot(itr->second.m_variable, file, arg); } } diff --git a/src/rpc/command_map.h b/src/rpc/command_map.h index 4f5c3878..4fd3db40 100644 --- a/src/rpc/command_map.h +++ b/src/rpc/command_map.h @@ -67,18 +67,18 @@ struct command_map_data_type { typedef const torrent::Object (*file_slot)(Command*, torrent::File*, const torrent::Object&); command_map_data_type(Command* variable, int flags, const char* parm, const char* doc) : - m_variable(variable), m_genericSlot(NULL), m_downloadSlot(NULL), m_fileSlot(NULL), - m_flags(flags), m_parm(parm), m_doc(doc) {} + m_variable(variable), m_flags(flags), m_parm(parm), m_doc(doc) {} Command* m_variable; - // Should make this into a union and pass a type id when calling - // commands, making it all use the same generic interface. - generic_slot m_genericSlot; - download_slot m_downloadSlot; - file_slot m_fileSlot; + union { + generic_slot m_genericSlot; + download_slot m_downloadSlot; + file_slot m_fileSlot; + }; int m_flags; + int m_target; const char* m_parm; const char* m_doc; @@ -103,6 +103,12 @@ public: using base_type::end; using base_type::find; + typedef std::pair target_type; + + static const int target_generic = 0; + static const int target_download = 1; + static const int target_file = 2; + static const int flag_dont_delete = 0x1; static const int flag_public_xmlrpc = 0x2; @@ -114,16 +120,15 @@ public: iterator insert(key_type key, Command* variable, int flags, const char* parm, const char* doc); - void insert(key_type key, Command* variable, generic_slot genericSlot, download_slot downloadSlot, int flags, - const char* parm, const char* doc); - - void insert_file(key_type key, Command* variable, file_slot fileSlot, int flags, const char* parm, const char* doc); + void insert_generic(key_type key, Command* variable, generic_slot targetSlot, int flags, const char* parm, const char* doc); + void insert_download(key_type key, Command* variable, download_slot targetSlot, int flags, const char* parm, const char* doc); + void insert_file(key_type key, Command* variable, file_slot targetSlot, int flags, const char* parm, const char* doc); void insert(key_type key, const command_map_data_type src); - const mapped_type call_command(key_type key, const mapped_type& arg); - const mapped_type call_command_d(key_type key, core::Download* download, const mapped_type& arg); - const mapped_type call_command_f(key_type key, torrent::File* file, const mapped_type& arg); + 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)); } private: CommandMap(const CommandMap&); diff --git a/src/rpc/xmlrpc.cc b/src/rpc/xmlrpc.cc index 5ac08de7..c904d94f 100644 --- a/src/rpc/xmlrpc.cc +++ b/src/rpc/xmlrpc.cc @@ -502,10 +502,10 @@ XmlRpc::set_dialect(int dialect) { void XmlRpc::initialize() { throw torrent::resource_error("XMLRPC not supported."); } void XmlRpc::cleanup() {} -void XmlRpc::insert_command(const char* name, const char* parm, const char* doc, bool onDownload) {} +void XmlRpc::insert_command(__UNUSED const char* name, __UNUSED const char* parm, __UNUSED const char* doc, __UNUSED int call) {} void XmlRpc::set_dialect(__UNUSED int dialect) {} -bool XmlRpc::process(const char* inBuffer, uint32_t length, slot_write slotWrite) { return false; } +bool XmlRpc::process(__UNUSED const char* inBuffer, __UNUSED uint32_t length, __UNUSED slot_write slotWrite) { return false; } #endif