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

#include "rpcserver.h"
#include "rpcclient.h"

#include "base58.h"
#include "wallet.h"

#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>

using namespace std;
using namespace json_spirit;

extern Array createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL);
extern Value CallRPC(string args);

extern CWallet* pwalletMain;

BOOST_AUTO_TEST_SUITE(rpc_wallet_tests)

BOOST_AUTO_TEST_CASE(rpc_addmultisig)
{
    LOCK(pwalletMain->cs_wallet);

    rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;

    // old, 65-byte-long:
    const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
    // new, compressed:
    const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";

    Value v;
    CBitcoinAddress address;
    BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
    address.SetString(v.get_str());
    BOOST_CHECK(address.IsValid() && address.IsScript());

    BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
    address.SetString(v.get_str());
    BOOST_CHECK(address.IsValid() && address.IsScript());

    BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
    address.SetString(v.get_str());
    BOOST_CHECK(address.IsValid() && address.IsScript());

    BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
    BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
    BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);

    BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
    BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);

    string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing
    BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);

    string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing
    BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
}

BOOST_AUTO_TEST_CASE(rpc_wallet)
{
    // Test RPC calls for various wallet statistics
    Value r;

    LOCK2(cs_main, pwalletMain->cs_wallet);

    CPubKey demoPubkey = pwalletMain->GenerateNewKey();
	CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
	Value retValue;
	string strAccount = "walletDemoAccount";
	string strPurpose = "receive";
	BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
		CWalletDB walletdb(pwalletMain->strWalletFile);
		CAccount account;
		account.vchPubKey = demoPubkey;
		pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose);
		walletdb.WriteAccount(strAccount, account);
	});

	/*********************************
	 * 			setaccount
	 *********************************/
	BOOST_CHECK_NO_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount"));
	BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
	/* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */
	BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error);

    /*********************************
     * 			listunspent
     *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
    BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
    BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
    BOOST_CHECK(r.get_array().empty());

    /*********************************
	 * 		listreceivedbyaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);

    /*********************************
	 * 		listreceivedbyaccount
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);

    /*********************************
	 * 		getrawchangeaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress"));

    /*********************************
	 * 		getnewaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("getnewaddress"));
    BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount"));

    /*********************************
	 * 		getaccountaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\""));
	BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account
	BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
	BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get());

	/*********************************
	 * 			getaccount
	 *********************************/
	BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error);
	BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString()));

	/*********************************
	 * 	signmessage + verifymessage
	 *********************************/
	BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage"));
	BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error);
	/* Should throw error because this address is not loaded in the wallet */
	BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error);

	/* missing arguments */
	BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString()), runtime_error);
	BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str()), runtime_error);
	/* Illegal address */
	BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error);
	/* wrong address */
	BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false);
	/* Correct address and signature but wrong message */
	BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
	/* Correct address, message and signature*/
	BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true);

	/*********************************
	 * 		getaddressesbyaccount
	 *********************************/
	BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error);
	BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
	Array arr = retValue.get_array();
	BOOST_CHECK(arr.size() > 0);
	BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get());

}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Replaced test addresses with Dogecoin/Dogecoin-like addresses.<commit_after>// Copyright (c) 2013-2014 The Bitcoin Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "rpcserver.h"
#include "rpcclient.h"

#include "base58.h"
#include "wallet.h"

#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>

using namespace std;
using namespace json_spirit;

extern Array createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL);
extern Value CallRPC(string args);

extern CWallet* pwalletMain;

BOOST_AUTO_TEST_SUITE(rpc_wallet_tests)

BOOST_AUTO_TEST_CASE(rpc_addmultisig)
{
    LOCK(pwalletMain->cs_wallet);

    rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;

    // old, 65-byte-long:
    const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
    // new, compressed:
    const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";

    Value v;
    CBitcoinAddress address;
    BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
    address.SetString(v.get_str());
    BOOST_CHECK(address.IsValid() && address.IsScript());

    BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
    address.SetString(v.get_str());
    BOOST_CHECK(address.IsValid() && address.IsScript());

    BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
    address.SetString(v.get_str());
    BOOST_CHECK(address.IsValid() && address.IsScript());

    BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
    BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
    BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);

    BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
    BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);

    string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing
    BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);

    string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing
    BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
}

BOOST_AUTO_TEST_CASE(rpc_wallet)
{
    // Test RPC calls for various wallet statistics
    Value r;

    LOCK2(cs_main, pwalletMain->cs_wallet);

    CPubKey demoPubkey = pwalletMain->GenerateNewKey();
	CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
	Value retValue;
	string strAccount = "walletDemoAccount";
	string strPurpose = "receive";
	BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
		CWalletDB walletdb(pwalletMain->strWalletFile);
		CAccount account;
		account.vchPubKey = demoPubkey;
		pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose);
		walletdb.WriteAccount(strAccount, account);
	});

	/*********************************
	 * 			setaccount
	 *********************************/
	BOOST_CHECK_NO_THROW(CallRPC("setaccount DJ7zB7c5BsB9UJLy1rKQtY7c6CQfGiaRLM nullaccount"));
	BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
	/* DJ7zB7c5BsB9UJLy1rKQtY7c6CQfGiaRL (33 chars) is an illegal address (should be 34 chars) */
	BOOST_CHECK_THROW(CallRPC("setaccount DJ7zB7c5BsB9UJLy1rKQtY7c6CQfGiaRL nullaccount"), runtime_error);

    /*********************************
     * 			listunspent
     *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
    BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
    BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
    BOOST_CHECK(r.get_array().empty());

    /*********************************
	 * 		listreceivedbyaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);

    /*********************************
	 * 		listreceivedbyaccount
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
    BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
    BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);

    /*********************************
	 * 		getrawchangeaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress"));

    /*********************************
	 * 		getnewaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("getnewaddress"));
    BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount"));

    /*********************************
	 * 		getaccountaddress
	 *********************************/
    BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\""));
	BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account
	BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
	BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get());

	/*********************************
	 * 			getaccount
	 *********************************/
	BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error);
	BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString()));

	/*********************************
	 * 	signmessage + verifymessage
	 *********************************/
	BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage"));
	BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error);
	/* Should throw error because this address is not loaded in the wallet */
	BOOST_CHECK_THROW(CallRPC("signmessage D6AyeHunfkVcarXvw4S4gjNT1rokp5KRK6 mymessage"), runtime_error);

	/* missing arguments */
	BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString()), runtime_error);
	BOOST_CHECK_THROW(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str()), runtime_error);
	/* Illegal address */
	BOOST_CHECK_THROW(CallRPC("verifymessage DJ7zB7c5BsB9UJLy1rKQtY7c6CQfGiaRL " + retValue.get_str() + " mymessage"), runtime_error);
	/* wrong address */
	BOOST_CHECK(CallRPC("verifymessage DJ7zB7c5BsB9UJLy1rKQtY7c6CQfGiaRLM " + retValue.get_str() + " mymessage").get_bool() == false);
	/* Correct address and signature but wrong message */
	BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
	/* Correct address, message and signature*/
	BOOST_CHECK(CallRPC("verifymessage "+ demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true);

	/*********************************
	 * 		getaddressesbyaccount
	 *********************************/
	BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error);
	BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
	Array arr = retValue.get_array();
	BOOST_CHECK(arr.size() > 0);
	BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get());

}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>
#include <Hord/Error.hpp>
#include <Hord/Driver.hpp>

#include <algorithm>

namespace Hord {

// class Driver implementation

#define HORD_SCOPE_CLASS_IDENT__ Driver

Hive& Driver::placehold_hive(String root) {
#define HORD_SCOPE_FUNC_IDENT__ placehold_hive
	if (root.empty()) {
		HORD_THROW_ERROR_SCOPED(
			ErrorCode::driver_hive_root_empty,
			"cannot placehold hive with empty root path"
		);
	} else if (
		m_hives.cend()!=std::find_if(m_hives.cbegin(), m_hives.cend(),
			[&root](Hive const& hive) -> bool {
				return 0==root.compare(hive.get_root());
			})
	) {
		HORD_THROW_ERROR_SCOPED_FQN(
			ErrorCode::driver_hive_root_shared,
			"cannot placehold hive with non-unique root path"
		);
	}
	m_hives.emplace_back(std::move(root));
	return m_hives.back();
#undef HORD_SCOPE_FUNC_IDENT__
}

#undef HORD_SCOPE_CLASS_IDENT__

} // namespace Hord
<commit_msg>Driver::placehold_hive: use FQN throw for first error.<commit_after>
#include <Hord/Error.hpp>
#include <Hord/Driver.hpp>

