<commit_before>// Copyright (c) 2013, Matthew Harvey. All rights reserved.

#include "transaction_ctrl.hpp"
#include "account.hpp"
#include "account_ctrl.hpp"
#include "account_reader.hpp"
#include "account_type.hpp"
#include "b_string.hpp"
#include "date.hpp"
#include "date_ctrl.hpp"
#include "decimal_text_ctrl.hpp"
#include "decimal_validator.hpp"
#include "entry.hpp"
#include "finformat.hpp"
#include "frame.hpp"
#include "ordinary_journal.hpp"
#include "locale.hpp"
#include "phatbooks_database_connection.hpp"
#include "top_panel.hpp"
#include "transaction_type_ctrl.hpp"
#include "transaction_type.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/scoped_ptr.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <jewel/on_windows.hpp>
#include <wx/arrstr.h>
#include <wx/button.h>
#include <wx/combobox.h>
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/msgdlg.h>
#include <wx/gbsizer.h>
#include <wx/stattext.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

using boost::scoped_ptr;
using jewel::Decimal;
using std::endl;
using std::vector;

namespace gregorian = boost::gregorian;

namespace phatbooks
{
namespace gui
{

BEGIN_EVENT_TABLE(TransactionCtrl, wxPanel)
	EVT_BUTTON
	(	wxID_OK,
		TransactionCtrl::on_ok_button_click
	)
	EVT_BUTTON
	(	s_recurring_transaction_button_id,
		TransactionCtrl::on_recurring_transaction_button_click
	)
	EVT_BUTTON
	(	wxID_CANCEL,
		TransactionCtrl::on_cancel_button_click
	)
END_EVENT_TABLE()

// WARNING There are bugs in wxWidgets' wxDatePickerCtrl under wxGTK.
// Firstly, tab traversal gets stuck on that control.
// Secondly, if we type a different date and then press "Enter" for OK,
// the date that actually gets picked up as the transaction date always
// seems to be TODAY's date, not the date actually entered. This appears to
// be an unresolved bug in wxWidgets.
// Note adding wxTAB_TRAVERSAL to style does not seem to fix the problem.
// We have used a simple custom class, DateCtrl here instead, to avoid
// these problems. Might later add a button to pop up a wxCalendarCtrl
// if the user wants one.

TransactionCtrl::TransactionCtrl
(	TopPanel* p_parent,
	vector<Account> const& p_balance_sheet_accounts,
	vector<Account> const& p_pl_accounts,
	PhatbooksDatabaseConnection& p_database_connection
):
	wxPanel
	(	p_parent,
		wxID_ANY,
		wxDefaultPosition,
		wxDefaultSize
	),
	m_top_sizer(0),
	m_transaction_type_ctrl(0),
	m_primary_amount_ctrl(0),
	m_date_ctrl(0),
	m_cancel_button(0),
	m_recurring_transaction_button(0),
	m_ok_button(0),
	m_database_connection(p_database_connection)
{
	assert (m_account_name_boxes.empty());
	assert (m_comment_boxes.empty());
	assert (m_split_buttons.empty());
	assert (!p_balance_sheet_accounts.empty() || !p_pl_accounts.empty());
	assert (p_balance_sheet_accounts.size() + p_pl_accounts.size() >= 2);

	// Figure out the natural TransactionType given the Accounts we have
	// been passed. We will use this initialize the TransactionTypeCtrl.
	Account account_x(p_database_connection);
	Account account_y(p_database_connection);
	if (p_balance_sheet_accounts.empty())
	{
		assert (p_pl_accounts.size() >= 2);
		account_x = p_pl_accounts[0];
		account_y = p_pl_accounts[1];
	}
	else if (p_pl_accounts.empty())
	{
		assert (p_balance_sheet_accounts.size() >= 2);
		account_x = p_balance_sheet_accounts[0];
		account_y = p_balance_sheet_accounts[1];
	}
	else
	{
		assert (!p_balance_sheet_accounts.empty());
		assert (!p_pl_accounts.empty());
		account_x = p_balance_sheet_accounts[0];
		account_y = p_pl_accounts[0];
	}
	if (account_y.account_type() == account_type::revenue)
	{
		using std::swap;
		swap(account_x, account_y);
	}
	assert (account_x.has_id());
	assert (account_y.has_id());
	transaction_type::TransactionType const initial_transaction_type =
		natural_transaction_type(account_x, account_y);

	size_t row = 0;

	// We construct m_ok_button first as we want to be able to refer to its
	// size when sizing certain other controls below. But we will not add
	// the OK button to m_top_sizer till later.
	m_ok_button = new wxButton
	(	this,
		wxID_OK,
		wxString("&OK"),
		wxDefaultPosition,
		wxDefaultSize
	);
	wxSize const ok_button_size = m_ok_button->GetSize();

	// Top sizer
	m_top_sizer = new wxGridBagSizer();
	SetSizer(m_top_sizer);

	m_transaction_type_ctrl = new TransactionTypeCtrl
	(	this,
		wxID_ANY,
		wxSize(ok_button_size.x * 2, ok_button_size.y)
	);
	m_transaction_type_ctrl->set_transaction_type(initial_transaction_type);
	m_top_sizer->Add(m_transaction_type_ctrl, wxGBPosition(row, 1));
	m_primary_amount_ctrl = new DecimalTextCtrl
	(	this,
		s_primary_amount_ctrl_id,
		wxSize(ok_button_size.x * 2, ok_button_size.y),
		m_database_connection.default_commodity().precision(),
		false
	);
	m_top_sizer->Add(m_primary_amount_ctrl, wxGBPosition(row, 2));
	wxSize const date_ctrl_sz(ok_button_size.x, ok_button_size.y);
	m_date_ctrl = new DateCtrl(this, wxID_ANY, date_ctrl_sz);
	m_top_sizer->Add(m_date_ctrl, wxGBPosition(row, 4));

	row += 2;

	// We need the names of available Accounts, for the given
	// TransactionType, from which the user will choose
	// Accounts, for each side of the transaction.
	scoped_ptr<AccountReaderBase> const account_reader_x
	(	create_source_account_reader
		(	m_database_connection,
			initial_transaction_type
		)
	);
	scoped_ptr<AccountReaderBase> const account_reader_y
	(	create_destination_account_reader
		(	m_database_connection,
			initial_transaction_type
		)
	);

	// Rows for entering Entry details
	typedef vector<Account>::size_type Size;
	vector<Account> accounts;
	accounts.push_back(account_x);
	accounts.push_back(account_y);

	Size const sz = accounts.size();
	for (Size id = s_min_entry_row_id, i = 0 ; i != sz; ++i, id += 2, ++row)
	{
		Account const account = accounts[i];
		assert ((i == 0) || (i == 1));
		assert (accounts.size() == 2);
		AccountReaderBase* account_reader =
		(	(i == 0)?
			account_reader_x.get():
			account_reader_y.get()
		);
		AccountCtrl* account_name_box = new AccountCtrl
		(	this,
			id,
			account,
			wxSize(ok_button_size.x * 2, ok_button_size.y),
			account_reader->begin(),
			account_reader->end(),
			m_database_connection
		);
		wxSize const account_name_box_size = account_name_box->GetSize();
		wxTextCtrl* comment_ctrl = new wxTextCtrl
		(	this,
			id,
			wxEmptyString,
			wxDefaultPosition,
			wxSize(ok_button_size.x * 4.5, account_name_box_size.y),
			wxALIGN_LEFT
		);
		wxButton* split_button = new wxButton
		(	this,
			id + 1,
			wxString("&Split..."),
			wxDefaultPosition,
			ok_button_size
		);
		int base_flag = wxLEFT;
		if (i == 0) base_flag |= wxTOP;
		m_top_sizer->Add(account_name_box, wxGBPosition(row, 1));
		m_top_sizer->Add(comment_ctrl, wxGBPosition(row, 2), wxGBSpan(1, 2));
		m_top_sizer->Add(split_button, wxGBPosition(row, 4));

		m_account_name_boxes.push_back(account_name_box);
		m_comment_boxes.push_back(comment_ctrl);
		m_split_buttons.push_back(split_button);
	}

	// Button row
	m_cancel_button = new wxButton
	(	this,
		wxID_CANCEL,
		wxString("&Cancel"),
		wxDefaultPosition,
		ok_button_size
	);
	m_top_sizer->Add(m_cancel_button, wxGBPosition(row, 1));
	m_recurring_transaction_button = new wxButton
	(	this,
		s_recurring_transaction_button_id,
		wxString("&Recurring..."),
		wxDefaultPosition,
		wxSize(ok_button_size.x, ok_button_size.y)
	);
	m_top_sizer->Add(m_recurring_transaction_button, wxGBPosition(row, 2));
	m_top_sizer->Add(m_ok_button, wxGBPosition(row, 4));
	m_ok_button->SetDefault();  // Enter key will now trigger "OK" button

	++row;

	// Radio box for selecting actual vs. budget
	wxArrayString radio_box_strings;
	radio_box_strings.Add(wxString("Actual"));
	radio_box_strings.Add(wxString("Budget"));

	// "Admin"
	// SetSizer(m_top_sizer);
	m_top_sizer->Fit(this);
	m_top_sizer->SetSizeHints(this);
	Layout();
}

void
TransactionCtrl::refresh_for_transaction_type
(	transaction_type::TransactionType p_transaction_type
)
{
	JEWEL_DEBUG_LOG << "Called TransactionCtrl::refresh_for_transaction_type."
	                << endl;
	// TODO Implement.

}

void
TransactionCtrl::on_ok_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	if (Validate() && TransferDataFromWindow())
	{
		if (is_balanced())
		{
			post_journal();
			TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
			assert (panel);
			panel->update();
		}
		else
		{
			wxMessageBox("Transaction does not balance.");
		}
	}
	return;
}

void
TransactionCtrl::on_recurring_transaction_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	return;
}

void
TransactionCtrl::on_cancel_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
	assert (panel);
	panel->update();
}

void
TransactionCtrl::post_journal() const
{
	OrdinaryJournal journal(m_database_connection);
	transaction_type::TransactionType const ttype =
		m_transaction_type_ctrl->transaction_type();
	journal.set_whether_actual(transaction_type_is_actual(ttype));
	size_t const sz = m_account_name_boxes.size();
	assert (sz == m_comment_boxes.size());
	Decimal const primary_amount = wx_to_decimal
	(	wxString(m_primary_amount_ctrl->GetValue()),
		locale()
	);
	// WARNING This can't yet handle Journals with a number of entries
	// other than 2.
	assert (sz == 2);
	for (size_t i = 0; i != sz; ++i)
	{
		Account const account
		(	m_database_connection,
			wx_to_bstring(wxString(m_account_name_boxes[i]->GetValue()))
		);
		Entry entry(m_database_connection);
		entry.set_account(account);
		entry.set_comment
		(	wx_to_bstring(m_comment_boxes[i]->GetValue())
		);
		Decimal amount = primary_amount;
		if (i == 0)
		{
			// This is the source account
			amount = -amount;
		}
		if (!journal.is_actual())
		{
			amount = -amount;
		}
		amount = round(amount, account.commodity().precision());
		entry.set_amount(amount);
		entry.set_whether_reconciled(false);
		journal.push_entry(entry);
	}
	assert (journal.is_balanced());
	journal.set_comment("");

	// Process date
	journal.set_date(m_date_ctrl->date());

	// Save journal
	journal.save();
}

bool
TransactionCtrl::is_balanced() const
{
	// WARNING For now this is trivial, as we have only the primary_amount
	// informing one each of only two sides of the transaction. But it
	// probably won't always be trivial.
	return true;
	/*
	Decimal balance(0, 0);
	vector<DecimalTextCtrl*>::size_type i = 0;
	vector<DecimalTextCtrl*>::size_type const sz = m_amount_boxes.size();
	for ( ; i != sz; ++i)
	{
		balance += wx_to_decimal(m_amount_boxes[i]->GetValue(), locale());
	}
	return balance == Decimal(0, 0);
	*/
}

}  // namespace gui
}  // namespace phatbooks
<commit_msg>Repositioned and resized some elements in TransactionCtrl. Date is now on bottom row. Added labels "Source:", "Destination:" and "Comment:" to help user navigate the interface. Put spaces between rows.<commit_after>// Copyright (c) 2013, Matthew Harvey. All rights reserved.

