* Added 'method.rlookup' and 'method.rlookup.clear' commands for looking up the event handlers holding a specified key.

git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1231 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2011-05-26 03:38:45 +00:00
parent 5200454cf7
commit d2f328cc8e
7 changed files with 125 additions and 21 deletions
+8
View File
@@ -80,6 +80,9 @@ public:
bool operator == (const fixed_key_type& rhs) const { return m_size == rhs.m_size && std::memcmp(m_data, rhs.m_data, m_size) == 0; }
bool operator != (const fixed_key_type& rhs) const { return m_size != rhs.m_size || std::memcmp(m_data, rhs.m_data, m_size) != 0; }
bool operator == (const torrent::raw_string& rhs) const { return m_size == rhs.size() && std::memcmp(m_data, rhs.data(), m_size) == 0; }
bool operator != (const torrent::raw_string& rhs) const { return m_size != rhs.size() || std::memcmp(m_data, rhs.data(), m_size) != 0; }
bool operator == (const std::string& rhs) const { return m_size == rhs.size() && std::memcmp(m_data, rhs.data(), m_size) == 0; }
private:
@@ -110,6 +113,11 @@ struct hash_fixed_key_type {
}
};
template <size_t MaxSize>
bool operator == (const torrent::raw_string& lhs, const fixed_key_type<MaxSize>& rhs) {
return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
}
}
#endif
+56
View File
@@ -38,6 +38,7 @@
#include "object_storage.h"
#include "rak/functional.h"
#include "parse.h"
#include "parse_commands.h"
@@ -77,6 +78,9 @@ object_storage::insert(const char* key_data, uint32_t key_size, const torrent::O
if (!(flags & mask_type))
throw torrent::input_error("No type flags set when calling object_storage::insert.");
if ((flags & flag_rlookup) && (!(flags & flag_static) || !(flags & flag_multi_type)))
throw torrent::input_error("Cannot insert non-static or non-multi-type object with rlookup enabled.");
std::pair<iterator, bool> result = base_type::insert(std::make_pair(key_type(key_data, key_size), object_storage_node()));
if (!result.second)
@@ -183,6 +187,21 @@ object_storage::erase_multi_key(const torrent::raw_string& key, const std::strin
return;
itr->second.object.erase_key(cmd_key);
if (!(itr->second.flags & flag_rlookup))
return;
// Remove the rlookup entry.
rlookup_iterator r_itr = m_rlookup.find(cmd_key);
if (r_itr == m_rlookup.end())
return;
rlookup_mapped_iterator rm_itr = std::find_if(r_itr->second.begin(), r_itr->second.end(),
rak::equal(key, rak::mem_ptr(&value_type::first)));
if (rm_itr != r_itr->second.end())
r_itr->second.erase(rm_itr);
}
void
@@ -192,7 +211,44 @@ object_storage::set_multi_key(const torrent::raw_string& key, const std::string&
if (itr == end(0) || (itr->second.flags & mask_type) != flag_multi_type)
throw torrent::input_error("Key not found or wrong type.");
if (itr->second.flags & flag_rlookup) {
rlookup_iterator r_itr = m_rlookup.find(cmd_key);
if (r_itr == m_rlookup.end())
r_itr = m_rlookup.insert(std::make_pair(cmd_key, rlookup_type::mapped_type())).first;
if (std::find_if(r_itr->second.begin(), r_itr->second.end(),
rak::equal(key, rak::mem_ptr(&value_type::first))) == r_itr->second.end())
r_itr->second.push_back(&*itr);
}
itr->second.object.insert_key(cmd_key, object);
}
torrent::Object::list_type
object_storage::rlookup_list(const std::string& cmd_key) {
torrent::Object::list_type result;
rlookup_iterator r_itr = m_rlookup.find(cmd_key);
if (r_itr != m_rlookup.end())
std::transform(r_itr->second.begin(), r_itr->second.end(), std::back_inserter(result),
std::bind(&key_type::c_str, std::bind(rak::mem_ptr(&value_type::first), std::placeholders::_1)));
return result;
}
void
object_storage::rlookup_clear(const std::string& cmd_key) {
rlookup_iterator r_itr = m_rlookup.find(cmd_key);
if (r_itr == m_rlookup.end())
return;
for (rlookup_mapped_iterator first = r_itr->second.begin(), last = r_itr->second.end(); first != last; first++)
(*first)->second.object.erase_key(cmd_key);
r_itr->second.clear();
}
}
+26 -7
View File
@@ -45,6 +45,7 @@
#include <tr1/unordered_map>
#include <torrent/object.h>
#include "rak/unordered_vector.h"
#include "command.h"
#include "fixed_key.h"
@@ -55,9 +56,13 @@ struct object_storage_node {
char flags;
};
class object_storage : private std::unordered_map<fixed_key_type<64>, object_storage_node, hash_fixed_key_type> {
typedef std::unordered_map<fixed_key_type<64>, object_storage_node, hash_fixed_key_type> object_storage_base_type;
class object_storage : private object_storage_base_type {
public:
typedef std::unordered_map<fixed_key_type<64>, object_storage_node, hash_fixed_key_type> base_type;
// Should really change rlookup_type into a set with pair values.
typedef object_storage_base_type base_type;
typedef std::map<std::string, rak::unordered_vector<base_type::value_type*> > rlookup_type;
using base_type::key_type;
using base_type::value_type;
@@ -66,6 +71,9 @@ public:
using base_type::local_iterator;
using base_type::const_local_iterator;
typedef rlookup_type::iterator rlookup_iterator;
typedef rlookup_type::mapped_type::iterator rlookup_mapped_iterator;
using base_type::begin;
using base_type::end;
using base_type::size;
@@ -76,6 +84,8 @@ public:
using base_type::max_bucket_count;
using base_type::load_factor;
// Verify rlookup is static / const.
using base_type::clear;
using base_type::find;
using base_type::erase;
@@ -90,9 +100,10 @@ public:
static const unsigned int mask_type = 0xf;
static const unsigned int flag_constant = 0x10;
static const unsigned int flag_static = 0x20;
static const unsigned int flag_private = 0x40;
static const unsigned int flag_constant = 0x10;
static const unsigned int flag_static = 0x20;
static const unsigned int flag_private = 0x40;
static const unsigned int flag_rlookup = 0x80;
static const size_t key_size = key_type::max_size;
@@ -128,8 +139,8 @@ public:
const torrent::Object& set_str_list(const std::string& str, const torrent::Object::list_type& object) { return set_list(torrent::raw_string::from_string(str), object); }
// Functions callers:
torrent::Object call_function(const torrent::raw_string& key, target_type target, const torrent::Object& object);
torrent::Object call_function_str(const std::string& key, target_type target, const torrent::Object& object);
torrent::Object call_function(const torrent::raw_string& key, target_type target, const torrent::Object& object);
torrent::Object call_function_str(const std::string& key, target_type target, const torrent::Object& object);
// Single-command function:
@@ -144,6 +155,14 @@ public:
bool has_str_multi_key(const std::string& key, const std::string& cmd_key);
void erase_str_multi_key(const std::string& key, const std::string& cmd_key);
void set_str_multi_key(const std::string& key, const std::string& cmd_key, const std::string& object);
torrent::Object::list_type rlookup_list(const std::string& cmd_key);
torrent::Object rlookup_obj_list(const std::string& cmd_key) { return torrent::Object::from_list(rlookup_list(cmd_key)); }
void rlookup_clear(const std::string& cmd_key);
private:
rlookup_type m_rlookup;
};
//
+6
View File
@@ -452,6 +452,9 @@ print_object(char* first, char* last, const torrent::Object* src, int flags) {
return std::min(first + snprintf(first, std::distance(first, last), "%lli", src->as_value()), last);
case torrent::Object::TYPE_LIST:
if (first != last)
*first = '\0';
for (torrent::Object::list_const_iterator itr = src->as_list().begin(), itrEnd = src->as_list().end(); itr != itrEnd; itr++) {
first = print_object(first, last, &*itr, flags);
@@ -462,6 +465,9 @@ print_object(char* first, char* last, const torrent::Object* src, int flags) {
return first;
case torrent::Object::TYPE_NONE:
if (first != last)
*first = '\0';
return first;
default:
throw torrent::input_error("Invalid type.");