#include <algorithm>

namespace Hord {

// class Driver implementation

#define HORD_SCOPE_CLASS_IDENT__ Driver

Hive& Driver::placehold_hive(String root) {
#define HORD_SCOPE_FUNC_IDENT__ placehold_hive
	if (root.empty()) {
		HORD_THROW_ERROR_SCOPED_FQN(
			ErrorCode::driver_hive_root_empty,
			"cannot placehold hive with empty root path"
		);
	} else if (
		m_hives.cend()!=std::find_if(m_hives.cbegin(), m_hives.cend(),
			[&root](Hive const& hive) -> bool {
				return 0==root.compare(hive.get_root());
			})
	) {
		HORD_THROW_ERROR_SCOPED_FQN(
			ErrorCode::driver_hive_root_shared,
			"cannot placehold hive with non-unique root path"
		);
	}
	m_hives.emplace_back(std::move(root));
	return m_hives.back();
#undef HORD_SCOPE_FUNC_IDENT__
}

#undef HORD_SCOPE_CLASS_IDENT__

} // namespace Hord
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include "Formulas.h"

TEST(FormulasTest, hk_honor_at_level)
{
    EXPECT_EQ(acore::Honor::hk_honor_at_level(80), 124);
    EXPECT_EQ(acore::Honor::hk_honor_at_level(80, 2), 248);
    EXPECT_EQ(acore::Honor::hk_honor_at_level(80, 0.5), 62);
    EXPECT_EQ(acore::Honor::hk_honor_at_level(1), 2);
    EXPECT_EQ(acore::Honor::hk_honor_at_level(1, 10), 16);
    EXPECT_EQ(acore::Honor::hk_honor_at_level(2), 4);
    EXPECT_EQ(acore::Honor::hk_honor_at_level(3), 5);
}
<commit_msg>test(Formulas.h): GetGrayLevel, GetColorCode, GetZeroDifference (#3734)<commit_after>#include "gtest/gtest.h"
#include "Formulas.h"
#include "SharedDefines.h"

using namespace acore::Honor;
using namespace acore::XP;

TEST(FormulasTest, hk_honor_at_level)
{
    EXPECT_EQ(hk_honor_at_level(80), 124);
    EXPECT_EQ(hk_honor_at_level(80, 2), 248);
    EXPECT_EQ(hk_honor_at_level(80, 0.5), 62);
    EXPECT_EQ(hk_honor_at_level(1), 2);
    EXPECT_EQ(hk_honor_at_level(1, 10), 16);
    EXPECT_EQ(hk_honor_at_level(2), 4);
    EXPECT_EQ(hk_honor_at_level(3), 5);
}

TEST(FormulasTest, GetGrayLevel)
{
    EXPECT_EQ(GetGrayLevel(0), 0);
    EXPECT_EQ(GetGrayLevel(5), 0);
    EXPECT_EQ(GetGrayLevel(6), 1);
    EXPECT_EQ(GetGrayLevel(39), 31);
    EXPECT_EQ(GetGrayLevel(40), 31);
    EXPECT_EQ(GetGrayLevel(59), 47);
    EXPECT_EQ(GetGrayLevel(60), 51);
    EXPECT_EQ(GetGrayLevel(80), 71);
}

TEST(FormulasTest, GetColorCode)
{
    EXPECT_EQ(GetColorCode(60, 80), XP_RED);
    EXPECT_EQ(GetColorCode(60, 65), XP_RED);
    EXPECT_EQ(GetColorCode(60, 64), XP_ORANGE);
    EXPECT_EQ(GetColorCode(60, 63), XP_ORANGE);
    EXPECT_EQ(GetColorCode(60, 62), XP_YELLOW);
    EXPECT_EQ(GetColorCode(60, 58), XP_YELLOW);
    EXPECT_EQ(GetColorCode(60, 57), XP_GREEN);
    EXPECT_EQ(GetColorCode(60, 52), XP_GREEN);
    EXPECT_EQ(GetColorCode(60, 51), XP_GRAY);
    EXPECT_EQ(GetColorCode(60, 1), XP_GRAY);
}

TEST(FormulasTest, GetZeroDifference)
{
    EXPECT_EQ(GetZeroDifference(1), 5);
    EXPECT_EQ(GetZeroDifference(7), 5);
    EXPECT_EQ(GetZeroDifference(8), 6);
    EXPECT_EQ(GetZeroDifference(9), 6);
    EXPECT_EQ(GetZeroDifference(10), 7);
    EXPECT_EQ(GetZeroDifference(11), 7);
    EXPECT_EQ(GetZeroDifference(12), 8);
    EXPECT_EQ(GetZeroDifference(15), 8);
    EXPECT_EQ(GetZeroDifference(16), 9);
    EXPECT_EQ(GetZeroDifference(19), 9);
    EXPECT_EQ(GetZeroDifference(20), 11);
    EXPECT_EQ(GetZeroDifference(29), 11);
    EXPECT_EQ(GetZeroDifference(30), 12);
    EXPECT_EQ(GetZeroDifference(39), 12);
    EXPECT_EQ(GetZeroDifference(40), 13);
    EXPECT_EQ(GetZeroDifference(44), 13);
    EXPECT_EQ(GetZeroDifference(45), 14);
    EXPECT_EQ(GetZeroDifference(49), 14);
    EXPECT_EQ(GetZeroDifference(50), 15);
    EXPECT_EQ(GetZeroDifference(54), 15);
    EXPECT_EQ(GetZeroDifference(55), 16);
    EXPECT_EQ(GetZeroDifference(59), 16);
    EXPECT_EQ(GetZeroDifference(60), 17);
    EXPECT_EQ(GetZeroDifference(80), 17);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** This file is part of a Qt Solutions component.
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Solutions Commercial License Agreement provided
** with the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** Please note Third Party Software included with Qt Solutions may impose
** additional restrictions and it is the user's responsibility to ensure
** that they have met the licensing requirements of the GPL, LGPL, or Qt
** Solutions Commercial license and the relevant license of the Third
** Party Software they are using.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
****************************************************************************/

#include "qtlocalpeer.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QTime>

#if defined(Q_OS_WIN)
#include <QtCore/QLibrary>
#include <QtCore/qt_windows.h>
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
static PProcessIdToSessionId pProcessIdToSessionId = 0;
#endif
#if defined(Q_OS_UNIX)
#include <time.h>
#endif

namespace QtLP_Private {
#include "qtlockedfile.cpp"
#if defined(Q_OS_WIN)
#include "qtlockedfile_win.cpp"
#else
#include "qtlockedfile_unix.cpp"
#endif
}

const char* QtLocalPeer::ack = "ack";

QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
    : QObject(parent), id(appId)
{
    QString prefix = id;
    if (id.isEmpty()) {
        id = QCoreApplication::applicationFilePath();
#if defined(Q_OS_WIN)
        id = id.toLower();
#endif
        prefix = id.section(QLatin1Char('/'), -1);
    }
    prefix.remove(QRegExp("[^a-zA-Z]"));
    prefix.truncate(6);

    QByteArray idc = id.toUtf8();
    quint16 idNum = qChecksum(idc.constData(), idc.size());
    socketName = QLatin1String("qtsingleapp-") + prefix
                 + QLatin1Char('-') + QString::number(idNum, 16);

#if defined(Q_OS_WIN)
    if (!pProcessIdToSessionId) {
        QLibrary lib("kernel32");
        pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
    }
    if (pProcessIdToSessionId) {
        DWORD sessionId = 0;
        pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
        socketName += QLatin1Char('-') + QString::number(sessionId, 16);
    }
#else
    socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
#endif

    server = new QLocalServer(this);
    QString lockName = QDir(QDir::tempPath()).absolutePath()
                       + QLatin1Char('/') + socketName
                       + QLatin1String("-lockfile");
    lockFile.setFileName(lockName);
    lockFile.open(QIODevice::ReadWrite);
}

bool QtLocalPeer::isClient()
{
    if (lockFile.isLocked())
        return false;

    if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
        return true;

    bool res = server->listen(socketName);
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
    // ### Workaround
    if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
        QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
        res = server->listen(socketName);
    }
#endif
    if (!res)
        qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
    QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
    return false;
}

bool QtLocalPeer::sendMessage(const QString &message, int timeout)
{
    if (!isClient())
        return false;

    QLocalSocket socket;
    bool connOk = false;
    for(int i = 0; i < 2; i++) {
        // Try twice, in case the other instance is just starting up
        socket.connectToServer(socketName);
        connOk = socket.waitForConnected(timeout/2);
        if (connOk || i)
            break;
        int ms = 250;
#if defined(Q_OS_WIN)
        Sleep(DWORD(ms));
#else
        struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
        nanosleep(&ts, NULL);
#endif
    }
    if (!connOk)
        return false;

    QByteArray uMsg(message.toUtf8());
    QDataStream ds(&socket);
    ds.writeBytes(uMsg.constData(), uMsg.size());
    bool res = socket.waitForBytesWritten(timeout);
    res &= socket.waitForReadyRead(timeout);   // wait for ack
    res &= (socket.read(qstrlen(ack)) == ack);
    return res;
}

void QtLocalPeer::receiveConnection()
{
    QLocalSocket* socket = server->nextPendingConnection();
    if (!socket)
        return;

    while (socket->bytesAvailable() < (int)sizeof(quint32))
        socket->waitForReadyRead();
    QDataStream ds(socket);
    QByteArray uMsg;
    quint32 remaining;
    ds >> remaining;
    uMsg.resize(remaining);
    int got = 0;
    char* uMsgBuf = uMsg.data();
    do {
        got = ds.readRawData(uMsgBuf, remaining);
        remaining -= got;
        uMsgBuf += got;
    } while (remaining && got >= 0 && socket->waitForReadyRead(2000));
    if (got < 0) {
        qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString();
        delete socket;
        return;
    }
    QString message(QString::fromUtf8(uMsg));
    socket->write(ack, qstrlen(ack));
    socket->waitForBytesWritten(1000);
    delete socket;
    emit messageReceived(message); //### (might take a long time to return)
}
<commit_msg>Trying to fix build problems with gcc 4.7 on Linux (#132).<commit_after>/****************************************************************************
**
** This file is part of a Qt Solutions component.
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Solutions Commercial License Agreement provided
** with the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** Please note Third Party Software included with Qt Solutions may impose
** additional restrictions and it is the user's responsibility to ensure
** that they have met the licensing requirements of the GPL, LGPL, or Qt
** Solutions Commercial license and the relevant license of the Third
** Party Software they are using.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
****************************************************************************/

#include "qtlocalpeer.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QTime>

#if defined(Q_OS_WIN)
#include <QtCore/QLibrary>
#include <QtCore/qt_windows.h>
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
static PProcessIdToSessionId pProcessIdToSessionId = 0;
#endif
#if defined(Q_OS_UNIX)
#include <time.h>
#include <unistd.h>
#endif

namespace QtLP_Private {
#include "qtlockedfile.cpp"
#if defined(Q_OS_WIN)
#include "qtlockedfile_win.cpp"
#else
#include "qtlockedfile_unix.cpp"
#endif
}

const char* QtLocalPeer::ack = "ack";

QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
    : QObject(parent), id(appId)
{
    QString prefix = id;
    if (id.isEmpty()) {
        id = QCoreApplication::applicationFilePath();
#if defined(Q_OS_WIN)
        id = id.toLower();
#endif
        prefix = id.section(QLatin1Char('/'), -1);
    }
    prefix.remove(QRegExp("[^a-zA-Z]"));
    prefix.truncate(6);

    QByteArray idc = id.toUtf8();
    quint16 idNum = qChecksum(idc.constData(), idc.size());
    socketName = QLatin1String("qtsingleapp-") + prefix
                 + QLatin1Char('-') + QString::number(idNum, 16);

#if defined(Q_OS_WIN)
    if (!pProcessIdToSessionId) {
        QLibrary lib("kernel32");
        pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
    }
    if (pProcessIdToSessionId) {
        DWORD sessionId = 0;
        pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
        socketName += QLatin1Char('-') + QString::number(sessionId, 16);
    }
#else
    socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
#endif

    server = new QLocalServer(this);
    QString lockName = QDir(QDir::tempPath()).absolutePath()
                       + QLatin1Char('/') + socketName
                       + QLatin1String("-lockfile");
    lockFile.setFileName(lockName);
    lockFile.open(QIODevice::ReadWrite);
}

bool QtLocalPeer::isClient()
{
    if (lockFile.isLocked())
        return false;

    if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
        return true;

    bool res = server->listen(socketName);
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
    // ### Workaround
    if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
        QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
        res = server->listen(socketName);
    }
#endif
    if (!res)
        qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
    QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
    return false;
}

bool QtLocalPeer::sendMessage(const QString &message, int timeout)
{
    if (!isClient())
        return false;

    QLocalSocket socket;
    bool connOk = false;
    for(int i = 0; i < 2; i++) {
        // Try twice, in case the other instance is just starting up
        socket.connectToServer(socketName);
        connOk = socket.waitForConnected(timeout/2);
        if (connOk || i)
            break;
        int ms = 250;
#if defined(Q_OS_WIN)
        Sleep(DWORD(ms));
#else
        struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
        nanosleep(&ts, NULL);
#endif
    }
    if (!connOk)
        return false;

    QByteArray uMsg(message.toUtf8());
    QDataStream ds(&socket);
    ds.writeBytes(uMsg.constData(), uMsg.size());
    bool res = socket.waitForBytesWritten(timeout);
    if (res) {
        res &= socket.waitForReadyRead(timeout);   // wait for ack
        if (res) {
            res &= (socket.read(qstrlen(ack)) == ack);
        }
    }
    return res;
}

void QtLocalPeer::receiveConnection()
{
    QLocalSocket* socket = server->nextPendingConnection();
    if (!socket)
        return;

    while (socket->bytesAvailable() < (int)sizeof(quint32))
        socket->waitForReadyRead();
    QDataStream ds(socket);
    QByteArray uMsg;
    quint32 remaining;
    ds >> remaining;
    uMsg.resize(remaining);
    int got = 0;
    char* uMsgBuf = uMsg.data();
    do {
        got = ds.readRawData(uMsgBuf, remaining);
        remaining -= got;
        uMsgBuf += got;
    } while (remaining && got >= 0 && socket->waitForReadyRead(2000));
    if (got < 0) {
        qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString();
        delete socket;
        return;
    }
    QString message(QString::fromUtf8(uMsg));
    socket->write(ack, qstrlen(ack));
    socket->waitForBytesWritten(1000);
    delete socket;
    emit messageReceived(message); //### (might take a long time to return)
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>

#include "../simrank.hpp"

typedef SimRank<int, float> MeFiSimRank;

void read_favorites(MeFiSimRank &mfsr, const char *filename) {
	std::ifstream ifs(filename);
	std::string line;
	std::getline(ifs, line); // timestamp
	std::getline(ifs, line); // headers
	while (std::getline(ifs, line)) {
		// fave_id \t faver \t favee \t ...
		std::istringstream iss(line);
		int fave_id, faver, favee;
		iss >> fave_id >> faver >> favee;
		mfsr.add_edge(faver, favee);
	}
}

void print_statistics(MeFiSimRank &mfsr) {
	// Print SimRank parameters
	std::cout << "SimRank: K = " << mfsr.K() << ", C = " << mfsr.C() << ", D = " << mfsr.D() << std::endl;

	// Print user-related totals
	std::cout << mfsr.num_nodes() << " total users" << std::endl;
	std::cout << mfsr.num_heads() << " users are favers" << std::endl;
	std::cout << mfsr.num_tails() << " users are favees" << std::endl;

	// Calculate favorite-related totals
	size_t num_pairs = 0;
	size_t total_favorites = 0;
	size_t max_favorites = 0; int max_faves_faver = 0, max_faves_favee = 0;
	std::map<size_t, size_t> favorites_histogram;
	for (auto edge : mfsr.edges()) {
		num_pairs++;
		size_t pair_favorites = (size_t)edge.weight;
		total_favorites += pair_favorites;
		if (pair_favorites > max_favorites) {
			max_favorites = pair_favorites;
			max_faves_faver = edge.head;
			max_faves_favee = edge.tail;
		}
		favorites_histogram[pair_favorites]++;
	}
	// Print favorite-related totals
	std::cout << total_favorites << " total favorites" << std::endl;
	std::cout << num_pairs << " unique faver-favee pairs" << std::endl;

	// Print statistical averages
	std::cout << "average " << (total_favorites / mfsr.num_heads()) << " favorites given per user" << std::endl;
	std::cout << "average " << (total_favorites / mfsr.num_tails()) << " favorites received per user" << std::endl;
	std::cout << "average " << (total_favorites / num_pairs) << " favorites per faver-favee pair" << std::endl;

	// Calculate statistical maxima
	size_t max_faves_given = 0; int max_faves_given_user = 0;
	size_t max_faves_received = 0; int max_faves_received_user = 0;
	size_t max_favee_count = 0; int max_favee_count_user = 0;
	size_t max_faver_count = 0; int max_faver_count_user = 0;
	std::map<size_t, size_t> favers_histogram, favees_histogram;
	for (int user : mfsr.nodes()) {
		size_t num_faves_given = (size_t)mfsr.out_degree(user);
		if (num_faves_given > max_faves_given) {
			max_faves_given = num_faves_given;
			max_faves_given_user = user;
		}
		favers_histogram[num_faves_given]++;

		size_t num_faves_received = (size_t)mfsr.in_degree(user);
		if (num_faves_received > max_faves_received) {
			max_faves_received = num_faves_received;
			max_faves_received_user = user;
		}
		favees_histogram[num_faves_received]++;

#pragma warning(disable: 4189) // '_': local variable is initialized but not referenced
		size_t num_favee_count = 0;
		for (int _ : mfsr.out_neighbors(user)) { num_favee_count++; }
		if (num_favee_count > max_favee_count) {
			max_favee_count = num_favee_count;
			max_favee_count_user = user;
		}

		size_t num_faver_count = 0;
		for (int _ : mfsr.in_neighbors(user)) { num_faver_count++; }
		if (num_faver_count > max_faver_count) {
			max_faver_count = num_faver_count;
			max_faver_count_user = user;
		}
	}
	// Print maxima
	std::cout << "maximum " << max_faves_given << " favorites given by user #" << max_faves_given_user << std::endl;
	std::cout << "maximum " << max_faves_received << " favorites received by user #" << max_faves_received_user << std::endl;
	std::cout << "maximum " << max_favorites << " favorites given by user #" << max_faves_faver << " to user #" << max_faves_favee << std::endl;
	std::cout << "maximum " << max_favee_count << " favees for user #" << max_favee_count_user << std::endl;
	std::cout << "maximum " << max_faver_count << " favers of user #" << max_faver_count_user << std::endl;

	// Print histogram data
	// num favorites \t count givers (favers) \t count receivers (favees) \t count faver-favee pairs (connections)
	std::cout << std::endl;
	std::cout << "num_faves\tfaver_count\tfavee_count\tpair_count" << std::endl;
	size_t max_count = std::max(std::max(favers_histogram.rbegin()->first, favees_histogram.rbegin()->first), favorites_histogram.rbegin()->first);
	for (size_t n = 0; n <= max_count; n++) {
		size_t favers_count = favers_histogram[n];
		size_t favees_count = favees_histogram[n];
		size_t favorites_count = favorites_histogram[n];
		if (favers_count || favees_count || favorites_count) {
			std::cout << n << "\t" << favers_count << "\t" << favees_count << "\t" << favorites_count << std::endl;
		}
	}
}

int main(int argc, char *argv[]) {
	MeFiSimRank mefisimrank(6, 0.6f);
	const char *filename = argc > 1 ? argv[1] : "favoritesdata.txt";
	read_favorites(mefisimrank, filename);
	print_statistics(mefisimrank);
	// TODO: run SimRank on the significant subset of data
	return 0;
}
<commit_msg>Print connections with at least 5 favorites.<commit_after>#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <map>

#include "../simrank.hpp"

typedef SimRank<int, float> MeFiSimRank;

std::string timestamp;

void read_favorites(MeFiSimRank &mfsr, const char *filename) {
	std::ifstream ifs(filename);
	std::string line;
	std::getline(ifs, timestamp); // timestamp
	std::getline(ifs, line); // headers
	while (std::getline(ifs, line)) {
		// fave_id \t faver \t favee \t ...
		std::istringstream iss(line);
		int fave_id, faver, favee;
		iss >> fave_id >> faver >> favee;
		mfsr.add_edge(faver, favee);
	}
}

void print_statistics(MeFiSimRank &mfsr) {
	// Print timestamp
	std::cout << timestamp << std::endl;

	// Print user-related totals
	std::cout << mfsr.num_nodes() << " total users" << std::endl;
	std::cout << mfsr.num_heads() << " users are favers" << std::endl;
	std::cout << mfsr.num_tails() << " users are favees" << std::endl;

	// Calculate favorite-related totals
	size_t num_pairs = 0;
	size_t total_favorites = 0;
	size_t max_favorites = 0; int max_faves_faver = 0, max_faves_favee = 0;
	std::map<size_t, size_t> favorites_histogram;
	for (auto edge : mfsr.edges()) {
		num_pairs++;
		size_t pair_favorites = (size_t)edge.weight;
		total_favorites += pair_favorites;
		if (pair_favorites > max_favorites) {
			max_favorites = pair_favorites;
			max_faves_faver = edge.head;
			max_faves_favee = edge.tail;
		}
		favorites_histogram[pair_favorites]++;
	}
	// Print favorite-related totals
	std::cout << total_favorites << " total favorites" << std::endl;
	std::cout << num_pairs << " unique faver-favee pairs" << std::endl;

	// Print statistical averages
	std::cout << "average " << (total_favorites / mfsr.num_heads()) << " favorites given per user" << std::endl;
	std::cout << "average " << (total_favorites / mfsr.num_tails()) << " favorites received per user" << std::endl;
	std::cout << "average " << (total_favorites / num_pairs) << " favorites per faver-favee pair" << std::endl;

	// Calculate statistical maxima
	size_t max_faves_given = 0; int max_faves_given_user = 0;
	size_t max_faves_received = 0; int max_faves_received_user = 0;
	size_t max_favee_count = 0; int max_favee_count_user = 0;
	size_t max_faver_count = 0; int max_faver_count_user = 0;
	std::map<size_t, size_t> favers_histogram, favees_histogram;
	for (int user : mfsr.nodes()) {
		size_t num_faves_given = (size_t)mfsr.out_degree(user);
		if (num_faves_given > max_faves_given) {
			max_faves_given = num_faves_given;
			max_faves_given_user = user;
		}
		favers_histogram[num_faves_given]++;

		size_t num_faves_received = (size_t)mfsr.in_degree(user);
		if (num_faves_received > max_faves_received) {
			max_faves_received = num_faves_received;
			max_faves_received_user = user;
		}
		favees_histogram[num_faves_received]++;

#pragma warning(disable: 4189) // '_': local variable is initialized but not referenced
		size_t num_favee_count = 0;
		for (int _ : mfsr.out_neighbors(user)) { num_favee_count++; }
		if (num_favee_count > max_favee_count) {
			max_favee_count = num_favee_count;
			max_favee_count_user = user;
		}

		size_t num_faver_count = 0;
		for (int _ : mfsr.in_neighbors(user)) { num_faver_count++; }
		if (num_faver_count > max_faver_count) {
			max_faver_count = num_faver_count;
			max_faver_count_user = user;
		}
	}
	// Print maxima
	std::cout << "maximum " << max_faves_given << " favorites given by user #" << max_faves_given_user << std::endl;
	std::cout << "maximum " << max_faves_received << " favorites received by user #" << max_faves_received_user << std::endl;
	std::cout << "maximum " << max_favorites << " favorites given by user #" << max_faves_faver << " to user #" << max_faves_favee << std::endl;
	std::cout << "maximum " << max_favee_count << " favees for user #" << max_favee_count_user << std::endl;
	std::cout << "maximum " << max_faver_count << " favers of user #" << max_faver_count_user << std::endl;

	std::cout << std::endl;

	// Print histogram data
	// num favorites \t count givers (favers) \t count receivers (favees) \t count faver-favee pairs (connections)
	std::cout << "num_faves\tfaver_count\tfavee_count\tpair_count" << std::endl;
	size_t max_count = std::max(std::max(favers_histogram.rbegin()->first, favees_histogram.rbegin()->first), favorites_histogram.rbegin()->first);
	for (size_t n = 0; n <= max_count; n++) {
		size_t favers_count = favers_histogram[n];
		size_t favees_count = favees_histogram[n];
		size_t favorites_count = favorites_histogram[n];
		if (favers_count || favees_count || favorites_count) {
			std::cout << n << "\t" << favers_count << "\t" << favees_count << "\t" << favorites_count << std::endl;
		}
	}

	std::cout << std::endl;

	// Print connections with at least 5 favorites (fewer than 10% of the total)
	// faver \t favee \t count (instead of 1 favorite per line)
	std::cout << "faver\tfavee\tcount" << std::endl;
	for (auto edge : mfsr.edges()) {
		if (edge.weight > 4) {
			std::cout << edge.head << "\t" << edge.tail << "\t" << edge.weight << std::endl;
		}
	}

	std::cout << std::endl;
}

void run_simrank(MeFiSimRank &mfsr) {
	// Print SimRank parameters
	std::cout << "SimRank: K = " << mfsr.K() << ", C = " << mfsr.C() << ", D = " << mfsr.D() << std::endl;
	// TODO: run SimRank on the significant subset of data
}

int main(int argc, char *argv[]) {
	MeFiSimRank mefisimrank(6, 0.6f);
	const char *filename = argc > 1 ? argv[1] : "favoritesdata.txt";
	read_favorites(mefisimrank, filename);
	print_statistics(mefisimrank);
	run_simrank(mefisimrank);
	return 0;
}
<|endoftext|>


<commit_before>/* Copyright (C) 2013 Slawomir Cygan <slawomir.cygan@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "gtest/gtest.h"

#include <DGLGUI/dgladbinterface.h>

namespace {

namespace mock {

    class DGLAdbCookieMock: public DGLAdbCookie {
    public:
        DGLAdbCookieMock(std::shared_ptr<DGLAdbOutputFilter> filter):DGLAdbCookie(filter) {}
    private:
        virtual void process() override {

        }
    };

    class DGLAdbCookieFactoryMock: public DGLAdbCookieFactoryBase {
    private:
        virtual DGLAdbCookie* CreateCookie(const std::vector<std::string>& params,
            std::shared_ptr<DGLAdbOutputFilter> filter) override {
                return new DGLAdbCookieMock(/*m_adbPath, params*/ filter);
        }
    };
}

