<commit_before>/*
 * class.hpp - Copyright (C) 2007 by Nathan Reed
 * Implementation of the class__ class from luabridge.hpp.
 */

/*
 * Container for registered class names, with awareness of const types
 */

template <typename T>
struct classname
{
	static const char *name_;
	static const char *name ()
	{
		return classname<T>::name_;
	}
	static bool is_const ()
	{
		return false;
	}
	static void set_name (const char *name)
	{
		classname<T>::name_ = name;
	}
};

// Initial type names are unknown
template <typename T>
const char *classname<T>::name_ = classname_unknown;

// Specialization for const types, mapping to same names
template <typename T>
struct classname <const T>
{
	static const char *name ()
	{
		return classname<T>::name_;
	}
	static bool is_const ()
	{
		return true;
	}
	static void set_name (const char *name)
	{
		classname<T>::name_ = name;
	}
};

/*
 * Lua-registerable C function template for destructors.  Objects are stored
 * in Lua as userdata containing a shared_ptr, and this is registered as the
 * __gc metamethod.  The expected classname is passed as an upvalue so that
 * we can ensure that we are destructing the right kind of object.
 */

template <typename T>
int destructor_dispatch (lua_State *L)
{
	void *obj = checkclass(L, 1, lua_tostring(L, lua_upvalueindex(1)), true);
	shared_ptr<T> &ptr = *((shared_ptr<T> *)obj);
	ptr.~shared_ptr();
	return 0;
}

/*
 * Functions for metatable construction.  These functions create a metatable and
 * leave it in the top element of the Lua stack (in addition to registering it
 * wherever it needs to be registered).
 */

template <typename T>
void create_metatable (lua_State *L, const char *name)
{
	luaL_newmetatable(L, name);
	// Set it as its own metatable
	lua_pushvalue(L, -1);
	lua_setmetatable(L, -2);
	// Set subclass_indexer as the __index metamethod
	lua_pushcfunction(L, &subclass_indexer);
	lua_setfield(L, -2, "__index");
	// Set the __gc metamethod to call the class destructor
	lua_pushstring(L, name);
	lua_pushcclosure(L, &destructor_dispatch<T>, 1);
	lua_setfield(L, -2, "__gc");
	// Set the __type metafield to the name of the class
	lua_pushstring(L, name);
	lua_setfield(L, -2, "__type");
}

template <typename T>
void create_const_metatable (lua_State *L, const char *name)
{
	std::string constname = std::string("const ") + name;
	luaL_newmetatable(L, constname.c_str());
	lua_pushvalue(L, -1);
	lua_setmetatable(L, -2);
	lua_pushcfunction(L, &subclass_indexer);
	lua_setfield(L, -2, "__index");
	lua_pushstring(L, constname.c_str());
	lua_pushcclosure(L, &destructor_dispatch<T>, 1);
	lua_setfield(L, -2, "__gc");
	lua_pushstring(L, constname.c_str());
	lua_setfield(L, -2, "__type");
}

template <typename T>
void create_static_table (lua_State *L, const char *name)
{
	lua_newtable(L);
	// Set it as its own metatable
	lua_pushvalue(L, -1);
	lua_setmetatable(L, -2);
	// Set subclass_indexer as the __index metamethod
	lua_pushcfunction(L, &subclass_indexer);
	lua_setfield(L, -2, "__index");
	// Install it in the global environment
	lua_pushvalue(L, -1);
	lua_setglobal(L, name);
}

/*
 * class__ constructors
 */

template <typename T>
class__<T>::class__ (lua_State *L_): L(L_)
{
	assert(classname<T>::name() != classname_unknown);
}

template <typename T>
class__<T>::class__ (lua_State *L_, const char *name): L(L_)
{
	assert(!classname<T>::is_const());
	classname<T>::set_name(name);

	// Create metatable for this class.  The metatable is stored in the Lua
	// registry, keyed by the given class name.
	create_metatable<T>(L, name);

	// Create const metatable for this class.  This is identical to the
	// previous metatable, except that it has "const " prepended to the __type
	// field.  Const methods will be added to the const metatable, non-const
	// methods to the normal metatable.
	create_const_metatable<T>(L, name);

	// Set __const metafield to point to the const metatable
	lua_setfield(L, -2, "__const");
	// Pop the original metatable
	lua_pop(L, 1);

	// Create static table for this class.  This is stored in the global
	// environment, keyed by the given class name.  Its __call metamethod
	// will be the constructor, and it will also contain static members.
	create_static_table<T>(L, name);
	lua_pop(L, 1);
}

template <typename T>
class__<T>::class__ (lua_State *L_, const char *name,
	const char *basename): L(L_)
{
	assert(!classname<T>::is_const());
	classname<T>::set_name(name);

	// Create metatable for this class
	create_metatable<T>(L, name);
	// Set the __parent metafield to the base class's metatable
	luaL_getmetatable(L, basename);
	lua_setfield(L, -2, "__parent");

	// Create const metatable for this class.  Its __parent field will points
	// to the const metatable of the parent class.
	create_const_metatable<T>(L, name);
	std::string base_constname = std::string("const ") + basename;
	luaL_getmetatable(L, base_constname.c_str());
	lua_setfield(L, -2, "__parent");

	// Set __const metafield to point to the const metatable
	lua_setfield(L, -2, "__const");
	// Pop the original metatable
	lua_pop(L, 1);

	// Create static table for this class
	create_static_table<T>(L, name);
	// Set the __parent metafield to the base class's static table
	lua_getglobal(L, basename);
	lua_setfield(L, -2, "__parent");
	lua_pop(L, 1);
}

/*
 * Lua-registerable C function template for constructor proxies.  These are
 * registered to Lua as global functions with the name of the class, with the
 * appropriate metatable passed as an upvalue.  They allocate a new userdata,
 * initialize it with a shared_ptr to an appropriately constructed new class
 * object, and set the metatable so that Lua can use the object.
 */

template <typename T, typename Params>
int constructor_proxy (lua_State *L)
{
	// Allocate a new userdata and construct a shared_ptr<T> in-place there
	void *block = lua_newuserdata(L, sizeof(shared_ptr<T>));
	arglist<Params, 2> args(L);
	new(block) shared_ptr<T>(constructor<T, Params>::apply(args));

	// Set the userdata's metatable
	lua_pushvalue(L, lua_upvalueindex(1));
	lua_setmetatable(L, -2);

	return 1;
}

/*
 * Perform constructor registration in a class.
 */

template <typename T>
template <typename FnPtr>
class__<T>& class__<T>::constructor ()
{
	// Get a reference to the class's static table
	lua_getglobal(L, classname<T>::name());
	// Push the constructor proxy, with the class's metatable as an upvalue
	luaL_getmetatable(L, classname<T>::name());
	lua_pushcclosure(L,
		&constructor_proxy<T, typename fnptr<FnPtr>::params>, 1);
	// Set the constructor proxy as the __call metamethod of the static table
	lua_setfield(L, -2, "__call");
	lua_pop(L, 1);
	return *this;
}

/*
 * Lua-registerable C function templates for method proxies.  These are
 * registered with the expected classname as upvalue 1 and the member function
 * pointer as upvalue 2.  When called from Lua, they will receive the object
 * on which they are called as argument 1 and all the method arguments as
 * args 2 and up.
 */

template <typename FnPtr, typename Ret = typename fnptr<FnPtr>::resulttype>
struct method_proxy
{
	typedef typename fnptr<FnPtr>::classtype classtype;
	typedef typename fnptr<FnPtr>::params params;
	static int f (lua_State *L)
	{
		classtype *obj = ((shared_ptr<classtype> *)checkclass(L, 1,
			lua_tostring(L, lua_upvalueindex(1))))->get();
		FnPtr fp = *(FnPtr *)lua_touserdata(L, lua_upvalueindex(2));
		arglist<params, 2> args(L);
		tdstack<Ret>::push(L, fnptr<FnPtr>::apply(obj, fp, args));
		return 1;
	}
};

template <typename FnPtr>
struct method_proxy <FnPtr, void>
{
	typedef typename fnptr<FnPtr>::classtype classtype;
	typedef typename fnptr<FnPtr>::params params;
	static int f (lua_State *L)
	{
		classtype *obj = ((shared_ptr<classtype> *)checkclass(L, 1,
			lua_tostring(L, lua_upvalueindex(1))))->get();
		FnPtr fp = *(FnPtr *)lua_touserdata(L, lua_upvalueindex(2));
		arglist<params, 2> args(L);
		fnptr<FnPtr>::apply(obj, fp, args);
		return 1;
	}
};

/*
 * Perform method registration in a class.  The method proxies are all
 * registered as values in the class's metatable, which is searched by the
 * subclass_indexer function we've installed as __index metamethod.
 */

template <typename T>
template <typename FnPtr>
class__<T>& class__<T>::method (const char *name, FnPtr fp)
{
	assert(fnptr<FnPtr>::mfp);
	std::string metatable_name = classname<T>::name();
	if (fnptr<FnPtr>::const_mfp)
		metatable_name = "const " + metatable_name;
	luaL_getmetatable(L, metatable_name.c_str());
	lua_pushstring(L, metatable_name.c_str());
	void *v = lua_newuserdata(L, sizeof(FnPtr));
	memcpy(v, &fp, sizeof(FnPtr));
	lua_pushcclosure(L, &method_proxy<FnPtr>::f, 2);
	lua_setfield(L, -2, name);
	lua_pop(L, 1);
	return *this;
}

/*
 * Static method registration.  Method proxies are registered as values
 * in the class's static table.  We use the global function proxies defined
 * in module.hpp, since static methods are really just hidden globals.
 */

template <typename T>
template <typename FnPtr>
class__<T>& class__<T>::static_method (const char *name, FnPtr fp)
{
	assert(!fnptr<FnPtr>::mfp);
	lua_getglobal(L, classname<T>::name());
	lua_pushlightuserdata(L, (void *)fp);
	lua_pushcclosure(L, &function_proxy<FnPtr>::f, 1);
	lua_setfield(L, -2, name);
	lua_pop(L, 1);
	return *this;
}
<commit_msg>Minor change to destructor_dispatch that makes g++ 4 happier.<commit_after>/*
 * class.hpp - Copyright (C) 2007 by Nathan Reed
 * Implementation of the class__ class from luabridge.hpp.
 */

/*
 * Container for registered class names, with awareness of const types
 */

template <typename T>
struct classname
{
	static const char *name_;
	static const char *name ()
	{
		return classname<T>::name_;
	}
	static bool is_const ()
	{
		return false;
	}
	static void set_name (const char *name)
	{
		classname<T>::name_ = name;
	}
};

// Initial type names are unknown
template <typename T>
const char *classname<T>::name_ = classname_unknown;

