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

#include "txhistorydialog.h"
#include "ui_txhistorydialog.h"

#include "guiutil.h"
#include "optionsmodel.h"
#include "walletmodel.h"
#include "wallet.h"
#include "base58.h"
#include "ui_interface.h"

#include <boost/filesystem.hpp>

#include "leveldb/db.h"
#include "leveldb/write_batch.h"

// potentially overzealous includes here
#include "base58.h"
#include "rpcserver.h"
#include "init.h"
#include "util.h"
#include <fstream>
#include <algorithm>
#include <vector>
#include <utility>
#include <string>
#include <boost/assign/list_of.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
// end potentially overzealous includes

using namespace json_spirit;
#include "mastercore.h"
using namespace mastercore;

// potentially overzealous using here
using namespace std;
using namespace boost;
using namespace boost::assign;
using namespace leveldb;
// end potentially overzealous using

#include "mastercore_dex.h"
#include "mastercore_tx.h"
#include "mastercore_sp.h"
#include "mastercore_parse_string.h"

#include <QDateTime>
#include <QMessageBox>
#include <QScrollBar>
#include <QTextDocument>

#include "txlistdelegate.h"

TXHistoryDialog::TXHistoryDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::txHistoryDialog),
    model(0)
{
    ui->setupUi(this);
    this->model = model;
    ui->txHistoryLW->setItemDelegate(new TXListDelegate(ui->txHistoryLW));

    CWallet *wallet = pwalletMain;
    string sAddress = "";
    string addressParam = "";

    int64_t nCount = 10;
    int64_t nFrom = 0;
    int64_t nStartBlock = 0;
    int64_t nEndBlock = 999999;

    Array response; //prep an array to hold our output

    // rewrite to use original listtransactions methodology from core
    LOCK(wallet->cs_wallet);
    std::list<CAccountingEntry> acentries;
    CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*");

    // iterate backwards
    for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
    {
        CWalletTx *const pwtx = (*it).second.first;
        if (pwtx != 0)
        {
            uint256 hash = pwtx->GetHash();
            CTransaction wtx;
            uint256 blockHash = 0;
            if (!GetTransaction(hash, wtx, blockHash, true)) continue;
            // get the time of the tx
            int64_t nTime = pwtx->GetTxTime();
            // get the height of the transaction and check it's within the chosen parameters
            blockHash = pwtx->hashBlock;
            if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) continue;
            CBlockIndex* pBlockIndex = mapBlockIndex[blockHash];
            if (NULL == pBlockIndex) continue;
            int blockHeight = pBlockIndex->nHeight;
            if ((blockHeight < nStartBlock) || (blockHeight > nEndBlock)) continue; // ignore it if not within our range
            // check if the transaction exists in txlist, and if so is it correct type (21)
            if (p_txlistdb->exists(hash))
            {
                string statusText;
                unsigned int propertyId = 0;
                uint64_t amount = 0;
                string address;
                bool divisible = false;
                bool valid = false;
                string MPTxType;

                CMPTransaction mp_obj;
                int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj);
                if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity
                {
                    if (0<=mp_obj.step1())
                    {
                        MPTxType = mp_obj.getTypeString();
                        address = mp_obj.getSender();

                        int tmpblock=0;
                        uint32_t tmptype=0;
                        uint64_t amountNew=0;
                        valid=getValidMPTX(hash, &tmpblock, &tmptype, &amountNew);

                        if (0 == mp_obj.step2_Value())
                        {
                            propertyId = mp_obj.getProperty();
                            amount = mp_obj.getAmount();
                            divisible = isPropertyDivisible(propertyId);
                        }
                    }
                }
                QListWidgetItem *qItem = new QListWidgetItem();
                qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex()));
                string displayType = MPTxType;
                string displayAmount;
                string displayToken;
                string displayValid;
                string displayAddress = address;
                if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); }
                if (valid) { displayValid = "valid"; } else { displayValid = "invalid"; }
                if (propertyId < 3)
                {
                    if(propertyId == 1) { displayToken = " MSC"; }
                    if(propertyId == 2) { displayToken = " TMSC"; }
                }
                else
                {
                    string s = to_string(propertyId);
                    displayToken = " SPT#" + s;
                }
                string displayDirection = "out";
                QDateTime txTime;
                txTime.setTime_t(nTime);
                QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate);
                qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayType));
                qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount + " " + displayToken));
                qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayDirection));
                qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayAddress));
                qItem->setData(Qt::UserRole + 5, txTimeStr);
                qItem->setData(Qt::UserRole + 6, QString::fromStdString(displayValid));
                ui->txHistoryLW->addItem(qItem);
            }
        }
    }
            // don't burn time doing more work than we need to
//            if ((int)response.size() >= (nCount+nFrom)) break;
    // sort array here and cut on nFrom and nCount
//    if (nFrom > (int)response.size())
//        nFrom = response.size();
//    if ((nFrom + nCount) > (int)response.size())
//        nCount = response.size() - nFrom;
//    Array::iterator first = response.begin();
//    std::advance(first, nFrom);
//    Array::iterator last = response.begin();
//    std::advance(last, nFrom+nCount);

//    if (last != response.end()) response.erase(last, response.end());
//    if (first != response.begin()) response.erase(response.begin(), first);

//    std::reverse(response.begin(), response.end()); // return oldest to newest?
 //   return response;   // return response array for JSON serialization

}

void TXHistoryDialog::setModel(WalletModel *model)
{
    this->model = model;
    //connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh()));
}

<commit_msg>Fix decimals and direction<commit_after>// Copyright (c) 2011-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txhistorydialog.h"
#include "ui_txhistorydialog.h"

#include "guiutil.h"
#include "optionsmodel.h"
#include "walletmodel.h"
#include "wallet.h"
#include "base58.h"
#include "ui_interface.h"

#include <boost/filesystem.hpp>

#include "leveldb/db.h"
#include "leveldb/write_batch.h"

// potentially overzealous includes here
#include "base58.h"
#include "rpcserver.h"
#include "init.h"
#include "util.h"
#include <fstream>
#include <algorithm>
#include <vector>
#include <utility>
#include <string>
#include <boost/assign/list_of.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/find.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
// end potentially overzealous includes

using namespace json_spirit;
#include "mastercore.h"
using namespace mastercore;

// potentially overzealous using here
using namespace std;
using namespace boost;
using namespace boost::assign;
using namespace leveldb;
// end potentially overzealous using

#include "mastercore_dex.h"
#include "mastercore_tx.h"
#include "mastercore_sp.h"
#include "mastercore_parse_string.h"

#include <QDateTime>
#include <QMessageBox>
#include <QScrollBar>
#include <QTextDocument>

#include "txlistdelegate.h"

TXHistoryDialog::TXHistoryDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::txHistoryDialog),
    model(0)
{
    ui->setupUi(this);
    this->model = model;
    ui->txHistoryLW->setItemDelegate(new TXListDelegate(ui->txHistoryLW));

    CWallet *wallet = pwalletMain;
    string sAddress = "";
    string addressParam = "";

    int64_t nCount = 10;
    int64_t nFrom = 0;
    int64_t nStartBlock = 0;
    int64_t nEndBlock = 999999;

    Array response; //prep an array to hold our output

    // rewrite to use original listtransactions methodology from core
    LOCK(wallet->cs_wallet);
    std::list<CAccountingEntry> acentries;
    CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, "*");

    // iterate backwards
    for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
    {
        CWalletTx *const pwtx = (*it).second.first;
        if (pwtx != 0)
        {
            uint256 hash = pwtx->GetHash();
            CTransaction wtx;
            uint256 blockHash = 0;
            if (!GetTransaction(hash, wtx, blockHash, true)) continue;
            // get the time of the tx
            int64_t nTime = pwtx->GetTxTime();
            // get the height of the transaction and check it's within the chosen parameters
            blockHash = pwtx->hashBlock;
            if ((0 == blockHash) || (NULL == mapBlockIndex[blockHash])) continue;
            CBlockIndex* pBlockIndex = mapBlockIndex[blockHash];
            if (NULL == pBlockIndex) continue;
            int blockHeight = pBlockIndex->nHeight;
            if ((blockHeight < nStartBlock) || (blockHeight > nEndBlock)) continue; // ignore it if not within our range
            // check if the transaction exists in txlist, and if so is it correct type (21)
            if (p_txlistdb->exists(hash))
            {
                string statusText;
                unsigned int propertyId = 0;
                uint64_t amount = 0;
                string address;
                bool divisible = false;
                bool valid = false;
                string MPTxType;

                CMPTransaction mp_obj;
                int parseRC = parseTransaction(true, wtx, blockHeight, 0, &mp_obj);
                if (0 <= parseRC) //negative RC means no MP content/badly encoded TX, we shouldn't see this if TX in levelDB but check for sanity
                {
                    if (0<=mp_obj.step1())
                    {
                        MPTxType = mp_obj.getTypeString();
                        address = mp_obj.getSender();

                        int tmpblock=0;
                        uint32_t tmptype=0;
                        uint64_t amountNew=0;
                        valid=getValidMPTX(hash, &tmpblock, &tmptype, &amountNew);

                        if (0 == mp_obj.step2_Value())
                        {
                            propertyId = mp_obj.getProperty();
                            amount = mp_obj.getAmount();
                            divisible = isPropertyDivisible(propertyId);
                        }
                    }
                }
                QListWidgetItem *qItem = new QListWidgetItem();
                qItem->setData(Qt::DisplayRole, QString::fromStdString(hash.GetHex()));
                string displayType = MPTxType;
                string displayAmount;
                string displayToken;
                string displayValid;
                string displayAddress = address;
                if (divisible) { displayAmount = FormatDivisibleMP(amount); } else { displayAmount = FormatIndivisibleMP(amount); }
                // clean up trailing zeros - good for RPC not so much for UI
                displayAmount.erase ( displayAmount.find_last_not_of('0') + 1, std::string::npos );
                if (displayAmount.length() > 0) { std::string::iterator it = displayAmount.end() - 1; if (*it == '.') { displayAmount.erase(it); } } //get rid of trailing dot if non decimal
                if (valid) { displayValid = "valid"; } else { displayValid = "invalid"; }
                if (propertyId < 3)
                {
                    if(propertyId == 1) { displayToken = " MSC"; }
                    if(propertyId == 2) { displayToken = " TMSC"; }
                }
                else
                {
                    string s = to_string(propertyId);
                    displayToken = " SPT#" + s;
                }
                string displayDirection = "out";
                if (!IsMyAddress(displayAddress)) displayDirection = "in";
                QDateTime txTime;
                txTime.setTime_t(nTime);
                QString txTimeStr = txTime.toString(Qt::SystemLocaleShortDate);
                qItem->setData(Qt::UserRole + 1, QString::fromStdString(displayType));
                qItem->setData(Qt::UserRole + 2, QString::fromStdString(displayAmount + displayToken));
                qItem->setData(Qt::UserRole + 3, QString::fromStdString(displayDirection));
                qItem->setData(Qt::UserRole + 4, QString::fromStdString(displayAddress));
                qItem->setData(Qt::UserRole + 5, txTimeStr);
                qItem->setData(Qt::UserRole + 6, QString::fromStdString(displayValid));
                ui->txHistoryLW->addItem(qItem);
            }
        }
    }
            // don't burn time doing more work than we need to