// The fixture for testing class Foo.
class AdbInterface : public ::testing::Test {
   protected:
    // You can remove any or all of the following functions if its body
    // is empty.

    AdbInterface() {
        // You can do set-up work for each test here.
    }

    virtual ~AdbInterface() {
        // You can do clean-up work that doesn't throw exceptions here.
    }

    // If the constructor and destructor are not enough for setting up
    // and cleaning up each test, you can define the following methods:

    virtual void SetUp() {
        // Code here will be called immediately after the constructor (right
        // before each test).
    }

    virtual void TearDown() {
        // Code here will be called immediately after each test (right
        // before the destructor).
    }

    // Objects declared here can be used by all tests in the test case for Foo.
};

// Smoke test all inputs of codegen has been parsed to functionList
TEST_F(AdbInterface, empty) {

}

}    // namespace
<commit_msg>UT compilation fix.<commit_after>/* Copyright (C) 2013 Slawomir Cygan <slawomir.cygan@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "gtest/gtest.h"

#include <DGLGUI/dgladbinterface.h>

namespace {

namespace mock {

    class DGLAdbCookieMock: public DGLAdbCookie {
    public:
        DGLAdbCookieMock(std::shared_ptr<DGLAdbOutputFilter> filter):DGLAdbCookie(nullptr, filter) {}
    private:
        virtual void process() override {

        }
    };

    class DGLAdbCookieFactoryMock: public DGLAdbCookieFactoryBase {
    private:
        virtual DGLAdbCookie* CreateCookie(const std::vector<std::string>& /*params*/,
            DGLAdbHandler* /*handler*/,
            std::shared_ptr<DGLAdbOutputFilter> filter) override {
                return new DGLAdbCookieMock(filter/*m_adbPath, params*/);
        }
    };
}

