* Added 'rpc/fixed_key.h' header.

* Replaced Command with command_base.


git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@1168 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
rakshasa
2010-04-30 04:36:02 +00:00
parent 7dad6d34f3
commit 8b03988612
15 changed files with 307 additions and 248 deletions
+94 -15
View File
@@ -37,6 +37,12 @@
#ifndef RTORRENT_RPC_COMMAND_H
#define RTORRENT_RPC_COMMAND_H
#include <functional>
#include <limits>
#include <inttypes.h>
#include <torrent/object.h>
#include <tr1/functional>
#include <torrent/object.h>
#include <torrent/data/file_list_iterator.h>
@@ -99,7 +105,15 @@ struct rt_triple : private std::pair<T1, T2> {
//typedef std::pair<int, void*> target_type;
typedef rt_triple<int, void*, void*> target_type;
class Command {
class command_base;
typedef const torrent::Object (*command_base_call_type)(command_base*, target_type, const torrent::Object&);
typedef std::tr1::function<torrent::Object (target_type, const torrent::Object&)> base_function;
template <typename tmpl> struct command_base_is_valid {};
template <command_base_call_type tmpl_func> struct command_base_is_type {};
class command_base {
public:
typedef torrent::Object::value_type value_type;
typedef torrent::Object::string_type string_type;
@@ -107,16 +121,16 @@ public:
typedef torrent::Object::map_type map_type;
typedef torrent::Object::key_type key_type;
typedef const torrent::Object (*generic_slot) (Command*, const torrent::Object&);
typedef const torrent::Object (*cleaned_slot) (Command*, target_wrapper<void>::cleaned_type, const torrent::Object&);
typedef const torrent::Object (*any_slot) (Command*, target_type, const torrent::Object&);
typedef const torrent::Object (*download_slot) (Command*, core::Download*, const torrent::Object&);
typedef const torrent::Object (*file_slot) (Command*, torrent::File*, const torrent::Object&);
typedef const torrent::Object (*file_itr_slot) (Command*, torrent::FileListIterator*, const torrent::Object&);
typedef const torrent::Object (*peer_slot) (Command*, torrent::Peer*, const torrent::Object&);
typedef const torrent::Object (*tracker_slot) (Command*, torrent::Tracker*, const torrent::Object&);
typedef const torrent::Object (*generic_slot) (command_base*, const torrent::Object&);
typedef const torrent::Object (*cleaned_slot) (command_base*, target_wrapper<void>::cleaned_type, const torrent::Object&);
typedef const torrent::Object (*any_slot) (command_base*, target_type, const torrent::Object&);
typedef const torrent::Object (*download_slot) (command_base*, core::Download*, const torrent::Object&);
typedef const torrent::Object (*file_slot) (command_base*, torrent::File*, const torrent::Object&);
typedef const torrent::Object (*file_itr_slot) (command_base*, torrent::FileListIterator*, const torrent::Object&);
typedef const torrent::Object (*peer_slot) (command_base*, torrent::Peer*, const torrent::Object&);
typedef const torrent::Object (*tracker_slot) (command_base*, torrent::Tracker*, const torrent::Object&);
typedef const torrent::Object (*download_pair_slot) (Command*, core::Download*, core::Download*, const torrent::Object&);
typedef const torrent::Object (*download_pair_slot) (command_base*, core::Download*, core::Download*, const torrent::Object&);
static const int target_generic = 0;
static const int target_any = 1;
@@ -145,8 +159,8 @@ public:
char buffer[sizeof(torrent::Object) * max_arguments];
};
Command() {}
virtual ~Command() {}
command_base() { new (&_pod<base_function>()) base_function(); }
virtual ~command_base() { _pod<base_function>().~base_function(); }
static torrent::Object* argument(unsigned int index) { return current_stack.begin() + index; }
static torrent::Object& argument_ref(unsigned int index) { return *(current_stack.begin() + index); }
@@ -160,13 +174,35 @@ public:
static torrent::Object* push_stack(const torrent::Object* first_arg, const torrent::Object* last_arg, stack_type* stack);
static void pop_stack(stack_type* stack, torrent::Object* last_stack);
template <typename T>
void set_function(T s, int value = command_base_is_valid<T>::value) { _pod<T>() = s; }
template <command_base_call_type T>
void set_function_2(typename command_base_is_type<T>::type s, int value = command_base_is_valid<typename command_base_is_type<T>::type>::value) {
_pod<typename command_base_is_type<T>::type>() = s;
}
// The std::function object in GCC is castable between types with a
// pointer to a struct of ctor/dtor/calls for non-POD slots. As such
// it should be safe to cast between different std::function
// template types, yet what the C++0x standard will say about this I
// have no idea atm.
template <typename tmpl> tmpl& _pod() { return reinterpret_cast<tmpl&>(t_pod); }
template <typename Func, typename T, typename Args>
static const torrent::Object _call(command_base* cmd, target_type target, Args args);
protected:
Command(const Command&);
void operator = (const Command&);
command_base(const command_base&);
void operator = (const command_base&);
// For use by functions that need to use placeholders to arguments
// within commands. E.d. callable command strings where one of the
// arguments within the command needs to be supplied by the caller.
union {
char t_pod[sizeof(base_function)];
};
};
template <typename T1 = void, typename T2 = void>
@@ -178,7 +214,7 @@ template <typename T> inline bool
is_target_compatible(const target_type& target) { return target.first == target_type_id<T>::value; }
// Splitting pairs into separate targets.
inline bool is_target_pair(const target_type& target) { return target.first >= Command::target_download_pair; }
inline bool is_target_pair(const target_type& target) { return target.first >= command_base::target_download_pair; }
template <typename T> inline T
get_target_cast(target_type target, int type = target_type_id<T>::value) { return (T)target.second; }
@@ -190,4 +226,47 @@ inline target_type get_target_right(const target_type& target) { return target_t
#include "command_impl.h"
namespace rpc {
template <typename Func, typename T, typename Args>
inline const torrent::Object
command_base::_call(command_base* cmd, target_type target, Args args) {
return static_cast<command_base*>(cmd)->_pod<Func>()(get_target_cast<T>(target), args);
}
#define COMMAND_BASE_TEMPLATE_TYPE(func_type, func_parm) \
template <typename T, int proper = target_type_id<T>::proper_type> struct func_type { typedef std::tr1::function<func_parm> type; }; \
\
template <> struct command_base_is_valid<func_type<target_type>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<core::Download*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::Peer*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::Tracker*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::File*>::type> { static const int value = 1; }; \
template <> struct command_base_is_valid<func_type<torrent::FileListIterator*>::type> { static const int value = 1; };
// template <typename Q> struct command_base_is_valid<typename func_type<Q>::type > { static const int value = 1; };
COMMAND_BASE_TEMPLATE_TYPE(command_function, torrent::Object (T, const torrent::Object&));
COMMAND_BASE_TEMPLATE_TYPE(command_value_function, torrent::Object (T, const torrent::Object::value_type&));
COMMAND_BASE_TEMPLATE_TYPE(command_string_function, torrent::Object (T, const std::string&));
COMMAND_BASE_TEMPLATE_TYPE(command_list_function, torrent::Object (T, const torrent::Object::list_type&));
#define COMMAND_BASE_TEMPLATE_CALL(func_name, func_type) \
template <typename T> const torrent::Object func_name(command_base* rawCommand, target_type target, const torrent::Object& args); \
\
template <> struct command_base_is_type<func_name<target_type> > { static const int value = 1; typedef func_type<target_type>::type type; }; \
template <> struct command_base_is_type<func_name<core::Download*> > { static const int value = 1; typedef func_type<core::Download*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::Peer*> > { static const int value = 1; typedef func_type<torrent::Peer*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::Tracker*> > { static const int value = 1; typedef func_type<torrent::Tracker*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::File*> > { static const int value = 1; typedef func_type<torrent::File*>::type type; }; \
template <> struct command_base_is_type<func_name<torrent::FileListIterator*> > { static const int value = 1; typedef func_type<torrent::FileListIterator*>::type type; };
COMMAND_BASE_TEMPLATE_CALL(command_base_call, command_function);
COMMAND_BASE_TEMPLATE_CALL(command_base_call_value, command_value_function);
COMMAND_BASE_TEMPLATE_CALL(command_base_call_value_kb, command_value_function);
COMMAND_BASE_TEMPLATE_CALL(command_base_call_string, command_string_function);
COMMAND_BASE_TEMPLATE_CALL(command_base_call_list, command_list_function);
}
#endif