// Specialization for const types, mapping to same names
template <typename T>
struct classname <const T>
{
	static const char *name ()
	{
		return classname<T>::name_;
	}
	static bool is_const ()
	{
		return true;
	}
	static void set_name (const char *name)
	{
		classname<T>::name_ = name;
	}
};

/*
 * Lua-registerable C function template for destructors.  Objects are stored
 * in Lua as userdata containing a shared_ptr, and this is registered as the
 * __gc metamethod.  The expected classname is passed as an upvalue so that
 * we can ensure that we are destructing the right kind of object.
 */

template <typename T>
int destructor_dispatch (lua_State *L)
{
	void *obj = checkclass(L, 1, lua_tostring(L, lua_upvalueindex(1)), true);
	shared_ptr<T> &ptr = *((shared_ptr<T> *)obj);
	ptr.~shared_ptr<T>();
	return 0;
}

/*
 * Functions for metatable construction.  These functions create a metatable and
 * leave it in the top element of the Lua stack (in addition to registering it
 * wherever it needs to be registered).
 */

template <typename T>
void create_metatable (lua_State *L, const char *name)
{
	luaL_newmetatable(L, name);
	// Set it as its own metatable
	lua_pushvalue(L, -1);
	lua_setmetatable(L, -2);
	// Set subclass_indexer as the __index metamethod
	lua_pushcfunction(L, &subclass_indexer);
	lua_setfield(L, -2, "__index");
	// Set the __gc metamethod to call the class destructor
	lua_pushstring(L, name);
	lua_pushcclosure(L, &destructor_dispatch<T>, 1);
	lua_setfield(L, -2, "__gc");
	// Set the __type metafield to the name of the class
	lua_pushstring(L, name);
	lua_setfield(L, -2, "__type");
}

template <typename T>
void create_const_metatable (lua_State *L, const char *name)
{
	std::string constname = std::string("const ") + name;
	luaL_newmetatable(L, constname.c_str());
	lua_pushvalue(L, -1);
	lua_setmetatable(L, -2);
	lua_pushcfunction(L, &subclass_indexer);
	lua_setfield(L, -2, "__index");
	lua_pushstring(L, constname.c_str());
	lua_pushcclosure(L, &destructor_dispatch<T>, 1);
	lua_setfield(L, -2, "__gc");
	lua_pushstring(L, constname.c_str());
	lua_setfield(L, -2, "__type");
}

template <typename T>
void create_static_table (lua_State *L, const char *name)
{
	lua_newtable(L);
	// Set it as its own metatable
	lua_pushvalue(L, -1);
	lua_setmetatable(L, -2);
	// Set subclass_indexer as the __index metamethod
	lua_pushcfunction(L, &subclass_indexer);
	lua_setfield(L, -2, "__index");
	// Install it in the global environment
	lua_pushvalue(L, -1);
	lua_setglobal(L, name);
}

/*
 * class__ constructors
 */

template <typename T>
class__<T>::class__ (lua_State *L_): L(L_)
{
	assert(classname<T>::name() != classname_unknown);
}

template <typename T>
class__<T>::class__ (lua_State *L_, const char *name): L(L_)
{
	assert(!classname<T>::is_const());
	classname<T>::set_name(name);

	// Create metatable for this class.  The metatable is stored in the Lua
	// registry, keyed by the given class name.
	create_metatable<T>(L, name);

	// Create const metatable for this class.  This is identical to the
	// previous metatable, except that it has "const " prepended to the __type
	// field.  Const methods will be added to the const metatable, non-const
	// methods to the normal metatable.
	create_const_metatable<T>(L, name);

	// Set __const metafield to point to the const metatable
	lua_setfield(L, -2, "__const");
	// Pop the original metatable
	lua_pop(L, 1);

	// Create static table for this class.  This is stored in the global
	// environment, keyed by the given class name.  Its __call metamethod
	// will be the constructor, and it will also contain static members.
	create_static_table<T>(L, name);
	lua_pop(L, 1);
}

template <typename T>
class__<T>::class__ (lua_State *L_, const char *name,
	const char *basename): L(L_)
{
	assert(!classname<T>::is_const());
	classname<T>::set_name(name);

	// Create metatable for this class
	create_metatable<T>(L, name);
	// Set the __parent metafield to the base class's metatable
	luaL_getmetatable(L, basename);
	lua_setfield(L, -2, "__parent");

	// Create const metatable for this class.  Its __parent field will points
	// to the const metatable of the parent class.
	create_const_metatable<T>(L, name);
	std::string base_constname = std::string("const ") + basename;
	luaL_getmetatable(L, base_constname.c_str());
	lua_setfield(L, -2, "__parent");

	// Set __const metafield to point to the const metatable
	lua_setfield(L, -2, "__const");
	// Pop the original metatable
	lua_pop(L, 1);

	// Create static table for this class
	create_static_table<T>(L, name);
	// Set the __parent metafield to the base class's static table
	lua_getglobal(L, basename);
	lua_setfield(L, -2, "__parent");
	lua_pop(L, 1);
}

/*
 * Lua-registerable C function template for constructor proxies.  These are
 * registered to Lua as global functions with the name of the class, with the
 * appropriate metatable passed as an upvalue.  They allocate a new userdata,
 * initialize it with a shared_ptr to an appropriately constructed new class
 * object, and set the metatable so that Lua can use the object.
 */

template <typename T, typename Params>
int constructor_proxy (lua_State *L)
{
	// Allocate a new userdata and construct a shared_ptr<T> in-place there
	void *block = lua_newuserdata(L, sizeof(shared_ptr<T>));
	arglist<Params, 2> args(L);
	new(block) shared_ptr<T>(constructor<T, Params>::apply(args));

	// Set the userdata's metatable
	lua_pushvalue(L, lua_upvalueindex(1));
	lua_setmetatable(L, -2);

	return 1;
}

/*
 * Perform constructor registration in a class.
 */

template <typename T>
template <typename FnPtr>
class__<T>& class__<T>::constructor ()
{
	// Get a reference to the class's static table
	lua_getglobal(L, classname<T>::name());
	// Push the constructor proxy, with the class's metatable as an upvalue
	luaL_getmetatable(L, classname<T>::name());
	lua_pushcclosure(L,
		&constructor_proxy<T, typename fnptr<FnPtr>::params>, 1);
	// Set the constructor proxy as the __call metamethod of the static table
	lua_setfield(L, -2, "__call");
	lua_pop(L, 1);
	return *this;
}

/*
 * Lua-registerable C function templates for method proxies.  These are
 * registered with the expected classname as upvalue 1 and the member function
 * pointer as upvalue 2.  When called from Lua, they will receive the object
 * on which they are called as argument 1 and all the method arguments as
 * args 2 and up.
 */

template <typename FnPtr, typename Ret = typename fnptr<FnPtr>::resulttype>
struct method_proxy
{
	typedef typename fnptr<FnPtr>::classtype classtype;
	typedef typename fnptr<FnPtr>::params params;
	static int f (lua_State *L)
	{
		classtype *obj = ((shared_ptr<classtype> *)checkclass(L, 1,
			lua_tostring(L, lua_upvalueindex(1))))->get();
		FnPtr fp = *(FnPtr *)lua_touserdata(L, lua_upvalueindex(2));
		arglist<params, 2> args(L);
		tdstack<Ret>::push(L, fnptr<FnPtr>::apply(obj, fp, args));
		return 1;
	}
};

template <typename FnPtr>
struct method_proxy <FnPtr, void>
{
	typedef typename fnptr<FnPtr>::classtype classtype;
	typedef typename fnptr<FnPtr>::params params;
	static int f (lua_State *L)
	{
		classtype *obj = ((shared_ptr<classtype> *)checkclass(L, 1,
			lua_tostring(L, lua_upvalueindex(1))))->get();
		FnPtr fp = *(FnPtr *)lua_touserdata(L, lua_upvalueindex(2));
		arglist<params, 2> args(L);
		fnptr<FnPtr>::apply(obj, fp, args);
		return 1;
	}
};

/*
 * Perform method registration in a class.  The method proxies are all
 * registered as values in the class's metatable, which is searched by the
 * subclass_indexer function we've installed as __index metamethod.
 */

template <typename T>
template <typename FnPtr>
class__<T>& class__<T>::method (const char *name, FnPtr fp)
{
	assert(fnptr<FnPtr>::mfp);
	std::string metatable_name = classname<T>::name();
	if (fnptr<FnPtr>::const_mfp)
		metatable_name = "const " + metatable_name;
	luaL_getmetatable(L, metatable_name.c_str());
	lua_pushstring(L, metatable_name.c_str());
	void *v = lua_newuserdata(L, sizeof(FnPtr));
	memcpy(v, &fp, sizeof(FnPtr));
	lua_pushcclosure(L, &method_proxy<FnPtr>::f, 2);
	lua_setfield(L, -2, name);
	lua_pop(L, 1);
	return *this;
}

/*
 * Static method registration.  Method proxies are registered as values
 * in the class's static table.  We use the global function proxies defined
 * in module.hpp, since static methods are really just hidden globals.
 */

template <typename T>
template <typename FnPtr>
class__<T>& class__<T>::static_method (const char *name, FnPtr fp)
{
	assert(!fnptr<FnPtr>::mfp);
	lua_getglobal(L, classname<T>::name());
	lua_pushlightuserdata(L, (void *)fp);
	lua_pushcclosure(L, &function_proxy<FnPtr>::f, 1);
	lua_setfield(L, -2, name);
	lua_pop(L, 1);
	return *this;
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chainparams.h"
#include "validation.h"
#include "net.h"

#include "test/test_gulden.h"

#include <boost/signals2/signal.hpp>
#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup)

static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams)
{
    int maxHalvings = 64;
    CAmount nInitialSubsidy = 50 * COIN;

    CAmount nPreviousSubsidy = nInitialSubsidy * 2; // for height == 0
    BOOST_CHECK_EQUAL(nPreviousSubsidy, nInitialSubsidy * 2);
    for (int nHalvings = 0; nHalvings < maxHalvings; nHalvings++) {
        int nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval;
        CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
        BOOST_CHECK(nSubsidy <= nInitialSubsidy);
        BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2);
        nPreviousSubsidy = nSubsidy;
    }
    BOOST_CHECK_EQUAL(GetBlockSubsidy(maxHalvings * consensusParams.nSubsidyHalvingInterval, consensusParams), 0);
}

static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
{
    Consensus::Params consensusParams;
    consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval;
    TestBlockSubsidyHalvings(consensusParams);
}

BOOST_AUTO_TEST_CASE(block_subsidy_test)
{
    const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
    TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main
    TestBlockSubsidyHalvings(150); // As in regtest
    TestBlockSubsidyHalvings(1000); // Just another interval
}

BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
    const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
    CAmount nSum = 0;
    for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) {
        CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
        BOOST_CHECK(nSubsidy <= 50 * COIN);
        nSum += nSubsidy * 1000;
        BOOST_CHECK(MoneyRange(nSum));
    }
    BOOST_CHECK_EQUAL(nSum, 2099999997690000ULL);
}

bool ReturnFalse() { return false; }
bool ReturnTrue() { return true; }

BOOST_AUTO_TEST_CASE(test_combiner_all)
{
    boost::signals2::signal<bool (), CombinerAll> Test;
    BOOST_CHECK(Test());
    Test.connect(&ReturnFalse);
    BOOST_CHECK(!Test());
    Test.connect(&ReturnTrue);
    BOOST_CHECK(!Test());
    Test.disconnect(&ReturnFalse);
    BOOST_CHECK(Test());
    Test.disconnect(&ReturnTrue);
    BOOST_CHECK(Test());
}
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>(tests) fix main_tests (all pass)<commit_after>// Copyright (c) 2014-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "chainparams.h"
#include "validation.h"
#include "net.h"

#include "test/test_gulden.h"

#include <boost/signals2/signal.hpp>
#include <boost/test/unit_test.hpp>

BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup)

BOOST_AUTO_TEST_CASE(block_subsidy_test)
{
    const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
    BOOST_CHECK_EQUAL(GetBlockSubsidy(1,        chainParams->GetConsensus()), COIN * 170000000);
    BOOST_CHECK_EQUAL(GetBlockSubsidy(250000,   chainParams->GetConsensus()), COIN * 1000);
    BOOST_CHECK_EQUAL(GetBlockSubsidy(250001,   chainParams->GetConsensus()), COIN * 100);
    BOOST_CHECK_EQUAL(GetBlockSubsidy(12850000, chainParams->GetConsensus()), COIN * 100);
    BOOST_CHECK_EQUAL(GetBlockSubsidy(12850001, chainParams->GetConsensus()), COIN * 0);
}

BOOST_AUTO_TEST_CASE(subsidy_limit_test)
{
    const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
    CAmount nSum = 0;
    for (int nHeight = 0; nHeight < 14000000; nHeight++) {
        CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
        nSum += nSubsidy;
        BOOST_CHECK(MoneyRange(nSum));
    }
    BOOST_CHECK_EQUAL(nSum, 168000000000000000LL);
}

bool ReturnFalse() { return false; }
bool ReturnTrue() { return true; }

BOOST_AUTO_TEST_CASE(test_combiner_all)
{
    boost::signals2::signal<bool (), CombinerAll> Test;
    BOOST_CHECK(Test());
    Test.connect(&ReturnFalse);
    BOOST_CHECK(!Test());
    Test.connect(&ReturnTrue);
    BOOST_CHECK(!Test());
    Test.disconnect(&ReturnFalse);
    BOOST_CHECK(Test());
    Test.disconnect(&ReturnTrue);
    BOOST_CHECK(Test());
}
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgProducer/Viewer>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/MatrixTransform>

#include <osgText/Text>