// The fixture for testing class Foo.
class AdbInterface : public ::testing::Test {
   protected:
    // You can remove any or all of the following functions if its body
    // is empty.

    AdbInterface() {
        // You can do set-up work for each test here.
    }

    virtual ~AdbInterface() {
        // You can do clean-up work that doesn't throw exceptions here.
    }

    // If the constructor and destructor are not enough for setting up
    // and cleaning up each test, you can define the following methods:

    virtual void SetUp() {
        // Code here will be called immediately after the constructor (right
        // before each test).
    }

    virtual void TearDown() {
        // Code here will be called immediately after each test (right
        // before the destructor).
    }

    // Objects declared here can be used by all tests in the test case for Foo.
};

// Smoke test all inputs of codegen has been parsed to functionList
TEST_F(AdbInterface, empty) {

}

}    // namespace
<|endoftext|>


<commit_before><commit_msg>i965: don't lower mod() in glsl ir<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/trace_processor_storage_impl.h"

#include "perfetto/base/logging.h"
#include "src/trace_processor/args_tracker.h"
#include "src/trace_processor/binder_tracker.h"
#include "src/trace_processor/clock_tracker.h"
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/forwarding_trace_parser.h"
#include "src/trace_processor/heap_profile_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
#include "src/trace_processor/importers/proto/android_probes_module.h"
#include "src/trace_processor/importers/proto/graphics_event_module.h"
#include "src/trace_processor/importers/proto/heap_graph_module.h"
#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
#include "src/trace_processor/importers/proto/system_probes_module.h"
#include "src/trace_processor/importers/proto/track_event_module.h"
#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/stack_profile_tracker.h"
#include "src/trace_processor/syscall_tracker.h"
#include "src/trace_processor/trace_blob_view.h"
#include "src/trace_processor/trace_sorter.h"
#include "src/trace_processor/track_tracker.h"
#include "src/trace_processor/vulkan_memory_tracker.h"