//            if ((int)response.size() >= (nCount+nFrom)) break;
    // sort array here and cut on nFrom and nCount
//    if (nFrom > (int)response.size())
//        nFrom = response.size();
//    if ((nFrom + nCount) > (int)response.size())
//        nCount = response.size() - nFrom;
//    Array::iterator first = response.begin();
//    std::advance(first, nFrom);
//    Array::iterator last = response.begin();
//    std::advance(last, nFrom+nCount);

//    if (last != response.end()) response.erase(last, response.end());
//    if (first != response.begin()) response.erase(response.begin(), first);

//    std::reverse(response.begin(), response.end()); // return oldest to newest?
 //   return response;   // return response array for JSON serialization

}

void TXHistoryDialog::setModel(WalletModel *model)
{
    this->model = model;
    //connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(OrderRefresh()));
}

<|endoftext|>


<commit_before>#include <string.h>
#include "command.h"
#include "../CmdHandler.h"
#include "../option.h"
#include "../stringparse.h"

/* full name of the command */
CMDNAME("mod");
/* description of the command */
CMDDESCR("perform moderation actions");
/* command usage synopsis */
CMDUSAGE("$mod <-b|-t> [-l LEN] USER [REASON...]");

/* mod: perform moderation commands */
int CmdHandler::mod(char *out, struct command *c)
{
	char *s;
	const char *t;
	int action, lenflag;
	int64_t len;
	char reason[MAX_MSG];
	char name[RSN_BUF];

	int opt;
	static struct l_option long_opts[] = {
		{ "ban", NO_ARG, 'b' },
		{ "help", NO_ARG, 'h' },
		{ "length", REQ_ARG, 'l' },
		{ "timeout", NO_ARG, 't' },
		{ 0, 0, 0 }
	};

	opt_init();
	action = lenflag = 0;
	len = 300;
	while ((opt = l_getopt_long(c->argc, c->argv, "bl:t", long_opts))
			!= EOF) {
		switch (opt) {
		case 'b':
			if (action) {
				_sprintf(out, MAX_MSG, "%s: cannot both timeout"
						" and ban", c->argv[0]);
				return EXIT_FAILURE;
			}
			action = BAN;
			break;
		case 'h':
			HELPMSG(out, CMDNAME, CMDUSAGE, CMDDESCR);
			return EXIT_SUCCESS;
		case 'l':
			if (!parsenum(l_optarg, &len)) {
				_sprintf(out, MAX_MSG, "%s: invalid number: %s",
						c->argv[0], l_optarg);
				return EXIT_FAILURE;
			}
			if (len < 0) {
				_sprintf(out, MAX_MSG, "%s: length cannot be "
						"negative", c->argv[0]);
				return EXIT_FAILURE;
			}
			lenflag = 1;
			break;
		case 't':
			if (action) {
				_sprintf(out, MAX_MSG, "%s: cannot both timeout"
						" and ban", c->argv[0]);
				return EXIT_FAILURE;
			}
			action = TIMEOUT;
			break;
		case '?':
			_sprintf(out, MAX_MSG, "%s", l_opterr());
			return EXIT_FAILURE;
		default:
			return EXIT_FAILURE;
		}
	}

	if (!action || l_optind == c->argc) {
		USAGEMSG(out, CMDNAME, CMDUSAGE);
		return EXIT_FAILURE;
	}

	if (lenflag && action != TIMEOUT) {
		_sprintf(out, MAX_MSG, "%s: specifying length doesn't "
				"make sense for a ban", c->nick);
		return EXIT_FAILURE;
	}

	/* convert names to lower for lookup */
	s = name;
	t = m_name;
	while ((*s++ = tolower(*t++)))
		;
	for (s = c->argv[l_optind]; *s; ++s)
		*s = tolower(*s);

	if (strcmp(c->argv[l_optind], name) == 0) {
		_sprintf(out, MAX_MSG, "@%s, I'd rather not.", c->nick);
		return EXIT_SUCCESS;
	}
	if (strcmp(c->argv[l_optind], c->nick) == 0) {
		_sprintf(out, MAX_MSG, "@%s, don't be silly!", c->nick);
		return EXIT_SUCCESS;
	}

	argvcat(reason, c->argc, c->argv, l_optind + 1, 1);
	/* attempt to perform the moderation action */
	if (!m_modp->mod_action(action, c->argv[l_optind],
				c->nick, reason, len)) {
		_sprintf(out, MAX_MSG, "%s: user '%s' is not currently in the "
				"channel", c->argv[0], c->argv[l_optind]);
		return EXIT_FAILURE;
	}

	_sprintf(out, MAX_MSG, "@%s, user '%s' has been %s",
			c->nick, c->argv[l_optind],
			action == BAN ? "banned" : "timed out");
	if (*reason) {
		strcat(out, " for ");
		strcat(out, reason);
	}
	strcat(out, ".");
	return EXIT_SUCCESS;
}
<commit_msg>Privilege check for mod command<commit_after>#include <string.h>
#include "command.h"
#include "../CmdHandler.h"
#include "../option.h"
#include "../stringparse.h"

/* full name of the command */
CMDNAME("mod");
/* description of the command */
CMDDESCR("perform moderation actions");
/* command usage synopsis */
CMDUSAGE("$mod <-b|-t> [-l LEN] USER [REASON...]");