osg::Node* createHUD()
{
    osg::Geode* geode = new osg::Geode();

    std::string timesFont("fonts/times.ttf");

    // turn lighting off for the text and disable depth test to ensure its always ontop.
    osg::StateSet* stateset = geode->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);

    osg::Vec3 position(150.0f,800.0f,0.0f);
    osg::Vec3 delta(0.0f,-120.0f,0.0f);

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Head Up Displays are simple :-)");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setAutoScaleToScreen(true);
        text->setPosition(position);
        text->setText("All you need to do is create your text in a subgraph.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Disable depth test in this subgraph to ensure its always ontop.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Then place an osg::Projection node above the subgraph\nto create an orthographic projection.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("And add an osg::ModelViewMatrix set to ABSOLUTE to ensure\nit remains independent from any external model view matrices.");

        position += delta;
    }

    // create the hud.
    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
    modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE);
    modelview_abs->setMatrix(osg::Matrix::identity());
    modelview_abs->addChild(geode);

    osg::Projection* projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
    projection->addChild(modelview_abs);

    return projection;

}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to do Head Up Displays.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    osg::ref_ptr<osg::Group> group = dynamic_cast<osg::Group*>(scene.get());
    if (!group)
    {
        group = new osg::Group;
        group->addChild(scene.get());
    }

    // add the HUD subgraph.
    group->addChild(createHUD());

    // set the scene to render
    viewer.setSceneData(group.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<commit_msg>Reverted the test of setAutoScaleToScreen.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgProducer/Viewer>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/MatrixTransform>

#include <osgText/Text>

osg::Node* createHUD()
{
    osg::Geode* geode = new osg::Geode();

    std::string timesFont("fonts/times.ttf");

    // turn lighting off for the text and disable depth test to ensure its always ontop.
    osg::StateSet* stateset = geode->getOrCreateStateSet();
    stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
    stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);

    osg::Vec3 position(150.0f,800.0f,0.0f);
    osg::Vec3 delta(0.0f,-120.0f,0.0f);

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Head Up Displays are simple :-)");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("All you need to do is create your text in a subgraph.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Disable depth test in this subgraph to ensure its always ontop.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("Then place an osg::Projection node above the subgraph\nto create an orthographic projection.");

        position += delta;
    }

    {
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );

        text->setFont(timesFont);
        text->setPosition(position);
        text->setText("And add an osg::ModelViewMatrix set to ABSOLUTE to ensure\nit remains independent from any external model view matrices.");

        position += delta;
    }

    // create the hud.
    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
    modelview_abs->setReferenceFrame(osg::Transform::RELATIVE_TO_ABSOLUTE);
    modelview_abs->setMatrix(osg::Matrix::identity());
    modelview_abs->addChild(geode);

    osg::Projection* projection = new osg::Projection;
    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
    projection->addChild(modelview_abs);

    return projection;

}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to do Head Up Displays.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    osg::ref_ptr<osg::Group> group = dynamic_cast<osg::Group*>(scene.get());
    if (!group)
    {
        group = new osg::Group;
        group->addChild(scene.get());
    }

    // add the HUD subgraph.
    group->addChild(createHUD());

    // set the scene to render
    viewer.setSceneData(group.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<|endoftext|>


<commit_before>#include <taichi/taichi>
#include <taichi/util.h>

TC_NAMESPACE_BEGIN

auto diff_conv = [](const std::vector<std::string> args) {
  int grid_resolution = 256;
  TC_ASSERT(args.size() == 2);
  auto f = fopen(args[0].c_str(), "rb");

  int n = pow<3>(grid_resolution);
  TC_ASSERT(f);

  std::vector<float32> ret1(n);
  std::fread(ret1.data(), sizeof(float32), ret1.size(), f);
  std::fclose(f);

  f = fopen(args[1].c_str(), "rb");
  TC_ASSERT(f);
  std::vector<float32> ret2(n);
  std::fread(ret2.data(), sizeof(float32), ret2.size(), f);
  std::fclose(f);

  int counter[2] = {0, 0};
  for (int i = 0; i < n; i++) {
    bool same = std::abs(ret1[i] - ret2[i]) < 1e-3f;
    if (same)
      counter[0]++;
    else
      counter[1]++;
  }
  TC_INFO("same {} {}%", counter[0], 100.0f * counter[0] / n);
};

TC_REGISTER_TASK(diff_conv);

TC_NAMESPACE_END
<commit_msg>threshold<commit_after>#include <taichi/taichi>
#include <taichi/util.h>

TC_NAMESPACE_BEGIN

auto diff_conv = [](const std::vector<std::string> args) {
  int grid_resolution = 256;
  TC_ASSERT(args.size() == 3);
  float th = std::stof(args[2]);
  TC_P(th);
  auto f = fopen(args[0].c_str(), "rb");

  int n = pow<3>(grid_resolution);
  TC_ASSERT(f);

  std::vector<float32> ret1(n);
  std::fread(ret1.data(), sizeof(float32), ret1.size(), f);
  std::fclose(f);

  f = fopen(args[1].c_str(), "rb");
  TC_ASSERT(f);
  std::vector<float32> ret2(n);
  std::fread(ret2.data(), sizeof(float32), ret2.size(), f);
  std::fclose(f);

  int counter[2] = {0, 0};
  for (int i = 0; i < n; i++) {
    bool same = std::abs(ret1[i] - ret2[i]) < 1e-3f;
    if (same)
      counter[0]++;
    else
      counter[1]++;
  }
  TC_INFO("same {} {}%", counter[0], 100.0f * counter[0] / n);
};

TC_REGISTER_TASK(diff_conv);

TC_NAMESPACE_END
<|endoftext|>


<commit_before>#line 2 "togo/serializer.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Serializer interface.
@ingroup serialization
@ingroup serializer
*/

#pragma once

#include <togo/config.hpp>
#include <togo/traits.hpp>
#include <togo/serialization_types.hpp>

#include <type_traits>
#include <utility>

/** @cond INTERNAL */

namespace togo {
namespace detail {
	struct unimplemented {};
} // namespace detail
} // namespace togo

// Unimplemented captures (least-sticky acceptor)
template<class... P>
togo::detail::unimplemented serialize(togo::serializer_tag, P&&...);
template<class... P>
togo::detail::unimplemented read(togo::serializer_tag, P&&...);
template<class... P>
togo::detail::unimplemented write(togo::serializer_tag, P&&...);

/** @endcond */ // INTERNAL

namespace togo {

/**
	@addtogroup serializer
	@{
*/

namespace {

template<class Ser, class T>
struct has_serializer_serialize {
	using ser_type = remove_cvr<Ser>;
	using unimpl_capture = is_same<
		detail::unimplemented,
		decltype(serialize(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T&>()
		))
	>;
	static constexpr bool const value = !unimpl_capture::value;
};

template<class Ser, class T>
struct has_serializer_read {
	using ser_type = remove_cvr<Ser>;
	using unimpl_capture_lvalue = is_same<
		detail::unimplemented,
		decltype(read(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T&>()
		))
	>;
	using unimpl_capture_rvalue = is_same<
		detail::unimplemented,
		decltype(read(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T&&>()
		))
	>;
	static constexpr bool const value =
		!unimpl_capture_lvalue::value ||
		!unimpl_capture_rvalue::value
	;
};

template<class Ser, class T>
struct has_serializer_write {
	using ser_type = remove_cvr<Ser>;
	using unimpl_capture = is_same<
		detail::unimplemented,
		decltype(write(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T const&>()
		))
	>;
	static constexpr bool const value = !unimpl_capture::value;
};

template<class Ser, class T>
inline constexpr unsigned serializer_read_num_defined() {
	return
		has_serializer_read<Ser, T>::value +
		has_serializer_serialize<Ser, T>::value
	;
}

template<class Ser, class T>
inline constexpr unsigned serializer_write_num_defined() {
	return
		has_serializer_write<Ser, T>::value +
		has_serializer_serialize<Ser, T>::value
	;
}

} // anonymous namespace

namespace serializer {

template<class Ser, class T>
inline enable_if<has_serializer_serialize<Ser, T>::value>
read(Ser& ser, T&& value) {
	serialize(serializer_tag{}, ser, std::forward<T>(value));
}

template<class Ser, class T>
inline enable_if<has_serializer_read<Ser, T>::value>
read(Ser& ser, T&& value) {
	read(serializer_tag{}, ser, std::forward<T>(value));
}

template<class Ser, class T>
inline enable_if<has_serializer_serialize<Ser, T>::value>
write(Ser& ser, T const& value) {
	serialize(serializer_tag{}, ser, const_cast<remove_cvr<T>&>(value));
}

template<class Ser, class T>
inline enable_if<has_serializer_write<Ser, T>::value>
write(Ser& ser, T const& value) {
	write(serializer_tag{}, ser, value);
}

} // namespace serializer

// BaseSerializer implementation

template<class Impl>
inline Impl& BaseSerializer<Impl>::impl() {
	return static_cast<Impl&>(*this);
}

// InputSerializer implementation

/// Read value.
template<class Impl, class T>
inline enable_if<serializer_read_num_defined<Impl, T>() == 1, Impl&>
operator%(
	InputSerializer<Impl>& ser,
	T&& value
) {
	serializer::read(ser.impl(), std::forward<T>(value));
	return ser.impl();
}

/** @cond INTERNAL */
template<class Impl, class T>
inline enable_if<serializer_read_num_defined<Impl, T>() != 1, Impl&>
operator%(
	InputSerializer<Impl>& /*ser*/,
	T&& /*value*/
) {
	static_assert(
		serializer_read_num_defined<Impl, T>() != 0,
		"no read-serialize function defined for T with this serializer"
	);
	static_assert(
		serializer_read_num_defined<Impl, T>() <= 1,
		"ambiguous serialization interface defined for T with this serializer"
		" (both read() and serialize() are defined)"
	);
}
/** @endcond */ // INTERNAL

// OutputSerializer implementation

/// Write value.
template<class Impl, class T>
inline enable_if<serializer_write_num_defined<Impl, T>() == 1, Impl&>
operator%(
	OutputSerializer<Impl>& ser,
	T const& value
) {
	serializer::write(ser.impl(), value);
	return ser.impl();
}

/** @cond INTERNAL */
template<class Impl, class T>
inline enable_if<serializer_write_num_defined<Impl, T>() != 1, Impl&>
operator%(
	OutputSerializer<Impl>& /*ser*/,
	T const& /*value*/
) {
	static_assert(
		serializer_write_num_defined<Impl, T>() != 0,
		"no write-serialize function defined for T with this serializer"
	);
	static_assert(
		serializer_write_num_defined<Impl, T>() <= 1,
		"ambiguous serialization interface defined for T with this serializer"
		" (both write() and serialize() are defined)"
	);
}
/** @endcond */ // INTERNAL

/** @} */ // end of doc-group serializer

} // namespace togo
<commit_msg>serializer: tidy.<commit_after>#line 2 "togo/serializer.hpp"
/**
@copyright MIT license; see @ref index or the accompanying LICENSE file.

@file
@brief Serializer interface.
@ingroup serialization
@ingroup serializer
*/

#pragma once

#include <togo/config.hpp>
#include <togo/traits.hpp>
#include <togo/serialization_types.hpp>

#include <type_traits>
#include <utility>

/** @cond INTERNAL */

namespace togo {
namespace detail {
	struct unimplemented {};
} // namespace detail
} // namespace togo

// Unimplemented captures (least-sticky acceptor)
template<class... P>
togo::detail::unimplemented serialize(togo::serializer_tag, P&&...);
template<class... P>
togo::detail::unimplemented read(togo::serializer_tag, P&&...);
template<class... P>
togo::detail::unimplemented write(togo::serializer_tag, P&&...);

/** @endcond */ // INTERNAL

namespace togo {

/**
	@addtogroup serializer
	@{
*/

namespace {

template<class Ser, class T>
struct has_serializer_serialize {
	using ser_type = remove_cvr<Ser>;
	using unimpl_capture = is_same<
		detail::unimplemented,
		decltype(serialize(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T&>()
		))
	>;
	static constexpr bool const value = !unimpl_capture::value;
};

template<class Ser, class T>
struct has_serializer_read {
	using ser_type = remove_cvr<Ser>;
	using unimpl_capture_lvalue = is_same<
		detail::unimplemented,
		decltype(read(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T&>()
		))
	>;
	using unimpl_capture_rvalue = is_same<
		detail::unimplemented,
		decltype(read(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T&&>()
		))
	>;
	static constexpr bool const value =
		!unimpl_capture_lvalue::value ||
		!unimpl_capture_rvalue::value
	;
};

template<class Ser, class T>
struct has_serializer_write {
	using ser_type = remove_cvr<Ser>;
	using unimpl_capture = is_same<
		detail::unimplemented,
		decltype(write(
			serializer_tag{},
			std::declval<ser_type&>(),
			std::declval<T const&>()
		))
	>;
	static constexpr bool const value = !unimpl_capture::value;
};

template<class Ser, class T>
inline constexpr unsigned serializer_read_num_defined() {
	return
		has_serializer_read<Ser, T>::value +
		has_serializer_serialize<Ser, T>::value
	;
}

template<class Ser, class T>
inline constexpr unsigned serializer_write_num_defined() {
	return
		has_serializer_write<Ser, T>::value +
		has_serializer_serialize<Ser, T>::value
	;
}

} // anonymous namespace

namespace serializer {

template<class Ser, class T>
inline enable_if<has_serializer_serialize<Ser, T>::value, void>
read(Ser& ser, T&& value) {
	serialize(serializer_tag{}, ser, std::forward<T>(value));
}

template<class Ser, class T>
inline enable_if<has_serializer_read<Ser, T>::value, void>
read(Ser& ser, T&& value) {
	read(serializer_tag{}, ser, std::forward<T>(value));
}

template<class Ser, class T>
inline enable_if<has_serializer_serialize<Ser, T>::value, void>
write(Ser& ser, T const& value) {
	serialize(serializer_tag{}, ser, const_cast<remove_cvr<T>&>(value));
}

template<class Ser, class T>
inline enable_if<has_serializer_write<Ser, T>::value, void>
write(Ser& ser, T const& value) {
	write(serializer_tag{}, ser, value);
}

} // namespace serializer

// BaseSerializer implementation

template<class Impl>
inline Impl& BaseSerializer<Impl>::impl() {
	return static_cast<Impl&>(*this);
}

// InputSerializer implementation

/// Read value.
template<class Impl, class T>
inline enable_if<serializer_read_num_defined<Impl, T>() == 1, Impl&>
operator%(
	InputSerializer<Impl>& ser,
	T&& value
) {
	serializer::read(ser.impl(), std::forward<T>(value));
	return ser.impl();
}

/** @cond INTERNAL */
template<class Impl, class T>
inline enable_if<serializer_read_num_defined<Impl, T>() != 1, Impl&>
operator%(
	InputSerializer<Impl>& /*ser*/,
	T&& /*value*/
) {
	static_assert(
		serializer_read_num_defined<Impl, T>() != 0,
		"no read-serialize function defined for T with this serializer"
	);
	static_assert(
		serializer_read_num_defined<Impl, T>() <= 1,
		"ambiguous serialization interface defined for T with this serializer"
		" (both read() and serialize() are defined)"
	);
}
/** @endcond */ // INTERNAL

// OutputSerializer implementation

/// Write value.
template<class Impl, class T>
inline enable_if<serializer_write_num_defined<Impl, T>() == 1, Impl&>
operator%(
	OutputSerializer<Impl>& ser,
	T const& value
) {
	serializer::write(ser.impl(), value);
	return ser.impl();
}

/** @cond INTERNAL */
template<class Impl, class T>
inline enable_if<serializer_write_num_defined<Impl, T>() != 1, Impl&>
operator%(
	OutputSerializer<Impl>& /*ser*/,
	T const& /*value*/
) {
	static_assert(
		serializer_write_num_defined<Impl, T>() != 0,
		"no write-serialize function defined for T with this serializer"
	);
	static_assert(
		serializer_write_num_defined<Impl, T>() <= 1,
		"ambiguous serialization interface defined for T with this serializer"
		" (both write() and serialize() are defined)"
	);
}
/** @endcond */ // INTERNAL

/** @} */ // end of doc-group serializer

} // namespace togo
<|endoftext|>


<commit_before>/*
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Heiko Strathmann
 */

#include <shogun/base/init.h>
#include <shogun/statistics/QuadraticTimeMMD.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Statistics.h>
#include <shogun/features/DataGenerator.h>

using namespace shogun;

/** tests the quadratic mmd statistic for a single data case and ensures
 * equality with matlab implementation */
void test_quadratic_mmd_fixed()
{
	index_t n=2;
	index_t d=3;
	float64_t sigma=2;
	float64_t sq_sigma_twice=sigma*sigma*2;
	SGMatrix<float64_t> data(d,2*n);
	for (index_t i=0; i<2*d*n; ++i)
		data.matrix[i]=i;

	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);
	CGaussianKernel* kernel=new CGaussianKernel(10, sq_sigma_twice);
	kernel->init(features, features);

	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, n);

	/* unbiased statistic */
	mmd->set_statistic_type(UNBIASED);
	float64_t difference=CMath::abs(mmd->compute_statistic()-0.051325806508381);
	ASSERT(difference<=10E-16);

	/* biased statistic */
	mmd->set_statistic_type(BIASED);
	difference=CMath::abs(mmd->compute_statistic()-1.017107688196714);
	ASSERT(difference<=10E-16);

	SG_UNREF(mmd);
}

/** tests the quadratic mmd statistic bootstrapping for a random data case and
 * ensures equality with matlab implementation (unbiased statistic) */
void test_quadratic_mmd_bootstrap()
{
	index_t dimension=3;
	index_t m=100;
	float64_t difference=0.5;
	float64_t sigma=2;
	index_t num_iterations=1000;
	num_iterations=10; //speed up

	SGMatrix<float64_t> data=CDataGenerator::generate_mean_data(m, dimension,
			difference);
	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);
	mmd->set_statistic_type(UNBIASED);
	mmd->set_bootstrap_iterations(num_iterations);

	/* use fixed seed */
	CMath::init_random(1);
	SGVector<float64_t> null_samples=mmd->bootstrap_null();

	float64_t mean=CStatistics::mean(null_samples);
	float64_t var=CStatistics::variance(null_samples);

	/* MATLAB mean 2-sigma confidence interval for 1000 repretitions is
	 * [-3.169406734013459e-04, 3.296399498466372e-04] */
	SG_SPRINT("mean %f\n", mean);