namespace perfetto {
namespace trace_processor {

TraceProcessorStorageImpl::TraceProcessorStorageImpl(const Config& cfg) {
  context_.config = cfg;
  context_.storage.reset(new TraceStorage());
  context_.track_tracker.reset(new TrackTracker(&context_));
  context_.args_tracker.reset(new ArgsTracker(&context_));
  context_.slice_tracker.reset(new SliceTracker(&context_));
  context_.event_tracker.reset(new EventTracker(&context_));
  context_.process_tracker.reset(new ProcessTracker(&context_));
#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
  context_.syscall_tracker.reset(new SyscallTracker(&context_));
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
  context_.clock_tracker.reset(new ClockTracker(&context_));
  context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
  context_.sched_tracker.reset(new SchedEventTracker(&context_));
  context_.systrace_parser.reset(new SystraceParser(&context_));
  context_.binder_tracker.reset(new BinderTracker(&context_));
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
  context_.vulkan_memory_tracker.reset(new VulkanMemoryTracker(&context_));
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
  context_.ftrace_module.reset(
      new ProtoImporterModule<FtraceModule>(&context_));
  context_.track_event_module.reset(
      new ProtoImporterModule<TrackEventModule>(&context_));
  context_.system_probes_module.reset(
      new ProtoImporterModule<SystemProbesModule>(&context_));
  context_.android_probes_module.reset(
      new ProtoImporterModule<AndroidProbesModule>(&context_));
  context_.heap_graph_module.reset(
      new ProtoImporterModule<HeapGraphModule>(&context_));
  context_.graphics_event_module.reset(
      new ProtoImporterModule<GraphicsEventModule>(&context_));
}

TraceProcessorStorageImpl::~TraceProcessorStorageImpl() {}

util::Status TraceProcessorStorageImpl::Parse(std::unique_ptr<uint8_t[]> data,
                                              size_t size) {
  if (size == 0)
    return util::OkStatus();
  if (unrecoverable_parse_error_)
    return util::ErrStatus(
        "Failed unrecoverably while parsing in a previous Parse call");
  if (!context_.chunk_reader)
    context_.chunk_reader.reset(new ForwardingTraceParser(&context_));

  auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
      stats::parse_trace_duration_ns);
  util::Status status = context_.chunk_reader->Parse(std::move(data), size);
  unrecoverable_parse_error_ |= !status.ok();
  return status;
}

void TraceProcessorStorageImpl::NotifyEndOfFile() {
  if (unrecoverable_parse_error_ || !context_.chunk_reader)
    return;

  if (context_.sorter)
    context_.sorter->ExtractEventsForced();
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
  context_.sched_tracker->FlushPendingEvents();
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
  context_.event_tracker->FlushPendingEvents();
  context_.slice_tracker->FlushPendingSlices();
}

}  // namespace trace_processor
}  // namespace perfetto
<commit_msg>processor: Actually propagate string pool size config to TraceStorage am: 0eccc52635 am: 1de4319841<commit_after>/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/trace_processor/trace_processor_storage_impl.h"

