mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-17 23:52:30 +00:00
* 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:
@@ -37,7 +37,7 @@
|
||||
#ifndef RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
#define RTORRENT_UTILS_COMMAND_HELPERS_H
|
||||
|
||||
#include "rpc/command_new_slot.h"
|
||||
#include "rpc/command.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/object_storage.h"
|
||||
|
||||
|
||||
@@ -249,14 +249,14 @@ initialize_command_local() {
|
||||
CMD2_ANY_STRING_V("log.xmlrpc", std::tr1::bind(&ThreadWorker::set_xmlrpc_log, worker_thread, std::tr1::placeholders::_2));
|
||||
|
||||
// TODO: Convert to new command types:
|
||||
*rpc::Command::argument(0) = "placeholder.0";
|
||||
*rpc::Command::argument(1) = "placeholder.1";
|
||||
*rpc::Command::argument(2) = "placeholder.2";
|
||||
*rpc::Command::argument(3) = "placeholder.3";
|
||||
CMD2_ANY_P("argument.0", std::tr1::bind(&rpc::Command::argument_ref, 0));
|
||||
CMD2_ANY_P("argument.1", std::tr1::bind(&rpc::Command::argument_ref, 1));
|
||||
CMD2_ANY_P("argument.2", std::tr1::bind(&rpc::Command::argument_ref, 2));
|
||||
CMD2_ANY_P("argument.3", std::tr1::bind(&rpc::Command::argument_ref, 3));
|
||||
*rpc::command_base::argument(0) = "placeholder.0";
|
||||
*rpc::command_base::argument(1) = "placeholder.1";
|
||||
*rpc::command_base::argument(2) = "placeholder.2";
|
||||
*rpc::command_base::argument(3) = "placeholder.3";
|
||||
CMD2_ANY_P("argument.0", std::tr1::bind(&rpc::command_base::argument_ref, 0));
|
||||
CMD2_ANY_P("argument.1", std::tr1::bind(&rpc::command_base::argument_ref, 1));
|
||||
CMD2_ANY_P("argument.2", std::tr1::bind(&rpc::command_base::argument_ref, 2));
|
||||
CMD2_ANY_P("argument.3", std::tr1::bind(&rpc::command_base::argument_ref, 3));
|
||||
|
||||
CMD2_ANY_LIST ("group.insert", std::tr1::bind(&group_insert, std::tr1::placeholders::_2));
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ apply_encryption(const torrent::Object::list_type& args) {
|
||||
|
||||
torrent::Object
|
||||
apply_tos(const torrent::Object::string_type& arg) {
|
||||
rpc::Command::value_type value;
|
||||
rpc::command_base::value_type value;
|
||||
torrent::ConnectionManager* cm = torrent::connection_manager();
|
||||
|
||||
if (arg == "default")
|
||||
|
||||
+1
-2
@@ -2,6 +2,7 @@ noinst_LIBRARIES = libsub_rpc.a
|
||||
|
||||
libsub_rpc_a_SOURCES = \
|
||||
command.h \
|
||||
command.cc \
|
||||
command_impl.h \
|
||||
command_map.cc \
|
||||
command_map.h \
|
||||
@@ -9,8 +10,6 @@ libsub_rpc_a_SOURCES = \
|
||||
command_scheduler.h \
|
||||
command_scheduler_item.cc \
|
||||
command_scheduler_item.h \
|
||||
command_new_slot.cc \
|
||||
command_new_slot.h \
|
||||
exec_file.cc \
|
||||
exec_file.h \
|
||||
fixed_key.h \
|
||||
|
||||
@@ -39,20 +39,20 @@
|
||||
#include "core/download.h"
|
||||
#include "parse.h"
|
||||
|
||||
#include "command_new_slot.h"
|
||||
#include "command.h"
|
||||
|
||||
#define COMMAND_BASE_TEMPLATE_DEFINE(func_name) \
|
||||
template const torrent::Object func_name<target_type>(Command* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<core::Download*>(Command* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Peer*>(Command* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Tracker*>(Command* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::File*>(Command* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::FileListIterator*>(Command* rawCommand, target_type target, const torrent::Object& args);
|
||||
template const torrent::Object func_name<target_type>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<core::Download*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Peer*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::Tracker*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::File*>(command_base* rawCommand, target_type target, const torrent::Object& args); \
|
||||
template const torrent::Object func_name<torrent::FileListIterator*>(command_base* rawCommand, target_type target, const torrent::Object& args);
|
||||
|
||||
namespace rpc {
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call(Command* rawCommand, target_type target, const torrent::Object& args) {
|
||||
command_base_call(command_base* rawCommand, target_type target, const torrent::Object& args) {
|
||||
if (!is_target_compatible<T>(target))
|
||||
throw torrent::input_error("Target of wrong type.");
|
||||
|
||||
@@ -62,7 +62,7 @@ command_base_call(Command* rawCommand, target_type target, const torrent::Object
|
||||
COMMAND_BASE_TEMPLATE_DEFINE(command_base_call);
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call_value_base(Command* rawCommand, target_type target, const torrent::Object& rawArgs, int base, int unit) {
|
||||
command_base_call_value_base(command_base* rawCommand, target_type target, const torrent::Object& rawArgs, int base, int unit) {
|
||||
if (!is_target_compatible<T>(target))
|
||||
throw torrent::input_error("Target of wrong type.");
|
||||
|
||||
@@ -81,12 +81,12 @@ command_base_call_value_base(Command* rawCommand, target_type target, const torr
|
||||
}
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call_value(Command* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
command_base_call_value(command_base* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
return command_base_call_value_base<T>(rawCommand, target, rawArgs, 0, 1);
|
||||
}
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call_value_kb(Command* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
command_base_call_value_kb(command_base* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
return command_base_call_value_base<T>(rawCommand, target, rawArgs, 0, 1024);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ COMMAND_BASE_TEMPLATE_DEFINE(command_base_call_value);
|
||||
COMMAND_BASE_TEMPLATE_DEFINE(command_base_call_value_kb);
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call_string(Command* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
command_base_call_string(command_base* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
if (!is_target_compatible<T>(target))
|
||||
throw torrent::input_error("Target of wrong type.");
|
||||
|
||||
@@ -109,7 +109,7 @@ command_base_call_string(Command* rawCommand, target_type target, const torrent:
|
||||
COMMAND_BASE_TEMPLATE_DEFINE(command_base_call_string);
|
||||
|
||||
template <typename T> const torrent::Object
|
||||
command_base_call_list(Command* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
command_base_call_list(command_base* rawCommand, target_type target, const torrent::Object& rawArgs) {
|
||||
if (!is_target_compatible<T>(target))
|
||||
throw torrent::input_error("Target of wrong type.");
|
||||
|
||||
+94
-15
@@ -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
|
||||
|
||||
+25
-25
@@ -39,50 +39,50 @@
|
||||
|
||||
namespace rpc {
|
||||
|
||||
//template <> struct target_type_id<Command::generic_slot> { static const int value = Command::target_generic; };
|
||||
template <> struct target_type_id<Command::cleaned_slot> { static const int value = Command::target_generic; };
|
||||
template <> struct target_type_id<Command::any_slot> { static const int value = Command::target_any; };
|
||||
template <> struct target_type_id<Command::download_slot> { static const int value = Command::target_download; };
|
||||
template <> struct target_type_id<Command::peer_slot> { static const int value = Command::target_peer; };
|
||||
template <> struct target_type_id<Command::tracker_slot> { static const int value = Command::target_tracker; };
|
||||
template <> struct target_type_id<Command::file_slot> { static const int value = Command::target_file; };
|
||||
template <> struct target_type_id<Command::file_itr_slot> { static const int value = Command::target_file_itr; };
|
||||
//template <> struct target_type_id<command_base::generic_slot> { static const int value = command_base::target_generic; };
|
||||
template <> struct target_type_id<command_base::cleaned_slot> { static const int value = command_base::target_generic; };
|
||||
template <> struct target_type_id<command_base::any_slot> { static const int value = command_base::target_any; };
|
||||
template <> struct target_type_id<command_base::download_slot> { static const int value = command_base::target_download; };
|
||||
template <> struct target_type_id<command_base::peer_slot> { static const int value = command_base::target_peer; };
|
||||
template <> struct target_type_id<command_base::tracker_slot> { static const int value = command_base::target_tracker; };
|
||||
template <> struct target_type_id<command_base::file_slot> { static const int value = command_base::target_file; };
|
||||
template <> struct target_type_id<command_base::file_itr_slot> { static const int value = command_base::target_file_itr; };
|
||||
|
||||
template <> struct target_type_id<Command::download_pair_slot> { static const int value = Command::target_download_pair; };
|
||||
template <> struct target_type_id<command_base::download_pair_slot> { static const int value = command_base::target_download_pair; };
|
||||
|
||||
template <> struct target_type_id<> { static const int value = Command::target_generic; };
|
||||
template <> struct target_type_id<target_type> { static const int value = Command::target_any; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<core::Download*> { static const int value = Command::target_download; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::Peer*> { static const int value = Command::target_peer; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::Tracker*> { static const int value = Command::target_tracker; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::File*> { static const int value = Command::target_file; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::FileListIterator*> { static const int value = Command::target_file_itr; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<> { static const int value = command_base::target_generic; };
|
||||
template <> struct target_type_id<target_type> { static const int value = command_base::target_any; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<core::Download*> { static const int value = command_base::target_download; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::Peer*> { static const int value = command_base::target_peer; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::Tracker*> { static const int value = command_base::target_tracker; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::File*> { static const int value = command_base::target_file; static const int proper_type = 1; };
|
||||
template <> struct target_type_id<torrent::FileListIterator*> { static const int value = command_base::target_file_itr; static const int proper_type = 1; };
|
||||
|
||||
template <> struct target_type_id<core::Download*, core::Download*> { static const int value = Command::target_download_pair; };
|
||||
template <> struct target_type_id<core::Download*, core::Download*> { static const int value = command_base::target_download_pair; };
|
||||
|
||||
template <> inline bool
|
||||
is_target_compatible<target_type>(const target_type& target) { return true; }
|
||||
template <> inline bool
|
||||
is_target_compatible<torrent::File*>(const target_type& target) { return target.first == Command::target_file || Command::target_file_itr; }
|
||||
is_target_compatible<torrent::File*>(const target_type& target) { return target.first == command_base::target_file || command_base::target_file_itr; }
|
||||
|
||||
template <> inline target_type
|
||||
get_target_cast<target_type>(target_type target, int type) { return target; }
|
||||
|
||||
template <> inline torrent::File*
|
||||
get_target_cast<torrent::File*>(target_type target, int type) {
|
||||
if (target.first == Command::target_file_itr)
|
||||
if (target.first == command_base::target_file_itr)
|
||||
return static_cast<torrent::FileListIterator*>(target.second)->file();
|
||||
else
|
||||
return static_cast<torrent::File*>(target.second);
|
||||
}
|
||||
|
||||
inline torrent::Object*
|
||||
Command::push_stack(const torrent::Object* first_arg, const torrent::Object* last_arg, stack_type* stack) {
|
||||
command_base::push_stack(const torrent::Object* first_arg, const torrent::Object* last_arg, stack_type* stack) {
|
||||
unsigned int idx = 0;
|
||||
|
||||
while (first_arg != last_arg && idx < Command::max_arguments) {
|
||||
while (first_arg != last_arg && idx < command_base::max_arguments) {
|
||||
new (&(*stack)[idx]) torrent::Object(*first_arg++);
|
||||
(*stack)[idx].swap(*Command::argument(idx));
|
||||
(*stack)[idx].swap(*command_base::argument(idx));
|
||||
|
||||
idx++;
|
||||
}
|
||||
@@ -91,14 +91,14 @@ Command::push_stack(const torrent::Object* first_arg, const torrent::Object* las
|
||||
}
|
||||
|
||||
inline torrent::Object*
|
||||
Command::push_stack(const torrent::Object::list_type& args, stack_type* stack) {
|
||||
command_base::push_stack(const torrent::Object::list_type& args, stack_type* stack) {
|
||||
return push_stack(args.data(), args.data() + args.size(), stack);
|
||||
}
|
||||
|
||||
inline void
|
||||
Command::pop_stack(stack_type* stack, torrent::Object* last_stack) {
|
||||
command_base::pop_stack(stack_type* stack, torrent::Object* last_stack) {
|
||||
while (last_stack-- != stack->begin()) {
|
||||
last_stack->swap(*Command::argument(std::distance(stack->begin(), last_stack)));
|
||||
last_stack->swap(*command_base::argument(std::distance(stack->begin(), last_stack)));
|
||||
last_stack->~Object();
|
||||
|
||||
// To ensure we catch errors:
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
namespace rpc {
|
||||
|
||||
Command::stack_type Command::current_stack;
|
||||
command_base::stack_type command_base::current_stack;
|
||||
|
||||
CommandMap::~CommandMap() {
|
||||
std::vector<const char*> keys;
|
||||
@@ -73,7 +73,7 @@ CommandMap::~CommandMap() {
|
||||
}
|
||||
|
||||
CommandMap::iterator
|
||||
CommandMap::insert(key_type key, Command* variable, int flags, const char* parm, const char* doc) {
|
||||
CommandMap::insert(key_type key, command_base* variable, int flags, const char* parm, const char* doc) {
|
||||
iterator itr = base_type::find(key);
|
||||
|
||||
if (itr != base_type::end())
|
||||
|
||||
+12
-12
@@ -57,11 +57,11 @@ struct command_map_data_type {
|
||||
//
|
||||
// The any_slot should perhaps replace generic_slot?
|
||||
|
||||
command_map_data_type(Command* variable, int flags, const char* parm, const char* doc) :
|
||||
command_map_data_type(command_base* variable, int flags, const char* parm, const char* doc) :
|
||||
m_variable(variable), m_flags(flags), m_parm(parm), m_doc(doc) {}
|
||||
|
||||
Command* m_variable;
|
||||
Command::any_slot m_anySlot;
|
||||
command_base* m_variable;
|
||||
command_base::any_slot m_anySlot;
|
||||
|
||||
int m_flags;
|
||||
|
||||
@@ -104,10 +104,10 @@ public:
|
||||
|
||||
bool is_modifiable(const_iterator itr) { return itr != end() && (itr->second.m_flags & flag_modifiable); }
|
||||
|
||||
iterator insert(key_type key, Command* variable, int flags, const char* parm, const char* doc);
|
||||
iterator insert(key_type key, command_base* variable, int flags, const char* parm, const char* doc);
|
||||
|
||||
// Make this a wrapper call to insert without extra fluff.
|
||||
void insert_type(key_type key, Command* variable, Command::any_slot targetSlot, int flags, const char* parm, const char* doc) {
|
||||
void insert_type(key_type key, command_base* variable, command_base::any_slot targetSlot, int flags, const char* parm, const char* doc) {
|
||||
iterator itr = insert(key, variable, flags, parm, doc);
|
||||
itr->second.m_anySlot = targetSlot;
|
||||
}
|
||||
@@ -121,20 +121,20 @@ public:
|
||||
const mapped_type call(key_type key, target_type target, const mapped_type& args = mapped_type()) { return call_command(key, args, target); }
|
||||
const mapped_type call_catch(key_type key, target_type target, const mapped_type& args = mapped_type(), const char* err = "Command failed: ");
|
||||
|
||||
const mapped_type call_command (key_type key, const mapped_type& arg, target_type target = target_type((int)Command::target_generic, NULL));
|
||||
const mapped_type call_command (const_iterator itr, const mapped_type& arg, target_type target = target_type((int)Command::target_generic, NULL));
|
||||
const mapped_type call_command (key_type key, const mapped_type& arg, target_type target = target_type((int)command_base::target_generic, NULL));
|
||||
const mapped_type call_command (const_iterator itr, const mapped_type& arg, target_type target = target_type((int)command_base::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)Command::target_download, download)); }
|
||||
const mapped_type call_command_p(key_type key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)Command::target_peer, peer)); }
|
||||
const mapped_type call_command_t(key_type key, torrent::Tracker* tracker, const mapped_type& arg) { return call_command(key, arg, target_type((int)Command::target_tracker, tracker)); }
|
||||
const mapped_type call_command_f(key_type key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)Command::target_file, file)); }
|
||||
const mapped_type call_command_d(key_type key, core::Download* download, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_download, download)); }
|
||||
const mapped_type call_command_p(key_type key, torrent::Peer* peer, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_peer, peer)); }
|
||||
const mapped_type call_command_t(key_type key, torrent::Tracker* tracker, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_tracker, tracker)); }
|
||||
const mapped_type call_command_f(key_type key, torrent::File* file, const mapped_type& arg) { return call_command(key, arg, target_type((int)command_base::target_file, file)); }
|
||||
|
||||
private:
|
||||
CommandMap(const CommandMap&);
|
||||
void operator = (const CommandMap&);
|
||||
};
|
||||
|
||||
inline target_type make_target() { return target_type((int)Command::target_generic, NULL); }
|
||||
inline target_type make_target() { return target_type((int)command_base::target_generic, NULL); }
|
||||
inline target_type make_target(int type, void* target) { return target_type(type, target); }
|
||||
inline target_type make_target(int type, void* target1, void* target2) { return target_type(type, target1, target2); }
|
||||
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// The command_new_slot object aims at replacing the current crop of
|
||||
// Command* objects with a new type that is safe to cast from the base
|
||||
// command type and thus allows for static initialization and fixed
|
||||
// sized objects.
|
||||
//
|
||||
// All commands changed to this new class shall be safe to call with
|
||||
// the raw object types.
|
||||
|
||||
#ifndef RTORRENT_RPC_COMMAND_NEW_SLOT_H
|
||||
#define RTORRENT_RPC_COMMAND_NEW_SLOT_H
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <inttypes.h>
|
||||
#include <torrent/object.h>
|
||||
#include <tr1/functional>
|
||||
|
||||
#include "command.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
typedef const torrent::Object (*command_base_call_type)(Command*, 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 Command {
|
||||
public:
|
||||
command_base() { new (&_pod<base_function>()) base_function(); }
|
||||
~command_base() { _pod<base_function>().~base_function(); }
|
||||
|
||||
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* cmd, target_type target, Args args) {
|
||||
return static_cast<command_base*>(cmd)->_pod<Func>()(get_target_cast<T>(target), args);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
union {
|
||||
char t_pod[sizeof(base_function)];
|
||||
};
|
||||
};
|
||||
|
||||
#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* 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
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
#ifndef RTORRENT_RPC_FIXED_KEY_H
|
||||
#define RTORRENT_RPC_FIXED_KEY_H
|
||||
|
||||
#include <torrent/object_raw_bencode.h>
|
||||
|
||||
namespace rpc {
|
||||
|
||||
// The key size should be such that the value type size which includes
|
||||
// the next-pointer.
|
||||
|
||||
template <size_t MaxSize>
|
||||
class fixed_key_type {
|
||||
public:
|
||||
typedef char value_type;
|
||||
typedef const char* iterator;
|
||||
typedef const char* const_iterator;
|
||||
typedef uint32_t size_type;
|
||||
|
||||
static const size_type max_size = MaxSize - 1;
|
||||
|
||||
fixed_key_type() : m_size(0) { m_data[0] = '\0'; }
|
||||
fixed_key_type(const fixed_key_type& k) : m_size(k.m_size) { std::memcpy(m_data, k.m_data, k.m_size + 1); }
|
||||
|
||||
fixed_key_type(const value_type* src_data, size_type src_size) { set_data(src_data, src_size); }
|
||||
|
||||
static fixed_key_type from_c_str(const char* str) { fixed_key_type k; k.set_c_str(str); return k; }
|
||||
static fixed_key_type from_string(const std::string& str) { fixed_key_type k; k.set_c_str(str.c_str(), str.size()); return k; }
|
||||
static fixed_key_type from_raw_string(const torrent::raw_string& str) { fixed_key_type k; k.set_data(str.data(), str.size()); return k; }
|
||||
|
||||
bool empty() const { return m_size == 0;; }
|
||||
size_type size() const { return m_size; }
|
||||
|
||||
iterator begin() const { return m_data; }
|
||||
iterator end() const { return m_data + m_size; }
|
||||
|
||||
value_type* data() { return m_data; }
|
||||
const value_type* data() const { return m_data; }
|
||||
const char* c_str() const { return m_data; }
|
||||
|
||||
void set_data(const value_type* src_data, size_type src_size);
|
||||
void set_c_str(const value_type* src_data);
|
||||
void set_c_str(const value_type* src_data, size_type src_size);
|
||||
|
||||
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 std::string& rhs) const { return m_size == rhs.size() && std::memcmp(m_data, rhs.data(), m_size) == 0; }
|
||||
|
||||
private:
|
||||
size_type m_size;
|
||||
char m_data[max_size];
|
||||
};
|
||||
|
||||
struct hash_fixed_key_type {
|
||||
template <size_t MaxSize>
|
||||
inline std::size_t operator () (const fixed_key_type<MaxSize>& p) const { return hash(p.data()); }
|
||||
|
||||
static inline std::size_t hash(const char* data) {
|
||||
std::size_t result = 0;
|
||||
|
||||
while (*data != '\0')
|
||||
result = (result * 131) + *data++;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline std::size_t hash(const char* data, uint32_t size) {
|
||||
std::size_t result = 0;
|
||||
|
||||
while (size--)
|
||||
result = (result * 131) + *data++;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+12
-12
@@ -230,39 +230,39 @@ parse_command_name(const char* first, const char* last, std::string* dest) {
|
||||
// Temp until it can be moved somewhere better...
|
||||
const torrent::Object
|
||||
command_function_call(const torrent::raw_string& cmd, target_type target, const torrent::Object& args) {
|
||||
rpc::Command::stack_type stack;
|
||||
rpc::command_base::stack_type stack;
|
||||
torrent::Object* last_stack;
|
||||
|
||||
if (args.is_list())
|
||||
last_stack = rpc::Command::push_stack(args.as_list(), &stack);
|
||||
last_stack = rpc::command_base::push_stack(args.as_list(), &stack);
|
||||
else if (args.type() != torrent::Object::TYPE_NONE)
|
||||
last_stack = rpc::Command::push_stack(&args, &args + 1, &stack);
|
||||
last_stack = rpc::command_base::push_stack(&args, &args + 1, &stack);
|
||||
else
|
||||
last_stack = rpc::Command::push_stack(NULL, NULL, &stack);
|
||||
last_stack = rpc::command_base::push_stack(NULL, NULL, &stack);
|
||||
|
||||
try {
|
||||
torrent::Object result = parse_command_multiple(target, cmd.begin(), cmd.end());
|
||||
|
||||
rpc::Command::pop_stack(&stack, last_stack);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
return result;
|
||||
|
||||
} catch (torrent::bencode_error& e) {
|
||||
rpc::Command::pop_stack(&stack, last_stack);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
const torrent::Object
|
||||
command_function_multi_call(const torrent::Object::map_type& cmd, target_type target, const torrent::Object& args) {
|
||||
rpc::Command::stack_type stack;
|
||||
rpc::command_base::stack_type stack;
|
||||
torrent::Object* last_stack;
|
||||
|
||||
if (args.is_list())
|
||||
last_stack = rpc::Command::push_stack(args.as_list(), &stack);
|
||||
last_stack = rpc::command_base::push_stack(args.as_list(), &stack);
|
||||
else if (args.type() != torrent::Object::TYPE_NONE)
|
||||
last_stack = rpc::Command::push_stack(&args, &args + 1, &stack);
|
||||
last_stack = rpc::command_base::push_stack(&args, &args + 1, &stack);
|
||||
else
|
||||
last_stack = rpc::Command::push_stack(NULL, NULL, &stack);
|
||||
last_stack = rpc::command_base::push_stack(NULL, NULL, &stack);
|
||||
|
||||
try {
|
||||
for (torrent::Object::map_const_iterator itr = cmd.begin(), last = cmd.end(); itr != last; itr++) {
|
||||
@@ -271,11 +271,11 @@ command_function_multi_call(const torrent::Object::map_type& cmd, target_type ta
|
||||
}
|
||||
|
||||
} catch (torrent::bencode_error& e) {
|
||||
rpc::Command::pop_stack(&stack, last_stack);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
throw e;
|
||||
}
|
||||
|
||||
rpc::Command::pop_stack(&stack, last_stack);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "rpc/command_map.h"
|
||||
#include "rpc/command_new_slot.h"
|
||||
|
||||
class CommandMapTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(CommandMapTest);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "rpc/command_new_slot.h"
|
||||
#include "rpc/command.h"
|
||||
|
||||
class CommandSlotTest : public CppUnit::TestFixture {
|
||||
CPPUNIT_TEST_SUITE(CommandSlotTest);
|
||||
|
||||
+22
-22
@@ -6,33 +6,33 @@ CPPUNIT_TEST_SUITE_REGISTRATION(CommandTest);
|
||||
|
||||
bool
|
||||
command_stack_all_empty() {
|
||||
return std::find_if(rpc::Command::stack_begin(), rpc::Command::stack_end(),
|
||||
std::mem_fun_ref(&torrent::Object::is_not_empty)) == rpc::Command::stack_end();
|
||||
return std::find_if(rpc::command_base::stack_begin(), rpc::command_base::stack_end(),
|
||||
std::mem_fun_ref(&torrent::Object::is_not_empty)) == rpc::command_base::stack_end();
|
||||
}
|
||||
|
||||
void
|
||||
CommandTest::test_stack() {
|
||||
torrent::Object::list_type args;
|
||||
rpc::Command::stack_type stack;
|
||||
rpc::command_base::stack_type stack;
|
||||
torrent::Object* last_stack;
|
||||
|
||||
// Test empty stack.
|
||||
CPPUNIT_ASSERT(command_stack_all_empty());
|
||||
|
||||
last_stack = rpc::Command::push_stack(args, &stack);
|
||||
last_stack = rpc::command_base::push_stack(args, &stack);
|
||||
CPPUNIT_ASSERT(command_stack_all_empty());
|
||||
|
||||
rpc::Command::pop_stack(&stack, last_stack);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
CPPUNIT_ASSERT(command_stack_all_empty());
|
||||
|
||||
// Test stack with one.
|
||||
args.push_back(int64_t(1));
|
||||
|
||||
last_stack = rpc::Command::push_stack(args, &stack);
|
||||
last_stack = rpc::command_base::push_stack(args, &stack);
|
||||
CPPUNIT_ASSERT(!command_stack_all_empty());
|
||||
CPPUNIT_ASSERT(rpc::Command::stack_begin()->as_value() == 1);
|
||||
CPPUNIT_ASSERT(rpc::command_base::stack_begin()->as_value() == 1);
|
||||
|
||||
rpc::Command::pop_stack(&stack, last_stack);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
CPPUNIT_ASSERT(command_stack_all_empty());
|
||||
|
||||
// Test stack with two
|
||||
@@ -40,44 +40,44 @@ CommandTest::test_stack() {
|
||||
args.push_back(int64_t(2));
|
||||
args.push_back(int64_t(3));
|
||||
|
||||
last_stack = rpc::Command::push_stack(args, &stack);
|
||||
last_stack = rpc::command_base::push_stack(args, &stack);
|
||||
CPPUNIT_ASSERT(!command_stack_all_empty());
|
||||
CPPUNIT_ASSERT(rpc::Command::current_stack[0].as_value() == 2);
|
||||
CPPUNIT_ASSERT(rpc::Command::current_stack[1].as_value() == 3);
|
||||
CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 2);
|
||||
CPPUNIT_ASSERT(rpc::command_base::current_stack[1].as_value() == 3);
|
||||
|
||||
rpc::Command::pop_stack(&stack, last_stack);
|
||||
rpc::command_base::pop_stack(&stack, last_stack);
|
||||
CPPUNIT_ASSERT(command_stack_all_empty());
|
||||
}
|
||||
|
||||
void
|
||||
CommandTest::test_stack_double() {
|
||||
torrent::Object::list_type args;
|
||||
rpc::Command::stack_type stack_first;
|
||||
rpc::Command::stack_type stack_second;
|
||||
rpc::command_base::stack_type stack_first;
|
||||
rpc::command_base::stack_type stack_second;
|
||||
torrent::Object* last_stack_first;
|
||||
torrent::Object* last_stack_second;
|
||||
|
||||
// Test double-stacked.
|
||||
args.push_back(int64_t(1));
|
||||
|
||||
last_stack_first = rpc::Command::push_stack(args, &stack_first);
|
||||
last_stack_first = rpc::command_base::push_stack(args, &stack_first);
|
||||
CPPUNIT_ASSERT(!command_stack_all_empty());
|
||||
CPPUNIT_ASSERT(rpc::Command::current_stack[0].as_value() == 1);
|
||||
CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 1);
|
||||
|
||||
args.clear();
|
||||
args.push_back(int64_t(2));
|
||||
args.push_back(int64_t(3));
|
||||
|
||||
last_stack_second = rpc::Command::push_stack(args, &stack_second);
|
||||
last_stack_second = rpc::command_base::push_stack(args, &stack_second);
|
||||
CPPUNIT_ASSERT(!command_stack_all_empty());
|
||||
|
||||
CPPUNIT_ASSERT(rpc::Command::current_stack[0].as_value() == 2);
|
||||
CPPUNIT_ASSERT(rpc::Command::current_stack[1].as_value() == 3);
|
||||
CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 2);
|
||||
CPPUNIT_ASSERT(rpc::command_base::current_stack[1].as_value() == 3);
|
||||
|
||||
rpc::Command::pop_stack(&stack_second, last_stack_second);
|
||||
rpc::command_base::pop_stack(&stack_second, last_stack_second);
|
||||
CPPUNIT_ASSERT(!command_stack_all_empty());
|
||||
CPPUNIT_ASSERT(rpc::Command::current_stack[0].as_value() == 1);
|
||||
CPPUNIT_ASSERT(rpc::command_base::current_stack[0].as_value() == 1);
|
||||
|
||||
rpc::Command::pop_stack(&stack_first, last_stack_first);
|
||||
rpc::command_base::pop_stack(&stack_first, last_stack_first);
|
||||
CPPUNIT_ASSERT(command_stack_all_empty());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user