//	ASSERT(mean>-3.169406734013459e-04);
//	ASSERT(mean<3.296399498466372e-04);

	/* MATLAB variance 2-sigma confidence interval for 1000 repretitions is
	 * [2.194192869469228e-05,2.936672859339959e-05] */
	SG_SPRINT("var %f\n", var);
//	ASSERT(var>2.194192869469228e-05);
//	ASSERT(var<2.936672859339959e-05);

	/* now again but with a precomputed kernel, same features.
	 * This avoids re-computing the kernel matrix in every bootstrapping
	 * iteration and should be num_iterations times faster */
	SG_REF(features);
	CCustomKernel* precomputed_kernel=new CCustomKernel(kernel);
	SG_UNREF(mmd);
	mmd=new CQuadraticTimeMMD(precomputed_kernel, features, m);
	mmd->set_statistic_type(UNBIASED);
	mmd->set_bootstrap_iterations(num_iterations);
	CMath::init_random(1);
	null_samples=mmd->bootstrap_null();

	/* assert that results do not change */
	SG_SPRINT("mean %f, var %f\n", CStatistics::mean(null_samples),
			CStatistics::variance(null_samples));
	ASSERT(CMath::abs(mean-CStatistics::mean(null_samples))<10E-5);
	ASSERT(CMath::abs(var-CStatistics::variance(null_samples))<10E-5);

	SG_UNREF(mmd);
	SG_UNREF(features);
}

#ifdef HAVE_LAPACK
/** tests the quadratic mmd statistic threshold method spectrum for radnom data
 * case and ensures equality with matlab implementation */
void test_quadratic_mmd_spectrum()
{
	index_t dimension=3;
	index_t m=100;
	float64_t difference=0.5;
	float64_t sigma=2;

	SGMatrix<float64_t> data=CDataGenerator::generate_mean_data(m, dimension,
			difference);

	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);

	mmd->set_num_samples_sepctrum(1000);
	mmd->set_num_samples_sepctrum(10); //speed up
	mmd->set_num_eigenvalues_spectrum(m);
	mmd->set_null_approximation_method(MMD2_SPECTRUM);
	mmd->set_statistic_type(BIASED);

	/* compute p-value for a fixed statistic value */
	float64_t p=mmd->compute_p_value(2);

	/* MATLAB 1000 iterations 3 sigma confidence interval is
	 * [0.021240218376709, 0.060875781623291] */
	SG_SPRINT("p %f\n", p);
//	ASSERT(p>0.021240218376709);
//	ASSERT(p<0.060875781623291);

	SG_UNREF(mmd);
}
#endif // HAVE_LAPACK

/** tests the quadratic mmd statistic threshold method gamma for fixed data
 * case and ensures equality with matlab implementation */
void test_quadratic_mmd_gamma()
{
	index_t dimension=3;
	index_t m=100;
	float64_t sigma=4;

	/* note: fixed data this time */
	SGMatrix<float64_t> data(dimension, 2*m);
	for (index_t i=0; i<2*dimension*m; ++i)
		data.matrix[i]=i;

	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);

	mmd->set_null_approximation_method(MMD2_GAMMA);
	mmd->set_statistic_type(BIASED);

	/* compute p-value for a fixed statistic value */
	float64_t p=mmd->compute_p_value(2);
	SG_SPRINT("p: %f\n", p);

	/* MATLAB 1000 iterations mean: 0.511547577996229 with variance 10E-15,
	 * asserting with only 10-12 to avoid problems. Shold never fail.
	 */
	ASSERT(CMath::abs(p-0.511547577996229)<10E-12);

	SG_UNREF(mmd);
}

/** tests the quadratic mmd statistic for a random data case (fixed distribution
 * and ensures equality with matlab implementation (unbiased case) */
void test_quadratic_mmd_random()
{
	index_t dimension=3;
	index_t m=300;
	float64_t difference=0.5;
	float64_t sigma=2;

	index_t num_runs=100;
	num_runs=10; //speed up
	SGVector<float64_t> mmds(num_runs);

	/* pre-allocate data matrix and features, just change elements later */
	SGMatrix<float64_t> data(dimension, 2*m);
	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);
	mmd->set_statistic_type(UNBIASED);
	for (index_t i=0; i<num_runs; ++i)
	{
		/* use pre-allocated space for data generation */
		CDataGenerator::generate_mean_data(m, dimension, difference, data);
		kernel->init(features, features);
		mmds[i]=mmd->compute_statistic();
	}

	/* MATLAB 95% mean confidence interval 0.007495841715582 0.037960088792417 */
	float64_t mean=CStatistics::mean(mmds);
	SG_SPRINT("mean %f\n", mean);
//	ASSERT((mean>0.007495841715582) && (mean<0.037960088792417));

	/* MATLAB variance is 5.800439687240292e-05 quite stable */
	float64_t variance=CStatistics::variance(mmds);
	SG_SPRINT("variance: %f\n", variance);
//	ASSERT(CMath::abs(variance-5.800439687240292e-05)<10E-5);
	SG_UNREF(mmd);
}

int main(int argc, char** argv)
{
	init_shogun_with_defaults();

//	sg_io->set_loglevel(MSG_DEBUG);

	/* all tests have been "speed up" by reducing the number of runs/samples.
	 * If you have any doubts in the results, set all num_runs to original
	 * numbers and activate asserts. If they fail, something is wrong. */

	test_quadratic_mmd_fixed();
	test_quadratic_mmd_random();
	test_quadratic_mmd_bootstrap();
#ifdef HAVE_LAPACK
	test_quadratic_mmd_spectrum();
#endif
	test_quadratic_mmd_gamma();

	exit_shogun();
	return 0;
}

<commit_msg>made example work for recent bootstrapping changes<commit_after>/*
 * 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 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2012 Heiko Strathmann
 */

#include <shogun/base/init.h>
#include <shogun/statistics/QuadraticTimeMMD.h>
#include <shogun/kernel/GaussianKernel.h>
#include <shogun/kernel/CustomKernel.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Statistics.h>
#include <shogun/features/DataGenerator.h>

using namespace shogun;

/** tests the quadratic mmd statistic for a single data case and ensures
 * equality with matlab implementation */
void test_quadratic_mmd_fixed()
{
	index_t n=2;
	index_t d=3;
	float64_t sigma=2;
	float64_t sq_sigma_twice=sigma*sigma*2;
	SGMatrix<float64_t> data(d,2*n);
	for (index_t i=0; i<2*d*n; ++i)
		data.matrix[i]=i;

	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);
	CGaussianKernel* kernel=new CGaussianKernel(10, sq_sigma_twice);
	kernel->init(features, features);

	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, n);

	/* unbiased statistic */
	mmd->set_statistic_type(UNBIASED);
	float64_t difference=CMath::abs(mmd->compute_statistic()-0.051325806508381);
	ASSERT(difference<=10E-16);

	/* biased statistic */
	mmd->set_statistic_type(BIASED);
	difference=CMath::abs(mmd->compute_statistic()-1.017107688196714);
	ASSERT(difference<=10E-16);

	SG_UNREF(mmd);
}

/** tests the quadratic mmd statistic bootstrapping for a random data case and
 * ensures equality with matlab implementation (unbiased statistic) */
void test_quadratic_mmd_bootstrap()
{
	/* reproducable results */
	CMath::init_random(1);

	index_t dimension=3;
	index_t m=100;
	float64_t difference=0.5;
	float64_t sigma=2;
	index_t num_iterations=1000;
	num_iterations=10; //speed up

	SGMatrix<float64_t> data=CDataGenerator::generate_mean_data(m, dimension,
			difference);
	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);
	mmd->set_statistic_type(UNBIASED);
	mmd->set_bootstrap_iterations(num_iterations);

	/* use fixed seed */
	CMath::init_random(1);
	SGVector<float64_t> null_samples=mmd->bootstrap_null();

	float64_t mean=CStatistics::mean(null_samples);
	float64_t var=CStatistics::variance(null_samples);

	/* MATLAB mean 2-sigma confidence interval for 1000 repretitions is
	 * [-3.169406734013459e-04, 3.296399498466372e-04] */
	SG_SPRINT("mean %f\n", mean);
//	ASSERT(mean>-3.169406734013459e-04);
//	ASSERT(mean<3.296399498466372e-04);

	/* MATLAB variance 2-sigma confidence interval for 1000 repretitions is
	 * [2.194192869469228e-05,2.936672859339959e-05] */
	SG_SPRINT("var %f\n", var);
//	ASSERT(var>2.194192869469228e-05);
//	ASSERT(var<2.936672859339959e-05);

	/* now again but with a precomputed kernel, same features.
	 * This avoids re-computing the kernel matrix in every bootstrapping
	 * iteration and should be num_iterations times faster */
	SG_REF(features);

	/* re-init kernel before kernel matrix is computed: this is due to a design
	 * error in subsets and should be worked on! */
	kernel->init(features, features);
	CCustomKernel* precomputed_kernel=new CCustomKernel(kernel);
	SG_UNREF(mmd);
	mmd=new CQuadraticTimeMMD(precomputed_kernel, features, m);
	mmd->set_statistic_type(UNBIASED);
	mmd->set_bootstrap_iterations(num_iterations);
	CMath::init_random(1);
	null_samples=mmd->bootstrap_null();

	/* assert that results do not change */
	SG_SPRINT("mean %f, var %f\n", CStatistics::mean(null_samples),
			CStatistics::variance(null_samples));
	ASSERT(CMath::abs(mean-CStatistics::mean(null_samples))<10E-5);
	ASSERT(CMath::abs(var-CStatistics::variance(null_samples))<10E-5);

	SG_UNREF(mmd);
	SG_UNREF(features);
}

#ifdef HAVE_LAPACK
/** tests the quadratic mmd statistic threshold method spectrum for radnom data
 * case and ensures equality with matlab implementation */
void test_quadratic_mmd_spectrum()
{
	index_t dimension=3;
	index_t m=100;
	float64_t difference=0.5;
	float64_t sigma=2;

	SGMatrix<float64_t> data=CDataGenerator::generate_mean_data(m, dimension,
			difference);

	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);

	mmd->set_num_samples_sepctrum(1000);
	mmd->set_num_samples_sepctrum(10); //speed up
	mmd->set_num_eigenvalues_spectrum(m);
	mmd->set_null_approximation_method(MMD2_SPECTRUM);
	mmd->set_statistic_type(BIASED);

	/* compute p-value for a fixed statistic value */
	float64_t p=mmd->compute_p_value(2);

	/* MATLAB 1000 iterations 3 sigma confidence interval is
	 * [0.021240218376709, 0.060875781623291] */
	SG_SPRINT("p %f\n", p);