#include "perfetto/base/logging.h"
#include "src/trace_processor/args_tracker.h"
#include "src/trace_processor/binder_tracker.h"
#include "src/trace_processor/clock_tracker.h"
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/forwarding_trace_parser.h"
#include "src/trace_processor/heap_profile_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
#include "src/trace_processor/importers/proto/android_probes_module.h"
#include "src/trace_processor/importers/proto/graphics_event_module.h"
#include "src/trace_processor/importers/proto/heap_graph_module.h"
#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
#include "src/trace_processor/importers/proto/proto_importer_module.h"
#include "src/trace_processor/importers/proto/proto_trace_tokenizer.h"
#include "src/trace_processor/importers/proto/system_probes_module.h"
#include "src/trace_processor/importers/proto/track_event_module.h"
#include "src/trace_processor/importers/systrace/systrace_parser.h"
#include "src/trace_processor/importers/systrace/systrace_trace_parser.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/stack_profile_tracker.h"
#include "src/trace_processor/syscall_tracker.h"
#include "src/trace_processor/trace_blob_view.h"
#include "src/trace_processor/trace_sorter.h"
#include "src/trace_processor/track_tracker.h"
#include "src/trace_processor/vulkan_memory_tracker.h"

namespace perfetto {
namespace trace_processor {

TraceProcessorStorageImpl::TraceProcessorStorageImpl(const Config& cfg) {
  context_.config = cfg;
  context_.storage.reset(new TraceStorage(context_.config));
  context_.track_tracker.reset(new TrackTracker(&context_));
  context_.args_tracker.reset(new ArgsTracker(&context_));
  context_.slice_tracker.reset(new SliceTracker(&context_));
  context_.event_tracker.reset(new EventTracker(&context_));
  context_.process_tracker.reset(new ProcessTracker(&context_));
#if PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
  context_.syscall_tracker.reset(new SyscallTracker(&context_));
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_SYSCALLS)
  context_.clock_tracker.reset(new ClockTracker(&context_));
  context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
  context_.sched_tracker.reset(new SchedEventTracker(&context_));
  context_.systrace_parser.reset(new SystraceParser(&context_));
  context_.binder_tracker.reset(new BinderTracker(&context_));
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
#if PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
  context_.vulkan_memory_tracker.reset(new VulkanMemoryTracker(&context_));
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_GRAPHICS)
  context_.ftrace_module.reset(
      new ProtoImporterModule<FtraceModule>(&context_));
  context_.track_event_module.reset(
      new ProtoImporterModule<TrackEventModule>(&context_));
  context_.system_probes_module.reset(
      new ProtoImporterModule<SystemProbesModule>(&context_));
  context_.android_probes_module.reset(
      new ProtoImporterModule<AndroidProbesModule>(&context_));
  context_.heap_graph_module.reset(
      new ProtoImporterModule<HeapGraphModule>(&context_));
  context_.graphics_event_module.reset(
      new ProtoImporterModule<GraphicsEventModule>(&context_));
}

TraceProcessorStorageImpl::~TraceProcessorStorageImpl() {}

util::Status TraceProcessorStorageImpl::Parse(std::unique_ptr<uint8_t[]> data,
                                              size_t size) {
  if (size == 0)
    return util::OkStatus();
  if (unrecoverable_parse_error_)
    return util::ErrStatus(
        "Failed unrecoverably while parsing in a previous Parse call");
  if (!context_.chunk_reader)
    context_.chunk_reader.reset(new ForwardingTraceParser(&context_));

  auto scoped_trace = context_.storage->TraceExecutionTimeIntoStats(
      stats::parse_trace_duration_ns);
  util::Status status = context_.chunk_reader->Parse(std::move(data), size);
  unrecoverable_parse_error_ |= !status.ok();
  return status;
}

void TraceProcessorStorageImpl::NotifyEndOfFile() {
  if (unrecoverable_parse_error_ || !context_.chunk_reader)
    return;

  if (context_.sorter)
    context_.sorter->ExtractEventsForced();
#if PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
  context_.sched_tracker->FlushPendingEvents();
#endif  // PERFETTO_BUILDFLAG(PERFETTO_TP_FTRACE)
  context_.event_tracker->FlushPendingEvents();
  context_.slice_tracker->FlushPendingSlices();
}

}  // namespace trace_processor
}  // namespace perfetto
<|endoftext|>


<commit_before>// -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; c-file-offsets: ((innamespace . 0)); -*-
/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * 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 Nokia Corporation 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 <QDir>
#include <QFile>
#include <QRegExp>

#include "parser/layoutparser.h"

#include "keyboardloader.h"

namespace {

using namespace MaliitKeyboard;

const char *const languages_dir(MALIIT_PLUGINS_DATA_DIR "/languages");

TagKeyboardPtr get_tag_keyboard(const QString& id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.keyboard();
        }
    }

    return TagKeyboardPtr();
}

QStringList get_imports(const QString &id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.imports();
        }
    }

    return QStringList();

}

Keyboard get_keyboard(const TagKeyboardPtr& keyboard,
                      bool shifted = false,
                      int page = 0,
                      const QString &dead_label = "")
{
    Keyboard skeyboard;

    // FIXME: set style based on key count/style override.
    skeyboard.style_name = QString("keys33");
    const QChar dead_key((dead_label.size() == 1) ? dead_label[0] : QChar::Null);

    if (keyboard) {
        TagKeyboard::TagLayouts layouts(keyboard->layouts());

        if (not layouts.isEmpty()) {
            TagLayout::TagSections sections(layouts.first()->sections());
            // sections cannot be empty - parser does not allow that.
            TagSection::TagRows rows(sections[page % sections.size()]->rows());
            int row_num(0);

            Q_FOREACH (const TagRowPtr& row, rows) {
                TagRow::TagRowElements elements(row->elements());
                Q_FOREACH (const TagRowElementPtr& element, elements) {
                    if (element->element_type() == TagRowElement::Key) {
                        TagKeyPtr key(element.staticCast<TagKey>());
                        TagKey::TagBindings bindings(key->bindings());
                        Key skey;
                        KeyDescription skey_description;

                        skey_description.row = row_num;
                        skey_description.width = static_cast<KeyDescription::Width>(key->width());
                        skey_description.style = static_cast<KeyDescription::Style>(key->style());
                        skey_description.use_rtl_icon = key->rtl();

                        TagBindingPtr the_binding;

                        Q_FOREACH (const TagBindingPtr& binding, bindings) {
                            if (binding->shift() == shifted and not binding->alt()) {
                                the_binding = binding;
                                break;
                            }
                        }
                        if (not the_binding) {
                            the_binding = bindings.first();
                        }

                        KeyLabel label;
                        const int index(dead_key.isNull() ? -1 : the_binding->accents().indexOf(dead_key));

                        if (index < 0) {
                            label.setText(the_binding->label());
                        } else {
                            label.setText(the_binding->accented_labels()[index]);
                        }
                        if (the_binding->dead()) {
                            // TODO: document it.
                            skey.setAction(Key::ActionDead);
                        } else {
                            skey.setAction(static_cast<Key::Action>(the_binding->action()));
                        }
                        skey.setLabel(label);

                        skeyboard.keys.append(skey);
                        skeyboard.key_descriptions.append(skey_description);
                    }
                }
                ++row_num;
            }
        }
    }
    return skeyboard;
}