/* mod: perform moderation commands */
int CmdHandler::mod(char *out, struct command *c)
{
	char *s;
	const char *t;
	int action, lenflag;
	int64_t len;
	char reason[MAX_MSG];
	char name[RSN_BUF];

	int opt;
	static struct l_option long_opts[] = {
		{ "ban", NO_ARG, 'b' },
		{ "help", NO_ARG, 'h' },
		{ "length", REQ_ARG, 'l' },
		{ "timeout", NO_ARG, 't' },
		{ 0, 0, 0 }
	};

	if (!P_ALMOD(c->privileges)) {
		PERM_DENIED(out, c->nick, c->argv[0]);
		return EXIT_FAILURE;
	}

	opt_init();
	action = lenflag = 0;
	len = 300;
	while ((opt = l_getopt_long(c->argc, c->argv, "bl:t", long_opts))
			!= EOF) {
		switch (opt) {
		case 'b':
			if (action) {
				_sprintf(out, MAX_MSG, "%s: cannot both timeout"
						" and ban", c->argv[0]);
				return EXIT_FAILURE;
			}
			action = BAN;
			break;
		case 'h':
			HELPMSG(out, CMDNAME, CMDUSAGE, CMDDESCR);
			return EXIT_SUCCESS;
		case 'l':
			if (!parsenum(l_optarg, &len)) {
				_sprintf(out, MAX_MSG, "%s: invalid number: %s",
						c->argv[0], l_optarg);
				return EXIT_FAILURE;
			}
			if (len < 0) {
				_sprintf(out, MAX_MSG, "%s: length cannot be "
						"negative", c->argv[0]);
				return EXIT_FAILURE;
			}
			lenflag = 1;
			break;
		case 't':
			if (action) {
				_sprintf(out, MAX_MSG, "%s: cannot both timeout"
						" and ban", c->argv[0]);
				return EXIT_FAILURE;
			}
			action = TIMEOUT;
			break;
		case '?':
			_sprintf(out, MAX_MSG, "%s", l_opterr());
			return EXIT_FAILURE;
		default:
			return EXIT_FAILURE;
		}
	}

	if (!action || l_optind == c->argc) {
		USAGEMSG(out, CMDNAME, CMDUSAGE);
		return EXIT_FAILURE;
	}

	if (lenflag && action != TIMEOUT) {
		_sprintf(out, MAX_MSG, "%s: specifying length doesn't "
				"make sense for a ban", c->nick);
		return EXIT_FAILURE;
	}

	/* convert names to lower for lookup */
	s = name;
	t = m_name;
	while ((*s++ = tolower(*t++)))
		;
	for (s = c->argv[l_optind]; *s; ++s)
		*s = tolower(*s);

	if (strcmp(c->argv[l_optind], name) == 0) {
		_sprintf(out, MAX_MSG, "@%s, I'd rather not.", c->nick);
		return EXIT_SUCCESS;
	}
	if (strcmp(c->argv[l_optind], c->nick) == 0) {
		_sprintf(out, MAX_MSG, "@%s, don't be silly!", c->nick);
		return EXIT_SUCCESS;
	}

	argvcat(reason, c->argc, c->argv, l_optind + 1, 1);
	/* attempt to perform the moderation action */
	if (!m_modp->mod_action(action, c->argv[l_optind],
				c->nick, reason, len)) {
		_sprintf(out, MAX_MSG, "%s: user '%s' is not currently in the "
				"channel", c->argv[0], c->argv[l_optind]);
		return EXIT_FAILURE;
	}

	_sprintf(out, MAX_MSG, "@%s, user '%s' has been %s",
			c->nick, c->argv[l_optind],
			action == BAN ? "banned" : "timed out");
	if (*reason) {
		strcat(out, " for ");
		strcat(out, reason);
	}
	strcat(out, ".");
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// Copyright 2012, Google Inc.
// 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 Google Inc. 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.
// -----------------------------------------------------------------------------
//
//
/// \file
/// Provides an interpreter for assigning primitives and Factory-constructible
/// objects to named variables, as well as vectors thereof.
/// \author dbikel@google.com (Dan Bikel)

#ifndef RERANKER_INTERPRETER_H_
#define RERANKER_INTERPRETER_H_

#include <iostream>
#include <fstream>
#include <string>
#include <tr1/unordered_map>
#include <tr1/unordered_set>

#include "environment-impl.H"

namespace reranker {

using std::iostream;
using std::ifstream;

class EnvironmentImpl;

/// Provides an interpreter for assigning primitives and
/// Factory-constructible objects to named variables, as well as
/// vectors thereof.  The interpreter maintains an internal
/// environment whereby previously defined variables may be used in
/// the definition of subsequent ones.
///
/// The syntax of this language extends the syntax
/// of the \link reranker::Factory Factory \endlink class, described
/// in the documentation of the \link reranker::Factory::CreateOrDie
/// Factory::CreateOrDie \endlink method.
///
/// Statements in this language look like the following:
/// \code
/// // This is a comment.
/// b = true;  // assigns the value true to the boolean variable named "b"
/// f = 1;     // assigns the int value 1 to the variable "f"
/// g = 2.4;   // assigns the double value 2.4 to the variable "g"
/// n = "foo"; // assigns the string value "foo" to the variable "n"
/// b_vec = {true, false, true};  // assigns a vector of bool to "b_vec"
///
/// // Constructs an object of abstract type Model and assigns it to "m1"
/// m1 = PerceptronModel(name("foo"));
///
/// // Constructs an object of type Model and assigns it to "m2", crucially
/// // using the previously defined string variable "n" as the value for
/// // the PerceptronModel's name parameter.
/// m2 = PerceptronModel(name(n));
///
/// // Constructs a vector of Model objects and assigns it to "m_vec".
/// m_vec = {m2, PerceptronModel(name("bar"))};
/// \endcode
///
/// More formally, a statement in this language must conform to the
/// following grammar, defined on top of the BNF syntax in the
/// documentation of the \link reranker::Factory::CreateOrDie
/// Factory::CreateOrDie \endlink method:
///

///

///   <tt>\<statement_list\></tt>
///   <tt>::=</tt>
///   <tt>[ \<statement\> ]*</tt>
///

///

///   <tt>\<statement\></tt>
///   <tt>::=</tt>
///   <tt>\<variable_name\> '=' \<value\> ';' </tt>
///

///

///   <tt>\<variable_name\></tt>
///   <tt>::=</tt>
///   any valid C++ identifier
///

///

///   <tt>\<value\></tt>
///   <tt>::=</tt>
///   <tt>\<literal\> | '{' \<literal_list\> '}' |

///                      \<spec\> | '{' \<spec_list\> '}'</tt>
///
///

///

///
/// The above grammar doesn’t contain rules covering C++ style
/// line comments, but they have the same behavior in this language as
/// they do in C++, i.e., everything after the <tt>//</tt> to the end
/// of the current line is treated as a comment and ignored.  There
/// are no C-style comments in this language.
class Interpreter {
 public:
  /// Constructs a new instance with the specified debug level.  The
  /// wrapped \link reranker::Environment Environment \endlink will
  /// also have the specified debug level.
  Interpreter(int debug = 0) : debug_(debug) {
    env_ = new EnvironmentImpl(debug);
  }

  /// Destroys this interpreter.
  virtual ~Interpreter() {
    delete env_;
  }

  /// Evaluates the statements in the specified text file.
  void Eval(const string &filename) {
    filename_ = filename;
    ifstream file(filename_.c_str());
    Eval(file);
  }

  /// Evaluates the statements in the specified string.
  void EvalString(const string& input) {
    StreamTokenizer st(input);
    Eval(st);
  }

  /// Evaluates the statements in the specified stream.
  void Eval(istream &is) {
    StreamTokenizer st(is);
    Eval(st);
  }

  void PrintEnv(ostream &os) const {
    env_->Print(os);
  }

  /// Retrieves the value of the specified variable.  It is an error
  /// if the type of the specified pointer to a value object is different
  /// from the specified variable in this interpreter’s environment.
  ///
  /// \tparam the type of value object being set by this method
  ///
  /// \param varname the name of the variable for which to retrieve the value
  /// \param value   a pointer to the object whose value to be set by this
  ///                method
  template<typename T>
  bool Get(const string &varname, T *value) const {
    return env_->Get(varname, value);
  }

  /// Returns a pointer to the environment of this interpreter.
  /// Crucially, this method returns a pointer to the Environment
  /// implementation class, \link reranker::EnvironmentImpl
  /// EnvironmentImpl\endlink, so that its templated \link
  /// reranker::EnvironmentImpl::Get EnvironmentImpl::Get \endlink
  /// method may be invoked.
  EnvironmentImpl *env() { return env_; }

 private:
  void Eval(StreamTokenizer &st);

  void WrongTokenError(size_t pos,
                       const string &expected,
                       const string &found,
                       StreamTokenizer::TokenType found_type) const;

  void WrongTokenTypeError(size_t pos,
                           StreamTokenizer::TokenType expected,
                           StreamTokenizer::TokenType found,
                           const string &token) const;

  /// The environment of this interpreter.
  EnvironmentImpl *env_;

  /// The name of the file being interpreted, or the empty string if there
  /// is no file associated with the stream being interpreted.
  string filename_;

  /// The debug level of this interpreter and its associated environment.
  int debug_;
};

}  // namespace reranker

#endif
<commit_msg>Another tiny edit to the documentation of the Interpreter class.<commit_after>// Copyright 2012, Google Inc.
// 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 Google Inc. 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.
// -----------------------------------------------------------------------------
//
//
/// \file
/// Provides an interpreter for assigning primitives and Factory-constructible
/// objects to named variables, as well as vectors thereof.
/// \author dbikel@google.com (Dan Bikel)

#ifndef RERANKER_INTERPRETER_H_
#define RERANKER_INTERPRETER_H_

#include <iostream>
#include <fstream>
#include <string>
#include <tr1/unordered_map>
#include <tr1/unordered_set>

#include "environment-impl.H"

namespace reranker {

using std::iostream;
using std::ifstream;

class EnvironmentImpl;

/// Provides an interpreter for assigning primitives and
/// Factory-constructible objects to named variables, as well as
/// vectors thereof.  The interpreter maintains an internal
/// environment whereby previously defined variables may be used in
/// the definition of subsequent ones.  The syntax of this language
/// extends the syntax of the \link reranker::Factory Factory \endlink
/// class, described in the documentation of the \link
/// reranker::Factory::CreateOrDie Factory::CreateOrDie \endlink
/// method.
///
/// Statements in this language look like the following:
/// \code
/// // This is a comment.
/// b = true;  // assigns the value true to the boolean variable named "b"
/// f = 1;     // assigns the int value 1 to the variable "f"
/// g = 2.4;   // assigns the double value 2.4 to the variable "g"
/// n = "foo"; // assigns the string value "foo" to the variable "n"
/// b_vec = {true, false, true};  // assigns a vector of bool to "b_vec"
///
/// // Constructs an object of abstract type Model and assigns it to "m1"
/// m1 = PerceptronModel(name("foo"));
///
/// // Constructs an object of type Model and assigns it to "m2", crucially
/// // using the previously defined string variable "n" as the value for
/// // the PerceptronModel's name parameter.
/// m2 = PerceptronModel(name(n));
///
/// // Constructs a vector of Model objects and assigns it to "m_vec".
/// m_vec = {m2, PerceptronModel(name("bar"))};
/// \endcode
///
/// More formally, a statement in this language must conform to the
/// following grammar, defined on top of the BNF syntax in the
/// documentation of the \link reranker::Factory::CreateOrDie
/// Factory::CreateOrDie \endlink method:
///

///

///   <tt>\<statement_list\></tt>
///   <tt>::=</tt>
///   <tt>[ \<statement\> ]*</tt>
///

///

///   <tt>\<statement\></tt>
///   <tt>::=</tt>
///   <tt>\<variable_name\> '=' \<value\> ';' </tt>
///

///

///   <tt>\<variable_name\></tt>
///   <tt>::=</tt>
///   any valid C++ identifier
///

///

///   <tt>\<value\></tt>
///   <tt>::=</tt>
///   <tt>\<literal\> | '{' \<literal_list\> '}' |

///                      \<spec\> | '{' \<spec_list\> '}'</tt>
///
///

///

///
/// The above grammar doesn’t contain rules covering C++ style
/// line comments, but they have the same behavior in this language as
/// they do in C++, i.e., everything after the <tt>//</tt> to the end
/// of the current line is treated as a comment and ignored.  There
/// are no C-style comments in this language.
class Interpreter {
 public:
  /// Constructs a new instance with the specified debug level.  The
  /// wrapped \link reranker::Environment Environment \endlink will
  /// also have the specified debug level.
  Interpreter(int debug = 0) : debug_(debug) {
    env_ = new EnvironmentImpl(debug);
  }

  /// Destroys this interpreter.
  virtual ~Interpreter() {
    delete env_;
  }

  /// Evaluates the statements in the specified text file.
  void Eval(const string &filename) {
    filename_ = filename;
    ifstream file(filename_.c_str());
    Eval(file);
  }

  /// Evaluates the statements in the specified string.
  void EvalString(const string& input) {
    StreamTokenizer st(input);
    Eval(st);
  }

  /// Evaluates the statements in the specified stream.
  void Eval(istream &is) {
    StreamTokenizer st(is);
    Eval(st);
  }

  void PrintEnv(ostream &os) const {
    env_->Print(os);
  }

  /// Retrieves the value of the specified variable.  It is an error
  /// if the type of the specified pointer to a value object is different
  /// from the specified variable in this interpreter’s environment.
  ///
  /// \tparam the type of value object being set by this method
  ///
  /// \param varname the name of the variable for which to retrieve the value
  /// \param value   a pointer to the object whose value to be set by this
  ///                method
  template<typename T>
  bool Get(const string &varname, T *value) const {
    return env_->Get(varname, value);
  }

  /// Returns a pointer to the environment of this interpreter.
  /// Crucially, this method returns a pointer to the Environment
  /// implementation class, \link reranker::EnvironmentImpl
  /// EnvironmentImpl\endlink, so that its templated \link
  /// reranker::EnvironmentImpl::Get EnvironmentImpl::Get \endlink
  /// method may be invoked.
  EnvironmentImpl *env() { return env_; }

 private:
  void Eval(StreamTokenizer &st);

  void WrongTokenError(size_t pos,
                       const string &expected,
                       const string &found,
                       StreamTokenizer::TokenType found_type) const;

  void WrongTokenTypeError(size_t pos,
                           StreamTokenizer::TokenType expected,
                           StreamTokenizer::TokenType found,
                           const string &token) const;

  /// The environment of this interpreter.
  EnvironmentImpl *env_;

  /// The name of the file being interpreted, or the empty string if there
  /// is no file associated with the stream being interpreted.
  string filename_;

  /// The debug level of this interpreter and its associated environment.
  int debug_;
};

}  // namespace reranker

#endif
<|endoftext|>


<commit_before>

#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING 1
#define ELPP_DEFAULT_LOG_FILE "logs/swgchat.log"

#include "easylogging++.h"

#include "StationChatApp.hpp"

#include <boost/program_options.hpp>

#include <chrono>
#include <fstream>
#include <iostream>
#include <thread>

#ifdef __GNUC__
#include <execinfo.h>
#endif

INITIALIZE_EASYLOGGINGPP

StationChatConfig BuildConfiguration(int argc, const char* argv[]);

#ifdef __GNUC__
void SignalHandler(int sig);
#endif

int main(int argc, const char* argv[]) {
#ifdef __GNUC__
    signal(SIGSEGV, SignalHandler);
#endif

    auto config = BuildConfiguration(argc, argv);

    el::Loggers::setDefaultConfigurations(config.loggerConfig, true);
    START_EASYLOGGINGPP(argc, argv);

    StationChatApp app{config};

    while (app.IsRunning()) {
        app.Tick();
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    return 0;
}

StationChatConfig BuildConfiguration(int argc, const char* argv[]) {
    namespace po = boost::program_options;
    StationChatConfig config;
    std::string configFile;

    // Declare a group of options that will be
    // allowed only on command line
    po::options_description generic("Generic options");
    generic.add_options()
        ("help,h", "produces help message")
        ("config,c", po::value<std::string>(&configFile)->default_value("etc/stationapi/swgchat.cfg"),
            "sets path to the configuration file")
        ("logger_config", po::value<std::string>(&config.loggerConfig)->default_value("etc/stationapi/logger.cfg"),
            "sets path to the logger configuration file")
        ;

    po::options_description options("Configuration");
    options.add_options()
        ("gateway_address", po::value<std::string>(&config.gatewayAddress)->default_value("127.0.0.1"),
            "address for gateway connections")
        ("gateway_port", po::value<uint16_t>(&config.gatewayPort)->default_value(5001),
            "port for gateway connections")
        ("registrar_address", po::value<std::string>(&config.registrarAddress)->default_value("127.0.0.1"),
            "address for registrar connections")
        ("registrar_port", po::value<uint16_t>(&config.registrarPort)->default_value(5000),
            "port for registrar connections")
        ("bind_to_ip", po::value<bool>(&config.bindToIp)->default_value(false),
            "when set to true, binds to the config address; otherwise, binds on any interface")
        ("database_path", po::value<std::string>(&config.chatDatabasePath)->default_value("var/stationapi/stationchat.db"),
            "path to the sqlite3 database file")
        ;

    po::options_description cmdline_options;
    cmdline_options.add(generic).add(options);

    po::options_description config_file_options;
    config_file_options.add(options);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(cmdline_options).allow_unregistered().run(), vm);
    po::notify(vm);

    std::ifstream ifs(configFile.c_str());
    if (!ifs) {
        throw std::runtime_error("Cannot open configuration file: " + configFile);
    }

    po::store(po::parse_config_file(ifs, config_file_options), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << cmdline_options << "\n";
        exit(EXIT_SUCCESS);
    }

    return config;
}

#ifdef __GNUC__
void SignalHandler(int sig) {
    const int BACKTRACE_LIMIT = 10;
    void *arr[BACKTRACE_LIMIT];
    auto size = backtrace(arr, BACKTRACE_LIMIT);

    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(arr, size, STDERR_FILENO);
    exit(1);
}
#endif
<commit_msg>Disable the default log file<commit_after>

#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING 1
#define ELPP_NO_DEFAULT_LOG_FILE

#include "easylogging++.h"

#include "StationChatApp.hpp"

#include <boost/program_options.hpp>

#include <chrono>
#include <fstream>
#include <iostream>
#include <thread>

#ifdef __GNUC__
#include <execinfo.h>
#endif

INITIALIZE_EASYLOGGINGPP

StationChatConfig BuildConfiguration(int argc, const char* argv[]);

#ifdef __GNUC__
void SignalHandler(int sig);
#endif

int main(int argc, const char* argv[]) {
#ifdef __GNUC__
    signal(SIGSEGV, SignalHandler);
#endif

    auto config = BuildConfiguration(argc, argv);

    el::Loggers::setDefaultConfigurations(config.loggerConfig, true);
    START_EASYLOGGINGPP(argc, argv);

    StationChatApp app{config};

    while (app.IsRunning()) {
        app.Tick();
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }

    return 0;
}

StationChatConfig BuildConfiguration(int argc, const char* argv[]) {
    namespace po = boost::program_options;
    StationChatConfig config;
    std::string configFile;

    // Declare a group of options that will be
    // allowed only on command line
    po::options_description generic("Generic options");
    generic.add_options()
        ("help,h", "produces help message")
        ("config,c", po::value<std::string>(&configFile)->default_value("etc/stationapi/swgchat.cfg"),
            "sets path to the configuration file")
        ("logger_config", po::value<std::string>(&config.loggerConfig)->default_value("etc/stationapi/logger.cfg"),
            "sets path to the logger configuration file")
        ;

    po::options_description options("Configuration");
    options.add_options()
        ("gateway_address", po::value<std::string>(&config.gatewayAddress)->default_value("127.0.0.1"),
            "address for gateway connections")
        ("gateway_port", po::value<uint16_t>(&config.gatewayPort)->default_value(5001),
            "port for gateway connections")
        ("registrar_address", po::value<std::string>(&config.registrarAddress)->default_value("127.0.0.1"),
            "address for registrar connections")
        ("registrar_port", po::value<uint16_t>(&config.registrarPort)->default_value(5000),
            "port for registrar connections")
        ("bind_to_ip", po::value<bool>(&config.bindToIp)->default_value(false),
            "when set to true, binds to the config address; otherwise, binds on any interface")
        ("database_path", po::value<std::string>(&config.chatDatabasePath)->default_value("var/stationapi/stationchat.db"),
            "path to the sqlite3 database file")
        ;

    po::options_description cmdline_options;
    cmdline_options.add(generic).add(options);

    po::options_description config_file_options;
    config_file_options.add(options);

    po::variables_map vm;
    po::store(po::command_line_parser(argc, argv).options(cmdline_options).allow_unregistered().run(), vm);
    po::notify(vm);

    std::ifstream ifs(configFile.c_str());
    if (!ifs) {
        throw std::runtime_error("Cannot open configuration file: " + configFile);
    }

    po::store(po::parse_config_file(ifs, config_file_options), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << cmdline_options << "\n";
        exit(EXIT_SUCCESS);
    }

    return config;
}

#ifdef __GNUC__
void SignalHandler(int sig) {
    const int BACKTRACE_LIMIT = 10;
    void *arr[BACKTRACE_LIMIT];
    auto size = backtrace(arr, BACKTRACE_LIMIT);

    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(arr, size, STDERR_FILENO);
    exit(1);
}
#endif
<|endoftext|>


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

#include <boost/test/unit_test.hpp>

#include "base58.h"
#include "key.h"
#include "uint256.h"
#include "util.h"
#include "test/test_bitcoin.h"

#include <string>
#include <vector>

struct TestDerivation {
    std::string pub;
    std::string prv;
    unsigned int nChild;
};

struct TestVector {
    std::string strHexMaster;
    std::vector<TestDerivation> vDerive;

    TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {}

    TestVector& operator()(std::string pub, std::string prv, unsigned int nChild) {
        vDerive.emplace_back();
        TestDerivation &der = vDerive.back();
        der.pub = pub;
        der.prv = prv;
        der.nChild = nChild;
        return *this;
    }
};

TestVector test1 =
  TestVector("000102030405060708090a0b0c0d0e0f")
    ("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
     "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
     0x80000000)
    ("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
     "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
     1)
    ("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
     "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
     0x80000002)
    ("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
     "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
     2)
    ("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV",
     "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
     1000000000)
    ("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy",
     "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
     0);

TestVector test2 =
  TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")
    ("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
     "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
     0)
    ("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH",
     "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
     0xFFFFFFFF)
    ("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
     "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
     1)
    ("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon",
     "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
     0xFFFFFFFE)
    ("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL",
     "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
     2)
    ("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt",
     "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
     0);

void RunTest(const TestVector &test) {
    std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
    CExtKey key;
    CExtPubKey pubkey;
    key.SetSeed(&seed[0], seed.size());
    pubkey = key.Neuter();
    for (const TestDerivation &derive : test.vDerive) {
        unsigned char data[74];
        key.Encode(data);
        pubkey.Encode(data);
        // Test private key
        CBitcoinExtKey b58key; b58key.SetKey(key);
        BOOST_CHECK(b58key.ToString() == derive.prv);

        CBitcoinExtKey b58keyDecodeCheck(derive.prv);
        CExtKey checkKey = b58keyDecodeCheck.GetKey();
        assert(checkKey == key); //ensure a base58 decoded key also matches

        // Test public key
        CBitcoinExtPubKey b58pubkey; b58pubkey.SetKey(pubkey);
        BOOST_CHECK(b58pubkey.ToString() == derive.pub);

        CBitcoinExtPubKey b58PubkeyDecodeCheck(derive.pub);
        CExtPubKey checkPubKey = b58PubkeyDecodeCheck.GetKey();
        assert(checkPubKey == pubkey); //ensure a base58 decoded pubkey also matches

        // Derive new keys
        CExtKey keyNew;
        BOOST_CHECK(key.Derive(keyNew, derive.nChild));
        CExtPubKey pubkeyNew = keyNew.Neuter();
        if (!(derive.nChild & 0x80000000)) {
            // Compare with public derivation
            CExtPubKey pubkeyNew2;
            BOOST_CHECK(pubkey.Derive(pubkeyNew2, derive.nChild));
            BOOST_CHECK(pubkeyNew == pubkeyNew2);
        }
        key = keyNew;
        pubkey = pubkeyNew;

        CDataStream ssPub(SER_DISK, CLIENT_VERSION);
        ssPub << pubkeyNew;
        BOOST_CHECK(ssPub.size() == 75);

        CDataStream ssPriv(SER_DISK, CLIENT_VERSION);
        ssPriv << keyNew;
        BOOST_CHECK(ssPriv.size() == 75);

        CExtPubKey pubCheck;
        CExtKey privCheck;
        ssPub >> pubCheck;
        ssPriv >> privCheck;

        BOOST_CHECK(pubCheck == pubkeyNew);
        BOOST_CHECK(privCheck == keyNew);
    }
}

BOOST_FIXTURE_TEST_SUITE(bip32_tests, BasicTestingSetup)

BOOST_AUTO_TEST_CASE(bip32_test1) {
    RunTest(test1);
}

BOOST_AUTO_TEST_CASE(bip32_test2) {
    RunTest(test2);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>bip32_tests updated to latest upstream changes.<commit_after>// Copyright (c) 2013 The Bitcoin Core developers
// Copyright (c) 2019-2020 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/test/unit_test.hpp>

#include "key.h"
#include "key_io.h"
#include "test/test_pivx.h"

#include <string>
#include <vector>

struct TestDerivation {
    std::string pub;
    std::string prv;
    unsigned int nChild;
};

struct TestVector {
    std::string strHexMaster;
    std::vector<TestDerivation> vDerive;

    TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {}

    TestVector& operator()(std::string pub, std::string prv, unsigned int nChild) {
        vDerive.emplace_back();
        TestDerivation &der = vDerive.back();
        der.pub = pub;
        der.prv = prv;
        der.nChild = nChild;
        return *this;
    }
};

TestVector test1 =
  TestVector("000102030405060708090a0b0c0d0e0f")
    ("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
     "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
     0x80000000)
    ("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
     "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
     1)
    ("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
     "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
     0x80000002)
    ("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
     "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
     2)
    ("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV",
     "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
     1000000000)
    ("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy",
     "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
     0);

TestVector test2 =
  TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")
    ("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
     "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
     0)
    ("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH",
     "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
     0xFFFFFFFF)
    ("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
     "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
     1)
    ("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon",
     "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
     0xFFFFFFFE)
    ("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL",
     "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
     2)
    ("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt",
     "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
     0);

void RunTest(const TestVector &test) {
    std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
    CExtKey key;
    CExtPubKey pubkey;
    key.SetSeed(seed.data(), seed.size());
    pubkey = key.Neuter();
    for (const TestDerivation &derive : test.vDerive) {
        unsigned char data[74];
        key.Encode(data);
        pubkey.Encode(data);

        // Test private key
        BOOST_CHECK(KeyIO::EncodeExtKey(key) == derive.prv);
        BOOST_CHECK(KeyIO::DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches

        // Test public key
        BOOST_CHECK(KeyIO::EncodeExtPubKey(pubkey) == derive.pub);
        BOOST_CHECK(KeyIO::DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches

        // Derive new keys
        CExtKey keyNew;
        BOOST_CHECK(key.Derive(keyNew, derive.nChild));
        CExtPubKey pubkeyNew = keyNew.Neuter();
        if (!(derive.nChild & 0x80000000)) {
            // Compare with public derivation
            CExtPubKey pubkeyNew2;
            BOOST_CHECK(pubkey.Derive(pubkeyNew2, derive.nChild));
            BOOST_CHECK(pubkeyNew == pubkeyNew2);
        }
        key = keyNew;
        pubkey = pubkeyNew;
    }
}

BOOST_FIXTURE_TEST_SUITE(bip32_tests, TestingSetup)

BOOST_AUTO_TEST_CASE(bip32_test1) {
    RunTest(test1);
}

BOOST_AUTO_TEST_CASE(bip32_test2) {
    RunTest(test2);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "../common/init.h"
#include "../common/timer.h"

#include <iostream>
#include <vector>
#include <stdexcept>

#include "util/graphics/bitmap.h"
#include "util/font.h"
#include "util/debug.h"
#include "util/exceptions/load_exception.h"
#include "util/token_exception.h"
#include "util/input/input.h"
#include "util/input/input-manager.h"
#include "util/sound/sound.h"
#include "util/exceptions/exception.h"
#include "util/network/network.h"
#include "util/network/irc.h"
#include "util/thread.h"
#include "util/pointer.h"
#include "util/system.h"
#include "util/timedifference.h"
#include "util/configuration.h"

#include <queue>
#include <map>

static std::vector<std::string> split(std::string str, char splitter){
    std::vector<std::string> strings;
    size_t next = str.find(splitter);
    while (next != std::string::npos){
        strings.push_back(str.substr(0, next));
        str = str.substr(next+1);
        next = str.find(splitter);
    }
    if (str != ""){
        strings.push_back(str);
    }

    return strings;
}

static void setTrue(void * b){
    bool * what = (bool*) b;
    *what = true;
}

static void nextTab(void * i){
    ::Network::IRC::ChatInterface * interface = (::Network::IRC::ChatInterface *)i;
    interface->nextChannel();
}

static void previousTab(void * i){
    ::Network::IRC::ChatInterface * interface = (::Network::IRC::ChatInterface *)i;
    interface->previousChannel();
}

class Game{
public:
    Game(const std::string & name, bool host = true):
    name(name),
    host(host){
    }
    ~Game(){
    }

    void addClient(const std::string & name, const std::string & ip){
        clients[name] = ip;
    }

    std::string clientsAsString(){
        std::string clientlist;
        for (std::map<std::string, std::string>::iterator i = clients.begin(); i != clients.end(); i++){
            clientlist += (*i).first + ", ";
        }
        return clientlist.substr(0, clientlist.size() - 2);
    }

    void start(const std::string & hostip) {
        Global::debug(0) << "Game " << name << " is starting." << std::endl;
        Global::debug(0) << "Connecting to " << hostip << "...." << std::endl;
    }

    std::map<std::string, std::string> & getClients(){
        return clients;
    }

    const std::string & getName() const {
        return name;
    }

    bool isHost() const {
        return host;
    }

private:
    std::string name;
    bool host;
    std::map<std::string, std::string> clients;
};

class InputLogicDraw: public Util::Logic, public Util::Draw, public ::Network::IRC::Message::EventInterface {
public:
    InputLogicDraw(int port, const std::string & host, const std::string & username):
    chatInterface(host, port, username),
    escaped(false){
        ircClient = Util::ReferenceCount< ::Network::IRC::Client >(new ::Network::IRC::Client(host, port));
        chatInterface.getInputBox().addHook(Keyboard::Key_ESC, setTrue, &escaped);
        chatInterface.getInputBox().addHook(Keyboard::Key_TAB, nextTab, &chatInterface);
        chatInterface.subscribe(this);
        // Get IP
        chatInterface.getClient()->sendCommand(::Network::IRC::Command::Userhost, chatInterface.getClient()->getName());
    }

    ::Network::IRC::ChatInterface chatInterface;
    Util::ReferenceCount< ::Network::IRC::Client > ircClient;

    bool escaped;

    std::string ipAddress;
    Util::ReferenceCount<Game> game;
    std::map<std::string, std::string> hosts;

    void remoteCommand(const ::Network::IRC::Command & command){
        if (command.getType() == ::Network::IRC::Command::ReplyUserhost){
            const std::vector<std::string> & params = command.getParameters();
            const std::string & extract = params.at(1);
            for (unsigned int i = 0; i < extract.size(); i++){
                if (extract[i] == '@'){
                    ipAddress = extract.substr(++i, extract.size()-1);
                    Global::debug(0) << "Your IP Address is: " << ipAddress << std::endl;
                }
            }
        }
        if (command.hasCtcp()){
            const std::vector<std::string> & ctcp = command.getCtcp();
            if (command.getType() == ::Network::IRC::Command::PrivateMessage){
                try {
                    if (ctcp.at(0) == "game"){
                        const std::string & gameCommand = ctcp.at(1);
                        if (gameCommand == "invite"){
                            const std::string & gameName = ctcp.at(2);
                            const std::string & hostName = ctcp.at(3);
                            chatInterface.addMessageToTab("* " + hostName + " has invited you to join the game [" + gameName + "]. Type \"/game join " + gameName + "\".");
                            hosts[gameName] = hostName;
                        } else if (gameCommand == "join"){
                            if (game != NULL && game->isHost()){
                                const std::string & gameName = ctcp.at(2);
                                const std::string & clientName = ctcp.at(3);
                                const std::string & ip = ctcp.at(4);
                                chatInterface.addMessageToTab("* " + clientName + " has joined " + gameName + ".");
                                game->addClient(clientName, ip);
                            } else {
                                chatInterface.addMessageToTab("* received a join request with no game pending.");
                            }
                        } else if (gameCommand == "start"){
                            if (game != NULL && !game->isHost()){
                                const std::string & gameName = ctcp.at(2);
                                const std::string & serverIp = ctcp.at(3);
                                chatInterface.addMessageToTab("* Host has started game " + gameName);
                                game->start(serverIp);
                            }
                        }
                    } else {
                        Global::debug(0) << "Got ctcp: " << ctcp.at(0) << std::endl;
                    }
                } catch (const std::out_of_range & ex){
                }
            }
        }
    }

    void localCommand(const std::vector<std::string> & command){
        if (command.at(0) == "help"){
            chatInterface.addMessageToTab("* commands: lol, game");
        } else if (command.at(0) == "lol"){
            chatInterface.addMessageToTab("* You LOLOLOLOLLOLOLOL yourself.");
        } else if (command.at(0) == "game"){
            // Game
            if (command.size() > 1){
                if (command.at(1) == "help"){
                    chatInterface.addMessageToTab("* game commands: help, new, start, list-users, list-hosts, invite, join.");
                } else if (command.at(1) == "new"){
                    try{
                        game = Util::ReferenceCount<Game>(new Game(command.at(2)));
                        chatInterface.addMessageToTab("* game \"" + command.at(2) + "\" created.");
                    } catch (const std::out_of_range & ex){
                        chatInterface.addMessageToTab("* /game new [name]");
                    }
                } else if (command.at(1) == "start"){
                    if (game != NULL && game->isHost()){
                        chatInterface.addMessageToTab("* Starting game " + game->getName());
                        for (std::map<std::string, std::string>::iterator i = game->getClients().begin(); i != game->getClients().end(); i++){
                            chatInterface.getClient()->sendCommand(::Network::IRC::Command::PrivateMessage,
                                                                    (*i).first,
                                                                    ":\001game start " + game->getName() + " " + ipAddress + "\001");
                        }
                    } else {
                        chatInterface.addMessageToTab("* Create a game first...");
                    }
                } else if (command.at(1) == "list-users"){
                    if (game != NULL){
                        chatInterface.addMessageToTab("* Users who accepted game request: " + game->clientsAsString());
                    } else {
                        chatInterface.addMessageToTab("* Create a game first...");
                    }
                } else if (command.at(1) == "list-hosts"){
                    if (!hosts.empty()){
                        std::string hostlist;
                        for (std::map<std::string, std::string>::iterator i = hosts.begin(); i != hosts.end(); i++){
                            hostlist += (*i).first + +" [" + (*i).second + "], ";
                        }
                        chatInterface.addMessageToTab("* Hosts and games you've been invited to: " + hostlist.substr(0, hostlist.size() - 2));
                    } else {
                        chatInterface.addMessageToTab("* You have no invites.");
                    }
                } else if (command.at(1) == "invite"){
                    if (game != NULL){
                        try {
                            chatInterface.addMessageToTab("* Sending request to " + command.at(2));
                            chatInterface.getClient()->sendCommand(::Network::IRC::Command::PrivateMessage,
                                                            command.at(2),
                                                            ":\001game invite " + game->getName() + " " + chatInterface.getClient()->getName() + "\001");
                        } catch (const std::out_of_range & ex){
                            chatInterface.addMessageToTab("* /game invite [username]");
                        }
                    } else {
                        chatInterface.addMessageToTab("* Create a game first...");
                    }
                } else if (command.at(1) == "join"){
                    if (!hosts.empty()){
                        try {
                            const std::string & gameName = command.at(2);
                            const std::string & hostName = hosts[gameName];
                            chatInterface.addMessageToTab("* Joining game at " + gameName);
                            chatInterface.getClient()->sendCommand(::Network::IRC::Command::PrivateMessage,
                                                            hostName,
                                                            ":\001game join " + gameName + " " + chatInterface.getClient()->getName() + " " + ipAddress + "\001");
                            game = Util::ReferenceCount<Game>(new Game(gameName, false));
                        } catch (const std::out_of_range & ex){
                            chatInterface.addMessageToTab("* /game join [name]");
                        }
                    } else {
                        chatInterface.addMessageToTab("* You must be invited to a game first...");
                    }
                }
            }
        } else {
            //chatInterface.addMessageToTab("* Uknown command.");
        }
    }

    double ticks(double system){
        return system;
    }

    void run(){
        try {
            chatInterface.act();
        } catch (const Exception::Return & ex){
            escaped = true;
            throw ex;
        }
    }

    bool done(){
        return escaped;
    }

    void draw(const Graphics::Bitmap & screen){
        chatInterface.draw(screen);
    }
};

static void doIrc(const std::string & host, int port, const std::string & username){
    InputLogicDraw client(port, host, username);
    Util::standardLoop(client, client);
}

static void arguments(const std::string & application, int status){
    std::cout << "Usage: ./" << application << " port host [username]" << std::endl;
    exit(status);
}

int main(int argc, char ** argv){
    if (argc >= 2){
        int port = atoi(argv[1]);
        std::string hostname = argv[2];
        std::string username = "paintown-test";
        if (argc > 3){
            username = argv[3];
        }

        Screen::realInit(Configuration::getScreenWidth(), Configuration::getScreenHeight());
        atexit(Screen::realFinish);
        Common::startTimers();

        Sound::initialize();

        Global::setDebug(2);

        Util::Parameter<Graphics::Bitmap*> use(Graphics::screenParameter, Graphics::getScreenBuffer());
        Keyboard::pushRepeatState(true);

        InputManager manager;

        Util::Parameter<Util::ReferenceCount<Path::RelativePath> >
            defaultFont(Font::defaultFont, Util::ReferenceCount<Path::RelativePath>(new Path::RelativePath("fonts/arial.ttf")));

        Network::init();

        try {
            doIrc(hostname, port, username);
        } catch (const Exception::Return & ex){
        } catch (const Network::NetworkException & ex){
            Global::debug(0) << "Network Exception: " << ex.getMessage() << std::endl;
        }
        Network::shutdown();
    } else {
        arguments(argv[0],0);
    }
    return 0;
}
#ifdef USE_ALLEGRO
END_OF_MAIN()
#endif
<commit_msg>[util] Make irc game test clients connect to game server and send hello.<commit_after>#include "../common/init.h"
#include "../common/timer.h"

#include <iostream>
#include <vector>
#include <stdexcept>

#include "util/graphics/bitmap.h"
#include "util/font.h"
#include "util/debug.h"
#include "util/exceptions/load_exception.h"
#include "util/token_exception.h"
#include "util/input/input.h"
#include "util/input/input-manager.h"
#include "util/sound/sound.h"
#include "util/exceptions/exception.h"
#include "util/network/chat.h"
#include "util/network/network.h"
#include "util/network/irc.h"
#include "util/thread.h"
#include "util/pointer.h"
#include "util/system.h"
#include "util/timedifference.h"
#include "util/configuration.h"

#include <queue>
#include <map>

static std::vector<std::string> split(std::string str, char splitter){
    std::vector<std::string> strings;
    size_t next = str.find(splitter);
    while (next != std::string::npos){
        strings.push_back(str.substr(0, next));
        str = str.substr(next+1);
        next = str.find(splitter);
    }
    if (str != ""){
        strings.push_back(str);
    }

    return strings;
}

static void setTrue(void * b){
    bool * what = (bool*) b;
    *what = true;
}

static void nextTab(void * i){
    ::Network::IRC::ChatInterface * interface = (::Network::IRC::ChatInterface *)i;
    interface->nextChannel();
}

static void previousTab(void * i){
    ::Network::IRC::ChatInterface * interface = (::Network::IRC::ChatInterface *)i;
    interface->previousChannel();
}

class Game{
public:
    Game(const std::string & name, bool host = true):
    name(name),
    host(host){
    }
    ~Game(){
    }

    void addClient(const std::string & name, const std::string & ip){
        clients[name] = ip;
    }

    std::string clientsAsString(){
        std::string clientlist;
        for (std::map<std::string, std::string>::iterator i = clients.begin(); i != clients.end(); i++){
            clientlist += (*i).first + ", ";
        }
        return clientlist.substr(0, clientlist.size() - 2);
    }

    void start(const std::string & ip, const std::string & hostip) {
        // TODO move to a thread, otherwise the server is going to hang...
        int port = 9991;
        if (isHost()){
            Global::debug(0) << "Game " << name << " is starting." << std::endl;
            Global::debug(0) << "Starting server on port " << port << "...." << std::endl;
            ::Network::Chat::Server server(port);
            server.start();
            // Wait for all clients to send a message
            unsigned int allReceived = 0;
            while (allReceived < clients.size()){
                server.poll();
                while (server.hasMessages()){
                    ::Network::Chat::Message message = server.nextMessage();
                    std::map<std::string, std::string>::iterator check = clients.find(message.getName());
                    if (check != clients.end()){
                        Global::debug(0) << "Message Received: " << message.getMessage() << std::endl;
                        allReceived++;
                    }
                }
            }
            Global::debug(0) << "Received all messages. Shutting down." << std::endl;
            server.shutdown();
        } else {
            Global::debug(0) << "Game " << name << " is starting." << std::endl;
            Global::debug(0) << "Connecting to " << hostip << "...." << std::endl;
            Network::Socket socket = Network::connectReliable(hostip, port);
            Global::debug(0) << "Connected" << std::endl;
            ::Network::Chat::Client client(0, socket);
            client.start();
            ::Network::Chat::Message ourMessage(::Network::Chat::Message::Chat, ip, "Hello from: " + ip);
            client.sendMessage(ourMessage);
            Global::debug(0) << "Message sent. Shutting down." << std::endl;
            client.shutdown();
        }
    }

    std::map<std::string, std::string> & getClients(){
        return clients;
    }

    const std::string & getName() const {
        return name;
    }

    bool isHost() const {
        return host;
    }

private:
    std::string name;
    bool host;
    std::map<std::string, std::string> clients;
};

class InputLogicDraw: public Util::Logic, public Util::Draw, public ::Network::IRC::Message::EventInterface {
public:
    InputLogicDraw(int port, const std::string & host, const std::string & username):
    chatInterface(host, port, username),
    escaped(false){
        ircClient = Util::ReferenceCount< ::Network::IRC::Client >(new ::Network::IRC::Client(host, port));
        chatInterface.getInputBox().addHook(Keyboard::Key_ESC, setTrue, &escaped);
        chatInterface.getInputBox().addHook(Keyboard::Key_TAB, nextTab, &chatInterface);
        chatInterface.subscribe(this);
        // Get IP
        chatInterface.getClient()->sendCommand(::Network::IRC::Command::Userhost, chatInterface.getClient()->getName());
    }

    ::Network::IRC::ChatInterface chatInterface;
    Util::ReferenceCount< ::Network::IRC::Client > ircClient;

    bool escaped;

    std::string ipAddress;
    Util::ReferenceCount<Game> game;
    std::map<std::string, std::string> hosts;

    void remoteCommand(const ::Network::IRC::Command & command){
        if (command.getType() == ::Network::IRC::Command::ReplyUserhost){
            const std::vector<std::string> & params = command.getParameters();
            const std::string & extract = params.at(1);
            for (unsigned int i = 0; i < extract.size(); i++){
                if (extract[i] == '@'){
                    ipAddress = extract.substr(++i, extract.size()-1);
                    Global::debug(0) << "Your IP Address is: " << ipAddress << std::endl;
                }
            }
        }
        if (command.hasCtcp()){
            const std::vector<std::string> & ctcp = command.getCtcp();
            if (command.getType() == ::Network::IRC::Command::PrivateMessage){
                try {
                    if (ctcp.at(0) == "game"){
                        const std::string & gameCommand = ctcp.at(1);
                        if (gameCommand == "invite"){
                            const std::string & gameName = ctcp.at(2);
                            const std::string & hostName = ctcp.at(3);
                            chatInterface.addMessageToTab("* " + hostName + " has invited you to join the game [" + gameName + "]. Type \"/game join " + gameName + "\".");
                            hosts[gameName] = hostName;
                        } else if (gameCommand == "join"){
                            if (game != NULL && game->isHost()){
                                const std::string & gameName = ctcp.at(2);
                                const std::string & clientName = ctcp.at(3);
                                const std::string & ip = ctcp.at(4);
                                chatInterface.addMessageToTab("* " + clientName + " has joined " + gameName + ".");
                                game->addClient(clientName, ip);
                            } else {
                                chatInterface.addMessageToTab("* received a join request with no game pending.");
                            }
                        } else if (gameCommand == "start"){
                            if (game != NULL && !game->isHost()){
                                const std::string & gameName = ctcp.at(2);
                                const std::string & serverIp = ctcp.at(3);
                                chatInterface.addMessageToTab("* Host has started game " + gameName);
                                game->start(ipAddress, serverIp);
                            }
                        }
                    } else {
                        Global::debug(0) << "Got ctcp: " << ctcp.at(0) << std::endl;
                    }
                } catch (const std::out_of_range & ex){
                }
            }
        }
    }

    void localCommand(const std::vector<std::string> & command){
        if (command.at(0) == "help"){
            chatInterface.addMessageToTab("* commands: lol, game");
        } else if (command.at(0) == "lol"){
            chatInterface.addMessageToTab("* You LOLOLOLOLLOLOLOL yourself.");
        } else if (command.at(0) == "game"){
            // Game
            if (command.size() > 1){
                if (command.at(1) == "help"){
                    chatInterface.addMessageToTab("* game commands: help, new, start, list-users, list-hosts, invite, join.");
                } else if (command.at(1) == "new"){
                    try{
                        game = Util::ReferenceCount<Game>(new Game(command.at(2)));
                        chatInterface.addMessageToTab("* game \"" + command.at(2) + "\" created.");
                    } catch (const std::out_of_range & ex){
                        chatInterface.addMessageToTab("* /game new [name]");
                    }
                } else if (command.at(1) == "start"){
                    if (game != NULL && game->isHost()){
                        chatInterface.addMessageToTab("* Starting game " + game->getName());
                        game->start(ipAddress, ipAddress);
                        for (std::map<std::string, std::string>::iterator i = game->getClients().begin(); i != game->getClients().end(); i++){
                            chatInterface.getClient()->sendCommand(::Network::IRC::Command::PrivateMessage,
                                                                    (*i).first,
                                                                    ":\001game start " + game->getName() + " " + ipAddress + "\001");
                        }
                    } else {
                        chatInterface.addMessageToTab("* Create a game first...");
                    }
                } else if (command.at(1) == "list-users"){
                    if (game != NULL){
                        chatInterface.addMessageToTab("* Users who accepted game request: " + game->clientsAsString());
                    } else {
                        chatInterface.addMessageToTab("* Create a game first...");
                    }
                } else if (command.at(1) == "list-hosts"){
                    if (!hosts.empty()){
                        std::string hostlist;
                        for (std::map<std::string, std::string>::iterator i = hosts.begin(); i != hosts.end(); i++){
                            hostlist += (*i).first + +" [" + (*i).second + "], ";
                        }
                        chatInterface.addMessageToTab("* Hosts and games you've been invited to: " + hostlist.substr(0, hostlist.size() - 2));
                    } else {
                        chatInterface.addMessageToTab("* You have no invites.");
                    }
                } else if (command.at(1) == "invite"){
                    if (game != NULL){
                        try {
                            chatInterface.addMessageToTab("* Sending request to " + command.at(2));
                            chatInterface.getClient()->sendCommand(::Network::IRC::Command::PrivateMessage,
                                                            command.at(2),
                                                            ":\001game invite " + game->getName() + " " + chatInterface.getClient()->getName() + "\001");
                        } catch (const std::out_of_range & ex){
                            chatInterface.addMessageToTab("* /game invite [username]");
                        }
                    } else {
                        chatInterface.addMessageToTab("* Create a game first...");
                    }
                } else if (command.at(1) == "join"){
                    if (!hosts.empty()){
                        try {
                            const std::string & gameName = command.at(2);
                            const std::string & hostName = hosts[gameName];
                            chatInterface.addMessageToTab("* Joining game at " + gameName);
                            chatInterface.getClient()->sendCommand(::Network::IRC::Command::PrivateMessage,
                                                            hostName,
                                                            ":\001game join " + gameName + " " + chatInterface.getClient()->getName() + " " + ipAddress + "\001");
                            game = Util::ReferenceCount<Game>(new Game(gameName, false));
                        } catch (const std::out_of_range & ex){
                            chatInterface.addMessageToTab("* /game join [name]");
                        }
                    } else {
                        chatInterface.addMessageToTab("* You must be invited to a game first...");
                    }
                }
            }
        } else {
            //chatInterface.addMessageToTab("* Uknown command.");
        }
    }

    double ticks(double system){
        return system;
    }

    void run(){
        try {
            chatInterface.act();
        } catch (const Exception::Return & ex){
            escaped = true;
            throw ex;
        }
    }

    bool done(){
        return escaped;
    }

    void draw(const Graphics::Bitmap & screen){
        chatInterface.draw(screen);
    }
};

static void doIrc(const std::string & host, int port, const std::string & username){
    InputLogicDraw client(port, host, username);
    Util::standardLoop(client, client);
}

static void arguments(const std::string & application, int status){
    std::cout << "Usage: ./" << application << " port host [username]" << std::endl;
    exit(status);
}

int main(int argc, char ** argv){
    if (argc >= 2){
        int port = atoi(argv[1]);
        std::string hostname = argv[2];
        std::string username = "paintown-test";
        if (argc > 3){
            username = argv[3];
        }

        Screen::realInit(Configuration::getScreenWidth(), Configuration::getScreenHeight());
        atexit(Screen::realFinish);
        Common::startTimers();

        Sound::initialize();

        Global::setDebug(2);

        Util::Parameter<Graphics::Bitmap*> use(Graphics::screenParameter, Graphics::getScreenBuffer());
        Keyboard::pushRepeatState(true);

        InputManager manager;

        Util::Parameter<Util::ReferenceCount<Path::RelativePath> >
            defaultFont(Font::defaultFont, Util::ReferenceCount<Path::RelativePath>(new Path::RelativePath("fonts/arial.ttf")));

        Network::init();

        try {
            doIrc(hostname, port, username);
        } catch (const Exception::Return & ex){
        } catch (const Network::NetworkException & ex){
            Global::debug(0) << "Network Exception: " << ex.getMessage() << std::endl;
        }
        Network::shutdown();
    } else {
        arguments(argv[0],0);
    }
    return 0;
}
#ifdef USE_ALLEGRO
END_OF_MAIN()
#endif
<|endoftext|>


<commit_before>// The Art of C++ / Tuple
// Copyright (c) 2015 Daniel Frey

#include <tao/tuple/tuple.hpp>

#include <type_traits>
#include <cassert>

int main()
{
  using namespace tao;

  auto t = tuple< int, double, int >();
  auto t2 = tuple< int, double, int >( 1, 2, 3 );
  auto t3( t2 );

  auto t4 = tuple< int, double, int >( 1, 2, 2 );
  auto t5 = tuple< int, double, int >( 1, 2, 4 );

  static_assert( tuple_size< decltype( t ) >::value == 3, "oops" );
  static_assert( tuple_size< decltype( t2 ) >::value == 3, "oops" );
  static_assert( tuple_size< decltype( t3 ) >::value == 3, "oops" );

  assert( get< 0 >( t2 ) == 1 );
  assert( get< 1 >( t2 ) == 2 );
  assert( get< 2 >( t2 ) == 3 );

  assert( get< double >( t2 ) == 2 );

  assert( get< 0 >( t3 ) == 1 );
  assert( get< 1 >( t3 ) == 2 );
  assert( get< 2 >( t3 ) == 3 );

  assert( get< double >( t3 ) == 2 );

  assert( t2 == t3 );
  assert( t2 != t4 );
  assert( t2 > t4 );
  assert( t2 < t5 );
  assert( t2 >= t3 );
  assert( t2 <= t3 );
  assert( t2 >= t4 );
  assert( t2 <= t5 );

  assert( tuple<>() == tuple<>() );
  assert( !( tuple<>() < tuple<>() ) );

#if (__cplusplus >= 201402L)

  static_assert( tuple<>() == tuple<>(), "oops" );
  static_assert( make_tuple() == make_tuple(), "oops" );
  static_assert( make_tuple( 0 ) == make_tuple( 0 ), "oops" );

  static_assert( make_tuple( 1, 2, 3 ) > make_tuple( 1, 2, 2 ), "oops" );
  static_assert( make_tuple( 1, 2, 3 ) < make_tuple( 1, 2, 4 ), "oops" );

  // TODO: More constexpr checks

#endif

}
<commit_msg>Added run-time checks<commit_after>// The Art of C++ / Tuple
// Copyright (c) 2015 Daniel Frey

#include <tao/tuple/tuple.hpp>

#include <type_traits>
#include <cassert>

int main()
{
  using namespace tao;

  auto t = tuple< int, double, int >();
  auto t2 = tuple< int, double, int >( 1, 2, 3 );
  auto t3( t2 );

  auto t4 = tuple< int, double, int >( 1, 2, 2 );
  auto t5 = tuple< int, double, int >( 1, 2, 4 );

  static_assert( tuple_size< decltype( t ) >::value == 3, "oops" );
  static_assert( tuple_size< decltype( t2 ) >::value == 3, "oops" );
  static_assert( tuple_size< decltype( t3 ) >::value == 3, "oops" );

  assert( get< 0 >( t2 ) == 1 );
  assert( get< 1 >( t2 ) == 2 );
  assert( get< 2 >( t2 ) == 3 );

  assert( get< double >( t2 ) == 2 );

  assert( get< 0 >( t3 ) == 1 );
  assert( get< 1 >( t3 ) == 2 );
  assert( get< 2 >( t3 ) == 3 );

  assert( get< double >( t3 ) == 2 );

  assert( t2 == t3 );
  assert( t2 != t4 );
  assert( t2 > t4 );
  assert( t2 < t5 );
  assert( t2 >= t3 );
  assert( t2 <= t3 );
  assert( t2 >= t4 );
  assert( t2 <= t5 );

  assert( tuple<>() == tuple<>() );
  assert( !( tuple<>() < tuple<>() ) );

  assert( make_tuple( 0 ) == make_tuple( 0 ) );

  assert( make_tuple( 1, 2, 3 ) > make_tuple( 1, 2, 2 ) );
  assert( make_tuple( 1, 2, 3 ) < make_tuple( 1, 2, 4 ) );

  assert(( tuple< int, int, int >( std::allocator_arg, 5, 1, 2, 3 ) < make_tuple( 1, 2, 4 ) ));

#if (__cplusplus >= 201402L)

  static_assert( tuple<>() == tuple<>(), "oops" );
  static_assert( make_tuple() == make_tuple(), "oops" );
  static_assert( make_tuple( 0 ) == make_tuple( 0 ), "oops" );

  static_assert( make_tuple( 1, 2, 3 ) > make_tuple( 1, 2, 2 ), "oops" );
  static_assert( make_tuple( 1, 2, 3 ) < make_tuple( 1, 2, 4 ), "oops" );

  // TODO: More constexpr checks

#endif

}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2007-2012, Timothy Stack
 *
 * 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 Timothy Stack 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 REGENTS 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 REGENTS 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.
 */

#ifndef _top_status_source_hh
#define _top_status_source_hh

#include <string>

#include "logfile_sub_source.hh"
#include "statusview_curses.hh"

class top_status_source
    : public status_data_source {
public:

    typedef listview_curses::action::mem_functor_t<
            top_status_source> lv_functor_t;

    typedef enum {
        TSF_TIME,
        TSF_PARTITION_NAME,
        TSF_VIEW_NAME,
        TSF_STITCH_VIEW_FORMAT,
        TSF_FORMAT,
        TSF_STITCH_FORMAT_FILENAME,
        TSF_FILENAME,

        TSF__MAX
    } field_t;

    top_status_source()
        : filename_wire(*this, &top_status_source::update_filename)
    {
        this->tss_fields[TSF_TIME].set_width(24);
        this->tss_fields[TSF_PARTITION_NAME].set_width(30);
        this->tss_fields[TSF_VIEW_NAME].set_width(6);
        this->tss_fields[TSF_VIEW_NAME].right_justify(true);
        this->tss_fields[TSF_STITCH_VIEW_FORMAT].set_width(2);
        this->tss_fields[TSF_STITCH_VIEW_FORMAT].set_stitch_value(
            view_colors::ansi_color_pair_index(COLOR_CYAN, COLOR_BLUE));
        this->tss_fields[TSF_STITCH_VIEW_FORMAT].right_justify(true);
        this->tss_fields[TSF_FORMAT].set_width(20);
        this->tss_fields[TSF_FORMAT].right_justify(true);
        this->tss_fields[TSF_STITCH_FORMAT_FILENAME].set_width(2);
        this->tss_fields[TSF_STITCH_FORMAT_FILENAME].set_stitch_value(
            view_colors::ansi_color_pair_index(COLOR_WHITE, COLOR_CYAN));
        this->tss_fields[TSF_STITCH_FORMAT_FILENAME].right_justify(true);
        this->tss_fields[TSF_FILENAME].set_min_width(35); /* XXX */
        this->tss_fields[TSF_FILENAME].set_share(1);
        this->tss_fields[TSF_FILENAME].right_justify(true);
    };

    lv_functor_t filename_wire;

    size_t statusview_fields(void) { return TSF__MAX; };

    status_field &statusview_value_for_field(int field)
    {
        return this->tss_fields[field];
    };

    void update_time(void)
    {
        status_field &sf           = this->tss_fields[TSF_TIME];
        time_t        current_time = time(NULL);
        char          buffer[32];

        strftime(buffer, sizeof(buffer),
                 "%a %b %d %H:%M:%S %Z",
                 localtime(&current_time));
        sf.set_value(buffer);
    };

    void update_filename(listview_curses *lc)
    {
        status_field &    sf_partition = this->tss_fields[TSF_PARTITION_NAME];
        status_field &    sf_format   = this->tss_fields[TSF_FORMAT];
        status_field &    sf_filename = this->tss_fields[TSF_FILENAME];
        struct line_range lr(0);

        if (lc->get_inner_height() > 0) {
            string_attrs_t::const_iterator line_attr;
            attr_line_t           al;

            lc->get_data_source()->
            listview_value_for_row(*lc, lc->get_top(), al);
            string_attrs_t &sa = al.get_attrs();
            line_attr = find_string_attr(sa, &logline::L_FILE);
            if (line_attr != sa.cend()) {
                logfile *lf = (logfile *)line_attr->sa_value.sav_ptr;

                if (lf->get_format()) {
                    sf_format.set_value("% 13s",
                                        lf->get_format()->get_name().get());
                }
                else if (!lf->get_filename().empty()) {
                    sf_format.set_value("% 13s", "plain text");
                }
                else{
                    sf_format.clear();
                }

                sf_filename.set_value(lf->get_filename());
            }
            else {
                sf_format.clear();
                sf_filename.clear();
            }

            line_attr = find_string_attr(sa, &logline::L_PARTITION);
            if (line_attr != sa.end()) {
                bookmark_metadata *bm = (bookmark_metadata *)line_attr->sa_value.sav_ptr;

                sf_partition.set_value(bm->bm_name.c_str());
            }
            else {
                sf_partition.clear();
            }
        }
        else {
            sf_format.clear();
            if (lc->get_data_source() != NULL) {
                sf_filename.set_value(lc->get_data_source()->listview_source_name(*lc));
            }
        }
        sf_format.get_value().get_attrs().push_back(
            string_attr(lr, &view_curses::VC_STYLE,
                A_REVERSE | view_colors::ansi_color_pair(COLOR_CYAN, COLOR_BLACK)));
    };

private:
    status_field tss_fields[TSF__MAX];
};
#endif
<commit_msg>build fix<commit_after>/**
 * Copyright (c) 2007-2012, Timothy Stack
 *
 * 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 Timothy Stack 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 REGENTS 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 REGENTS 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.
 */

#ifndef _top_status_source_hh
#define _top_status_source_hh

#include <string>

#include "logfile_sub_source.hh"
#include "statusview_curses.hh"

class top_status_source
    : public status_data_source {
public:

    typedef listview_curses::action::mem_functor_t<
            top_status_source> lv_functor_t;

    typedef enum {
        TSF_TIME,
        TSF_PARTITION_NAME,
        TSF_VIEW_NAME,
        TSF_STITCH_VIEW_FORMAT,
        TSF_FORMAT,
        TSF_STITCH_FORMAT_FILENAME,
        TSF_FILENAME,

        TSF__MAX
    } field_t;

    top_status_source()
        : filename_wire(*this, &top_status_source::update_filename)
    {
        this->tss_fields[TSF_TIME].set_width(24);
        this->tss_fields[TSF_PARTITION_NAME].set_width(30);
        this->tss_fields[TSF_VIEW_NAME].set_width(6);
        this->tss_fields[TSF_VIEW_NAME].right_justify(true);
        this->tss_fields[TSF_STITCH_VIEW_FORMAT].set_width(2);
        this->tss_fields[TSF_STITCH_VIEW_FORMAT].set_stitch_value(
            view_colors::ansi_color_pair_index(COLOR_CYAN, COLOR_BLUE));
        this->tss_fields[TSF_STITCH_VIEW_FORMAT].right_justify(true);
        this->tss_fields[TSF_FORMAT].set_width(20);
        this->tss_fields[TSF_FORMAT].right_justify(true);
        this->tss_fields[TSF_STITCH_FORMAT_FILENAME].set_width(2);
        this->tss_fields[TSF_STITCH_FORMAT_FILENAME].set_stitch_value(
            view_colors::ansi_color_pair_index(COLOR_WHITE, COLOR_CYAN));
        this->tss_fields[TSF_STITCH_FORMAT_FILENAME].right_justify(true);
        this->tss_fields[TSF_FILENAME].set_min_width(35); /* XXX */
        this->tss_fields[TSF_FILENAME].set_share(1);
        this->tss_fields[TSF_FILENAME].right_justify(true);
    };

    lv_functor_t filename_wire;

    size_t statusview_fields(void) { return TSF__MAX; };

    status_field &statusview_value_for_field(int field)
    {
        return this->tss_fields[field];
    };

    void update_time(void)
    {
        status_field &sf           = this->tss_fields[TSF_TIME];
        time_t        current_time = time(NULL);
        char          buffer[32];

        strftime(buffer, sizeof(buffer),
                 "%a %b %d %H:%M:%S %Z",
                 localtime(&current_time));
        sf.set_value(buffer);
    };

    void update_filename(listview_curses *lc)
    {
        status_field &    sf_partition = this->tss_fields[TSF_PARTITION_NAME];
        status_field &    sf_format   = this->tss_fields[TSF_FORMAT];
        status_field &    sf_filename = this->tss_fields[TSF_FILENAME];
        struct line_range lr(0);

        if (lc->get_inner_height() > 0) {
            string_attrs_t::const_iterator line_attr;
            attr_line_t           al;

            lc->get_data_source()->
            listview_value_for_row(*lc, lc->get_top(), al);
            string_attrs_t &sa = al.get_attrs();
            line_attr = find_string_attr(sa, &logline::L_FILE);
            if (line_attr != sa.end()) {
                logfile *lf = (logfile *)line_attr->sa_value.sav_ptr;

                if (lf->get_format()) {
                    sf_format.set_value("% 13s",
                                        lf->get_format()->get_name().get());
                }
                else if (!lf->get_filename().empty()) {
                    sf_format.set_value("% 13s", "plain text");
                }
                else{
                    sf_format.clear();
                }

                sf_filename.set_value(lf->get_filename());
            }
            else {
                sf_format.clear();
                sf_filename.clear();
            }

            line_attr = find_string_attr(sa, &logline::L_PARTITION);
            if (line_attr != sa.end()) {
                bookmark_metadata *bm = (bookmark_metadata *)line_attr->sa_value.sav_ptr;

                sf_partition.set_value(bm->bm_name.c_str());
            }
            else {
                sf_partition.clear();
            }
        }
        else {
            sf_format.clear();
            if (lc->get_data_source() != NULL) {
                sf_filename.set_value(lc->get_data_source()->listview_source_name(*lc));
            }
        }
        sf_format.get_value().get_attrs().push_back(
            string_attr(lr, &view_curses::VC_STYLE,
                A_REVERSE | view_colors::ansi_color_pair(COLOR_CYAN, COLOR_BLACK)));
    };

private:
    status_field tss_fields[TSF__MAX];
};
#endif
<|endoftext|>