//	ASSERT(p>0.021240218376709);
//	ASSERT(p<0.060875781623291);

	SG_UNREF(mmd);
}
#endif // HAVE_LAPACK

/** tests the quadratic mmd statistic threshold method gamma for fixed data
 * case and ensures equality with matlab implementation */
void test_quadratic_mmd_gamma()
{
	index_t dimension=3;
	index_t m=100;
	float64_t sigma=4;

	/* note: fixed data this time */
	SGMatrix<float64_t> data(dimension, 2*m);
	for (index_t i=0; i<2*dimension*m; ++i)
		data.matrix[i]=i;

	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);

	mmd->set_null_approximation_method(MMD2_GAMMA);
	mmd->set_statistic_type(BIASED);

	/* compute p-value for a fixed statistic value */
	float64_t p=mmd->compute_p_value(2);
	SG_SPRINT("p: %f\n", p);

	/* MATLAB 1000 iterations mean: 0.511547577996229 with variance 10E-15,
	 * asserting with only 10-12 to avoid problems. Shold never fail.
	 */
	ASSERT(CMath::abs(p-0.511547577996229)<10E-12);

	SG_UNREF(mmd);
}

/** tests the quadratic mmd statistic for a random data case (fixed distribution
 * and ensures equality with matlab implementation (unbiased case) */
void test_quadratic_mmd_random()
{
	index_t dimension=3;
	index_t m=300;
	float64_t difference=0.5;
	float64_t sigma=2;

	index_t num_runs=100;
	num_runs=10; //speed up
	SGVector<float64_t> mmds(num_runs);

	/* pre-allocate data matrix and features, just change elements later */
	SGMatrix<float64_t> data(dimension, 2*m);
	CDenseFeatures<float64_t>* features=new CDenseFeatures<float64_t>(data);

	/* shoguns kernel width is different */
	CGaussianKernel* kernel=new CGaussianKernel(100, sigma*sigma*2);
	CQuadraticTimeMMD* mmd=new CQuadraticTimeMMD(kernel, features, m);
	mmd->set_statistic_type(UNBIASED);
	for (index_t i=0; i<num_runs; ++i)
	{
		/* use pre-allocated space for data generation */
		CDataGenerator::generate_mean_data(m, dimension, difference, data);
		kernel->init(features, features);
		mmds[i]=mmd->compute_statistic();
	}

	/* MATLAB 95% mean confidence interval 0.007495841715582 0.037960088792417 */
	float64_t mean=CStatistics::mean(mmds);
	SG_SPRINT("mean %f\n", mean);
//	ASSERT((mean>0.007495841715582) && (mean<0.037960088792417));

	/* MATLAB variance is 5.800439687240292e-05 quite stable */
	float64_t variance=CStatistics::variance(mmds);
	SG_SPRINT("variance: %f\n", variance);
//	ASSERT(CMath::abs(variance-5.800439687240292e-05)<10E-5);
	SG_UNREF(mmd);
}

int main(int argc, char** argv)
{
	init_shogun_with_defaults();

//	sg_io->set_loglevel(MSG_DEBUG);

	/* all tests have been "speed up" by reducing the number of runs/samples.
	 * If you have any doubts in the results, set all num_runs to original
	 * numbers and activate asserts. If they fail, something is wrong. */

	test_quadratic_mmd_fixed();
	test_quadratic_mmd_random();
	test_quadratic_mmd_bootstrap();
#ifdef HAVE_LAPACK
	test_quadratic_mmd_spectrum();
#endif
	test_quadratic_mmd_gamma();

	exit_shogun();
	return 0;
}

<|endoftext|>


<commit_before>#include <check.hpp>

#include <kdb.hpp>
#include <plugin.hpp>
#include <modules.hpp>
#include <cmdline.hpp>

#include <iostream>

using namespace std;
using namespace kdb;
using namespace kdb::tools;

CheckCommand::CheckCommand()
{}

int printProblems(Key k, std::string action, int off)
{
	bool wo = k.getMeta<const kdb::Key>("warnings");
	bool eo = k.getMeta<const kdb::Key>("error");
	if (wo || eo) std::cerr << action << " of kdb yield following problems:" << std::endl;
	printWarnings(cerr, k);
	return (wo + eo * 2) << off;
}

int CheckCommand::execute(Cmdline const& cl)
{
	if (cl.arguments.size() == 0)
	{
		int ret = 0;
		Key x;
		KDB kdb (x);
		ret += printProblems(x, "opening", 0);

		KeySet ks;
		Key a("/", KEY_END);
		kdb.get(ks, a);
		ret += printProblems(a, "getting", 2);

		if (cl.force)
		{
			Key b("/", KEY_END);
			kdb.set(ks, b);
			ret += printProblems(b, "setting", 4);
		}

		Key y;
		kdb.close(y);
		ret += printProblems(y, "closing", 6);
		return  ret;
	}

	if (cl.arguments.size() != 1)
	{
		throw invalid_argument ("One argument required");
	}

	std::string name = cl.arguments[0];

	Modules modules;
	if (cl.verbose) cout << "will try check the plugin " << name << endl;

	vector<string> warnings;
	try {
		KeySet ks = cl.getPluginsConfig();
		PluginPtr plugin;
		if (ks.size() == 0)
		{
			plugin = modules.load(name);
		}
		else
		{
			plugin = modules.load(name, ks);
		}
		plugin->check(warnings);

	}
	catch (NoPlugin const& p)
	{
		cerr << p.what() << endl;
		return 1;
	}
	catch (PluginCheckException const& p)
	{
		cerr << "Plugin did not pass all checks:" << endl;
		cerr << "See description below:" << endl;
		cerr << p.what() << endl;
		return 2;
	}

	if (warnings.size() > 0)
	{
		cerr << "There are " << warnings.size() << " Warnings for this plugin" << endl;
		cerr << "For high quality plugins there should be no warning" << endl;

		for (size_t i = 0; i < warnings.size(); ++i)
		{
			cerr << "Warning #" << i << ": " << warnings[i] << endl;
		}
		return 3;
	}

	return 0;
}

CheckCommand::~CheckCommand()
{}
<commit_msg>fix problem discussed in #304<commit_after>#include <check.hpp>

#include <kdb.hpp>
#include <plugin.hpp>
#include <modules.hpp>
#include <cmdline.hpp>

#include <iostream>

using namespace std;
using namespace kdb;
using namespace kdb::tools;

CheckCommand::CheckCommand()
{}

int printProblems(Key k, std::string action, int off)
{
	bool wo = k.getMeta<const kdb::Key>("warnings");
	bool eo = k.getMeta<const kdb::Key>("error");
	if (wo || eo) std::cerr << "\n======\n" << action << " of kdb yield following problems:" << std::endl;
	printWarnings(cerr, k);
	printError(cerr, k);
	return (wo + eo * 2) << off;
}

int CheckCommand::execute(Cmdline const& cl)
{
	if (cl.arguments.size() == 0)
	{
		Key x;
		try {
			int ret = 0;
			KDB kdb (x);
			ret += printProblems(x, "opening", 0);

			KeySet ks;
			Key a("/", KEY_END);
			try {kdb.get(ks, a);} catch(...) {}
			ret += printProblems(a, "getting", 2);

			if (cl.force)
			{
				Key b("/", KEY_END);
				try{kdb.set(ks, b);} catch(...) {}
				ret += printProblems(b, "setting", 4);
			}

			Key y;
			kdb.close(y);
			ret += printProblems(y, "closing", 6);
			return  ret;
		}
		catch(KDBException const & e)
		{
			std::cerr << "a fatal problem occurred, could not open KDB. This should not happen" << std::endl;
			return printProblems(x, "opening", 0);
		}
	}

	if (cl.arguments.size() != 1)
	{
		throw invalid_argument ("One argument required");
	}

	std::string name = cl.arguments[0];

	Modules modules;
	if (cl.verbose) cout << "will try check the plugin " << name << endl;

	vector<string> warnings;
	try {
		KeySet ks = cl.getPluginsConfig();
		PluginPtr plugin;
		if (ks.size() == 0)
		{
			plugin = modules.load(name);
		}
		else
		{
			plugin = modules.load(name, ks);
		}
		plugin->check(warnings);

	}
	catch (NoPlugin const& p)
	{
		cerr << p.what() << endl;
		return 1;
	}
	catch (PluginCheckException const& p)
	{
		cerr << "Plugin did not pass all checks:" << endl;
		cerr << "See description below:" << endl;
		cerr << p.what() << endl;
		return 2;
	}

	if (warnings.size() > 0)
	{
		cerr << "There are " << warnings.size() << " Warnings for this plugin" << endl;
		cerr << "For high quality plugins there should be no warning" << endl;

		for (size_t i = 0; i < warnings.size(); ++i)
		{
			cerr << "Warning #" << i << ": " << warnings[i] << endl;
		}
		return 3;
	}

	return 0;
}

CheckCommand::~CheckCommand()
{}
<|endoftext|>


<commit_before>#include "tracefilelister.h"
#include "ui_tracefilelister.h"

#include <QVBoxLayout>
#include <QLabel>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QTreeWidgetItem>

#include <QDebug>

TraceFileLister::TraceFileLister(QWidget *parent) :
  QDockWidget("Traces", parent)
{
  tree = new QTreeWidget(this);
  tree->setColumnCount(1);

  tree->clear();
  tree->setHeaderLabel("Filename");

  this->setWidget(tree);

  connect(tree, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(traceSelected(QTreeWidgetItem*,int)));
}

TraceFileLister::~TraceFileLister() {}

void TraceFileLister::addFolderToTree(QTreeWidgetItem * parent, QString dir)
{
  QDir * root = new QDir(dir);

  QStringList l = root->entryList();
  QTreeWidgetItem * j;
  for (auto o : l) {
    if (o != "." && o != "..") {
      j = new QTreeWidgetItem(parent);
      j->setText(0, o);

      QString newDir = root->absoluteFilePath(o);
      QFileInfo * fi = new QFileInfo(newDir);
      if (fi->isDir()) {
        addFolderToTree(j, newDir);
      }
      delete fi;
    }
  }

  delete root;
}

void TraceFileLister::update(QString path)
{
  QFileInfo * fi = new QFileInfo(path);

  if (fi->isDir()) {
    tree->clear();
    tree->setHeaderLabel(fi->absoluteFilePath());

    QTreeWidgetItem * j = new QTreeWidgetItem(tree);
    j->setText(0, fi->absoluteFilePath());
    addFolderToTree(j, path);
  }

  delete fi;
}