#include "transaction_ctrl.hpp"
#include "account.hpp"
#include "account_ctrl.hpp"
#include "account_reader.hpp"
#include "account_type.hpp"
#include "b_string.hpp"
#include "date.hpp"
#include "date_ctrl.hpp"
#include "decimal_text_ctrl.hpp"
#include "decimal_validator.hpp"
#include "entry.hpp"
#include "finformat.hpp"
#include "frame.hpp"
#include "ordinary_journal.hpp"
#include "locale.hpp"
#include "phatbooks_database_connection.hpp"
#include "top_panel.hpp"
#include "transaction_type_ctrl.hpp"
#include "transaction_type.hpp"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/scoped_ptr.hpp>
#include <jewel/debug_log.hpp>
#include <jewel/decimal.hpp>
#include <jewel/on_windows.hpp>
#include <wx/arrstr.h>
#include <wx/button.h>
#include <wx/combobox.h>
#include <wx/panel.h>
#include <wx/event.h>
#include <wx/msgdlg.h>
#include <wx/gbsizer.h>
#include <wx/stattext.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

using boost::scoped_ptr;
using jewel::Decimal;
using std::endl;
using std::vector;

namespace gregorian = boost::gregorian;

namespace phatbooks
{
namespace gui
{

BEGIN_EVENT_TABLE(TransactionCtrl, wxPanel)
	EVT_BUTTON
	(	wxID_OK,
		TransactionCtrl::on_ok_button_click
	)
	EVT_BUTTON
	(	s_recurring_transaction_button_id,
		TransactionCtrl::on_recurring_transaction_button_click
	)
	EVT_BUTTON
	(	wxID_CANCEL,
		TransactionCtrl::on_cancel_button_click
	)
END_EVENT_TABLE()

// WARNING There are bugs in wxWidgets' wxDatePickerCtrl under wxGTK.
// Firstly, tab traversal gets stuck on that control.
// Secondly, if we type a different date and then press "Enter" for OK,
// the date that actually gets picked up as the transaction date always
// seems to be TODAY's date, not the date actually entered. This appears to
// be an unresolved bug in wxWidgets.
// Note adding wxTAB_TRAVERSAL to style does not seem to fix the problem.
// We have used a simple custom class, DateCtrl here instead, to avoid
// these problems. Might later add a button to pop up a wxCalendarCtrl
// if the user wants one.

TransactionCtrl::TransactionCtrl
(	TopPanel* p_parent,
	vector<Account> const& p_balance_sheet_accounts,
	vector<Account> const& p_pl_accounts,
	PhatbooksDatabaseConnection& p_database_connection
):
	wxPanel
	(	p_parent,
		wxID_ANY,
		wxDefaultPosition,
		wxDefaultSize
	),
	m_top_sizer(0),
	m_transaction_type_ctrl(0),
	m_primary_amount_ctrl(0),
	m_date_ctrl(0),
	m_cancel_button(0),
	m_recurring_transaction_button(0),
	m_ok_button(0),
	m_database_connection(p_database_connection)
{
	assert (m_account_name_boxes.empty());
	assert (m_comment_boxes.empty());
	assert (m_split_buttons.empty());
	assert (!p_balance_sheet_accounts.empty() || !p_pl_accounts.empty());
	assert (p_balance_sheet_accounts.size() + p_pl_accounts.size() >= 2);

	// Figure out the natural TransactionType given the Accounts we have
	// been passed. We will use this initialize the TransactionTypeCtrl.
	Account account_x(p_database_connection);
	Account account_y(p_database_connection);
	if (p_balance_sheet_accounts.empty())
	{
		assert (p_pl_accounts.size() >= 2);
		account_x = p_pl_accounts[0];
		account_y = p_pl_accounts[1];
	}
	else if (p_pl_accounts.empty())
	{
		assert (p_balance_sheet_accounts.size() >= 2);
		account_x = p_balance_sheet_accounts[0];
		account_y = p_balance_sheet_accounts[1];
	}
	else
	{
		assert (!p_balance_sheet_accounts.empty());
		assert (!p_pl_accounts.empty());
		account_x = p_balance_sheet_accounts[0];
		account_y = p_pl_accounts[0];
	}
	if (account_y.account_type() == account_type::revenue)
	{
		using std::swap;
		swap(account_x, account_y);
	}
	assert (account_x.has_id());
	assert (account_y.has_id());
	transaction_type::TransactionType const initial_transaction_type =
		natural_transaction_type(account_x, account_y);

	size_t row = 0;

	// We construct m_ok_button first as we want to be able to refer to its
	// size when sizing certain other controls below. But we will not add
	// the OK button to m_top_sizer till later.
	m_ok_button = new wxButton
	(	this,
		wxID_OK,
		wxString("&OK"),
		wxDefaultPosition,
		wxDefaultSize
	);
	wxSize const ok_button_size = m_ok_button->GetSize();

	// Top sizer
	m_top_sizer = new wxGridBagSizer();
	SetSizer(m_top_sizer);

	m_transaction_type_ctrl = new TransactionTypeCtrl
	(	this,
		wxID_ANY,
		wxSize(ok_button_size.x * 2, ok_button_size.y)
	);
	m_transaction_type_ctrl->set_transaction_type(initial_transaction_type);
	m_top_sizer->Add(m_transaction_type_ctrl, wxGBPosition(row, 1));
	wxString const currency_abbreviation = bstring_to_wx
	(	m_database_connection.default_commodity().abbreviation()
	);
	wxStaticText* const currency_text = new wxStaticText
	(	this,
		wxID_ANY,
		currency_abbreviation,
		wxDefaultPosition,
		ok_button_size,
		wxALIGN_RIGHT
	);
	m_top_sizer->Add
	(	currency_text,
		wxGBPosition(row, 2),
		wxDefaultSpan,
		wxALIGN_RIGHT
	);
	m_primary_amount_ctrl = new DecimalTextCtrl
	(	this,
		s_primary_amount_ctrl_id,
		wxSize(ok_button_size.x * 2, ok_button_size.y),
		m_database_connection.default_commodity().precision(),
		false
	);
	m_top_sizer->Add
	(	m_primary_amount_ctrl,
		wxGBPosition(row, 3),
		wxDefaultSpan,
		wxALIGN_RIGHT
	);
	wxSize const date_ctrl_sz(ok_button_size.x, ok_button_size.y);

	row += 2;

	// We need the names of available Accounts, for the given
	// TransactionType, from which the user will choose
	// Accounts, for each side of the transaction.
	scoped_ptr<AccountReaderBase> const account_reader_x
	(	create_source_account_reader
		(	m_database_connection,
			initial_transaction_type
		)
	);
	scoped_ptr<AccountReaderBase> const account_reader_y
	(	create_destination_account_reader
		(	m_database_connection,
			initial_transaction_type
		)
	);

	// Rows for entering Entry details
	typedef vector<Account>::size_type Size;
	vector<Account> accounts;
	accounts.push_back(account_x);
	accounts.push_back(account_y);

	++row;

	Size const sz = accounts.size();
	for (Size id = s_min_entry_row_id, i = 0 ; i != sz; ++i, id += 2, row += 3)
	{
		wxStaticText* const account_label = new wxStaticText
		(	this,
			wxID_ANY,
			((i == 0)? wxString(" Source:"): wxString(" Destination:")),
			wxDefaultPosition,
			wxDefaultSize,
			wxALIGN_LEFT
		);
		m_top_sizer->Add(account_label, wxGBPosition(row - 1, 1));
		wxStaticText* const comment_label = new wxStaticText
		(	this,
			wxID_ANY,
			wxString("Comment:"),
			wxDefaultPosition,
			wxDefaultSize,
			wxALIGN_LEFT
		);
		m_top_sizer->Add(comment_label, wxGBPosition(row - 1, 2));
		Account const account = accounts[i];
		assert ((i == 0) || (i == 1));
		assert (accounts.size() == 2);
		AccountReaderBase* account_reader =
		(	(i == 0)?
			account_reader_x.get():
			account_reader_y.get()
		);
		AccountCtrl* account_name_box = new AccountCtrl
		(	this,
			id,
			account,
			wxSize(ok_button_size.x * 2, ok_button_size.y),
			account_reader->begin(),
			account_reader->end(),
			m_database_connection
		);
		wxSize const account_name_box_size = account_name_box->GetSize();
		wxTextCtrl* comment_ctrl = new wxTextCtrl
		(	this,
			id,
			wxEmptyString,
			wxDefaultPosition,
			wxSize(ok_button_size.x * 4.5, account_name_box_size.y),
			wxALIGN_LEFT
		);
		wxButton* split_button = new wxButton
		(	this,
			id + 1,
			wxString("Split..."),
			wxDefaultPosition,
			ok_button_size
		);
		int base_flag = wxLEFT;
		if (i == 0) base_flag |= wxTOP;
		m_top_sizer->Add(account_name_box, wxGBPosition(row, 1));
		m_top_sizer->Add(comment_ctrl, wxGBPosition(row, 2), wxGBSpan(1, 2));
		m_top_sizer->Add(split_button, wxGBPosition(row, 4));

		m_account_name_boxes.push_back(account_name_box);
		m_comment_boxes.push_back(comment_ctrl);
		m_split_buttons.push_back(split_button);
	}

	m_cancel_button = new wxButton
	(	this,
		wxID_CANCEL,
		wxString("&Cancel"),
		wxDefaultPosition,
		ok_button_size
	);
	m_top_sizer->Add(m_cancel_button, wxGBPosition(row, 1));
	m_date_ctrl = new DateCtrl(this, wxID_ANY, date_ctrl_sz);
	m_top_sizer->Add(m_date_ctrl, wxGBPosition(row, 2));
	m_recurring_transaction_button = new wxButton
	(	this,
		s_recurring_transaction_button_id,
		wxString("&Recurring..."),
		wxDefaultPosition,
		wxSize(ok_button_size.x, ok_button_size.y)
	);
	m_top_sizer->Add(m_recurring_transaction_button, wxGBPosition(row, 3));
	m_top_sizer->Add(m_ok_button, wxGBPosition(row, 4));
	m_ok_button->SetDefault();  // Enter key will now trigger "OK" button

	++row;

	// Radio box for selecting actual vs. budget
	wxArrayString radio_box_strings;
	radio_box_strings.Add(wxString("Actual"));
	radio_box_strings.Add(wxString("Budget"));

	// "Admin"
	// SetSizer(m_top_sizer);
	m_top_sizer->Fit(this);
	m_top_sizer->SetSizeHints(this);
	Layout();
}

void
TransactionCtrl::refresh_for_transaction_type
(	transaction_type::TransactionType p_transaction_type
)
{
	JEWEL_DEBUG_LOG << "Called TransactionCtrl::refresh_for_transaction_type."
	                << endl;
	// TODO Implement.

}

void
TransactionCtrl::on_ok_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	if (Validate() && TransferDataFromWindow())
	{
		if (is_balanced())
		{
			post_journal();
			TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
			assert (panel);
			panel->update();
		}
		else
		{
			wxMessageBox("Transaction does not balance.");
		}
	}
	return;
}

void
TransactionCtrl::on_recurring_transaction_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	return;
}

void
TransactionCtrl::on_cancel_button_click(wxCommandEvent& event)
{
	(void)event;  // Silence compiler re. unused parameter.
	TopPanel* const panel = dynamic_cast<TopPanel*>(GetParent());
	assert (panel);
	panel->update();
}