QPair<TagKeyPtr, TagBindingPtr> get_tag_key_and_binding(const TagKeyboardPtr &keyboard,
                                                        const QString &label)
{
    QPair<TagKeyPtr, TagBindingPtr> pair;

    if (keyboard) {
        TagKeyboard::TagLayouts layouts(keyboard->layouts());

        if (not layouts.isEmpty()) {
            // sections cannot be empty - parser does not allow that.
            TagSection::TagRows rows(layouts.first()->sections().first()->rows());

            Q_FOREACH (const TagRowPtr& row, rows) {
                TagRow::TagRowElements elements(row->elements());

                Q_FOREACH (const TagRowElementPtr& element, elements) {
                    if (element->element_type() == TagRowElement::Key) {
                        TagKeyPtr key(element.staticCast<TagKey>());
                        TagKey::TagBindings bindings(key->bindings());

                        Q_FOREACH (const TagBindingPtr& binding, bindings) {
                            if (binding->label() == label) {
                                pair.first = key;
                                pair.second = binding;
                                return pair;
                            }
                        }
                    }
                }
            }
        }
    }
    return pair;
}

}

namespace MaliitKeyboard {

class KeyboardLoaderPrivate
{
public:
    QString active_id;
    Keyboard keyboard;

    explicit KeyboardLoaderPrivate()
        : active_id()
    {}
};

KeyboardLoader::KeyboardLoader(QObject *parent)
    : QObject(parent)
    , d_ptr(new KeyboardLoaderPrivate)
{}

KeyboardLoader::~KeyboardLoader()
{}

QStringList KeyboardLoader::ids() const
{
    QStringList ids;
    QDir dir(languages_dir,
             "*.xml",
             QDir::Name | QDir::IgnoreCase,
             QDir::Files | QDir::NoSymLinks | QDir::Readable);

    if (dir.exists()) {
        QFileInfoList file_infos(dir.entryInfoList());

        Q_FOREACH (const QFileInfo& file_info, file_infos) {
            ids.append(file_info.baseName());
        }
    }
    return ids;
}

QString KeyboardLoader::activeId() const
{
    Q_D(const KeyboardLoader);
    return d->active_id;
}

void KeyboardLoader::setActiveId(const QString &id)
{
    Q_D(KeyboardLoader);

    if (d->active_id != id) {
        d->active_id = id;

        // FIXME: Emit only after parsing new keyboard.
        emit keyboardsChanged();
    }
}

QString KeyboardLoader::title(const QString &id) const
{
    TagKeyboardPtr keyboard(get_tag_keyboard(id));

    if (keyboard) {
        return keyboard->title();
    }
    return "invalid";
}

Keyboard KeyboardLoader::keyboard() const
{
    Q_D(const KeyboardLoader);
    TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));

    return get_keyboard(keyboard);
}

Keyboard KeyboardLoader::nextKeyboard() const
{
    Q_D(const KeyboardLoader);

    const QStringList all_ids(ids());

    if (all_ids.isEmpty()) {
        return Keyboard();
    }

    int next_index (all_ids.indexOf(d->active_id) + 1);

    if (next_index >= all_ids.size()) {
        next_index = 0;
    }

    TagKeyboardPtr keyboard(get_tag_keyboard(all_ids[next_index]));

    return get_keyboard(keyboard);
}

Keyboard KeyboardLoader::previousKeyboard() const
{
    Q_D(const KeyboardLoader);

    const QStringList all_ids(ids());

    if (all_ids.isEmpty()) {
        return Keyboard();
    }

    int previous_index (all_ids.indexOf(d->active_id) - 1);

    if (previous_index < 0) {
        previous_index = 0;
    }

    TagKeyboardPtr keyboard(get_tag_keyboard(all_ids[previous_index]));

    return get_keyboard(keyboard);
}

Keyboard KeyboardLoader::shiftedKeyboard() const
{
    Q_D(const KeyboardLoader);
    TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));

    return get_keyboard(keyboard, true);
}

Keyboard KeyboardLoader::symbolsKeyboard(int page) const
{
    Q_D(const KeyboardLoader);
    QStringList imports(get_imports(d->active_id));
    const QRegExp symbols_regexp("^(symbols.*).xml$");

    Q_FOREACH (const QString &import, imports) {
        if (symbols_regexp.exactMatch(import)) {
            TagKeyboardPtr keyboard(get_tag_keyboard(symbols_regexp.cap(1)));
            return get_keyboard(keyboard, false, page);
        }
    }

    return Keyboard();
}

Keyboard KeyboardLoader::deadKeyboard(const Key &dead) const
{
    Q_D(const KeyboardLoader);
    TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));

    // TODO: detect whether we want it shifted or not.
    return get_keyboard(keyboard, false, 0, dead.label().text());
}

Keyboard KeyboardLoader::extendedKeyboard(const Key &key) const
{
    Q_D(const KeyboardLoader);
    const TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));
    const QPair<TagKeyPtr, TagBindingPtr> pair(get_tag_key_and_binding(keyboard, key.label().text()));
    Keyboard skeyboard;

    if (pair.first and pair.second) {
        const QString extended_labels(pair.second->extended_labels());

        Q_FOREACH(const QChar &c, extended_labels) {
            Key skey;
            KeyDescription skey_description;
            KeyLabel label;

            label.setText(c);
            skey.setLabel(label);
            skey.setAction(static_cast<Key::Action>(pair.second->action()));
            skey_description.row = 0;
            skey_description.width = static_cast<KeyDescription::Width>(pair.first->width());
            skey_description.style = static_cast<KeyDescription::Style>(pair.first->style());
            skey_description.use_rtl_icon = pair.first->rtl();
            skeyboard.keys.append(skey);
            skeyboard.key_descriptions.append(skey_description);
        }
    }
    return skeyboard;
}

} // namespace MaliitKeyboard
<commit_msg>Fill spacer and icon information in key description<commit_after>// -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; c-file-offsets: ((innamespace . 0)); -*-
/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * 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 Nokia Corporation 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 <QDir>
#include <QFile>
#include <QRegExp>

#include "parser/layoutparser.h"

#include "keyboardloader.h"

namespace {

using namespace MaliitKeyboard;

const char *const languages_dir(MALIIT_PLUGINS_DATA_DIR "/languages");

TagKeyboardPtr get_tag_keyboard(const QString& id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.keyboard();
        }
    }

    return TagKeyboardPtr();
}

QStringList get_imports(const QString &id)
{
    QFile file (QString::fromLatin1(languages_dir) + "/" + id + ".xml");

    if (file.exists()) {
        file.open(QIODevice::ReadOnly);

        LayoutParser parser(&file);
        const bool result(parser.parse());

        file.close();
        if (result) {
            return parser.imports();
        }
    }

    return QStringList();

}