void TraceFileLister::traceSelected(QTreeWidgetItem * i, int col)
{
  QString fullPath;

  do {
    fullPath.insert(0, "/" + i->text(col));
    i = i->parent();
  } while (i != 0);

  fullPath.remove(0, 1);

  emit traceChosen(fullPath);
}
<commit_msg>File list starts expanded<commit_after>#include "tracefilelister.h"
#include "ui_tracefilelister.h"

#include <QVBoxLayout>
#include <QLabel>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QTreeWidgetItem>

#include <QDebug>

TraceFileLister::TraceFileLister(QWidget *parent) :
  QDockWidget("Traces", parent)
{
  tree = new QTreeWidget(this);
  tree->setColumnCount(1);

  tree->clear();
  tree->setHeaderLabel("Filename");

  this->setWidget(tree);

  connect(tree, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(traceSelected(QTreeWidgetItem*,int)));
}

TraceFileLister::~TraceFileLister() {}

void TraceFileLister::addFolderToTree(QTreeWidgetItem * parent, QString dir)
{
  QDir * root = new QDir(dir);

  QStringList l = root->entryList();
  QTreeWidgetItem * j;
  for (auto o : l) {
    if (o != "." && o != "..") {
      j = new QTreeWidgetItem(parent);
      j->setText(0, o);

      QString newDir = root->absoluteFilePath(o);
      QFileInfo * fi = new QFileInfo(newDir);
      if (fi->isDir()) {
        addFolderToTree(j, newDir);
      }
      delete fi;
    }
  }

  delete root;
}

void TraceFileLister::update(QString path)
{
  QFileInfo * fi = new QFileInfo(path);

  if (fi->isDir()) {
    tree->clear();
    tree->setHeaderLabel(fi->absoluteFilePath());

    QTreeWidgetItem * j = new QTreeWidgetItem(tree);
    j->setText(0, fi->absoluteFilePath());
    addFolderToTree(j, path);
    j->setExpanded(true);
  }

  delete fi;
}

void TraceFileLister::traceSelected(QTreeWidgetItem * i, int col)
{
  QString fullPath;

  do {
    fullPath.insert(0, "/" + i->text(col));
    i = i->parent();
  } while (i != 0);

  fullPath.remove(0, 1);

  emit traceChosen(fullPath);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <vector>
#include <iostream>
#include <cctype>
#include <iomanip>
#include <sstream>

#include "zlib.h"

#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/udp_tracker_connection.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"

using namespace libtorrent;

namespace
{
	enum
	{
		minimum_tracker_response_length = 3,
		http_buffer_size = 2048
	};

	enum
	{
		FTEXT = 0x01,
		FHCRC = 0x02,
		FEXTRA = 0x04,
		FNAME = 0x08,
		FCOMMENT = 0x10,
		FRESERVED = 0xe0,

		GZIP_MAGIC0 = 0x1f,
		GZIP_MAGIC1 = 0x8b
	};

}

namespace libtorrent
{

	// returns -1 if gzip header is invalid or the header size in bytes
	int gzip_header(const char* buf, int size)
	{
		assert(buf != 0);
		assert(size > 0);

		const unsigned char* buffer = reinterpret_cast<const unsigned char*>(buf);
		const int total_size = size;

		// The zip header cannot be shorter than 10 bytes
		if (size < 10) return -1;

		// check the magic header of gzip
		if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1;

		int method = buffer[2];
		int flags = buffer[3];

		// check for reserved flag and make sure it's compressed with the correct metod
		if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1;

		// skip time, xflags, OS code
		size -= 10;
		buffer += 10;

		if (flags & FEXTRA)
		{
			int extra_len;

			if (size < 2) return -1;

			extra_len = (buffer[1] << 8) | buffer[0];

			if (size < (extra_len+2)) return -1;
			size -= (extra_len + 2);
			buffer += (extra_len + 2);
		}

		if (flags & FNAME)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FCOMMENT)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FHCRC)
		{
			if (size < 2) return -1;

			size -= 2;
			buffer += 2;
		}

		return total_size - size;
	}

	bool inflate_gzip(
		std::vector<char>& buffer
		, request_callback* requester
		, int maximum_tracker_response_length)
	{
		assert(maximum_tracker_response_length > 0);

		int header_len = gzip_header(&buffer[0], (int)buffer.size());
		if (header_len < 0)
		{
			requester->tracker_request_error(200, "invalid gzip header in tracker response");
			return true;
		}

		// start off wth one kilobyte and grow
		// if needed
		std::vector<char> inflate_buffer(1024);

		// initialize the zlib-stream
		z_stream str;

		// subtract 8 from the end of the buffer since that's CRC32 and input size
		// and those belong to the gzip file
		str.avail_in = (int)buffer.size() - header_len - 8;
		str.next_in = reinterpret_cast<Bytef*>(&buffer[header_len]);
		str.next_out = reinterpret_cast<Bytef*>(&inflate_buffer[0]);
		str.avail_out = (int)inflate_buffer.size();
		str.zalloc = Z_NULL;
		str.zfree = Z_NULL;
		str.opaque = 0;
		// -15 is really important. It will make inflate() not look for a zlib header
		// and just deflate the buffer
		if (inflateInit2(&str, -15) != Z_OK)
		{
			requester->tracker_request_error(200, "gzip out of memory");
			return true;
		}

		// inflate and grow inflate_buffer as needed
		int ret = inflate(&str, Z_SYNC_FLUSH);
		while (ret == Z_OK)
		{
			if (str.avail_out == 0)
			{
				if (inflate_buffer.size() >= (unsigned)maximum_tracker_response_length)
				{
					inflateEnd(&str);
					requester->tracker_request_error(200, "tracker response too large");
					return true;
				}
				int new_size = (int)inflate_buffer.size() * 2;
				if (new_size > maximum_tracker_response_length) new_size = maximum_tracker_response_length;
				int old_size = (int)inflate_buffer.size();

				inflate_buffer.resize(new_size);
				str.next_out = reinterpret_cast<Bytef*>(&inflate_buffer[old_size]);
				str.avail_out = new_size - old_size;
			}

			ret = inflate(&str, Z_SYNC_FLUSH);
		}

		inflate_buffer.resize(inflate_buffer.size() - str.avail_out);
		inflateEnd(&str);

		if (ret != Z_STREAM_END)
		{
			requester->tracker_request_error(200, "gzip error");
			return true;
		}

		// commit the resulting buffer
		std::swap(buffer, inflate_buffer);
		return false;
	}

	std::string base64encode(const std::string& s)
	{
		static const char base64_table[] =
		{
			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
			'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
			'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
			'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
			'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
			'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
			'w', 'x', 'y', 'z', '0', '1', '2', '3',
			'4', '5', '6', '7', '8', '9', '+', '/'
		};

		unsigned char inbuf[3];
		unsigned char outbuf[4];

		std::string ret;
		for (std::string::const_iterator i = s.begin(); i != s.end();)
		{
			// available input is 1,2 or 3 bytes
			// since we read 3 bytes at a time at most
			int available_input = std::min(3, (int)std::distance(i, s.end()));

			// clear input buffer
			std::fill(inbuf, inbuf+3, 0);

			// read a chunk of input into inbuf
			for (int j = 0; j < available_input; ++j)
			{
				inbuf[j] = *i;
				++i;
			}

			// encode inbuf to outbuf
			outbuf[0] = (inbuf[0] & 0xfc) >> 2;
			outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf [1] & 0xf0) >> 4);
			outbuf[2] = ((inbuf[1] & 0x0f) << 2) | ((inbuf [2] & 0xc0) >> 6);
			outbuf[3] = inbuf[2] & 0x3f;

			// write output
			for (int j = 0; j < available_input+1; ++j)
			{
				ret += base64_table[outbuf[j]];
			}

			// write pad
			for (int j = 0; j < 3 - available_input; ++j)
			{
				ret += '=';
			}
		}
		return ret;
	}

	void tracker_manager::tick()
	{
		std::vector<boost::shared_ptr<tracker_connection> >::iterator i;
		for (i = m_connections.begin(); i != m_connections.end(); ++i)
		{
			boost::shared_ptr<tracker_connection>& c = *i;
			try
			{
				if (!c->tick()) return;
			}
			catch (const std::exception& e)
			{
				if (c->requester())
					c->requester()->tracker_request_error(-1, e.what());
			}
			if (c->requester()) c->requester()->m_manager = 0;
			m_connections.erase(i);
			--i; // compensate for the remove
		}
	}

	void tracker_manager::queue_request(
		tracker_request const& req
		, request_callback* c
		, std::string const& password)
	{
		try
		{
			std::string hostname; // hostname only
			std::string protocol; // should be http
			int port = 80;

			// PARSE URL
			std::string::const_iterator start = req.url.begin();
			std::string::const_iterator end
				= std::find(req.url.begin(), req.url.end(), ':');
			protocol = std::string(start, end);

			if (end == req.url.end()) throw std::runtime_error("invalid url");
			++end;
			if (end == req.url.end()) throw std::runtime_error("invalid url");
			if (*end != '/') throw std::runtime_error("invalid url");
			++end;
			if (end == req.url.end()) throw std::runtime_error("invalid url");
			if (*end != '/') throw std::runtime_error("invalid url");
			++end;
			start = end;

			end = std::find(start, req.url.end(), '/');
			std::string::const_iterator port_pos
				= std::find(start, req.url.end(), ':');

			if (port_pos < end)
			{
				hostname.assign(start, port_pos);
				++port_pos;
				try
				{
					port = boost::lexical_cast<int>(std::string(port_pos, end));
				}
				catch(boost::bad_lexical_cast&)
				{
					throw std::runtime_error("invalid url");
				}
			}
			else
			{
				hostname.assign(start, end);
			}

			start = end;
			std::string request_string = std::string(start, req.url.end());

			boost::shared_ptr<tracker_connection> con;

			if (protocol == "http")
			{
				con.reset(new http_tracker_connection(
					req
					, hostname
					, port
					, request_string
					, c
					, m_settings
					, password));
			}
			else if (protocol == "udp")
			{
				con.reset(new udp_tracker_connection(
					req
					, hostname
					, port
					, c
					, m_settings));
			}
			else
			{
				throw std::runtime_error("unkown protocol in tracker url");
			}

			m_connections.push_back(con);

			if (con->requester()) con->requester()->m_manager = this;
		}
		catch (std::exception& e)
		{
			if (c) c->tracker_request_error(-1, e.what());
		}
	}

	void tracker_manager::abort_request(request_callback* c)
	{
		assert(c != 0);
		std::vector<boost::shared_ptr<tracker_connection> >::iterator i;
		for (i = m_connections.begin(); i != m_connections.end(); ++i)
		{
			if ((*i)->requester() == c)
			{
				m_connections.erase(i);
				break;
			}
		}
	}

	void tracker_manager::abort_all_requests()
	{
		// removes all connections from m_connections
		// except those with a requester == 0 (since those are
		// 'event=stopped'-requests)

		std::vector<boost::shared_ptr<tracker_connection> > keep_connections;

		for (std::vector<boost::shared_ptr<tracker_connection> >::const_iterator i =
				m_connections.begin();
			i != m_connections.end();
			++i)
		{
			if ((*i)->requester() == 0) keep_connections.push_back(*i);
		}

		std::swap(m_connections, keep_connections);
	}

	bool tracker_manager::send_finished() const
	{
		for (std::vector<boost::shared_ptr<tracker_connection> >::const_iterator i =
				m_connections.begin();
			i != m_connections.end();
			++i)
		{
			if (!(*i)->send_finished()) return false;
		}
		return true;
	}

}
<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <vector>
#include <iostream>
#include <cctype>
#include <iomanip>
#include <sstream>