void
TransactionCtrl::post_journal() const
{
	OrdinaryJournal journal(m_database_connection);
	transaction_type::TransactionType const ttype =
		m_transaction_type_ctrl->transaction_type();
	journal.set_whether_actual(transaction_type_is_actual(ttype));
	size_t const sz = m_account_name_boxes.size();
	assert (sz == m_comment_boxes.size());
	Decimal const primary_amount = wx_to_decimal
	(	wxString(m_primary_amount_ctrl->GetValue()),
		locale()
	);
	// WARNING This can't yet handle Journals with a number of entries
	// other than 2.
	assert (sz == 2);
	for (size_t i = 0; i != sz; ++i)
	{
		Account const account
		(	m_database_connection,
			wx_to_bstring(wxString(m_account_name_boxes[i]->GetValue()))
		);
		Entry entry(m_database_connection);
		entry.set_account(account);
		entry.set_comment
		(	wx_to_bstring(m_comment_boxes[i]->GetValue())
		);
		Decimal amount = primary_amount;
		if (i == 0)
		{
			// This is the source account
			amount = -amount;
		}
		if (!journal.is_actual())
		{
			amount = -amount;
		}
		amount = round(amount, account.commodity().precision());
		entry.set_amount(amount);
		entry.set_whether_reconciled(false);
		journal.push_entry(entry);
	}
	assert (journal.is_balanced());
	journal.set_comment("");

	// Process date
	journal.set_date(m_date_ctrl->date());

	// Save journal
	journal.save();
}

bool
TransactionCtrl::is_balanced() const
{
	// WARNING For now this is trivial, as we have only the primary_amount
	// informing one each of only two sides of the transaction. But it
	// probably won't always be trivial.
	return true;
	/*
	Decimal balance(0, 0);
	vector<DecimalTextCtrl*>::size_type i = 0;
	vector<DecimalTextCtrl*>::size_type const sz = m_amount_boxes.size();
	for ( ; i != sz; ++i)
	{
		balance += wx_to_decimal(m_amount_boxes[i]->GetValue(), locale());
	}
	return balance == Decimal(0, 0);
	*/
}

}  // namespace gui
}  // namespace phatbooks
<|endoftext|>


<commit_before>/**
 * This file is part of the CernVM File System.
 *
 * Some common functions.
 */

#ifndef __STDC_FORMAT_MACROS
// NOLINTNEXTLINE
#define __STDC_FORMAT_MACROS
#endif

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "cvmfs_config.h"
#include "util/algorithm.h"
#include "util/string.h"

#ifdef CVMFS_NAMESPACE_GUARD
namespace CVMFS_NAMESPACE_GUARD {
#endif

bool HighPrecisionTimer::g_is_enabled = false;

double DiffTimeSeconds(struct timeval start, struct timeval end) {
  // Time substraction, from GCC documentation
  if (end.tv_usec < start.tv_usec) {
    int64_t nsec = (end.tv_usec - start.tv_usec) / 1000000 + 1;
    start.tv_usec -= 1000000 * nsec;
    start.tv_sec += nsec;
  }
  if (end.tv_usec - start.tv_usec > 1000000) {
    int64_t nsec = (end.tv_usec - start.tv_usec) / 1000000;
    start.tv_usec += 1000000 * nsec;
    start.tv_sec -= nsec;
  }

  // Compute the time remaining to wait in microseconds.
  // tv_usec is certainly positive.
  uint64_t elapsed_usec = ((end.tv_sec - start.tv_sec)*1000000) +
  (end.tv_usec - start.tv_usec);
  return static_cast<double>(elapsed_usec)/1000000.0;
}

void StopWatch::Start() {
  assert(!running_);

  gettimeofday(&start_, NULL);
  running_ = true;
}

void StopWatch::Stop() {
  assert(running_);

  gettimeofday(&end_, NULL);
  running_ = false;
}

void StopWatch::Reset() {
  start_ = timeval();
  end_   = timeval();
  running_ = false;
}

double StopWatch::GetTime() const {
  assert(!running_);

  return DiffTimeSeconds(start_, end_);
}

namespace {

static unsigned int CountDigits(uint64_t n) {
  return static_cast<unsigned int>(floor(log10(static_cast<double>(n)))) + 1;
}

static std::string GenerateStars(unsigned int n) {
  return std::string(n, '*');
}

}  // anonymous namespace

Log2Histogram::Log2Histogram(unsigned int nbins) {
  assert(nbins != 0);
  this->bins_.assign(nbins + 1, 0);  // +1 for overflow bin.
  this->boundary_values_.assign(nbins + 1, 0);  // +1 to avoid big if statement

  unsigned int i;
  for (i = 1; i <= nbins; i++) {
    this->boundary_values_[i] = (1 << ((i - 1) + 1));
  }
}

std::vector<atomic_int32> UTLog2Histogram::GetBins(const Log2Histogram &h) {
  return h.bins_;
}

unsigned int Log2Histogram::GetQuantile(float n) {
  uint64_t total = this->N();
  // pivot is the index of the element corresponding to the requested quantile
  uint64_t pivot = total * static_cast<uint64_t>(n);
  float normalized_pivot = 0.0;
  // now we iterate through all the bins
  // note that we _exclude_ the overflow bin
  unsigned int i = 0;
  for (i = 1; 1 <= this->bins_.size() - 1; i++) {
    unsigned int bin_value =
      static_cast<unsigned int>(atomic_read32(&(this->bins_[i])));
    if (pivot <= bin_value) {
      normalized_pivot =
        static_cast<float>(pivot) / static_cast<float>(bin_value);
      break;
    }
    pivot -= bin_value;
  }
  // now i stores the index of the bin corresponding to the requested quantile
  // and normalized_pivot is the element we want inside the bin
  unsigned int min_value = this->boundary_values_[i - 1];
  unsigned int max_value = this->boundary_values_[i];
  // and we return the linear interpolation
  return min_value + static_cast<unsigned int>(
    static_cast<float>(max_value - min_value) * normalized_pivot);
}

std::string Log2Histogram::ToString() {
  unsigned int i = 0;

  unsigned int max_left_boundary_count = 1;
  unsigned int max_right_boundary_count = 1;
  unsigned int max_value_count = 1;
  unsigned int max_stars = 0;
  unsigned int max_bins = 0;
  unsigned int total_stars = 38;
  uint64_t total_sum_of_bins = 0;

  for (i = 1; i <= this->bins_.size() - 1; i++) {
    max_left_boundary_count = std::max(max_left_boundary_count,
                                CountDigits(boundary_values_[i] / 2));
    max_right_boundary_count = std::max(max_right_boundary_count,
                                CountDigits(boundary_values_[i] - 1));
    max_value_count = std::max(max_value_count, CountDigits(this->bins_[i]));
    max_bins = std::max(max_bins, static_cast<unsigned int>(
                        atomic_read32(&(this->bins_[i]))));
    total_sum_of_bins +=
      static_cast<unsigned int>(atomic_read32(&(this->bins_[i])));
  }

  max_bins = std::max(max_bins, static_cast<unsigned int>(
    atomic_read32(&(this->bins_[0]))));
  total_sum_of_bins +=
    static_cast<unsigned int>(atomic_read32(&(this->bins_[0])));

  if (total_sum_of_bins != 0) {
    max_stars = max_bins * total_stars / total_sum_of_bins;
  }

  std::string format = " %" + StringifyUint(max_left_boundary_count < 2 ?
                                  2 : max_left_boundary_count) +
                  "d -> %" + StringifyUint(max_right_boundary_count) +
                  "d :     %" + StringifyUint(max_value_count) + "d | %" +
                  StringifyUint(max_stars < 12 ? 12 : max_stars) + "s |\n";

  std::string title_format = " %" +
                  StringifyUint((max_left_boundary_count < 2 ?
                              2 : max_left_boundary_count) +
                              max_right_boundary_count +
                              4) +
                  "s | %" + StringifyUint(max_value_count + 4) +
                  "s | %" + StringifyUint(max_stars < 12 ? 12 : max_stars) +
                  "s |\n";

  std::string overflow_format = "%" +
                  StringifyUint(max_left_boundary_count +
                              max_right_boundary_count +
                              5) +
                  "s : %" + StringifyUint(max_value_count + 4) +
                  "d | %" + StringifyUint(max_stars < 12 ? 12 : max_stars) +
                  "s |\n";

  std::string total_format = "%" +
                  StringifyUint(max_left_boundary_count +
                              max_right_boundary_count +
                              5 < 8 ? 8 : max_left_boundary_count +
                              max_right_boundary_count + 5) +
                  "s : %" + StringifyUint(max_value_count + 4) + "lld\n";

  std::string result_string = "";

  const unsigned int kBufSize = 300;
  char buffer[kBufSize];
  memset(buffer, 0, sizeof(buffer));

  snprintf(buffer,
      kBufSize,
      title_format.c_str(),
      "nsec",
      "count",
      "distribution");
  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  for (i = 1; i <= this->bins_.size() - 1; i++) {
    unsigned int n_of_stars = 0;
    if (total_sum_of_bins != 0) {
      n_of_stars = static_cast<unsigned int>(atomic_read32(&(this->bins_[i]))) *
                   total_stars / total_sum_of_bins;
    }

    snprintf(buffer,
            kBufSize,
            format.c_str(),
            boundary_values_[i - 1],
            boundary_values_[i] - 1,
            static_cast<unsigned int>(atomic_read32(&this->bins_[i])),
            GenerateStars(n_of_stars).c_str());
    result_string += buffer;
    memset(buffer, 0, sizeof(buffer));
  }

  unsigned int n_of_stars = 0;
  if (total_sum_of_bins != 0) {
    n_of_stars = static_cast<unsigned int>(atomic_read32(&(this->bins_[0])))
                 * total_stars / total_sum_of_bins;
  }

  snprintf(buffer,
          kBufSize,
          overflow_format.c_str(),
          "overflow",
          static_cast<unsigned int>(atomic_read32(&(this->bins_[0]))),
          GenerateStars(n_of_stars).c_str());
  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  snprintf(buffer,
          kBufSize,
          total_format.c_str(),
          "total",
          total_sum_of_bins);
  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  float qs[15] = {.1,  .2, .25, .3,  .4,  .5,   .6,  .7,
                  .75, .8, .9,  .95, .99, .995, .999};
  snprintf(buffer, kBufSize,
           "\n\nQuantiles\n"
           "%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,"
           "%0.4f,%0.4f,%0.4f,%0.4f\n"
           "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n"
           "End Quantiles"
           "\n-----------------------\n",
           qs[0], qs[1], qs[2], qs[3], qs[4], qs[5], qs[6], qs[7], qs[8], qs[9],
           qs[10], qs[11], qs[12], qs[13], qs[14], GetQuantile(qs[0]),
           GetQuantile(qs[1]), GetQuantile(qs[2]), GetQuantile(qs[3]),
           GetQuantile(qs[4]), GetQuantile(qs[5]), GetQuantile(qs[6]),
           GetQuantile(qs[7]), GetQuantile(qs[8]), GetQuantile(qs[9]),
           GetQuantile(qs[10]), GetQuantile(qs[11]), GetQuantile(qs[12]),
           GetQuantile(qs[13]), GetQuantile(qs[14]));

  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  return result_string;
}

void Log2Histogram::PrintLog2Histogram() {
  printf("%s", this->ToString().c_str());
}

#ifdef CVMFS_NAMESPACE_GUARD
}  // namespace CVMFS_NAMESPACE_GUARD
#endif
<commit_msg>[tidy] Fix arithmetic in Log2Histogram<commit_after>/**
 * This file is part of the CernVM File System.
 *
 * Some common functions.
 */

#ifndef __STDC_FORMAT_MACROS
// NOLINTNEXTLINE
#define __STDC_FORMAT_MACROS
#endif

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include "cvmfs_config.h"
#include "util/algorithm.h"
#include "util/string.h"