Keyboard get_keyboard(const TagKeyboardPtr& keyboard,
                      bool shifted = false,
                      int page = 0,
                      const QString &dead_label = "")
{
    Keyboard skeyboard;

    // FIXME: set style based on key count/style override.
    skeyboard.style_name = QString("keys33");
    const QChar dead_key((dead_label.size() == 1) ? dead_label[0] : QChar::Null);

    if (keyboard) {
        TagKeyboard::TagLayouts layouts(keyboard->layouts());

        if (not layouts.isEmpty()) {
            TagLayout::TagSections sections(layouts.first()->sections());
            // sections cannot be empty - parser does not allow that.
            TagSection::TagRows rows(sections[page % sections.size()]->rows());
            int row_num(0);

            Q_FOREACH (const TagRowPtr& row, rows) {
                TagRow::TagRowElements elements(row->elements());
                bool spacer_met(false);

                Q_FOREACH (const TagRowElementPtr& element, elements) {
                    if (element->element_type() == TagRowElement::Key) {
                        TagKeyPtr key(element.staticCast<TagKey>());
                        TagKey::TagBindings bindings(key->bindings());
                        TagBindingPtr the_binding;

                        Q_FOREACH (const TagBindingPtr& binding, bindings) {
                            if (binding->shift() == shifted and not binding->alt()) {
                                the_binding = binding;
                                break;
                            }
                        }
                        if (not the_binding) {
                            the_binding = bindings.first();
                        }

                        KeyLabel label;
                        const int index(dead_key.isNull() ? -1 : the_binding->accents().indexOf(dead_key));

                        if (index < 0) {
                            label.setText(the_binding->label());
                        } else {
                            label.setText(the_binding->accented_labels()[index]);
                        }

                        Key skey;

                        if (the_binding->dead()) {
                            // TODO: document it.
                            skey.setAction(Key::ActionDead);
                        } else {
                            skey.setAction(static_cast<Key::Action>(the_binding->action()));
                        }
                        skey.setLabel(label);
                        skeyboard.keys.append(skey);

                        KeyDescription skey_description;

                        skey_description.row = row_num;
                        skey_description.use_rtl_icon = key->rtl();
                        skey_description.left_spacer = spacer_met;
                        skey_description.right_spacer = false;
                        skey_description.style = static_cast<KeyDescription::Style>(key->style());
                        skey_description.width = static_cast<KeyDescription::Width>(key->width());
                        switch (skey.action()) {
                        case Key::ActionBackspace:
                            skey_description.icon = KeyDescription::BackspaceIcon;
                            break;
                        case Key::ActionReturn:
                            skey_description.icon = KeyDescription::ReturnIcon;
                            break;
                        case Key::ActionShift:
                            skey_description.icon = KeyDescription::ShiftIcon;
                            break;
                        default:
                            skey_description.icon = KeyDescription::NoIcon;
                            break;
                        }
                        skey_description.font_group = KeyDescription::NormalFontGroup;
                        skeyboard.key_descriptions.append(skey_description);
                        spacer_met = false;
                    } else { // spacer
                        if (not skeyboard.key_descriptions.isEmpty()) {
                            KeyDescription& previous_skey_description(skeyboard.key_descriptions.last());

                            if (previous_skey_description.row == row_num) {
                                previous_skey_description.right_spacer = true;
                            }
                        }
                        spacer_met = true;
                    }
                }
                ++row_num;
            }
        }
    }
    return skeyboard;
}

QPair<TagKeyPtr, TagBindingPtr> get_tag_key_and_binding(const TagKeyboardPtr &keyboard,
                                                        const QString &label)
{
    QPair<TagKeyPtr, TagBindingPtr> pair;

    if (keyboard) {
        TagKeyboard::TagLayouts layouts(keyboard->layouts());

        if (not layouts.isEmpty()) {
            // sections cannot be empty - parser does not allow that.
            TagSection::TagRows rows(layouts.first()->sections().first()->rows());

            Q_FOREACH (const TagRowPtr& row, rows) {
                TagRow::TagRowElements elements(row->elements());

                Q_FOREACH (const TagRowElementPtr& element, elements) {
                    if (element->element_type() == TagRowElement::Key) {
                        TagKeyPtr key(element.staticCast<TagKey>());
                        TagKey::TagBindings bindings(key->bindings());

                        Q_FOREACH (const TagBindingPtr& binding, bindings) {
                            if (binding->label() == label) {
                                pair.first = key;
                                pair.second = binding;
                                return pair;
                            }
                        }
                    }
                }
            }
        }
    }
    return pair;
}

}

namespace MaliitKeyboard {

class KeyboardLoaderPrivate
{
public:
    QString active_id;
    Keyboard keyboard;

    explicit KeyboardLoaderPrivate()
        : active_id()
    {}
};

KeyboardLoader::KeyboardLoader(QObject *parent)
    : QObject(parent)
    , d_ptr(new KeyboardLoaderPrivate)
{}

KeyboardLoader::~KeyboardLoader()
{}

QStringList KeyboardLoader::ids() const
{
    QStringList ids;
    QDir dir(languages_dir,
             "*.xml",
             QDir::Name | QDir::IgnoreCase,
             QDir::Files | QDir::NoSymLinks | QDir::Readable);

    if (dir.exists()) {
        QFileInfoList file_infos(dir.entryInfoList());

        Q_FOREACH (const QFileInfo& file_info, file_infos) {
            ids.append(file_info.baseName());
        }
    }
    return ids;
}

QString KeyboardLoader::activeId() const
{
    Q_D(const KeyboardLoader);
    return d->active_id;
}

void KeyboardLoader::setActiveId(const QString &id)
{
    Q_D(KeyboardLoader);

    if (d->active_id != id) {
        d->active_id = id;

        // FIXME: Emit only after parsing new keyboard.
        emit keyboardsChanged();
    }
}

QString KeyboardLoader::title(const QString &id) const
{
    TagKeyboardPtr keyboard(get_tag_keyboard(id));

    if (keyboard) {
        return keyboard->title();
    }
    return "invalid";
}

Keyboard KeyboardLoader::keyboard() const
{
    Q_D(const KeyboardLoader);
    TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));

    return get_keyboard(keyboard);
}

Keyboard KeyboardLoader::nextKeyboard() const
{
    Q_D(const KeyboardLoader);

    const QStringList all_ids(ids());

    if (all_ids.isEmpty()) {
        return Keyboard();
    }

    int next_index (all_ids.indexOf(d->active_id) + 1);

    if (next_index >= all_ids.size()) {
        next_index = 0;
    }

    TagKeyboardPtr keyboard(get_tag_keyboard(all_ids[next_index]));

    return get_keyboard(keyboard);
}

Keyboard KeyboardLoader::previousKeyboard() const
{
    Q_D(const KeyboardLoader);

    const QStringList all_ids(ids());

    if (all_ids.isEmpty()) {
        return Keyboard();
    }

    int previous_index (all_ids.indexOf(d->active_id) - 1);

    if (previous_index < 0) {
        previous_index = 0;
    }

    TagKeyboardPtr keyboard(get_tag_keyboard(all_ids[previous_index]));

    return get_keyboard(keyboard);
}

Keyboard KeyboardLoader::shiftedKeyboard() const
{
    Q_D(const KeyboardLoader);
    TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));

    return get_keyboard(keyboard, true);
}

Keyboard KeyboardLoader::symbolsKeyboard(int page) const
{
    Q_D(const KeyboardLoader);
    QStringList imports(get_imports(d->active_id));
    const QRegExp symbols_regexp("^(symbols.*).xml$");

    Q_FOREACH (const QString &import, imports) {
        if (symbols_regexp.exactMatch(import)) {
            TagKeyboardPtr keyboard(get_tag_keyboard(symbols_regexp.cap(1)));
            return get_keyboard(keyboard, false, page);
        }
    }

    return Keyboard();
}

Keyboard KeyboardLoader::deadKeyboard(const Key &dead) const
{
    Q_D(const KeyboardLoader);
    TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));

    // TODO: detect whether we want it shifted or not.
    return get_keyboard(keyboard, false, 0, dead.label().text());
}

Keyboard KeyboardLoader::extendedKeyboard(const Key &key) const
{
    Q_D(const KeyboardLoader);
    const TagKeyboardPtr keyboard(get_tag_keyboard(d->active_id));
    const QPair<TagKeyPtr, TagBindingPtr> pair(get_tag_key_and_binding(keyboard, key.label().text()));
    Keyboard skeyboard;

    if (pair.first and pair.second) {
        const QString extended_labels(pair.second->extended_labels());

        Q_FOREACH(const QChar &c, extended_labels) {
            Key skey;
            KeyDescription skey_description;
            KeyLabel label;

            label.setText(c);
            skey.setLabel(label);
            skey.setAction(static_cast<Key::Action>(pair.second->action()));
            skey_description.row = 0;
            skey_description.width = static_cast<KeyDescription::Width>(pair.first->width());
            skey_description.style = static_cast<KeyDescription::Style>(pair.first->style());
            skey_description.use_rtl_icon = pair.first->rtl();
            skeyboard.keys.append(skey);
            skeyboard.key_descriptions.append(skey_description);
        }
    }
    return skeyboard;
}

} // namespace MaliitKeyboard
<|endoftext|>