#include "zlib.h"

#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/udp_tracker_connection.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"

using namespace libtorrent;

namespace
{
	enum
	{
		minimum_tracker_response_length = 3,
		http_buffer_size = 2048
	};

	enum
	{
		FTEXT = 0x01,
		FHCRC = 0x02,
		FEXTRA = 0x04,
		FNAME = 0x08,
		FCOMMENT = 0x10,
		FRESERVED = 0xe0,

		GZIP_MAGIC0 = 0x1f,
		GZIP_MAGIC1 = 0x8b
	};

}

namespace libtorrent
{

	// returns -1 if gzip header is invalid or the header size in bytes
	int gzip_header(const char* buf, int size)
	{
		assert(buf != 0);
		assert(size > 0);

		const unsigned char* buffer = reinterpret_cast<const unsigned char*>(buf);
		const int total_size = size;

		// The zip header cannot be shorter than 10 bytes
		if (size < 10) return -1;

		// check the magic header of gzip
		if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1;

		int method = buffer[2];
		int flags = buffer[3];

		// check for reserved flag and make sure it's compressed with the correct metod
		if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1;

		// skip time, xflags, OS code
		size -= 10;
		buffer += 10;

		if (flags & FEXTRA)
		{
			int extra_len;

			if (size < 2) return -1;

			extra_len = (buffer[1] << 8) | buffer[0];

			if (size < (extra_len+2)) return -1;
			size -= (extra_len + 2);
			buffer += (extra_len + 2);
		}

		if (flags & FNAME)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FCOMMENT)
		{
			while (size && *buffer)
			{
				--size;
				++buffer;
			}
			if (!size || *buffer) return -1;

			--size;
			++buffer;
		}

		if (flags & FHCRC)
		{
			if (size < 2) return -1;

			size -= 2;
			buffer += 2;
		}

		return total_size - size;
	}

	bool inflate_gzip(
		std::vector<char>& buffer
		, request_callback* requester
		, int maximum_tracker_response_length)
	{
		assert(maximum_tracker_response_length > 0);

		int header_len = gzip_header(&buffer[0], (int)buffer.size());
		if (header_len < 0)
		{
			requester->tracker_request_error(200, "invalid gzip header in tracker response");
			return true;
		}

		// start off wth one kilobyte and grow
		// if needed
		std::vector<char> inflate_buffer(1024);

		// initialize the zlib-stream
		z_stream str;

		// subtract 8 from the end of the buffer since that's CRC32 and input size
		// and those belong to the gzip file
		str.avail_in = (int)buffer.size() - header_len - 8;
		str.next_in = reinterpret_cast<Bytef*>(&buffer[header_len]);
		str.next_out = reinterpret_cast<Bytef*>(&inflate_buffer[0]);
		str.avail_out = (int)inflate_buffer.size();
		str.zalloc = Z_NULL;
		str.zfree = Z_NULL;
		str.opaque = 0;
		// -15 is really important. It will make inflate() not look for a zlib header
		// and just deflate the buffer
		if (inflateInit2(&str, -15) != Z_OK)
		{
			requester->tracker_request_error(200, "gzip out of memory");
			return true;
		}

		// inflate and grow inflate_buffer as needed
		int ret = inflate(&str, Z_SYNC_FLUSH);
		while (ret == Z_OK)
		{
			if (str.avail_out == 0)
			{
				if (inflate_buffer.size() >= (unsigned)maximum_tracker_response_length)
				{
					inflateEnd(&str);
					requester->tracker_request_error(200, "tracker response too large");
					return true;
				}
				int new_size = (int)inflate_buffer.size() * 2;
				if (new_size > maximum_tracker_response_length) new_size = maximum_tracker_response_length;
				int old_size = (int)inflate_buffer.size();

				inflate_buffer.resize(new_size);
				str.next_out = reinterpret_cast<Bytef*>(&inflate_buffer[old_size]);
				str.avail_out = new_size - old_size;
			}

			ret = inflate(&str, Z_SYNC_FLUSH);
		}

		inflate_buffer.resize(inflate_buffer.size() - str.avail_out);
		inflateEnd(&str);

		if (ret != Z_STREAM_END)
		{
			requester->tracker_request_error(200, "gzip error");
			return true;
		}

		// commit the resulting buffer
		std::swap(buffer, inflate_buffer);
		return false;
	}

	std::string base64encode(const std::string& s)
	{
		static const char base64_table[] =
		{
			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
			'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
			'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
			'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
			'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
			'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
			'w', 'x', 'y', 'z', '0', '1', '2', '3',
			'4', '5', '6', '7', '8', '9', '+', '/'
		};

		unsigned char inbuf[3];
		unsigned char outbuf[4];

		std::string ret;
		for (std::string::const_iterator i = s.begin(); i != s.end();)
		{
			// available input is 1,2 or 3 bytes
			// since we read 3 bytes at a time at most
			int available_input = std::min(3, (int)std::distance(i, s.end()));

			// clear input buffer
			std::fill(inbuf, inbuf+3, 0);

			// read a chunk of input into inbuf
			for (int j = 0; j < available_input; ++j)
			{
				inbuf[j] = *i;
				++i;
			}

			// encode inbuf to outbuf
			outbuf[0] = (inbuf[0] & 0xfc) >> 2;
			outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf [1] & 0xf0) >> 4);
			outbuf[2] = ((inbuf[1] & 0x0f) << 2) | ((inbuf [2] & 0xc0) >> 6);
			outbuf[3] = inbuf[2] & 0x3f;

			// write output
			for (int j = 0; j < available_input+1; ++j)
			{
				ret += base64_table[outbuf[j]];
			}

			// write pad
			for (int j = 0; j < 3 - available_input; ++j)
			{
				ret += '=';
			}
		}
		return ret;
	}

	void tracker_manager::tick()
	{
		std::vector<boost::shared_ptr<tracker_connection> >::iterator i;
		for (i = m_connections.begin(); i != m_connections.end(); ++i)
		{
			boost::shared_ptr<tracker_connection>& c = *i;
			try
			{
				if (!c->tick()) continue;
			}
			catch (const std::exception& e)
			{
				if (c->requester())
					c->requester()->tracker_request_error(-1, e.what());
			}
			if (c->requester()) c->requester()->m_manager = 0;
			m_connections.erase(i);
			--i; // compensate for the remove
		}
	}

	void tracker_manager::queue_request(
		tracker_request const& req
		, request_callback* c
		, std::string const& password)
	{
		try
		{
			std::string hostname; // hostname only
			std::string protocol; // should be http
			int port = 80;

			// PARSE URL
			std::string::const_iterator start = req.url.begin();
			std::string::const_iterator end
				= std::find(req.url.begin(), req.url.end(), ':');
			protocol = std::string(start, end);

			if (end == req.url.end()) throw std::runtime_error("invalid url");
			++end;
			if (end == req.url.end()) throw std::runtime_error("invalid url");
			if (*end != '/') throw std::runtime_error("invalid url");
			++end;
			if (end == req.url.end()) throw std::runtime_error("invalid url");
			if (*end != '/') throw std::runtime_error("invalid url");
			++end;
			start = end;

			end = std::find(start, req.url.end(), '/');
			std::string::const_iterator port_pos
				= std::find(start, req.url.end(), ':');

			if (port_pos < end)
			{
				hostname.assign(start, port_pos);
				++port_pos;
				try
				{
					port = boost::lexical_cast<int>(std::string(port_pos, end));
				}
				catch(boost::bad_lexical_cast&)
				{
					throw std::runtime_error("invalid url");
				}
			}
			else
			{
				hostname.assign(start, end);
			}

			start = end;
			std::string request_string = std::string(start, req.url.end());

			boost::shared_ptr<tracker_connection> con;

			if (protocol == "http")
			{
				con.reset(new http_tracker_connection(
					req
					, hostname
					, port
					, request_string
					, c
					, m_settings
					, password));
			}
			else if (protocol == "udp")
			{
				con.reset(new udp_tracker_connection(
					req
					, hostname
					, port
					, c
					, m_settings));
			}
			else
			{
				throw std::runtime_error("unkown protocol in tracker url");
			}

			m_connections.push_back(con);

			if (con->requester()) con->requester()->m_manager = this;
		}
		catch (std::exception& e)
		{
			if (c) c->tracker_request_error(-1, e.what());
		}
	}

	void tracker_manager::abort_request(request_callback* c)
	{
		assert(c != 0);
		std::vector<boost::shared_ptr<tracker_connection> >::iterator i;
		for (i = m_connections.begin(); i != m_connections.end(); ++i)
		{
			if ((*i)->requester() == c)
			{
				m_connections.erase(i);
				break;
			}
		}
	}

	void tracker_manager::abort_all_requests()
	{
		// removes all connections from m_connections
		// except those with a requester == 0 (since those are
		// 'event=stopped'-requests)

		std::vector<boost::shared_ptr<tracker_connection> > keep_connections;

		for (std::vector<boost::shared_ptr<tracker_connection> >::const_iterator i =
				m_connections.begin();
			i != m_connections.end();
			++i)
		{
			if ((*i)->requester() == 0) keep_connections.push_back(*i);
		}

		std::swap(m_connections, keep_connections);
	}

	bool tracker_manager::send_finished() const
	{
		for (std::vector<boost::shared_ptr<tracker_connection> >::const_iterator i =
				m_connections.begin();
			i != m_connections.end();
			++i)
		{
			if (!(*i)->send_finished()) return false;
		}
		return true;
	}

}
<|endoftext|>