#ifdef CVMFS_NAMESPACE_GUARD
namespace CVMFS_NAMESPACE_GUARD {
#endif

bool HighPrecisionTimer::g_is_enabled = false;

double DiffTimeSeconds(struct timeval start, struct timeval end) {
  // Time substraction, from GCC documentation
  if (end.tv_usec < start.tv_usec) {
    int64_t nsec = (end.tv_usec - start.tv_usec) / 1000000 + 1;
    start.tv_usec -= 1000000 * nsec;
    start.tv_sec += nsec;
  }
  if (end.tv_usec - start.tv_usec > 1000000) {
    int64_t nsec = (end.tv_usec - start.tv_usec) / 1000000;
    start.tv_usec += 1000000 * nsec;
    start.tv_sec -= nsec;
  }

  // Compute the time remaining to wait in microseconds.
  // tv_usec is certainly positive.
  uint64_t elapsed_usec = ((end.tv_sec - start.tv_sec)*1000000) +
  (end.tv_usec - start.tv_usec);
  return static_cast<double>(elapsed_usec)/1000000.0;
}

void StopWatch::Start() {
  assert(!running_);

  gettimeofday(&start_, NULL);
  running_ = true;
}

void StopWatch::Stop() {
  assert(running_);

  gettimeofday(&end_, NULL);
  running_ = false;
}

void StopWatch::Reset() {
  start_ = timeval();
  end_   = timeval();
  running_ = false;
}

double StopWatch::GetTime() const {
  assert(!running_);

  return DiffTimeSeconds(start_, end_);
}

namespace {

static unsigned int CountDigits(uint64_t n) {
  return static_cast<unsigned int>(floor(log10(static_cast<double>(n)))) + 1;
}

static std::string GenerateStars(unsigned int n) {
  return std::string(n, '*');
}

}  // anonymous namespace

Log2Histogram::Log2Histogram(unsigned int nbins) {
  assert(nbins != 0);
  this->bins_.assign(nbins + 1, 0);  // +1 for overflow bin.
  this->boundary_values_.assign(nbins + 1, 0);  // +1 to avoid big if statement

  unsigned int i;
  for (i = 1; i <= nbins; i++) {
    this->boundary_values_[i] = (1 << ((i - 1) + 1));
  }
}

std::vector<atomic_int32> UTLog2Histogram::GetBins(const Log2Histogram &h) {
  return h.bins_;
}

unsigned int Log2Histogram::GetQuantile(float n) {
  uint64_t total = this->N();
  // pivot is the index of the element corresponding to the requested quantile
  uint64_t pivot = static_cast<uint64_t>(static_cast<float>(total) * n);
  float normalized_pivot = 0.0;
  // now we iterate through all the bins
  // note that we _exclude_ the overflow bin
  unsigned int i = 0;
  for (i = 1; 1 <= this->bins_.size() - 1; i++) {
    unsigned int bin_value =
      static_cast<unsigned int>(atomic_read32(&(this->bins_[i])));
    if (pivot <= bin_value) {
      normalized_pivot =
        static_cast<float>(pivot) / static_cast<float>(bin_value);
      break;
    }
    pivot -= bin_value;
  }
  // now i stores the index of the bin corresponding to the requested quantile
  // and normalized_pivot is the element we want inside the bin
  unsigned int min_value = this->boundary_values_[i - 1];
  unsigned int max_value = this->boundary_values_[i];
  // and we return the linear interpolation
  return min_value + static_cast<unsigned int>(
    static_cast<float>(max_value - min_value) * normalized_pivot);
}

std::string Log2Histogram::ToString() {
  unsigned int i = 0;

  unsigned int max_left_boundary_count = 1;
  unsigned int max_right_boundary_count = 1;
  unsigned int max_value_count = 1;
  unsigned int max_stars = 0;
  unsigned int max_bins = 0;
  unsigned int total_stars = 38;
  uint64_t total_sum_of_bins = 0;

  for (i = 1; i <= this->bins_.size() - 1; i++) {
    max_left_boundary_count = std::max(max_left_boundary_count,
                                CountDigits(boundary_values_[i] / 2));
    max_right_boundary_count = std::max(max_right_boundary_count,
                                CountDigits(boundary_values_[i] - 1));
    max_value_count = std::max(max_value_count, CountDigits(this->bins_[i]));
    max_bins = std::max(max_bins, static_cast<unsigned int>(
                        atomic_read32(&(this->bins_[i]))));
    total_sum_of_bins +=
      static_cast<unsigned int>(atomic_read32(&(this->bins_[i])));
  }

  max_bins = std::max(max_bins, static_cast<unsigned int>(
    atomic_read32(&(this->bins_[0]))));
  total_sum_of_bins +=
    static_cast<unsigned int>(atomic_read32(&(this->bins_[0])));

  if (total_sum_of_bins != 0) {
    max_stars = max_bins * total_stars / total_sum_of_bins;
  }

  std::string format = " %" + StringifyUint(max_left_boundary_count < 2 ?
                                  2 : max_left_boundary_count) +
                  "d -> %" + StringifyUint(max_right_boundary_count) +
                  "d :     %" + StringifyUint(max_value_count) + "d | %" +
                  StringifyUint(max_stars < 12 ? 12 : max_stars) + "s |\n";

  std::string title_format = " %" +
                  StringifyUint((max_left_boundary_count < 2 ?
                              2 : max_left_boundary_count) +
                              max_right_boundary_count +
                              4) +
                  "s | %" + StringifyUint(max_value_count + 4) +
                  "s | %" + StringifyUint(max_stars < 12 ? 12 : max_stars) +
                  "s |\n";

  std::string overflow_format = "%" +
                  StringifyUint(max_left_boundary_count +
                              max_right_boundary_count +
                              5) +
                  "s : %" + StringifyUint(max_value_count + 4) +
                  "d | %" + StringifyUint(max_stars < 12 ? 12 : max_stars) +
                  "s |\n";

  std::string total_format = "%" +
                  StringifyUint(max_left_boundary_count +
                              max_right_boundary_count +
                              5 < 8 ? 8 : max_left_boundary_count +
                              max_right_boundary_count + 5) +
                  "s : %" + StringifyUint(max_value_count + 4) + "lld\n";

  std::string result_string = "";

  const unsigned int kBufSize = 300;
  char buffer[kBufSize];
  memset(buffer, 0, sizeof(buffer));

  snprintf(buffer,
      kBufSize,
      title_format.c_str(),
      "nsec",
      "count",
      "distribution");
  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  for (i = 1; i <= this->bins_.size() - 1; i++) {
    unsigned int n_of_stars = 0;
    if (total_sum_of_bins != 0) {
      n_of_stars = static_cast<unsigned int>(atomic_read32(&(this->bins_[i]))) *
                   total_stars / total_sum_of_bins;
    }

    snprintf(buffer,
            kBufSize,
            format.c_str(),
            boundary_values_[i - 1],
            boundary_values_[i] - 1,
            static_cast<unsigned int>(atomic_read32(&this->bins_[i])),
            GenerateStars(n_of_stars).c_str());
    result_string += buffer;
    memset(buffer, 0, sizeof(buffer));
  }

  unsigned int n_of_stars = 0;
  if (total_sum_of_bins != 0) {
    n_of_stars = static_cast<unsigned int>(atomic_read32(&(this->bins_[0])))
                 * total_stars / total_sum_of_bins;
  }

  snprintf(buffer,
          kBufSize,
          overflow_format.c_str(),
          "overflow",
          static_cast<unsigned int>(atomic_read32(&(this->bins_[0]))),
          GenerateStars(n_of_stars).c_str());
  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  snprintf(buffer,
          kBufSize,
          total_format.c_str(),
          "total",
          total_sum_of_bins);
  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  float qs[15] = {.1,  .2, .25, .3,  .4,  .5,   .6,  .7,
                  .75, .8, .9,  .95, .99, .995, .999};
  snprintf(buffer, kBufSize,
           "\n\nQuantiles\n"
           "%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,%0.4f,"
           "%0.4f,%0.4f,%0.4f,%0.4f\n"
           "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n"
           "End Quantiles"
           "\n-----------------------\n",
           qs[0], qs[1], qs[2], qs[3], qs[4], qs[5], qs[6], qs[7], qs[8], qs[9],
           qs[10], qs[11], qs[12], qs[13], qs[14], GetQuantile(qs[0]),
           GetQuantile(qs[1]), GetQuantile(qs[2]), GetQuantile(qs[3]),
           GetQuantile(qs[4]), GetQuantile(qs[5]), GetQuantile(qs[6]),
           GetQuantile(qs[7]), GetQuantile(qs[8]), GetQuantile(qs[9]),
           GetQuantile(qs[10]), GetQuantile(qs[11]), GetQuantile(qs[12]),
           GetQuantile(qs[13]), GetQuantile(qs[14]));

  result_string += buffer;
  memset(buffer, 0, sizeof(buffer));

  return result_string;
}

void Log2Histogram::PrintLog2Histogram() {
  printf("%s", this->ToString().c_str());
}

#ifdef CVMFS_NAMESPACE_GUARD
}  // namespace CVMFS_NAMESPACE_GUARD
#endif
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>

#include "..\include\Common.h"
#include "..\include\Player.h"

using namespace std;
using namespace Common;

void Player::SaveGame(){
    ofstream WriteData;
    WriteData.open("data.txt");
    WriteData << player_type << endl
			  << name << endl
              << level << endl
              << experience << endl
              << health << endl
              << arrows << endl
              << bombs << endl
              << potions << endl
              << whetstones << endl
              << weaponstrength << endl
              << coins;
    WriteData.close();
}

void Player::SetPlayerData(){
    // Primarily initializes default values at the beginning of the game.

	ifstream ReadData;
	ReadData.clear();
	ReadData.open("data.txt");

	ReadData >> player_type;
    ReadData >> name;
    ReadData >> level;
    ReadData >> experience;
    ReadData >> health;
    ReadData >> arrows;
    ReadData >> bombs;
    ReadData >> potions;
    ReadData >> whetstones;
    ReadData >> weaponstrength;
    ReadData >> coins;

    ReadData.close();

}

int Player::Attack(){
    // Returns the amount of attack points the player gives.
    // Also the main battle screen.

    int choice = 0;

    // Displays the inventory.
    DisplayInventory();

    // Gives player a list of moves to choose from.
	cout << "Choose your move:" << endl
		<< "1) Attack" << endl
		<< "2) Risk Attack" << endl
		<< "3) Bow and Arrow" << endl
		<< "4) Heal" << endl << endl
		<< "5) Use Bomb" << endl
		<< "6) Use Potion" << endl
		<< "7) Use Whetstone" << endl
		<< "0) Get me out of here!" << endl << endl;

	while (true) {
		choice = input();

		// Evaluates player's choice.
		switch (choice) {
		case 0:
			return Flee();
		case 1:
			// Player generically attacks.
			return GenericAttack();
		case 2:
			// Player takes a risk and attacks.
			return RiskAttack();
		case 3:
			// Player shoots their bow.
			if (arrows > 0)
				return BowAndArrow();
			break;
		case 4:
			// Player heals, no damage is done to enemy.
			Heal();
			return 0;
		case 5:
			// Player throws a bomb.
			// Does not execute if there are no bombs in the inventory.
			if (bombs > 0)
				return UseBomb();
			break;
		case 6:
			// Player drinks a potion.
			// Does not execute if there are no potions in the inventory.
			if (potions > 0) {
				UsePotion();
				return 0;
			}
			break;
		case 7:
			// Player sharpens their weapon with a whetstone.
			// Does not execute if there are no whetstones in inventory.
			// No damage is done to the enemy.
			if (whetstones > 0) {
				UseWhetstone();
				return 0;
			}
			break;
		default:
			// Generically attacks by default if player's choice does not equal above cases.
			return GenericAttack();
		}
	}
}

void Player::UseItem() {
	// Use item from inventory
	int choice = 0;

	while (true) {
		ClearScreen();

		// Displays the inventory.
		DisplayInventory();

		// Gives player a list of moves to choose from.
		cout << "Choose which item use:" << endl
			<< "1) Use Potion" << endl
			<< "2) Use Whetstone" << endl
			<< "0) Quit" << endl << endl;

		choice = input();

		// Evaluates player's choice.
		switch (choice) {
		case 0:
			return;
		case 1:
			// Player drinks a potion.
			// Does not execute if there are no potions in the inventory.
			if (potions > 0) {
				UsePotion();
				Sleep(SLEEP_MS);
			}

			break;
		case 2:
			// Player sharpens their weapon with a whetstone.
			// Does not execute if there are no whetstones in inventory.
			// No damage is done to the enemy.
			if (whetstones > 0) {
				UseWhetstone();
				Sleep(SLEEP_MS);
			}

			break;
		default:
			break;
		}
	}
}

void Player::AddToInventory(vector<int> drops){
    // Adds items to inventory and prints out what the player received.

    // Adds items received to total items.
    arrows += drops.at(0);
	bombs += drops.at(1);
	potions += drops.at(2);
	whetstones += drops.at(3);
    coins += drops.at(4);

    // Prints number of items received.
	cout << "You have gained: " << endl;
	if (drops[0] > 0)
		cout << "[" << drops.at(0) << "] arrows" << endl;
	if (drops[1] > 0)
		cout << "[" << drops.at(1) << "] bombs" << endl;
	if (drops[2] > 0)
		cout << "[" << drops.at(2) << "] potions" << endl;
	if (drops[3] > 0)
		cout << "[" << drops.at(3) << "] whetstones" << endl;
	if (drops[4] > 0)
         cout << "[" << drops.at(4) << "] coins" << endl;

	cout << endl;
}

void Player::DisplayHUD(Enemy *_Enemy){
    // Displays player's name and health bar. Enemy object is used to print name on the same line as player name for aesthetics.

    // Prints player's name.
    cout << endl;
	ColourPrint(name, DARK_GREY);
    // Tabs to make room for enemy's name.
    if (name.length() > 5){
        cout << "\t\t\t";
    }
    else {
        cout <<" \t\t\t";
    }
    // Prints enemy name.
	ColourPrint(_Enemy->GetName(), DARK_GREY);
	cout << endl;
	DisplayHealthBar();
}

void Player::ReplenishHealth(){
    // Adds health points after player has defeated an enemy.
	if (health <= 0)
		health = 100;
	else {
		health += 30;
		if (health > 100) health = 100;
	}
}

void Player::AddExperience(int xp){
    // Adds points to the player's experience and levels player up.

    // Adds experience from passed in integer to local class variable experience.
    experience += xp;

    // Evaluates if experience is higher than 99, which means a level up is in order.
    if (experience>99) {
        // Experience is set to 0.
        experience = 0;

        // Player is leveled up.
        level+=1;

        // Sets level cap to 50, player cannot level higher than that.
        if (level >= 50) level = 50;

        // Alerts player that they have leveled up.
        cout << "You leveled up! Now you are level " << level << "!" << endl;
        Sleep(SLEEP_MS);
    }
}

void Player::LoseExperience(int xp){
    // Deducts points from the player's experience and de-levels player.

    // Deducts experience from passed in integer to local class variable experience.
    experience -= xp;

    // Evaluates if experience is less than 0.
    if (experience<0){
        // Experience is deducted continuing from the experience which de-leveled the player (hard to explain...)
        experience = 100-(0-experience);

        // De-levels player.
        level-=1;

        // Checks any glitches and sets player level to 1 if level is below 1 or above 50.
        // Also resets experience points.
        if (level<1 || level>50){
            level=1;
            experience = 0;
        }

        // Alerts the player that they have de-leveled.
        else {
            cout << "You de-leveled back to level " << level << "..." << endl;
            Sleep(SLEEP_MS);
        }
    }
}

void Player::AddCoins(int c){
    coins += c;
}

void Player::LoseCoins(int c){
    coins -= c;
    if (coins < 0) coins = 0;
}

void Player::DisplayInventory(){
    // Checks valid weapon strength.
    if (weaponstrength < 0){
        weaponstrength = 0;
    }
    // Simply prints the player's inventory.

    cout << "*----------- INVENTORY -----------* " << endl;
    cout << "Level " << level << "\t\t\t" << experience << "/100 xp" << endl;
    cout << "| Arrows: [" << arrows << "]" << endl;
    cout << "| Potions: [" << potions << "]" << endl;
    cout << "| Bombs: [" << bombs << "]" << endl;
    cout << "| Whetstones: [" << whetstones << "]" << endl;
    cout << "| Weapon strength: [" << weaponstrength << "%]" << endl;
    cout << "| Wealth: [" << coins << "] coins" << endl;
    cout << "*---------------------------------*" << endl << endl;
}

int Player::GenericAttack(){
    int damage = ReturnDamage();
    DeductDamage(damage);
	ColourPrint(name, DARK_GREY);
    cout << " attacks! He deals ";
	ColourPrint(to_string(damage), RED);
    cout << " damage points!" << endl;
    if (damage>0) weaponstrength-= 2+rand()%5;
    return damage;
}

int Player::RiskAttack(){
    int damage = ReturnRiskAttackDamage();
    DeductDamage(damage);
	ColourPrint(name, DARK_GREY);
    cout << " takes a risk and attack! It deals ";
	ColourPrint(to_string(damage), RED);
    cout << " damage points!" << endl;

    if (damage>0) weaponstrength-= 4+rand()%5;
    return damage;
}

int Player::BowAndArrow(){
    int damage = ReturnBowDamage();
	ColourPrint(name, DARK_GREY);
    cout << " shoots his bow! He deals ";
    SetConsoleTextAttribute(hConsole, RED);
    cout << damage;
    SetConsoleTextAttribute(hConsole, GREY);
    cout << " damage points!" << endl;
    return damage;
}

void Player::UseWhetstone(){
    weaponstrength=100;
	ColourPrint(name, DARK_GREY);
    cout << " sharpened his weapon!" << endl;
    whetstones--;
}

void Player::UsePotion(){
    health=100;
	ColourPrint(name, DARK_GREY);
    cout << " drank a healing potion!" << endl;
    potions--;
}

int Player::UseBomb(){
	ColourPrint(name, DARK_GREY);
    cout << " hurls a bomb! It deals ";
	ColourPrint("50", RED);
	cout << " damage points!" << endl;

	bombs--;
    return 50;
}

void Player::DeductDamage(int &damage){
    if (weaponstrength<=75&&weaponstrength>50)
        damage-=1;
    else if (weaponstrength<=50&&weaponstrength>30)
        damage-=4;
    else if (weaponstrength<=30&&weaponstrength>20)
        damage-=5;
    else if (weaponstrength<=20&&weaponstrength>10)
        damage-=6;
    else if (weaponstrength<=10)
        damage-=7;
    if (damage<0)
        damage=0;
}

int Player::ReturnBowDamage(){
    if (arrows < 1)
        return 0;
    arrows--;
    return 10+rand()%6; // 10 - 15
}

int Player::Flee(){
	ColourPrint(name, DARK_GREY);
    cout << " chooses to flee!" << endl;
    return -1;
}<commit_msg>Added messages when items = 0<commit_after>#include <fstream>
#include <iostream>

#include "..\include\Common.h"
#include "..\include\Player.h"

using namespace std;
using namespace Common;

void Player::SaveGame(){
    ofstream WriteData;
    WriteData.open("data.txt");
    WriteData << player_type << endl
			  << name << endl
              << level << endl
              << experience << endl
              << health << endl
              << arrows << endl
              << bombs << endl
              << potions << endl
              << whetstones << endl
              << weaponstrength << endl
              << coins;
    WriteData.close();
}

void Player::SetPlayerData(){
    // Primarily initializes default values at the beginning of the game.

	ifstream ReadData;
	ReadData.clear();
	ReadData.open("data.txt");

	ReadData >> player_type;
    ReadData >> name;
    ReadData >> level;
    ReadData >> experience;
    ReadData >> health;
    ReadData >> arrows;
    ReadData >> bombs;
    ReadData >> potions;
    ReadData >> whetstones;
    ReadData >> weaponstrength;
    ReadData >> coins;

    ReadData.close();

}

int Player::Attack(){
    // Returns the amount of attack points the player gives.
    // Also the main battle screen.

    int choice = 0;

    // Displays the inventory.
    DisplayInventory();

    // Gives player a list of moves to choose from.
	cout << "Choose your move:" << endl
		<< "1) Attack" << endl
		<< "2) Risk Attack" << endl
		<< "3) Bow and Arrow" << endl
		<< "4) Heal" << endl << endl
		<< "5) Use Bomb" << endl
		<< "6) Use Potion" << endl
		<< "7) Use Whetstone" << endl
		<< "0) Get me out of here!" << endl << endl;

	while (true) {
		choice = input();

		// Evaluates player's choice.
		switch (choice) {
		case 0:
			return Flee();
		case 1:
			// Player generically attacks.
			return GenericAttack();
		case 2:
			// Player takes a risk and attacks.
			return RiskAttack();
		case 3:
			// Player shoots their bow.
			if (arrows > 0)
				return BowAndArrow();
			break;
		case 4:
			// Player heals, no damage is done to enemy.
			Heal();
			return 0;
		case 5:
			// Player throws a bomb.
			// Does not execute if there are no bombs in the inventory.
			if (bombs > 0)
				return UseBomb();
			break;
		case 6:
			// Player drinks a potion.
			// Does not execute if there are no potions in the inventory.
			if (potions > 0) {
				UsePotion();
				return 0;
			}
			break;
		case 7:
			// Player sharpens their weapon with a whetstone.
			// Does not execute if there are no whetstones in inventory.
			// No damage is done to the enemy.
			if (whetstones > 0) {
				UseWhetstone();
				return 0;
			}
			break;
		default:
			// Generically attacks by default if player's choice does not equal above cases.
			return GenericAttack();
		}
	}
}

void Player::UseItem() {
	// Use item from inventory
	int choice = 0;

	while (true) {
		ClearScreen();

		// Displays the inventory.
		DisplayInventory();

		// Gives player a list of moves to choose from.
		cout << "Choose which item use:" << endl
			<< "1) Use Potion" << endl
			<< "2) Use Whetstone" << endl
			<< "0) Quit" << endl << endl;

		choice = input();

		// Evaluates player's choice.
		switch (choice) {
		case 0:
			return;
		case 1:
			// Player drinks a potion.
			// Does not execute if there are no potions in the inventory.
			if (potions > 0) {
				UsePotion();
				Sleep(SLEEP_MS);
			} else {
				cout << "No potions in the inventory!" << endl;
				Sleep(SLEEP_MS);
			}

			break;
		case 2:
			// Player sharpens their weapon with a whetstone.
			// Does not execute if there are no whetstones in inventory.
			// No damage is done to the enemy.
			if (whetstones > 0) {
				UseWhetstone();
				Sleep(SLEEP_MS);
			} else {
				cout << "No whetstones in the inventory!" << endl;
				Sleep(SLEEP_MS);
			}

			break;
		default:
			break;
		}
	}
}

void Player::AddToInventory(vector<int> drops){
    // Adds items to inventory and prints out what the player received.

    // Adds items received to total items.
    arrows += drops.at(0);
	bombs += drops.at(1);
	potions += drops.at(2);
	whetstones += drops.at(3);
    coins += drops.at(4);

    // Prints number of items received.
	cout << "You have gained: " << endl;
	if (drops[0] > 0)
		cout << "[" << drops.at(0) << "] arrows" << endl;
	if (drops[1] > 0)
		cout << "[" << drops.at(1) << "] bombs" << endl;
	if (drops[2] > 0)
		cout << "[" << drops.at(2) << "] potions" << endl;
	if (drops[3] > 0)
		cout << "[" << drops.at(3) << "] whetstones" << endl;
	if (drops[4] > 0)
         cout << "[" << drops.at(4) << "] coins" << endl;

	cout << endl;
}

void Player::DisplayHUD(Enemy *_Enemy){
    // Displays player's name and health bar. Enemy object is used to print name on the same line as player name for aesthetics.

    // Prints player's name.
    cout << endl;
	ColourPrint(name, DARK_GREY);
    // Tabs to make room for enemy's name.
    if (name.length() > 5){
        cout << "\t\t\t";
    }
    else {
        cout <<" \t\t\t";
    }
    // Prints enemy name.
	ColourPrint(_Enemy->GetName(), DARK_GREY);
	cout << endl;
	DisplayHealthBar();
}

void Player::ReplenishHealth(){
    // Adds health points after player has defeated an enemy.
	if (health <= 0)
		health = 100;
	else {
		health += 30;
		if (health > 100) health = 100;
	}
}

void Player::AddExperience(int xp){
    // Adds points to the player's experience and levels player up.

    // Adds experience from passed in integer to local class variable experience.
    experience += xp;

    // Evaluates if experience is higher than 99, which means a level up is in order.
    if (experience>99) {
        // Experience is set to 0.
        experience = 0;

        // Player is leveled up.
        level+=1;

        // Sets level cap to 50, player cannot level higher than that.
        if (level >= 50) level = 50;

        // Alerts player that they have leveled up.
        cout << "You leveled up! Now you are level " << level << "!" << endl;
        Sleep(SLEEP_MS);
    }
}

void Player::LoseExperience(int xp){
    // Deducts points from the player's experience and de-levels player.

    // Deducts experience from passed in integer to local class variable experience.
    experience -= xp;

    // Evaluates if experience is less than 0.
    if (experience<0){
        // Experience is deducted continuing from the experience which de-leveled the player (hard to explain...)
        experience = 100-(0-experience);

        // De-levels player.
        level-=1;

        // Checks any glitches and sets player level to 1 if level is below 1 or above 50.
        // Also resets experience points.
        if (level<1 || level>50){
            level=1;
            experience = 0;
        }

        // Alerts the player that they have de-leveled.
        else {
            cout << "You de-leveled back to level " << level << "..." << endl;
            Sleep(SLEEP_MS);
        }
    }
}

void Player::AddCoins(int c){
    coins += c;
}

void Player::LoseCoins(int c){
    coins -= c;
    if (coins < 0) coins = 0;
}

void Player::DisplayInventory(){
    // Checks valid weapon strength.
    if (weaponstrength < 0){
        weaponstrength = 0;
    }
    // Simply prints the player's inventory.

    cout << "*----------- INVENTORY -----------* " << endl;
    cout << "Level " << level << "\t\t\t" << experience << "/100 xp" << endl;
    cout << "| Arrows: [" << arrows << "]" << endl;
    cout << "| Potions: [" << potions << "]" << endl;
    cout << "| Bombs: [" << bombs << "]" << endl;
    cout << "| Whetstones: [" << whetstones << "]" << endl;
    cout << "| Weapon strength: [" << weaponstrength << "%]" << endl;
    cout << "| Wealth: [" << coins << "] coins" << endl;
    cout << "*---------------------------------*" << endl << endl;
}

int Player::GenericAttack(){
    int damage = ReturnDamage();
    DeductDamage(damage);
	ColourPrint(name, DARK_GREY);
    cout << " attacks! He deals ";
	ColourPrint(to_string(damage), RED);
    cout << " damage points!" << endl;
    if (damage>0) weaponstrength-= 2+rand()%5;
    return damage;
}

int Player::RiskAttack(){
    int damage = ReturnRiskAttackDamage();
    DeductDamage(damage);
	ColourPrint(name, DARK_GREY);
    cout << " takes a risk and attack! It deals ";
	ColourPrint(to_string(damage), RED);
    cout << " damage points!" << endl;

    if (damage>0) weaponstrength-= 4+rand()%5;
    return damage;
}

int Player::BowAndArrow(){
    int damage = ReturnBowDamage();
	ColourPrint(name, DARK_GREY);
    cout << " shoots his bow! He deals ";
    SetConsoleTextAttribute(hConsole, RED);
    cout << damage;
    SetConsoleTextAttribute(hConsole, GREY);
    cout << " damage points!" << endl;
    return damage;
}

void Player::UseWhetstone(){
    weaponstrength=100;
	ColourPrint(name, DARK_GREY);
    cout << " sharpened his weapon!" << endl;
    whetstones--;
}

void Player::UsePotion(){
    health=100;
	ColourPrint(name, DARK_GREY);
    cout << " drank a healing potion!" << endl;
    potions--;
}

int Player::UseBomb(){
	ColourPrint(name, DARK_GREY);
    cout << " hurls a bomb! It deals ";
	ColourPrint("50", RED);
	cout << " damage points!" << endl;

	bombs--;
    return 50;
}

void Player::DeductDamage(int &damage){
    if (weaponstrength<=75&&weaponstrength>50)
        damage-=1;
    else if (weaponstrength<=50&&weaponstrength>30)
        damage-=4;
    else if (weaponstrength<=30&&weaponstrength>20)
        damage-=5;
    else if (weaponstrength<=20&&weaponstrength>10)
        damage-=6;
    else if (weaponstrength<=10)
        damage-=7;
    if (damage<0)
        damage=0;
}

int Player::ReturnBowDamage(){
    if (arrows < 1)
        return 0;
    arrows--;
    return 10+rand()%6; // 10 - 15
}

int Player::Flee(){
	ColourPrint(name, DARK_GREY);
    cout << " chooses to flee!" << endl;
    return -1;
}
<|endoftext|>


<commit_before>// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef RPC_CONNECTIVITY_MESSAGES_HPP_
#define RPC_CONNECTIVITY_MESSAGES_HPP_

#include <vector>

// For cluster_version_t.  Once we drop old gcc's, we can just declare "enum class
// cluster_version_t;" in this header.
// RSI: Can we do that now?
#include "version.hpp"

class connectivity_service_t;
class peer_id_t;
class read_stream_t;
class write_stream_t;

namespace boost {
template <class> class function;
}

/* `message_service_t` is an abstract superclass for things that let you send
messages to other nodes. `message_handler_t` is an abstract superclass for
things that handle messages received from other nodes. The general pattern
usually looks something like this:

    class cluster_t : public message_service_t {
    public:
        class run_t {
        public:
            run_t(cluster_t *, message_handler_t *);
        };
        ...
    };

    class application_t : public message_handler_t {
    public:
        application_t(message_service_t *);
        ...
    };

    void do_cluster() {
        cluster_t cluster;
        application_t app(&cluster);
        cluster_t::run_t cluster_run(&cluster, &app);
        ...
    }

The rationale for splitting the lower-level messaging stuff into two components
(e.g. `cluster_t` and `cluster_t::run_t`) is that it makes it clear how to stop
further messages from being delivered. When the `cluster_t::run_t` is destroyed,
no further messages are delivered. This gives a natural way to make sure that no
messages are still being delivered at the time that the `application_t`
destructor is called. */

class send_message_write_callback_t {
public:
    virtual ~send_message_write_callback_t() { }
    virtual void write(cluster_version_t cluster_version, write_stream_t *stream) = 0;
};

class message_service_t  {
public:
    virtual void send_message(peer_id_t dest_peer, send_message_write_callback_t *callback) = 0;
    virtual void kill_connection(peer_id_t dest_peer) = 0;
    virtual connectivity_service_t *get_connectivity_service() = 0;
protected:
    virtual ~message_service_t() { }
};

class message_handler_t {
public:
    virtual void on_message(peer_id_t source_peer, cluster_version_t version,
                            read_stream_t *) = 0;

    // Default implementation. Override to optimize for the local case.
    virtual void on_local_message(peer_id_t source_peer, cluster_version_t version,
                                  std::vector<char> &&data);
protected:
    virtual ~message_handler_t() { }
};

#endif /* RPC_CONNECTIVITY_MESSAGES_HPP_ */
<commit_msg>Removed pointless RSI comment.<commit_after>// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef RPC_CONNECTIVITY_MESSAGES_HPP_
#define RPC_CONNECTIVITY_MESSAGES_HPP_

#include <vector>

#include "version.hpp"

class connectivity_service_t;
class peer_id_t;
class read_stream_t;
class write_stream_t;

namespace boost {
template <class> class function;
}

/* `message_service_t` is an abstract superclass for things that let you send
messages to other nodes. `message_handler_t` is an abstract superclass for
things that handle messages received from other nodes. The general pattern
usually looks something like this:

    class cluster_t : public message_service_t {
    public:
        class run_t {
        public:
            run_t(cluster_t *, message_handler_t *);
        };
        ...
    };

    class application_t : public message_handler_t {
    public:
        application_t(message_service_t *);
        ...
    };

    void do_cluster() {
        cluster_t cluster;
        application_t app(&cluster);
        cluster_t::run_t cluster_run(&cluster, &app);
        ...
    }

The rationale for splitting the lower-level messaging stuff into two components
(e.g. `cluster_t` and `cluster_t::run_t`) is that it makes it clear how to stop
further messages from being delivered. When the `cluster_t::run_t` is destroyed,
no further messages are delivered. This gives a natural way to make sure that no
messages are still being delivered at the time that the `application_t`
destructor is called. */

class send_message_write_callback_t {
public:
    virtual ~send_message_write_callback_t() { }
    virtual void write(cluster_version_t cluster_version, write_stream_t *stream) = 0;
};

class message_service_t  {
public:
    virtual void send_message(peer_id_t dest_peer, send_message_write_callback_t *callback) = 0;
    virtual void kill_connection(peer_id_t dest_peer) = 0;
    virtual connectivity_service_t *get_connectivity_service() = 0;
protected:
    virtual ~message_service_t() { }
};

class message_handler_t {
public:
    virtual void on_message(peer_id_t source_peer, cluster_version_t version,
                            read_stream_t *) = 0;

    // Default implementation. Override to optimize for the local case.
    virtual void on_local_message(peer_id_t source_peer, cluster_version_t version,
                                  std::vector<char> &&data);
protected:
    virtual ~message_handler_t() { }
};

#endif /* RPC_CONNECTIVITY_MESSAGES_HPP_ */
<|endoftext|>


<commit_before>#include "WProgram.h"
#include "Midi.h"
#include <GUI.h>

void __attribute__((weak)) setup() {
}

void __attribute__((weak)) loop() {
}

void __attribute__((weak)) onNoteOn(uint8_t *msg) {
}

void __attribute__((weak)) onNoteOff(uint8_t *msg) {
}

void __attribute__((weak)) onControlChange(uint8_t *msg) {
}

void __attribute__((weak)) onNoteOn2(uint8_t *msg) {
}

void __attribute__((weak)) onNoteOff2(uint8_t *msg) {
}

void __attribute__((weak)) onControlChange2(uint8_t *msg) {
}

void __attribute__((weak)) on16Callback(uint32_t pos) {
}

void __attribute__((weak)) on32Callback(uint32_t pos) {
}

bool __attribute__((weak)) handleEvent(gui_event_t *evt) {
	return false;
}

class DefaultCallbacks : public MidiCallback, public ClockCallback {
public:
	void onNoteOn(uint8_t *msg) {
		::onNoteOn(msg);
	}
	void onNoteOff(uint8_t *msg) {
		::onNoteOff(msg);
	}
	void onControlChange(uint8_t *msg) {
		::onControlChange(msg);
	}
	void onNoteOn2(uint8_t *msg) {
		::onNoteOn2(msg);
	}
	void onNoteOff2(uint8_t *msg) {
		::onNoteOff2(msg);
	}
	void onControlChange2(uint8_t *msg) {
		::onControlChange2(msg);
	}
	void on16Callback(uint32_t pos) {
		::on16Callback(pos);
	}
	void on32Callback(uint32_t pos) {
		::on32Callback(pos);
	}

	void setupMidiCallbacks() {
		Midi.addOnNoteOnCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOn);
		Midi.addOnNoteOffCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOff);
		Midi.addOnControlChangeCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onControlChange);
		Midi2.addOnNoteOnCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOn2);
		Midi2.addOnNoteOffCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOff2);
		Midi2.addOnControlChangeCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onControlChange2);
	}

	void setupClockCallbacks() {
		MidiClock.addOn16Callback(this, (midi_clock_callback_ptr_t)&DefaultCallbacks::on16Callback);
		MidiClock.addOn32Callback(this, (midi_clock_callback_ptr_t)&DefaultCallbacks::on32Callback);
	}

};

DefaultCallbacks defaultCallbacks;

void __attribute__((weak)) setupEventHandlers() {
	GUI.addEventHandler(&handleEvent);
}

void __attribute__((weak)) setupMidiCallbacks() {
	defaultCallbacks.setupMidiCallbacks();
}

void __attribute__((weak)) setupClockCallbacks() {
	defaultCallbacks.setupClockCallbacks();
}
<commit_msg>added comment to test refing in commit messages<commit_after>#include "WProgram.h"
#include "Midi.h"
#include <GUI.h>

void __attribute__((weak)) setup() {
}

void __attribute__((weak)) loop() {
}

void __attribute__((weak)) onNoteOn(uint8_t *msg) {
}

void __attribute__((weak)) onNoteOff(uint8_t *msg) {
}

void __attribute__((weak)) onControlChange(uint8_t *msg) {
}

void __attribute__((weak)) onNoteOn2(uint8_t *msg) {
}

void __attribute__((weak)) onNoteOff2(uint8_t *msg) {
}

void __attribute__((weak)) onControlChange2(uint8_t *msg) {
}

void __attribute__((weak)) on16Callback(uint32_t pos) {
}

void __attribute__((weak)) on32Callback(uint32_t pos) {
}

bool __attribute__((weak)) handleEvent(gui_event_t *evt) {
	return false;
}

class DefaultCallbacks : public MidiCallback, public ClockCallback {
public:
	void onNoteOn(uint8_t *msg) {
		::onNoteOn(msg);
	}
	void onNoteOff(uint8_t *msg) {
		::onNoteOff(msg);
	}
	void onControlChange(uint8_t *msg) {
		::onControlChange(msg);
	}
	void onNoteOn2(uint8_t *msg) {
		::onNoteOn2(msg);
	}
	void onNoteOff2(uint8_t *msg) {
		::onNoteOff2(msg);
	}
	void onControlChange2(uint8_t *msg) {
		::onControlChange2(msg);
	}
	void on16Callback(uint32_t pos) {
		::on16Callback(pos);
	}
	void on32Callback(uint32_t pos) {
		::on32Callback(pos);
	}

	void setupMidiCallbacks() {
		Midi.addOnNoteOnCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOn);
		Midi.addOnNoteOffCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOff);
		Midi.addOnControlChangeCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onControlChange);
		Midi2.addOnNoteOnCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOn2);
		Midi2.addOnNoteOffCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onNoteOff2);
		Midi2.addOnControlChangeCallback(this, (midi_callback_ptr_t)&DefaultCallbacks::onControlChange2);
	}

	void setupClockCallbacks() {
		MidiClock.addOn16Callback(this, (midi_clock_callback_ptr_t)&DefaultCallbacks::on16Callback);
		// on32callbacks weakly linked, XXX check performance
		MidiClock.addOn32Callback(this, (midi_clock_callback_ptr_t)&DefaultCallbacks::on32Callback);
	}

};

DefaultCallbacks defaultCallbacks;

void __attribute__((weak)) setupEventHandlers() {
	GUI.addEventHandler(&handleEvent);
}

void __attribute__((weak)) setupMidiCallbacks() {
	defaultCallbacks.setupMidiCallbacks();
}

void __attribute__((weak)) setupClockCallbacks() {
	defaultCallbacks.setupClockCallbacks();
}
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2017 Raffaello D. Di Napoli

This file is part of Lofty.

Lofty is free software: you can redistribute it and/or modify it under the terms of version 2.1 of the GNU
Lesser General Public License as published by the Free Software Foundation.

Lofty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
------------------------------------------------------------------------------------------------------------*/

#include <lofty.hxx>
#include <lofty/app.hxx>
#include <lofty/collections/vector.hxx>
#include <lofty/defer_to_scope_end.hxx>
#include <lofty/io/text.hxx>
#include <lofty/logging.hxx>
#include <lofty/net/udp.hxx>

using namespace lofty;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

class udp_echo_client_app : public app {
public:
   /*! Main function of the program.

   @param args
      Arguments that were provided to this program via command line.
   @return
      Return value of this program.
   */
   virtual int main(collections::vector<str> & args) override {
      LOFTY_TRACE_METHOD();

      LOFTY_UNUSED_ARG(args);

      net::udp::client client;
      LOFTY_FOR_EACH(auto arg, args) {
         auto dgram_data(_std::make_shared<io::binary::memory_stream>());
         {
            auto dgram_ostream(io::text::make_ostream(dgram_data));
            LOFTY_DEFER_TO_SCOPE_END(dgram_ostream->finalize());
            dgram_ostream->print(LOFTY_SL("{}\n"), arg);
         }
         net::udp::datagram dgram(net::ip::address::localhost_v4, net::ip::port(9081), _std::move(dgram_data));
         LOFTY_LOG(info, LOFTY_SL("client: sending datagram\n"));
         client.send(dgram);
      }

      return 0;
   }
};

LOFTY_APP_CLASS(udp_echo_client_app)
<commit_msg>Use auto const & to iterate over vector<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2017-2018 Raffaello D. Di Napoli

This file is part of Lofty.

Lofty is free software: you can redistribute it and/or modify it under the terms of version 2.1 of the GNU
Lesser General Public License as published by the Free Software Foundation.

Lofty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details.
------------------------------------------------------------------------------------------------------------*/

#include <lofty.hxx>
#include <lofty/app.hxx>
#include <lofty/collections/vector.hxx>
#include <lofty/defer_to_scope_end.hxx>
#include <lofty/io/text.hxx>
#include <lofty/logging.hxx>
#include <lofty/net/udp.hxx>

using namespace lofty;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

class udp_echo_client_app : public app {
public:
   /*! Main function of the program.

   @param args
      Arguments that were provided to this program via command line.
   @return
      Return value of this program.
   */
   virtual int main(collections::vector<str> & args) override {
      LOFTY_TRACE_METHOD();

      LOFTY_UNUSED_ARG(args);

      net::udp::client client;
      LOFTY_FOR_EACH(auto const & arg, args) {
         auto dgram_data(_std::make_shared<io::binary::memory_stream>());
         {
            auto dgram_ostream(io::text::make_ostream(dgram_data));
            LOFTY_DEFER_TO_SCOPE_END(dgram_ostream->finalize());
            dgram_ostream->print(LOFTY_SL("{}\n"), arg);
         }
         net::udp::datagram dgram(net::ip::address::localhost_v4, net::ip::port(9081), _std::move(dgram_data));
         LOFTY_LOG(info, LOFTY_SL("client: sending datagram\n"));
         client.send(dgram);
      }

      return 0;
   }
};

LOFTY_APP_CLASS(udp_echo_client_app)
<|endoftext|>


<commit_before>
#include <stack.cpp>
#include <catch.hpp>
#include <iostream>
//using namespace std;

SCENARIO("count", "[count]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
}

SCENARIO("push", "[push]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}

SCENARIO("top", "[top]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}

SCENARIO("pop", "[pop]"){
  stack<int> s;
  s.push(1);
  s.push(2);
  s.pop();
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}

SCENARIO("prisv", "[prisv]"){
  stack<int> s;
  s.push(1);
  stack<int> s2;
  s2=s;
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}
SCENARIO("copy", "[copy]"){
  stack<int> s;
  s.push(1);
  stack <int> a = s;
  REQUIRE(a.count()==1);
  REQUIRE(a.top()==1);
}
SCENARIO("test", "[test]"){
  stack<int> s;
  REQUIRE(s.count()==0);
}
SCENARIO("empty", "[empty]"){
  stack<int> s;
  REQUIRE(s.empty()==true);
}
<commit_msg>Update init.cpp<commit_after>#include <stack.cpp>
#include <catch.hpp>
#include <iostream>
using namespace std;

SCENARIO("count", "[count]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
}

SCENARIO("push", "[push]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
  REQUIRE(s.pop()==1);
}

SCENARIO("pop", "[pop]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
  REQUIRE(s.pop()==1);
}

SCENARIO("prisv", "[prisv]"){
  stack<int> s;
  s.push(1);
  stack<int> s2;
  s2=s;
  REQUIRE(s.count()==1);
  REQUIRE(s.pop()==1);
}
SCENARIO("copy", "[copy]"){
  stack<int> s;
  s.push(1);
  stack <int> a = s;
  REQUIRE(a.count()==1);
  REQUIRE(a.pop()==1);
}
SCENARIO("test", "[test]"){
  stack<int> s;
  REQUIRE(s.count()==0);
}
<|endoftext|>


<commit_before>#define PY_SSIZE_T_CLEAN 1
#include <Python.h>
#include <bytesobject.h>
#include "../enc/encode.h"
#include "../dec/decode.h"
#include "../tools/version.h"

#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
#endif

using namespace brotli;

static PyObject *BrotliError;

static int mode_convertor(PyObject *o, BrotliParams::Mode *mode) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  *mode = (BrotliParams::Mode) PyInt_AsLong(o);
  if (*mode != BrotliParams::MODE_GENERIC &&
      *mode != BrotliParams::MODE_TEXT &&
      *mode != BrotliParams::MODE_FONT) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  return 1;
}

static int quality_convertor(PyObject *o, int *quality) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid quality");
    return 0;
  }

  *quality = PyInt_AsLong(o);
  if (*quality < 0 || *quality > 11) {
    PyErr_SetString(BrotliError, "Invalid quality. Range is 0 to 11.");
    return 0;
  }

  return 1;
}

static int lgwin_convertor(PyObject *o, int *lgwin) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgwin");
    return 0;
  }

  *lgwin = PyInt_AsLong(o);
  if (*lgwin < 10 || *lgwin > 24) {
    PyErr_SetString(BrotliError, "Invalid lgwin. Range is 10 to 24.");
    return 0;
  }

  return 1;
}

static int lgblock_convertor(PyObject *o, int *lgblock) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgblock");
    return 0;
  }

  *lgblock = PyInt_AsLong(o);
  if ((*lgblock != 0 && *lgblock < 16) || *lgblock > 24) {
    PyErr_SetString(BrotliError, "Invalid lgblock. Can be 0 or in range 16 to 24.");
    return 0;
  }

  return 1;
}

PyDoc_STRVAR(compress__doc__,
"Compress a byte string.\n"
"\n"
"Signature:\n"
"  compress(string, mode=MODE_GENERIC, quality=11, lgwin=22, lgblock=0)\n"
"\n"
"Args:\n"
"  string (bytes): The input data.\n"
"  mode (int, optional): The compression mode can be MODE_GENERIC (default),\n"
"    MODE_TEXT (for UTF-8 format text input) or MODE_FONT (for WOFF 2.0). \n"
"  quality (int, optional): Controls the compression-speed vs compression-\n"
"    density tradeoff. The higher the quality, the slower the compression.\n"
"    Range is 0 to 11. Defaults to 11.\n"
"  lgwin (int, optional): Base 2 logarithm of the sliding window size. Range\n"
"    is 10 to 24. Defaults to 22.\n"
"  lgblock (int, optional): Base 2 logarithm of the maximum input block size.\n"
"    Range is 16 to 24. If set to 0, the value will be set based on the\n"
"    quality. Defaults to 0.\n"
"\n"
"Returns:\n"
"  The compressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If arguments are invalid, or compressor fails.\n");

static PyObject* brotli_compress(PyObject *self, PyObject *args, PyObject *keywds) {
  PyObject *ret = NULL;
  uint8_t *input, *output;
  size_t length, output_length;
  BrotliParams::Mode mode = (BrotliParams::Mode) -1;
  int quality = -1;
  int lgwin = -1;
  int lgblock = -1;
  int ok;

  static const char *kwlist[] = {"string", "mode", "quality", "lgwin", "lgblock", NULL};

  ok = PyArg_ParseTupleAndKeywords(args, keywds, "s#|O&O&O&O&:compress",
                        const_cast<char **>(kwlist),
                        &input, &length,
                        &mode_convertor, &mode,
                        &quality_convertor, &quality,
                        &lgwin_convertor, &lgwin,
                        &lgblock_convertor, &lgblock);

  if (!ok)
    return NULL;

  output_length = 1.2 * length + 10240;
  output = new uint8_t[output_length];

  BrotliParams params;
  if (mode != -1)
    params.mode = mode;
  if (quality != -1)
    params.quality = quality;
  if (lgwin != -1)
    params.lgwin = lgwin;
  if (lgblock != -1)
    params.lgblock = lgblock;

  ok = BrotliCompressBuffer(params, length, input,
                            &output_length, output);
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)output, output_length);
  } else {
    PyErr_SetString(BrotliError, "BrotliCompressBuffer failed");
  }

  delete[] output;

  return ret;
}

PyDoc_STRVAR(decompress__doc__,
"Decompress a compressed byte string.\n"
"\n"
"Signature:\n"
"  decompress(string)\n"
"\n"
"Args:\n"
"  string (bytes): The compressed input data.\n"
"\n"
"Returns:\n"
"  The decompressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If decompressor fails.\n");

static PyObject* brotli_decompress(PyObject *self, PyObject *args) {
  PyObject *ret = NULL;
  uint8_t *input;
  size_t length;
  int ok;

  ok = PyArg_ParseTuple(args, "s#:decompress", &input, &length);
  if (!ok)
    return NULL;

  std::vector<uint8_t> output;
  const size_t kBufferSize = 65536;
  uint8_t* buffer = new uint8_t[kBufferSize];
  BrotliState state;
  BrotliStateInit(&state);

  BrotliResult result = BROTLI_RESULT_NEEDS_MORE_OUTPUT;
  while (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) {
    size_t available_out = kBufferSize;
    uint8_t* next_out = buffer;
    size_t total_out = 0;
    result = BrotliDecompressStream(&length, &input,
                                    &available_out, &next_out,
                                    &total_out, &state);
    size_t used_out = kBufferSize - available_out;
    if (used_out != 0)
      output->insert(output->end(), buffer, buffer + used_out);
  }
  ok = result == BROTLI_RESULT_SUCCESS;
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)(output.size() ? &output[0] : NULL), output.size());
  } else {
    PyErr_SetString(BrotliError, "BrotliDecompress failed");
  }

  BrotliStateCleanup(&state);
  delete[] buffer;

  return ret;
}

static PyMethodDef brotli_methods[] = {
  {"compress",   (PyCFunction)brotli_compress, METH_VARARGS | METH_KEYWORDS, compress__doc__},
  {"decompress", brotli_decompress, METH_VARARGS, decompress__doc__},
  {NULL, NULL, 0, NULL}
};

PyDoc_STRVAR(brotli__doc__,
"The functions in this module allow compression and decompression using the\n"
"Brotli library.\n\n");

#if PY_MAJOR_VERSION >= 3
#define INIT_BROTLI   PyInit_brotli
#define CREATE_BROTLI PyModule_Create(&brotli_module)
#define RETURN_BROTLI return m

static struct PyModuleDef brotli_module = {
  PyModuleDef_HEAD_INIT,
  "brotli",
  brotli__doc__,
  0,
  brotli_methods,
  NULL,
  NULL,
  NULL
};
#else
#define INIT_BROTLI   initbrotli
#define CREATE_BROTLI Py_InitModule3("brotli", brotli_methods, brotli__doc__)
#define RETURN_BROTLI return
#endif

PyMODINIT_FUNC INIT_BROTLI(void) {
  PyObject *m = CREATE_BROTLI;

  BrotliError = PyErr_NewException((char*) "brotli.error", NULL, NULL);

  if (BrotliError != NULL) {
    Py_INCREF(BrotliError);
    PyModule_AddObject(m, "error", BrotliError);
  }

  PyModule_AddIntConstant(m, "MODE_GENERIC", (int) BrotliParams::MODE_GENERIC);
  PyModule_AddIntConstant(m, "MODE_TEXT", (int) BrotliParams::MODE_TEXT);
  PyModule_AddIntConstant(m, "MODE_FONT", (int) BrotliParams::MODE_FONT);

  PyModule_AddStringConstant(m, "__version__", BROTLI_VERSION);

  RETURN_BROTLI;
}
<commit_msg>Fix pointer dereferencing.<commit_after>#define PY_SSIZE_T_CLEAN 1
#include <Python.h>
#include <bytesobject.h>
#include "../enc/encode.h"
#include "../dec/decode.h"
#include "../tools/version.h"

#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong
#endif

using namespace brotli;

static PyObject *BrotliError;

static int mode_convertor(PyObject *o, BrotliParams::Mode *mode) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  *mode = (BrotliParams::Mode) PyInt_AsLong(o);
  if (*mode != BrotliParams::MODE_GENERIC &&
      *mode != BrotliParams::MODE_TEXT &&
      *mode != BrotliParams::MODE_FONT) {
    PyErr_SetString(BrotliError, "Invalid mode");
    return 0;
  }

  return 1;
}

static int quality_convertor(PyObject *o, int *quality) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid quality");
    return 0;
  }

  *quality = PyInt_AsLong(o);
  if (*quality < 0 || *quality > 11) {
    PyErr_SetString(BrotliError, "Invalid quality. Range is 0 to 11.");
    return 0;
  }

  return 1;
}

static int lgwin_convertor(PyObject *o, int *lgwin) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgwin");
    return 0;
  }

  *lgwin = PyInt_AsLong(o);
  if (*lgwin < 10 || *lgwin > 24) {
    PyErr_SetString(BrotliError, "Invalid lgwin. Range is 10 to 24.");
    return 0;
  }

  return 1;
}

static int lgblock_convertor(PyObject *o, int *lgblock) {
  if (!PyInt_Check(o)) {
    PyErr_SetString(BrotliError, "Invalid lgblock");
    return 0;
  }

  *lgblock = PyInt_AsLong(o);
  if ((*lgblock != 0 && *lgblock < 16) || *lgblock > 24) {
    PyErr_SetString(BrotliError, "Invalid lgblock. Can be 0 or in range 16 to 24.");
    return 0;
  }

  return 1;
}

PyDoc_STRVAR(compress__doc__,
"Compress a byte string.\n"
"\n"
"Signature:\n"
"  compress(string, mode=MODE_GENERIC, quality=11, lgwin=22, lgblock=0)\n"
"\n"
"Args:\n"
"  string (bytes): The input data.\n"
"  mode (int, optional): The compression mode can be MODE_GENERIC (default),\n"
"    MODE_TEXT (for UTF-8 format text input) or MODE_FONT (for WOFF 2.0). \n"
"  quality (int, optional): Controls the compression-speed vs compression-\n"
"    density tradeoff. The higher the quality, the slower the compression.\n"
"    Range is 0 to 11. Defaults to 11.\n"
"  lgwin (int, optional): Base 2 logarithm of the sliding window size. Range\n"
"    is 10 to 24. Defaults to 22.\n"
"  lgblock (int, optional): Base 2 logarithm of the maximum input block size.\n"
"    Range is 16 to 24. If set to 0, the value will be set based on the\n"
"    quality. Defaults to 0.\n"
"\n"
"Returns:\n"
"  The compressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If arguments are invalid, or compressor fails.\n");

static PyObject* brotli_compress(PyObject *self, PyObject *args, PyObject *keywds) {
  PyObject *ret = NULL;
  uint8_t *input, *output;
  size_t length, output_length;
  BrotliParams::Mode mode = (BrotliParams::Mode) -1;
  int quality = -1;
  int lgwin = -1;
  int lgblock = -1;
  int ok;

  static const char *kwlist[] = {"string", "mode", "quality", "lgwin", "lgblock", NULL};

  ok = PyArg_ParseTupleAndKeywords(args, keywds, "s#|O&O&O&O&:compress",
                        const_cast<char **>(kwlist),
                        &input, &length,
                        &mode_convertor, &mode,
                        &quality_convertor, &quality,
                        &lgwin_convertor, &lgwin,
                        &lgblock_convertor, &lgblock);

  if (!ok)
    return NULL;

  output_length = 1.2 * length + 10240;
  output = new uint8_t[output_length];

  BrotliParams params;
  if (mode != -1)
    params.mode = mode;
  if (quality != -1)
    params.quality = quality;
  if (lgwin != -1)
    params.lgwin = lgwin;
  if (lgblock != -1)
    params.lgblock = lgblock;

  ok = BrotliCompressBuffer(params, length, input,
                            &output_length, output);
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)output, output_length);
  } else {
    PyErr_SetString(BrotliError, "BrotliCompressBuffer failed");
  }

  delete[] output;

  return ret;
}

PyDoc_STRVAR(decompress__doc__,
"Decompress a compressed byte string.\n"
"\n"
"Signature:\n"
"  decompress(string)\n"
"\n"
"Args:\n"
"  string (bytes): The compressed input data.\n"
"\n"
"Returns:\n"
"  The decompressed byte string.\n"
"\n"
"Raises:\n"
"  brotli.error: If decompressor fails.\n");

static PyObject* brotli_decompress(PyObject *self, PyObject *args) {
  PyObject *ret = NULL;
  uint8_t *input;
  size_t length;
  int ok;

  ok = PyArg_ParseTuple(args, "s#:decompress", &input, &length);
  if (!ok)
    return NULL;

  std::vector<uint8_t> output;
  const size_t kBufferSize = 65536;
  uint8_t* buffer = new uint8_t[kBufferSize];
  BrotliState state;
  BrotliStateInit(&state);

  BrotliResult result = BROTLI_RESULT_NEEDS_MORE_OUTPUT;
  while (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) {
    size_t available_out = kBufferSize;
    uint8_t* next_out = buffer;
    size_t total_out = 0;
    result = BrotliDecompressStream(&length, &input,
                                    &available_out, &next_out,
                                    &total_out, &state);
    size_t used_out = kBufferSize - available_out;
    if (used_out != 0)
      output.insert(output.end(), buffer, buffer + used_out);
  }
  ok = result == BROTLI_RESULT_SUCCESS;
  if (ok) {
    ret = PyBytes_FromStringAndSize((char*)(output.size() ? &output[0] : NULL), output.size());
  } else {
    PyErr_SetString(BrotliError, "BrotliDecompress failed");
  }

  BrotliStateCleanup(&state);
  delete[] buffer;

  return ret;
}

static PyMethodDef brotli_methods[] = {
  {"compress",   (PyCFunction)brotli_compress, METH_VARARGS | METH_KEYWORDS, compress__doc__},
  {"decompress", brotli_decompress, METH_VARARGS, decompress__doc__},
  {NULL, NULL, 0, NULL}
};

PyDoc_STRVAR(brotli__doc__,
"The functions in this module allow compression and decompression using the\n"
"Brotli library.\n\n");

#if PY_MAJOR_VERSION >= 3
#define INIT_BROTLI   PyInit_brotli
#define CREATE_BROTLI PyModule_Create(&brotli_module)
#define RETURN_BROTLI return m

static struct PyModuleDef brotli_module = {
  PyModuleDef_HEAD_INIT,
  "brotli",
  brotli__doc__,
  0,
  brotli_methods,
  NULL,
  NULL,
  NULL
};
#else
#define INIT_BROTLI   initbrotli
#define CREATE_BROTLI Py_InitModule3("brotli", brotli_methods, brotli__doc__)
#define RETURN_BROTLI return
#endif

PyMODINIT_FUNC INIT_BROTLI(void) {
  PyObject *m = CREATE_BROTLI;

  BrotliError = PyErr_NewException((char*) "brotli.error", NULL, NULL);

  if (BrotliError != NULL) {
    Py_INCREF(BrotliError);
    PyModule_AddObject(m, "error", BrotliError);
  }

  PyModule_AddIntConstant(m, "MODE_GENERIC", (int) BrotliParams::MODE_GENERIC);
  PyModule_AddIntConstant(m, "MODE_TEXT", (int) BrotliParams::MODE_TEXT);
  PyModule_AddIntConstant(m, "MODE_FONT", (int) BrotliParams::MODE_FONT);

  PyModule_AddStringConstant(m, "__version__", BROTLI_VERSION);

  RETURN_BROTLI;
}
<|endoftext|>