<commit_before>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2016, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "base-precomp.h"  // Precompiled headers

#include <mrpt/utils/CStream.h>
#include <mrpt/utils/CFileOutputStream.h>
#include <mrpt/utils/COutputLogger.h>
#include <mrpt/system/threads.h>
#include <cstdio>
#include <sstream>
#include <iostream>
#include <cstdarg> // for logFmt

#ifdef _MSC_VER
	#define WIN32_LEAN_AND_MEAN
	#include <windows.h>   // OutputDebugString() for MSVC
#endif

namespace std {
bool operator <(const mrpt::utils::COutputLogger::TCallbackEntry &e1, const mrpt::utils::COutputLogger::TCallbackEntry &e2)
{
	return e1.func<e2.func;
}
}

using namespace mrpt;
using namespace mrpt::system;
using namespace mrpt::utils;

using namespace std;

/**
 * Implementation file for the COutputLogger header class
 */

// COutputLogger
// ////////////////////////////////////////////////////////////

mrpt::system::TConsoleColor COutputLogger::logging_levels_to_colors[NUMBER_OF_VERBOSITY_LEVELS] = {
	CONCOL_BLUE,  // LVL_DEBUG
	CONCOL_NORMAL, // LVL_INFO
	CONCOL_GREEN, // LVL_WARN
	CONCOL_RED // LVL_ERROR
};

std::string COutputLogger::logging_levels_to_names[NUMBER_OF_VERBOSITY_LEVELS] = {
 	"DEBUG", //LVL_DEBUG
	"INFO ", // LVL_INFO
	"WARN ", // LVL_WARN
	"ERROR" // LVL_ERROR
};

COutputLogger::COutputLogger(const std::string &name) {
	this->loggerReset();
	m_logger_name = name;

}
COutputLogger::COutputLogger() {
	this->loggerReset();
}
COutputLogger::~COutputLogger() { }

void COutputLogger::logStr(const VerbosityLevel level, const std::string& msg_str) const {
	if (level<m_min_verbosity_level)
		return;

	// initialize a TMsg object
	TMsg msg(level, msg_str, *this);
	if (logging_enable_keep_record)
		m_history.push_back(msg);

	if (logging_enable_console_output) {
		msg.dumpToConsole();

		// User callbacks:
		for (const auto &c : m_listCallbacks)
			(*c.func)(msg.body,msg.level,msg.name,msg.timestamp,c.userParam);
	}
}

void COutputLogger::logFmt(const VerbosityLevel level, const char* fmt, ...) const {
	// see MRPT/libs/base/src/utils/CDeugOutputCapable.cpp for the iniitial
	// implementtion

	// check for NULL pointer
	if (!fmt) return;

	// initialize the va_list and let generateStringFromFormat do the work
	// http://c-faq.com/varargs/handoff.html
	va_list argp;
	va_start(argp, fmt);
	std::string str = this->generateStringFromFormat(fmt, argp);
	va_end(argp);

	this->logStr(level,str);
}

std::string COutputLogger::generateStringFromFormat(const char* fmt, va_list argp) const{
	int   result = -1, length = 1024;
	std::vector<char> buffer;
	// make sure that the buffer is large enough to handle the string
	while (result == -1)
	{
		buffer.resize(length + 10);
		result = os::vsnprintf(&buffer[0], length, fmt, argp);

		// http://www.cplusplus.com/reference/cstdio/vsnprintf/
		// only when this returned value is non-negative and less than n, the
		// string has been completely written
		if (result>=length) result=-1;
		length*=2;
	}

	// return result to the caller
	return std::string(&buffer[0]);

}
void COutputLogger::logCond(const VerbosityLevel level, bool cond, const std::string& msg_str) const
{
	if (!cond) return;
	this->logStr(level,msg_str);
}

void COutputLogger::setLoggerName(const std::string& name) { m_logger_name = name; }

std::string COutputLogger::getLoggerName() const { return m_logger_name; }

void COutputLogger::setMinLoggingLevel(const VerbosityLevel level /*= LVL_INFO */) {
	m_min_verbosity_level = level;
}
void COutputLogger::setVerbosityLevel(const VerbosityLevel level) {
	m_min_verbosity_level = level;
}

void COutputLogger::getLogAsString(std::string& fname) const {
	fname.clear();
	for (const auto & h : m_history)
		fname += h.getAsString();
}
std::string COutputLogger::getLogAsString() const{
	std::string str;
	this->getLogAsString(str);
	return str;
}
void COutputLogger::writeLogToFile(const std::string* fname_in /* = NULL */) const {
	// determine the filename - open it
	std::string fname;
	if (fname_in) {
		fname = *fname_in;
	}
	else {
		fname = m_logger_name + ".log";
	}
	CFileOutputStream fstream(fname);
	ASSERTMSG_(fstream.fileOpenCorrectly(),
			mrpt::format("\n[%s:] Could not open external file: %s",
				m_logger_name.c_str(), fname.c_str()) );

	std::string hist_str;
	this->getLogAsString(hist_str);
	fstream.printf("%s", hist_str.c_str());
	fstream.close();
}

void COutputLogger::dumpLogToConsole() const{
	for (const auto &h :m_history)
		h.dumpToConsole();
}

std::string COutputLogger::getLoggerLastMsg() const {
	TMsg last_msg = m_history.back();
	return last_msg.getAsString();
}

void COutputLogger::getLoggerLastMsg(std::string& msg_str) const {
	msg_str = this->getLoggerLastMsg();
}

void COutputLogger::loggerReset() {
	m_logger_name = "log"; // just the default name

	m_history.clear();
	logging_enable_console_output = true;
	logging_enable_keep_record    = false;

	// set the minimum logging level allowed for printing. By default its
	// LVL_INFO
	m_min_verbosity_level = LVL_INFO;
}

// TMsg Struct
// ////////////////////////////////////////////////////////////

COutputLogger::TMsg::TMsg(const mrpt::utils::VerbosityLevel level, const std::string& msg_str, const COutputLogger& logger) {
	this->reset();

	name = logger.getLoggerName();
	this->level = level;
	timestamp = mrpt::system::getCurrentTime(); // fill with the current time
	body = msg_str;
}
COutputLogger::TMsg::~TMsg() { }

void COutputLogger::TMsg::reset() {
	timestamp = INVALID_TIMESTAMP;
	level = LVL_INFO;
	name = "Message"; // default name
	body.clear();
}

std::string COutputLogger::TMsg::getAsString() const {
	stringstream out;
	out.str("");
	out << "[" << name <<  "|" << COutputLogger::logging_levels_to_names[level]  << "|"
		<< mrpt::system::timeLocalToString(timestamp,4)
		<< "] " << body;
	if (!body.empty() && *body.rbegin()!='\n')
		out<<std::endl;

	return out.str();
}
void COutputLogger::TMsg::getAsString(std::string* contents) const {
	*contents = this->getAsString();
}
void COutputLogger::TMsg::writeToStream(mrpt::utils::CStream& out) const {
	const std::string str = getAsString();
	out.printf("%s", str.c_str());
#ifdef _MSC_VER
	OutputDebugStringA(str.c_str());
#endif
}
void COutputLogger::TMsg::dumpToConsole() const {
	const std::string str = getAsString();

	const bool dump_to_cerr = (level==LVL_ERROR); // LVL_ERROR alternatively dumped to stderr instead of stdout

	// Set console color:
	const TConsoleColor concol = COutputLogger::logging_levels_to_colors[level];
	if (concol!=CONCOL_NORMAL)
		mrpt::system::setConsoleColor(concol, dump_to_cerr);
	// Output msg:
	::fputs(str.c_str(), dump_to_cerr ? stderr:stdout );
	// Switch back to normal color:
	if (concol!=CONCOL_NORMAL)
		mrpt::system::setConsoleColor(CONCOL_NORMAL);
#ifdef _MSC_VER
	OutputDebugStringA(str.c_str());
#endif
}

void COutputLogger::logRegisterCallback(output_logger_callback_t  userFunc, void *userParam )
{
	ASSERT_(userFunc!=NULL);
	TCallbackEntry cbe;
	cbe.func = userFunc;
	cbe.userParam = userParam;
	m_listCallbacks.insert(cbe);
}

void COutputLogger::logDeregisterCallback(output_logger_callback_t  userFunc, void *userParam )
{
	ASSERT_(userFunc!=NULL);
	TCallbackEntry cbe;
	cbe.func = userFunc;
	cbe.userParam = userParam;
	m_listCallbacks.erase(cbe);
}

<commit_msg>Outputlogger: fix callbacks when console is disabled; cout instead of stdout<commit_after>/* +---------------------------------------------------------------------------+
   |                     Mobile Robot Programming Toolkit (MRPT)               |
   |                          http://www.mrpt.org/                             |
   |                                                                           |
   | Copyright (c) 2005-2016, Individual contributors, see AUTHORS file        |
   | See: http://www.mrpt.org/Authors - All rights reserved.                   |
   | Released under BSD License. See details in http://www.mrpt.org/License    |
   +---------------------------------------------------------------------------+ */

#include "base-precomp.h"  // Precompiled headers

#include <mrpt/utils/CStream.h>
#include <mrpt/utils/CFileOutputStream.h>
#include <mrpt/utils/COutputLogger.h>
#include <mrpt/system/threads.h>
#include <cstdio>
#include <sstream>
#include <iostream>
#include <cstdarg> // for logFmt

#ifdef _MSC_VER
	#define WIN32_LEAN_AND_MEAN
	#include <windows.h>   // OutputDebugString() for MSVC
#endif

namespace std {
bool operator <(const mrpt::utils::COutputLogger::TCallbackEntry &e1, const mrpt::utils::COutputLogger::TCallbackEntry &e2)
{
	return e1.func<e2.func;
}
}

using namespace mrpt;
using namespace mrpt::system;
using namespace mrpt::utils;

using namespace std;

/**
 * Implementation file for the COutputLogger header class
 */

// COutputLogger
// ////////////////////////////////////////////////////////////

mrpt::system::TConsoleColor COutputLogger::logging_levels_to_colors[NUMBER_OF_VERBOSITY_LEVELS] = {
	CONCOL_BLUE,  // LVL_DEBUG
	CONCOL_NORMAL, // LVL_INFO
	CONCOL_GREEN, // LVL_WARN
	CONCOL_RED // LVL_ERROR
};

std::string COutputLogger::logging_levels_to_names[NUMBER_OF_VERBOSITY_LEVELS] = {
 	"DEBUG", //LVL_DEBUG
	"INFO ", // LVL_INFO
	"WARN ", // LVL_WARN
	"ERROR" // LVL_ERROR
};

COutputLogger::COutputLogger(const std::string &name) {
	this->loggerReset();
	m_logger_name = name;

}
COutputLogger::COutputLogger() {
	this->loggerReset();
}
COutputLogger::~COutputLogger() { }

void COutputLogger::logStr(const VerbosityLevel level, const std::string& msg_str) const {
	if (level<m_min_verbosity_level)
		return;

	// initialize a TMsg object
	TMsg msg(level, msg_str, *this);
	if (logging_enable_keep_record)
		m_history.push_back(msg);

	if (logging_enable_console_output) {
		msg.dumpToConsole();
	}

	// User callbacks:
	for (const auto &c : m_listCallbacks)
		(*c.func)(msg.body,msg.level,msg.name,msg.timestamp,c.userParam);
}

void COutputLogger::logFmt(const VerbosityLevel level, const char* fmt, ...) const {
	// see MRPT/libs/base/src/utils/CDeugOutputCapable.cpp for the iniitial
	// implementtion

	// check for NULL pointer
	if (!fmt) return;

	// initialize the va_list and let generateStringFromFormat do the work
	// http://c-faq.com/varargs/handoff.html
	va_list argp;
	va_start(argp, fmt);
	std::string str = this->generateStringFromFormat(fmt, argp);
	va_end(argp);

	this->logStr(level,str);
}

std::string COutputLogger::generateStringFromFormat(const char* fmt, va_list argp) const{
	int   result = -1, length = 1024;
	std::vector<char> buffer;
	// make sure that the buffer is large enough to handle the string
	while (result == -1)
	{
		buffer.resize(length + 10);
		result = os::vsnprintf(&buffer[0], length, fmt, argp);

		// http://www.cplusplus.com/reference/cstdio/vsnprintf/
		// only when this returned value is non-negative and less than n, the
		// string has been completely written
		if (result>=length) result=-1;
		length*=2;
	}

	// return result to the caller
	return std::string(&buffer[0]);

}
void COutputLogger::logCond(const VerbosityLevel level, bool cond, const std::string& msg_str) const
{
	if (!cond) return;
	this->logStr(level,msg_str);
}

void COutputLogger::setLoggerName(const std::string& name) { m_logger_name = name; }

std::string COutputLogger::getLoggerName() const { return m_logger_name; }

void COutputLogger::setMinLoggingLevel(const VerbosityLevel level /*= LVL_INFO */) {
	m_min_verbosity_level = level;
}
void COutputLogger::setVerbosityLevel(const VerbosityLevel level) {
	m_min_verbosity_level = level;
}

void COutputLogger::getLogAsString(std::string& fname) const {
	fname.clear();
	for (const auto & h : m_history)
		fname += h.getAsString();
}
std::string COutputLogger::getLogAsString() const{
	std::string str;
	this->getLogAsString(str);
	return str;
}
void COutputLogger::writeLogToFile(const std::string* fname_in /* = NULL */) const {
	// determine the filename - open it
	std::string fname;
	if (fname_in) {
		fname = *fname_in;
	}
	else {
		fname = m_logger_name + ".log";
	}
	CFileOutputStream fstream(fname);
	ASSERTMSG_(fstream.fileOpenCorrectly(),
			mrpt::format("\n[%s:] Could not open external file: %s",
				m_logger_name.c_str(), fname.c_str()) );

	std::string hist_str;
	this->getLogAsString(hist_str);
	fstream.printf("%s", hist_str.c_str());
	fstream.close();
}

void COutputLogger::dumpLogToConsole() const{
	for (const auto &h :m_history)
		h.dumpToConsole();
}

std::string COutputLogger::getLoggerLastMsg() const {
	TMsg last_msg = m_history.back();
	return last_msg.getAsString();
}

void COutputLogger::getLoggerLastMsg(std::string& msg_str) const {
	msg_str = this->getLoggerLastMsg();
}

void COutputLogger::loggerReset() {
	m_logger_name = "log"; // just the default name

	m_history.clear();
	logging_enable_console_output = true;
	logging_enable_keep_record    = false;

	// set the minimum logging level allowed for printing. By default its
	// LVL_INFO
	m_min_verbosity_level = LVL_INFO;
}

// TMsg Struct
// ////////////////////////////////////////////////////////////

COutputLogger::TMsg::TMsg(const mrpt::utils::VerbosityLevel level, const std::string& msg_str, const COutputLogger& logger) {
	this->reset();

	name = logger.getLoggerName();
	this->level = level;
	timestamp = mrpt::system::getCurrentTime(); // fill with the current time
	body = msg_str;
}
COutputLogger::TMsg::~TMsg() { }

void COutputLogger::TMsg::reset() {
	timestamp = INVALID_TIMESTAMP;
	level = LVL_INFO;
	name = "Message"; // default name
	body.clear();
}

std::string COutputLogger::TMsg::getAsString() const {
	stringstream out;
	out.str("");
	out << "[" << name <<  "|" << COutputLogger::logging_levels_to_names[level]  << "|"
		<< mrpt::system::timeLocalToString(timestamp,4)
		<< "] " << body;
	if (!body.empty() && *body.rbegin()!='\n')
		out<<std::endl;

	return out.str();
}
void COutputLogger::TMsg::getAsString(std::string* contents) const {
	*contents = this->getAsString();
}
void COutputLogger::TMsg::writeToStream(mrpt::utils::CStream& out) const {
	const std::string str = getAsString();
	out.printf("%s", str.c_str());
#ifdef _MSC_VER
	OutputDebugStringA(str.c_str());
#endif
}
void COutputLogger::TMsg::dumpToConsole() const {
	const std::string str = getAsString();

	const bool dump_to_cerr = (level==LVL_ERROR); // LVL_ERROR alternatively dumped to stderr instead of stdout

	// Set console color:
	const TConsoleColor concol = COutputLogger::logging_levels_to_colors[level];
	if (concol!=CONCOL_NORMAL)
		mrpt::system::setConsoleColor(concol, dump_to_cerr);
	// Output msg:
	(dump_to_cerr ? std::cerr : std::cout) << str;
	// Switch back to normal color:
	if (concol!=CONCOL_NORMAL)
		mrpt::system::setConsoleColor(CONCOL_NORMAL);
#ifdef _MSC_VER
	OutputDebugStringA(str.c_str());
#endif
}

void COutputLogger::logRegisterCallback(output_logger_callback_t  userFunc, void *userParam )
{
	ASSERT_(userFunc!=NULL);
	TCallbackEntry cbe;
	cbe.func = userFunc;
	cbe.userParam = userParam;
	m_listCallbacks.insert(cbe);
}

void COutputLogger::logDeregisterCallback(output_logger_callback_t  userFunc, void *userParam )
{
	ASSERT_(userFunc!=NULL);
	TCallbackEntry cbe;
	cbe.func = userFunc;
	cbe.userParam = userParam;
	m_listCallbacks.erase(cbe);
}

<|endoftext|>


<commit_before>/*
	This file is part of solidity.

	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * Analyzer part of inline assembly.
 */

#include <libsolidity/inlineasm/AsmAnalysis.h>

#include <libsolidity/inlineasm/AsmData.h>
#include <libsolidity/inlineasm/AsmScopeFiller.h>
#include <libsolidity/inlineasm/AsmScope.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>

#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/interface/Utils.h>

#include <boost/range/adaptor/reversed.hpp>

#include <memory>
#include <functional>

using namespace std;
using namespace dev;
using namespace dev::solidity;
using namespace dev::solidity::assembly;

namespace {

set<string> const builtinTypes{"bool", "u8", "s8", "u32", "s32", "u64", "s64", "u128", "s128", "u256", "s256"};

}

bool AsmAnalyzer::analyze(Block const& _block)
{
	if (!(ScopeFiller(m_info, m_errorReporter))(_block))
		return false;

	return (*this)(_block);
}

bool AsmAnalyzer::operator()(Label const& _label)
{
	solAssert(!m_julia, "");
	m_info.stackHeightInfo[&_label] = m_stackHeight;
	return true;
}

bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction)
{
	solAssert(!m_julia, "");
	auto const& info = instructionInfo(_instruction.instruction);
	m_stackHeight += info.ret - info.args;
	m_info.stackHeightInfo[&_instruction] = m_stackHeight;
	return true;
}

bool AsmAnalyzer::operator()(assembly::Literal const& _literal)
{
	expectValidType(_literal.type, _literal.location);
	++m_stackHeight;
	if (_literal.kind == assembly::LiteralKind::String && _literal.value.size() > 32)
	{
		m_errorReporter.typeError(
			_literal.location,
			"String literal too long (" + boost::lexical_cast<std::string>(_literal.value.size()) + " > 32)"
		);
		return false;
	}
	m_info.stackHeightInfo[&_literal] = m_stackHeight;
	return true;
}

bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
{
	size_t numErrorsBefore = m_errorReporter.errors().size();
	bool success = true;
	if (m_currentScope->lookup(_identifier.name, Scope::Visitor(
		[&](Scope::Variable const& _var)
		{
			if (!_var.active)
			{
				m_errorReporter.declarationError(
					_identifier.location,
					"Variable " + _identifier.name + " used before it was declared."
				);
				success = false;
			}
			++m_stackHeight;
		},
		[&](Scope::Label const&)
		{
			++m_stackHeight;
		},
		[&](Scope::Function const&)
		{
			m_errorReporter.typeError(
				_identifier.location,
				"Function " + _identifier.name + " used without being called."
			);
			success = false;
		}
	)))
	{
	}
	else
	{
		size_t stackSize(-1);
		if (m_resolver)
			stackSize = m_resolver(_identifier, julia::IdentifierContext::RValue);
		if (stackSize == size_t(-1))
		{
			// Only add an error message if the callback did not do it.
			if (numErrorsBefore == m_errorReporter.errors().size())
				m_errorReporter.declarationError(_identifier.location, "Identifier not found.");
			success = false;
		}
		m_stackHeight += stackSize == size_t(-1) ? 1 : stackSize;
	}
	m_info.stackHeightInfo[&_identifier] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr)
{
	solAssert(!m_julia, "");
	bool success = true;
	for (auto const& arg: _instr.arguments | boost::adaptors::reversed)
		if (!expectExpression(arg))
			success = false;
	// Parser already checks that the number of arguments is correct.
	solAssert(instructionInfo(_instr.instruction.instruction).args == int(_instr.arguments.size()), "");
	if (!(*this)(_instr.instruction))
		success = false;
	m_info.stackHeightInfo[&_instr] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment)
{
	solAssert(!m_julia, "");
	bool success = checkAssignment(_assignment.variableName, size_t(-1));
	m_info.stackHeightInfo[&_assignment] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::Assignment const& _assignment)
{
	int const stackHeight = m_stackHeight;
	bool success = boost::apply_visitor(*this, *_assignment.value);
	solAssert(m_stackHeight >= stackHeight, "Negative value size.");
	if (!checkAssignment(_assignment.variableName, m_stackHeight - stackHeight))
		success = false;
	m_info.stackHeightInfo[&_assignment] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)
{
	int const expectedItems = _varDecl.variables.size();
	int const stackHeight = m_stackHeight;
	bool success = boost::apply_visitor(*this, *_varDecl.value);
	if ((m_stackHeight - stackHeight) != expectedItems)
	{
		m_errorReporter.declarationError(_varDecl.location, "Variable count mismatch.");
		return false;
	}

	for (auto const& variable: _varDecl.variables)
	{
		expectValidType(variable.type, variable.location);
		boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)).active = true;
	}
	m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
{
	Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get();
	solAssert(virtualBlock, "");
	Scope& varScope = scope(virtualBlock);
	for (auto const& var: _funDef.arguments + _funDef.returns)
	{
		expectValidType(var.type, var.location);
		boost::get<Scope::Variable>(varScope.identifiers.at(var.name)).active = true;
	}

	int const stackHeight = m_stackHeight;
	m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();

	bool success = (*this)(_funDef.body);

	m_stackHeight = stackHeight;
	m_info.stackHeightInfo[&_funDef] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
{
	bool success = true;
	size_t arguments = 0;
	size_t returns = 0;
	if (!m_currentScope->lookup(_funCall.functionName.name, Scope::Visitor(
		[&](Scope::Variable const&)
		{
			m_errorReporter.typeError(
				_funCall.functionName.location,
				"Attempt to call variable instead of function."
			);
			success = false;
		},
		[&](Scope::Label const&)
		{
			m_errorReporter.typeError(
				_funCall.functionName.location,
				"Attempt to call label instead of function."
			);
			success = false;
		},
		[&](Scope::Function const& _fun)
		{
			/// TODO: compare types too
			arguments = _fun.arguments.size();
			returns = _fun.returns.size();
		}
	)))
	{
		m_errorReporter.declarationError(_funCall.functionName.location, "Function not found.");
		success = false;
	}
	if (success)
	{
		if (_funCall.arguments.size() != arguments)
		{
			m_errorReporter.typeError(
				_funCall.functionName.location,
				"Expected " + boost::lexical_cast<string>(arguments) + " arguments but got " +
				boost::lexical_cast<string>(_funCall.arguments.size()) + "."
			);
			success = false;
		}
	}
	for (auto const& arg: _funCall.arguments | boost::adaptors::reversed)
		if (!expectExpression(arg))
			success = false;
	m_stackHeight += int(returns) - int(arguments);
	m_info.stackHeightInfo[&_funCall] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(Switch const& _switch)
{
	bool success = true;

	if (!expectExpression(*_switch.expression))
		success = false;

	set<tuple<LiteralKind, string>> cases;
	for (auto const& _case: _switch.cases)
	{
		if (_case.value)
		{
			if (!expectExpression(*_case.value))
				success = false;
			m_stackHeight--;

			/// Note: the parser ensures there is only one default case
			auto val = make_tuple(_case.value->kind, _case.value->value);
			if (!cases.insert(val).second)
			{
				m_errorReporter.declarationError(
					_case.location,
					"Duplicate case defined"
				);
				success = false;
			}
		}

		if (!(*this)(_case.body))
			success = false;
	}

	m_stackHeight--;

	return success;
}

bool AsmAnalyzer::operator()(Block const& _block)
{
	bool success = true;
	auto previousScope = m_currentScope;
	m_currentScope = &scope(&_block);

	int const initialStackHeight = m_stackHeight;

	for (auto const& s: _block.statements)
		if (!boost::apply_visitor(*this, s))
			success = false;

	for (auto const& identifier: scope(&_block).identifiers)
		if (identifier.second.type() == typeid(Scope::Variable))
			--m_stackHeight;

	int const stackDiff = m_stackHeight - initialStackHeight;
	if (stackDiff != 0)
	{
		m_errorReporter.declarationError(
			_block.location,
			"Unbalanced stack at the end of a block: " +
			(
				stackDiff > 0 ?
				to_string(stackDiff) + string(" surplus item(s).") :
				to_string(-stackDiff) + string(" missing item(s).")
			)
		);
		success = false;
	}

	m_info.stackHeightInfo[&_block] = m_stackHeight;
	m_currentScope = previousScope;
	return success;
}

bool AsmAnalyzer::expectExpression(Statement const& _statement)
{
	bool success = true;
	int const initialHeight = m_stackHeight;
	if (!boost::apply_visitor(*this, _statement))
		success = false;
	if (m_stackHeight - initialHeight != 1)
	{
		m_errorReporter.typeError(
			locationOf(_statement),
			"Expected instruction(s) to deposit one item to the stack but did deposit " +
			boost::lexical_cast<string>(m_stackHeight - initialHeight) +
			" items."
		);
		success = false;
	}
	return success;
}

bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t _valueSize)
{
	bool success = true;
	size_t numErrorsBefore = m_errorReporter.errors().size();
	size_t variableSize(-1);
	if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
	{
		// Check that it is a variable
		if (var->type() != typeid(Scope::Variable))
		{
			m_errorReporter.typeError(_variable.location, "Assignment requires variable.");
			success = false;
		}
		else if (!boost::get<Scope::Variable>(*var).active)
		{
			m_errorReporter.declarationError(
				_variable.location,
				"Variable " + _variable.name + " used before it was declared."
			);
			success = false;
		}
		variableSize = 1;
	}
	else if (m_resolver)
		variableSize = m_resolver(_variable, julia::IdentifierContext::LValue);
	if (variableSize == size_t(-1))
	{
		// Only add message if the callback did not.
		if (numErrorsBefore == m_errorReporter.errors().size())
			m_errorReporter.declarationError(_variable.location, "Variable not found or variable not lvalue.");
		success = false;
	}
	if (_valueSize == size_t(-1))
		_valueSize = variableSize == size_t(-1) ? 1 : variableSize;

	m_stackHeight -= _valueSize;

	if (_valueSize != variableSize && variableSize != size_t(-1))
	{
		m_errorReporter.typeError(
			_variable.location,
			"Variable size (" +
			to_string(variableSize) +
			") and value size (" +
			to_string(_valueSize) +
			") do not match."
		);
		success = false;
	}
	return success;
}

Scope& AsmAnalyzer::scope(Block const* _block)
{
	solAssert(m_info.scopes.count(_block) == 1, "Scope requested but not present.");
	auto scopePtr = m_info.scopes.at(_block);
	solAssert(scopePtr, "Scope requested but not present.");
	return *scopePtr;
}

void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _location)
{
	if (!m_julia)
		return;

	if (!builtinTypes.count(type))
		m_errorReporter.typeError(
			_location,
			"\"" + type + "\" is not a valid type (user defined types are not yet supported)."
		);
}
<commit_msg>Improved error message.<commit_after>/*
	This file is part of solidity.

	solidity is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with solidity.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * Analyzer part of inline assembly.
 */

#include <libsolidity/inlineasm/AsmAnalysis.h>

#include <libsolidity/inlineasm/AsmData.h>
#include <libsolidity/inlineasm/AsmScopeFiller.h>
#include <libsolidity/inlineasm/AsmScope.h>
#include <libsolidity/inlineasm/AsmAnalysisInfo.h>

#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/interface/Utils.h>

#include <boost/range/adaptor/reversed.hpp>

#include <memory>
#include <functional>

using namespace std;
using namespace dev;
using namespace dev::solidity;
using namespace dev::solidity::assembly;

namespace {

set<string> const builtinTypes{"bool", "u8", "s8", "u32", "s32", "u64", "s64", "u128", "s128", "u256", "s256"};

}

bool AsmAnalyzer::analyze(Block const& _block)
{
	if (!(ScopeFiller(m_info, m_errorReporter))(_block))
		return false;

	return (*this)(_block);
}

bool AsmAnalyzer::operator()(Label const& _label)
{
	solAssert(!m_julia, "");
	m_info.stackHeightInfo[&_label] = m_stackHeight;
	return true;
}

bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction)
{
	solAssert(!m_julia, "");
	auto const& info = instructionInfo(_instruction.instruction);
	m_stackHeight += info.ret - info.args;
	m_info.stackHeightInfo[&_instruction] = m_stackHeight;
	return true;
}

bool AsmAnalyzer::operator()(assembly::Literal const& _literal)
{
	expectValidType(_literal.type, _literal.location);
	++m_stackHeight;
	if (_literal.kind == assembly::LiteralKind::String && _literal.value.size() > 32)
	{
		m_errorReporter.typeError(
			_literal.location,
			"String literal too long (" + boost::lexical_cast<std::string>(_literal.value.size()) + " > 32)"
		);
		return false;
	}
	m_info.stackHeightInfo[&_literal] = m_stackHeight;
	return true;
}

bool AsmAnalyzer::operator()(assembly::Identifier const& _identifier)
{
	size_t numErrorsBefore = m_errorReporter.errors().size();
	bool success = true;
	if (m_currentScope->lookup(_identifier.name, Scope::Visitor(
		[&](Scope::Variable const& _var)
		{
			if (!_var.active)
			{
				m_errorReporter.declarationError(
					_identifier.location,
					"Variable " + _identifier.name + " used before it was declared."
				);
				success = false;
			}
			++m_stackHeight;
		},
		[&](Scope::Label const&)
		{
			++m_stackHeight;
		},
		[&](Scope::Function const&)
		{
			m_errorReporter.typeError(
				_identifier.location,
				"Function " + _identifier.name + " used without being called."
			);
			success = false;
		}
	)))
	{
	}
	else
	{
		size_t stackSize(-1);
		if (m_resolver)
			stackSize = m_resolver(_identifier, julia::IdentifierContext::RValue);
		if (stackSize == size_t(-1))
		{
			// Only add an error message if the callback did not do it.
			if (numErrorsBefore == m_errorReporter.errors().size())
				m_errorReporter.declarationError(_identifier.location, "Identifier not found.");
			success = false;
		}
		m_stackHeight += stackSize == size_t(-1) ? 1 : stackSize;
	}
	m_info.stackHeightInfo[&_identifier] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(FunctionalInstruction const& _instr)
{
	solAssert(!m_julia, "");
	bool success = true;
	for (auto const& arg: _instr.arguments | boost::adaptors::reversed)
		if (!expectExpression(arg))
			success = false;
	// Parser already checks that the number of arguments is correct.
	solAssert(instructionInfo(_instr.instruction.instruction).args == int(_instr.arguments.size()), "");
	if (!(*this)(_instr.instruction))
		success = false;
	m_info.stackHeightInfo[&_instr] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment)
{
	solAssert(!m_julia, "");
	bool success = checkAssignment(_assignment.variableName, size_t(-1));
	m_info.stackHeightInfo[&_assignment] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::Assignment const& _assignment)
{
	int const stackHeight = m_stackHeight;
	bool success = boost::apply_visitor(*this, *_assignment.value);
	solAssert(m_stackHeight >= stackHeight, "Negative value size.");
	if (!checkAssignment(_assignment.variableName, m_stackHeight - stackHeight))
		success = false;
	m_info.stackHeightInfo[&_assignment] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)
{
	int const expectedItems = _varDecl.variables.size();
	int const stackHeight = m_stackHeight;
	bool success = boost::apply_visitor(*this, *_varDecl.value);
	if ((m_stackHeight - stackHeight) != expectedItems)
	{
		m_errorReporter.declarationError(_varDecl.location, "Variable count mismatch.");
		return false;
	}

	for (auto const& variable: _varDecl.variables)
	{
		expectValidType(variable.type, variable.location);
		boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)).active = true;
	}
	m_info.stackHeightInfo[&_varDecl] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
{
	Block const* virtualBlock = m_info.virtualBlocks.at(&_funDef).get();
	solAssert(virtualBlock, "");
	Scope& varScope = scope(virtualBlock);
	for (auto const& var: _funDef.arguments + _funDef.returns)
	{
		expectValidType(var.type, var.location);
		boost::get<Scope::Variable>(varScope.identifiers.at(var.name)).active = true;
	}

	int const stackHeight = m_stackHeight;
	m_stackHeight = _funDef.arguments.size() + _funDef.returns.size();

	bool success = (*this)(_funDef.body);

	m_stackHeight = stackHeight;
	m_info.stackHeightInfo[&_funDef] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(assembly::FunctionCall const& _funCall)
{
	bool success = true;
	size_t arguments = 0;
	size_t returns = 0;
	if (!m_currentScope->lookup(_funCall.functionName.name, Scope::Visitor(
		[&](Scope::Variable const&)
		{
			m_errorReporter.typeError(
				_funCall.functionName.location,
				"Attempt to call variable instead of function."
			);
			success = false;
		},
		[&](Scope::Label const&)
		{
			m_errorReporter.typeError(
				_funCall.functionName.location,
				"Attempt to call label instead of function."
			);
			success = false;
		},
		[&](Scope::Function const& _fun)
		{
			/// TODO: compare types too
			arguments = _fun.arguments.size();
			returns = _fun.returns.size();
		}
	)))
	{
		m_errorReporter.declarationError(_funCall.functionName.location, "Function not found.");
		success = false;
	}
	if (success)
	{
		if (_funCall.arguments.size() != arguments)
		{
			m_errorReporter.typeError(
				_funCall.functionName.location,
				"Expected " + boost::lexical_cast<string>(arguments) + " arguments but got " +
				boost::lexical_cast<string>(_funCall.arguments.size()) + "."
			);
			success = false;
		}
	}
	for (auto const& arg: _funCall.arguments | boost::adaptors::reversed)
		if (!expectExpression(arg))
			success = false;
	m_stackHeight += int(returns) - int(arguments);
	m_info.stackHeightInfo[&_funCall] = m_stackHeight;
	return success;
}

bool AsmAnalyzer::operator()(Switch const& _switch)
{
	bool success = true;

	if (!expectExpression(*_switch.expression))
		success = false;

	set<tuple<LiteralKind, string>> cases;
	for (auto const& _case: _switch.cases)
	{
		if (_case.value)
		{
			if (!expectExpression(*_case.value))
				success = false;
			m_stackHeight--;

			/// Note: the parser ensures there is only one default case
			auto val = make_tuple(_case.value->kind, _case.value->value);
			if (!cases.insert(val).second)
			{
				m_errorReporter.declarationError(
					_case.location,
					"Duplicate case defined"
				);
				success = false;
			}
		}

		if (!(*this)(_case.body))
			success = false;
	}

	m_stackHeight--;

	return success;
}

bool AsmAnalyzer::operator()(Block const& _block)
{
	bool success = true;
	auto previousScope = m_currentScope;
	m_currentScope = &scope(&_block);

	int const initialStackHeight = m_stackHeight;

	for (auto const& s: _block.statements)
		if (!boost::apply_visitor(*this, s))
			success = false;

	for (auto const& identifier: scope(&_block).identifiers)
		if (identifier.second.type() == typeid(Scope::Variable))
			--m_stackHeight;

	int const stackDiff = m_stackHeight - initialStackHeight;
	if (stackDiff != 0)
	{
		m_errorReporter.declarationError(
			_block.location,
			"Unbalanced stack at the end of a block: " +
			(
				stackDiff > 0 ?
				to_string(stackDiff) + string(" surplus item(s).") :
				to_string(-stackDiff) + string(" missing item(s).")
			)
		);
		success = false;
	}

	m_info.stackHeightInfo[&_block] = m_stackHeight;
	m_currentScope = previousScope;
	return success;
}

bool AsmAnalyzer::expectExpression(Statement const& _statement)
{
	bool success = true;
	int const initialHeight = m_stackHeight;
	if (!boost::apply_visitor(*this, _statement))
		success = false;
	if (m_stackHeight - initialHeight != 1)
	{
		m_errorReporter.typeError(
			locationOf(_statement),
			"Expected expression to return one item to the stack but did return " +
			boost::lexical_cast<string>(m_stackHeight - initialHeight) +
			" items."
		);
		success = false;
	}
	return success;
}

bool AsmAnalyzer::checkAssignment(assembly::Identifier const& _variable, size_t _valueSize)
{
	bool success = true;
	size_t numErrorsBefore = m_errorReporter.errors().size();
	size_t variableSize(-1);
	if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
	{
		// Check that it is a variable
		if (var->type() != typeid(Scope::Variable))
		{
			m_errorReporter.typeError(_variable.location, "Assignment requires variable.");
			success = false;
		}
		else if (!boost::get<Scope::Variable>(*var).active)
		{
			m_errorReporter.declarationError(
				_variable.location,
				"Variable " + _variable.name + " used before it was declared."
			);
			success = false;
		}
		variableSize = 1;
	}
	else if (m_resolver)
		variableSize = m_resolver(_variable, julia::IdentifierContext::LValue);
	if (variableSize == size_t(-1))
	{
		// Only add message if the callback did not.
		if (numErrorsBefore == m_errorReporter.errors().size())
			m_errorReporter.declarationError(_variable.location, "Variable not found or variable not lvalue.");
		success = false;
	}
	if (_valueSize == size_t(-1))
		_valueSize = variableSize == size_t(-1) ? 1 : variableSize;

	m_stackHeight -= _valueSize;

	if (_valueSize != variableSize && variableSize != size_t(-1))
	{
		m_errorReporter.typeError(
			_variable.location,
			"Variable size (" +
			to_string(variableSize) +
			") and value size (" +
			to_string(_valueSize) +
			") do not match."
		);
		success = false;
	}
	return success;
}

Scope& AsmAnalyzer::scope(Block const* _block)
{
	solAssert(m_info.scopes.count(_block) == 1, "Scope requested but not present.");
	auto scopePtr = m_info.scopes.at(_block);
	solAssert(scopePtr, "Scope requested but not present.");
	return *scopePtr;
}

void AsmAnalyzer::expectValidType(string const& type, SourceLocation const& _location)
{
	if (!m_julia)
		return;

	if (!builtinTypes.count(type))
		m_errorReporter.typeError(
			_location,
			"\"" + type + "\" is not a valid type (user defined types are not yet supported)."
		);
}
<|endoftext|>


<commit_before>
#include "config.h"

// system
#include <iostream>

// boost
#include <boost/filesystem.hpp>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

// dune-stuff
#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/filesystem.hh>
#include <dune/stuff/common/string.hh>

// dune-grid-multiscale
#include <dune/grid/multiscale/provider/cube.hh>

/**
  \brief      Creates a parameter file if it does not exist.

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  Dune::Stuff::Common::Filesystem::testCreateDirectory(filename);
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[grid.multiscale.provider.cube]" << std::endl;
    file << "numElements.0 = 6" << std::endl;
    file << "numElements.1 = 6" << std::endl;
    file << "numElements.2 = 6" << std::endl;
    file << "boundaryId = 7" << std::endl;                  // a cube from the factory gets the boundary ids 1 to 4 ind 2d and 1 to 6 ? in 3d
    file << "filename = msGrid_visualization" << std::endl;
    file << "partitions.0 = 2" << std::endl;
    file << "partitions.1 = 2" << std::endl;
    file << "partitions.2 = 2" << std::endl;
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

template< class GridPartType >
void measureTiming(const GridPartType& gridPart, Dune::Stuff::Common::LogStream& out, const std::string name = "")
{
  out << "  walking " << name << " grid part... " << std::flush;
  Dune::Timer timer;
  unsigned int elements = 0;
  for (typename GridPartType::template Codim< 0 >::IteratorType it = gridPart.template begin< 0 >();
       it != gridPart.template end< 0 >();
       ++it)
    ++elements;
  out << " done (has " << elements << " elements, took " << timer.elapsed() << " sek)" << std::endl;
  return;
}

int main(int argc, char** argv)
{
  try {
    // mpi
    Dune::MPIHelper::instance(argc, argv);

    // parameter
    const std::string id = "cube";
    const std::string filename = id + ".param";
    ensureParamFile(filename);
    Dune::ParameterTree paramTree = Dune::Stuff::Common::Parameter::Tree::init(argc, argv, filename);

    // logger
    Dune::Stuff::Common::Logger().create(Dune::Stuff::Common::LOG_INFO |
                                         Dune::Stuff::Common::LOG_CONSOLE |
                                         Dune::Stuff::Common::LOG_DEBUG);
    Dune::Stuff::Common::LogStream& info = Dune::Stuff::Common::Logger().info();
    Dune::Stuff::Common::LogStream& debug = Dune::Stuff::Common::Logger().debug();

    // timer
    Dune::Timer timer;

    // grid
    info << "setting up grid: " << std::endl;
    debug.suspend();
    typedef Dune::grid::Multiscale::Provider::Cube< Dune::GridSelector::GridType > GridProviderType;
    Dune::Stuff::Common::Parameter::Tree::assertSub(paramTree, GridProviderType::id, id);
    GridProviderType gridProvider(paramTree.sub(GridProviderType::id));
    typedef GridProviderType::MsGridType MsGridType;
    const MsGridType& msGrid = gridProvider.msGrid();
    debug.resume();
    info << "  took " << timer.elapsed()
         << " sec (has " << msGrid.globalGridPart()->grid().size(0) << " elements, "
         << msGrid.size() << " subdomains)" << std::endl;

    info << "visualizing... " << std::flush;
    debug.suspend();
    timer.reset();
    msGrid.visualize();
    debug.resume();
    info << " done (took " << timer.elapsed() << " sek)" << std::endl;

    // time grid parts
    info << "timing grid parts:" << std::endl;
    typedef MsGridType::GlobalGridPartType GlobalGridPartType;
    const Dune::shared_ptr< const GlobalGridPartType > globalGridPart = msGrid.globalGridPart();
    measureTiming(*globalGridPart, info, "global");
    typedef MsGridType::LocalGridPartType LocalGridPartType;
    const Dune::shared_ptr< const LocalGridPartType > firstLocalGridPart = msGrid.localGridPart(0);
    measureTiming(*firstLocalGridPart, info, "local (subdomain 0)");
    for (unsigned int subdomain = 1; subdomain < msGrid.size(); ++subdomain) {
      const Dune::shared_ptr< const LocalGridPartType > localGridPart = msGrid.localGridPart(subdomain);
      measureTiming(*localGridPart, debug, "local (subdomain " + Dune::Stuff::Common::String::convertTo(subdomain) + ")");
    }

    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch(...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<commit_msg>[examples.provider.cube] added coupling example<commit_after>
#include "config.h"

// system
#include <iostream>

// boost
#include <boost/filesystem.hpp>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

// dune-stuff
#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/common/filesystem.hh>
#include <dune/stuff/common/string.hh>

// dune-grid-multiscale
#include <dune/grid/multiscale/provider/cube.hh>

/**
  \brief      Creates a parameter file if it does not exist.

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  Dune::Stuff::Common::Filesystem::testCreateDirectory(filename);
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[grid.multiscale.provider.cube]" << std::endl;
    file << "numElements.0 = 6" << std::endl;
    file << "numElements.1 = 6" << std::endl;
    file << "numElements.2 = 6" << std::endl;
    file << "boundaryId = 7" << std::endl;                  // a cube from the factory gets the boundary ids 1 to 4 ind 2d and 1 to 6 ? in 3d
    file << "filename = msGrid_visualization" << std::endl;
    file << "partitions.0 = 2" << std::endl;
    file << "partitions.1 = 2" << std::endl;
    file << "partitions.2 = 2" << std::endl;
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

template< class GridPartType >
void measureTiming(const GridPartType& gridPart, Dune::Stuff::Common::LogStream& out, const std::string name = "")
{
  out << "  walking " << name << " grid part... " << std::flush;
  Dune::Timer timer;
  unsigned int elements = 0;
  for (typename GridPartType::template Codim< 0 >::IteratorType it = gridPart.template begin< 0 >();
       it != gridPart.template end< 0 >();
       ++it)
    ++elements;
  out << " done (has " << elements << " elements, took " << timer.elapsed() << " sek)" << std::endl;
} // void measureTiming()

template< class GlobalGridPartType, class CouplingGridPartType >
void testCoupling(const GlobalGridPartType& globalGridPart, const CouplingGridPartType& couplingGridPart, Dune::Stuff::Common::LogStream& out)
{
  // walk the grid part
  for (typename CouplingGridPartType::template Codim< 0 >::IteratorType entityIterator = couplingGridPart.template begin< 0 >();
       entityIterator != couplingGridPart.template end< 0 >();
       ++entityIterator) {
    const typename CouplingGridPartType::template Codim< 0 >::EntityType& entity = *entityIterator;
    const unsigned int entityIndex = globalGridPart.indexSet().index(entity);
    out << "entity " << entityIndex << ", neighbors " << std::flush;
    // walk the intersections
    for (typename CouplingGridPartType::IntersectionIteratorType intersectionIterator = couplingGridPart.ibegin(entity);
         intersectionIterator != couplingGridPart.iend(entity);
         ++intersectionIterator) {
      const typename CouplingGridPartType::IntersectionIteratorType::Intersection& intersection = *intersectionIterator;
      const typename CouplingGridPartType::IntersectionIteratorType::Intersection::EntityPointer neighborPtr = intersection.outside();
      const typename CouplingGridPartType::template Codim< 0 >::EntityType& neighbor = *neighborPtr;
      const unsigned int neighborIndex = globalGridPart.indexSet().index(neighbor);
      out << neighborIndex << " ";
    } // walk the intersections
    out << std::endl;
  } // walk the grid part
} // void testCoupling()

int main(int argc, char** argv)
{
  try {
    // mpi
    Dune::MPIHelper::instance(argc, argv);

    // parameter
    const std::string id = "cube";
    const std::string filename = id + ".param";
    ensureParamFile(filename);
    Dune::ParameterTree paramTree = Dune::Stuff::Common::Parameter::Tree::init(argc, argv, filename);

    // logger
    Dune::Stuff::Common::Logger().create(Dune::Stuff::Common::LOG_INFO |
                                         Dune::Stuff::Common::LOG_CONSOLE |
                                         Dune::Stuff::Common::LOG_DEBUG);
    Dune::Stuff::Common::LogStream& info = Dune::Stuff::Common::Logger().info();
    Dune::Stuff::Common::LogStream& debug = Dune::Stuff::Common::Logger().debug();

    // timer
    Dune::Timer timer;

    // grid
    info << "setting up grid: " << std::endl;
    debug.suspend();
    typedef Dune::grid::Multiscale::Provider::Cube< Dune::GridSelector::GridType > GridProviderType;
    Dune::Stuff::Common::Parameter::Tree::assertSub(paramTree, GridProviderType::id, id);
    GridProviderType gridProvider(paramTree.sub(GridProviderType::id));
    typedef GridProviderType::MsGridType MsGridType;
    const MsGridType& msGrid = gridProvider.msGrid();
    debug.resume();
    info << "  took " << timer.elapsed()
         << " sec (has " << msGrid.globalGridPart()->grid().size(0) << " elements, "
         << msGrid.size() << " subdomains)" << std::endl;

    info << "visualizing... " << std::flush;
    debug.suspend();
    timer.reset();
    msGrid.visualize();
    debug.resume();
    info << " done (took " << timer.elapsed() << " sek)" << std::endl;

    // time grid parts
    info << "timing grid parts:" << std::endl;
    typedef MsGridType::GlobalGridPartType GlobalGridPartType;
    const Dune::shared_ptr< const GlobalGridPartType > globalGridPart = msGrid.globalGridPart();
    measureTiming(*globalGridPart, info, "global");
    typedef MsGridType::CouplingGridPartType CouplingGridPartType;
    const unsigned int neighbor = *(msGrid.neighborsOf(0)->begin());
    const Dune::shared_ptr< const CouplingGridPartType > couplingGridPart = msGrid.couplingGridPart(0, neighbor);
    measureTiming(*couplingGridPart, info, "coupling (subdomain 0 with " + Dune::Stuff::Common::String::convertTo(neighbor) + ")");
    typedef MsGridType::LocalGridPartType LocalGridPartType;
    const Dune::shared_ptr< const LocalGridPartType > firstLocalGridPart = msGrid.localGridPart(0);
    measureTiming(*firstLocalGridPart, info, "local (subdomain 0)");
    for (unsigned int subdomain = 1; subdomain < msGrid.size(); ++subdomain) {
      const Dune::shared_ptr< const LocalGridPartType > localGridPart = msGrid.localGridPart(subdomain);
      measureTiming(*localGridPart, debug, "local (subdomain " + Dune::Stuff::Common::String::convertTo(subdomain) + ")");
    }

//    // test coupling grid part
//    info << "testing coupling grid part:" << std::endl;
//    testCoupling(*globalGridPart, *couplingGridPart, info);

    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch(...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<|endoftext|>


<commit_before><commit_msg>Fast flag for h264 improves performance of loop filter. Increases performance by about 10% with minimal quality loss.<commit_after><|endoftext|>


<commit_before>#ifndef __Data_majorRequirement__
#define __Data_majorRequirement__

#include "data-general.hpp"
using namespace std;

class MajorRequirement {
private:
  int needed;
  int has;
  bool satisfied;
  vector<Course> validCourses;
public:
  bool fulfillsRequirement(const Course& c) {
    for (vector<Course>::iterator i=validCourses.begin(); i!=validCourses.end(); ++i) {
      if (*i==c)
	return true;
    }
    return false;
  }

  void incrementHas() {
    ++has;
  }
}
<commit_msg>reindent data-majorRequirement<commit_after>#ifndef __Data_majorRequirement__
#define __Data_majorRequirement__

#include "data-general.hpp"
using namespace std;

class MajorRequirement {
private:
	int needed;
	int has;
	bool satisfied;
	vector<Course> validCourses;
public:
	bool fulfillsRequirement(const Course& c) {
		for (vector<Course>::iterator i=validCourses.begin(); i!=validCourses.end(); ++i) {
			if (*i==c)
				return true;
		}
		return false;
	}

	void incrementHas() {
		++has;
	}
};

#endif
<|endoftext|>


<commit_before>#include "word.h"
#include "kwic.h"
#include "cute.h"
#include "ide_listener.h"
#include "xml_listener.h"
#include "cute_runner.h"

void testWordShouldBeLessComparesInternalValue() {
	//Arrange
	const Word word1("abc");
	const Word word2("bcd");
	//Assert
	ASSERT_LESS(word1, word2);
}

void testWordShouldBeLessComparesCaseInsensitive() {
	//Arrange
	const Word word1("abc");
	const Word word2("BCD");
	//Assert
	ASSERT_LESS(word1, word2);
}

void testWordShiftLeftPrintsInternalValue() {
	//Arrange
	std::ostringstream out { };
	const Word word("hallo");
	//Act
	out << word;
	//Assert
	ASSERT_EQUAL("hallo", out.str());

}

void testConstructWordThrowsInvalidArgumentExceptionForNumber() {
	//Assert
	ASSERT_THROWS(Word("124abd"), std::invalid_argument);
}

void testConstructWordThrowsInvalidArgumentExceptionForSpecialCharacters() {
	//Assert
	ASSERT_THROWS(Word("dsl!*%"), std::invalid_argument);
}

void testWordConsistsOfOnlyLetters() {
	//Arrange
	std::istringstream in { "abc123%" };
	Word word { };
	//Act
	in >> word;
	//Assert
	ASSERT_EQUAL(Word("abc"), word);
}

void testWordIsEmptyIfStreamIsEmpty() {
	//Arrange
	std::istringstream in { "              " };
	Word word { };
	//Act
	in >> word;
	//Assert
	ASSERT_EQUAL(Word(""), word);
}

void testWordsAreDelimitedByNonAlphanumericCharacters() {
	//Arrange
	std::istringstream in { "compl33tely ~ weird !!??!! 4matted in_put" };
	Word word1 { }, word2 { }, word3 { }, word4 { }, word5 { }, word6 { };
	//Act
	in >> word1;
	in >> word2;
	in >> word3;
	in >> word4;
	in >> word5;
	in >> word6;
	//Assert
	ASSERT_EQUAL(Word("compl"), word1);
	ASSERT_EQUAL(Word("tely"), word2);
	ASSERT_EQUAL(Word("weird"), word3);
	ASSERT_EQUAL(Word("matted"), word4);
	ASSERT_EQUAL(Word("in"), word5);
	ASSERT_EQUAL(Word("put"), word6);
}

void testRotateSingleLineReturnsAllRotationsSorted() {
	//Arrange
	const Word mockWord1("this");
	const Word mockWord2("is");
	const Word mockWord3("a");
	const Word mockWord4("test");

	const std::vector<Word> words { Word("this"), Word("is"), Word("a"), Word("test") };

	//Act
	const auto rotatedWords = rotateWords(words);
	auto permuted = std::vector<std::vector<Word>> { };

	for (auto word : rotatedWords) {
		permuted.push_back(word);
	}

	//Assert
	const std::vector<Word> expected1 { mockWord3, mockWord4, mockWord1, mockWord2 };
	ASSERT_EQUAL(expected1, permuted.at(0));

	const std::vector<Word> expected2 { mockWord2, mockWord3, mockWord4, mockWord1 };
	ASSERT_EQUAL(expected2, permuted.at(1));

	const std::vector<Word> expected3 { mockWord4, mockWord1, mockWord2, mockWord3 };
	ASSERT_EQUAL(expected3, permuted.at(2));

	const std::vector<Word> expected4 { mockWord1, mockWord2, mockWord3, mockWord4 };
	ASSERT_EQUAL(expected4, permuted.at(3));
}

void testRotateMultipleLinesReturnsAllRotationsSorted() {
	//Arrange
	std::istringstream in { "this is a test\n"
							"this is another test" };
	std::ostringstream out { };
	//Act
	rotateLines(in, out);
	//Assert
	ASSERT_EQUAL("a test this is \n"
                 "another test this is \n"
                 "is a test this \n"
                 "is another test this \n"
                 "test this is a \n"
                 "test this is another \n"
                 "this is a test \n"
                 "this is another test \n", out.str());
}

void testWordRightShiftPutsWordsIntoSentenceUntilEndOfLine() {
	//Arrange
	std::istringstream in { "this is a test" };
	std::vector<Word> sentence { };
	//Act
	in >> sentence;
	//Assert
	ASSERT_EQUAL(Word("this"), sentence.at(0));
	ASSERT_EQUAL(Word("is"), sentence.at(1));
	ASSERT_EQUAL(Word("a"), sentence.at(2));
	ASSERT_EQUAL(Word("test"), sentence.at(3));
}

void runAllTests(int argc, char const *argv[]) {
	cute::suite s { };

	s.push_back(CUTE(testWordConsistsOfOnlyLetters));
	s.push_back(CUTE(testWordsAreDelimitedByNonAlphanumericCharacters));
	s.push_back(CUTE(testWordIsEmptyIfStreamIsEmpty));
	s.push_back(CUTE(testConstructWordThrowsInvalidArgumentExceptionForNumber));
	s.push_back(CUTE(testConstructWordThrowsInvalidArgumentExceptionForSpecialCharacters));
	s.push_back(CUTE(testWordShiftLeftPrintsInternalValue));
	s.push_back(CUTE(testWordShouldBeLessComparesInternalValue));
	s.push_back(CUTE(testWordShouldBeLessComparesCaseInsensitive));
	s.push_back(CUTE(testRotateSingleLineReturnsAllRotationsSorted));
	s.push_back(CUTE(testRotateMultipleLinesReturnsAllRotationsSorted));
	s.push_back(CUTE(testWordRightShiftPutsWordsIntoSentenceUntilEndOfLine));

	cute::xml_file_opener xmlfile(argc, argv);
	cute::xml_listener<cute::ide_listener<> > lis(xmlfile.out);
	cute::makeRunner(lis, argc, argv)(s, "AllTests");
}

int main(int argc, char const *argv[]) {
	runAllTests(argc, argv);
	return 0;
}
<commit_msg>Improved<commit_after>#include "word.h"
#include "kwic.h"
#include "cute.h"
#include "ide_listener.h"
#include "xml_listener.h"
#include "cute_runner.h"

void testWordShouldBeLessComparesInternalValue() {
	//Arrange
	const Word word1("abc");
	const Word word2("bcd");
	//Assert
	ASSERT_LESS(word1, word2);
}

void testWordShouldBeLessComparesCaseInsensitive() {
	//Arrange
	const Word word1("abc");
	const Word word2("BCD");
	//Assert
	ASSERT_LESS(word1, word2);
}

void testWordShiftLeftPrintsInternalValue() {
	//Arrange
	std::ostringstream out { };
	const Word word("hallo");
	//Act
	out << word;
	//Assert
	ASSERT_EQUAL("hallo", out.str());

}

void testConstructWordThrowsInvalidArgumentExceptionForNumber() {
	//Assert
	ASSERT_THROWS(Word("124abd"), std::invalid_argument);
}

void testConstructWordThrowsInvalidArgumentExceptionForSpecialCharacters() {
	//Assert
	ASSERT_THROWS(Word("dsl!*%"), std::invalid_argument);
}

void testWordConsistsOfOnlyLetters() {
	//Arrange
	std::istringstream in { "abc123%" };
	Word word { };
	//Act
	in >> word;
	//Assert
	ASSERT_EQUAL(Word("abc"), word);
}

void testWordIsEmptyIfStreamIsEmpty() {
	//Arrange
	std::istringstream in { "              " };
	Word word { };
	//Act
	in >> word;
	//Assert
	ASSERT_EQUAL(Word(""), word);
}

void testWordsAreDelimitedByNonAlphanumericCharacters() {
	//Arrange
	std::istringstream in { "compl33tely ~ weird !!??!! 4matted in_put" };
	Word word1 { }, word2 { }, word3 { }, word4 { }, word5 { }, word6 { };
	//Act
	in >> word1;
	in >> word2;
	in >> word3;
	in >> word4;
	in >> word5;
	in >> word6;
	//Assert
	ASSERT_EQUAL(Word("compl"), word1);
	ASSERT_EQUAL(Word("tely"), word2);
	ASSERT_EQUAL(Word("weird"), word3);
	ASSERT_EQUAL(Word("matted"), word4);
	ASSERT_EQUAL(Word("in"), word5);
	ASSERT_EQUAL(Word("put"), word6);
}

void testRotateSingleLineReturnsAllRotationsSorted() {
	//Arrange
	const Word mockWord1("this");
	const Word mockWord2("is");
	const Word mockWord3("a");
	const Word mockWord4("test");

	const std::vector<Word> words { Word("this"), Word("is"), Word("a"), Word("test") };

	//Act
	const auto rotatedWords = rotateWords(words);
	auto permuted = std::vector<std::vector<Word>> { };

	for (auto word : rotatedWords) {
		permuted.push_back(word);
	}

	//Assert
	const std::vector<Word> expected1 { mockWord3, mockWord4, mockWord1, mockWord2 };
	ASSERT_EQUAL(expected1, permuted.at(0));

	const std::vector<Word> expected2 { mockWord2, mockWord3, mockWord4, mockWord1 };
	ASSERT_EQUAL(expected2, permuted.at(1));

	const std::vector<Word> expected3 { mockWord4, mockWord1, mockWord2, mockWord3 };
	ASSERT_EQUAL(expected3, permuted.at(2));

	const std::vector<Word> expected4 { mockWord1, mockWord2, mockWord3, mockWord4 };
	ASSERT_EQUAL(expected4, permuted.at(3));
}

void testRotateMultipleLinesReturnsAllRotationsSorted() {
	//Arrange
	std::istringstream in { "this is a test\n"
							"this is another test" };
	std::ostringstream out { };
	//Act
	rotateLines(in, out);
	//Assert
	ASSERT_EQUAL("a test this is \n"
                 "another test this is \n"
                 "is a test this \n"
                 "is another test this \n"
                 "test this is a \n"
                 "test this is another \n"
                 "this is a test \n"
                 "this is another test \n", out.str());
}

void testWordRightShiftPutsWordsIntoSentenceUntilEndOfLine() {
	//Arrange
	std::istringstream in { "this is a test" };
	std::vector<Word> sentence { };
	//Act
	in >> sentence;
	//Assert
	const std::vector<Word> expected { Word("this"), Word("is"), Word("a"), Word("test") };
	ASSERT_EQUAL(expected, sentence);
}

void runAllTests(int argc, char const *argv[]) {
	cute::suite s { };

	s.push_back(CUTE(testWordConsistsOfOnlyLetters));
	s.push_back(CUTE(testWordsAreDelimitedByNonAlphanumericCharacters));
	s.push_back(CUTE(testWordIsEmptyIfStreamIsEmpty));
	s.push_back(CUTE(testConstructWordThrowsInvalidArgumentExceptionForNumber));
	s.push_back(CUTE(testConstructWordThrowsInvalidArgumentExceptionForSpecialCharacters));
	s.push_back(CUTE(testWordShiftLeftPrintsInternalValue));
	s.push_back(CUTE(testWordShouldBeLessComparesInternalValue));
	s.push_back(CUTE(testWordShouldBeLessComparesCaseInsensitive));
	s.push_back(CUTE(testRotateSingleLineReturnsAllRotationsSorted));
	s.push_back(CUTE(testRotateMultipleLinesReturnsAllRotationsSorted));
	s.push_back(CUTE(testWordRightShiftPutsWordsIntoSentenceUntilEndOfLine));

	cute::xml_file_opener xmlfile(argc, argv);
	cute::xml_listener<cute::ide_listener<> > lis(xmlfile.out);
	cute::makeRunner(lis, argc, argv)(s, "AllTests");
}

int main(int argc, char const *argv[]) {
	runAllTests(argc, argv);
	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "nbostream.h"
#include "hexdump.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <cassert>

namespace vespalib {

nbostream::nbostream(size_t initialSize) :
    _wbuf(),
    _rbuf(),
    _rp(0),
    _wp(0),
    _state(ok),
    _longLivedBuffer(false)
{
    extend(initialSize);
}

nbostream::nbostream(const void * buf, size_t sz, bool longLivedBuffer) :
    _wbuf(),
    _rbuf(buf, sz),
    _rp(0),
    _wp(sz),
    _state(ok),
    _longLivedBuffer(longLivedBuffer)
{ }

nbostream_longlivedbuf::nbostream_longlivedbuf(const void * buf, size_t sz) :
    nbostream(buf, sz, true)
{ }

nbostream_longlivedbuf::nbostream_longlivedbuf(size_t initialSize) :
    nbostream(initialSize)
{ }

nbostream::nbostream(const void * buf, size_t sz) :
    nbostream(buf, sz, false)
{ }

nbostream::nbostream(Alloc && buf, size_t sz) :
    _wbuf(std::move(buf), sz),
    _rbuf(&_wbuf[0], sz),
    _rp(0),
    _wp(sz),
    _state(ok),
    _longLivedBuffer(false)
{
    assert(_wbuf.size() >= sz);
}

nbostream::nbostream(const nbostream & rhs) :
    _wbuf(),
    _rbuf(),
    _rp(0),
    _wp(0),
    _state(ok),
    _longLivedBuffer(false)
{
    extend(rhs.size());
    _wp = rhs.size();
    memcpy(&_wbuf[0], &rhs._rbuf[rhs._rp], _wp);
}

nbostream &
nbostream::operator = (const nbostream & rhs) {
    if (this != &rhs) {
        nbostream n(rhs);
        swap(n);
    }
    return *this;
}

nbostream::~nbostream() { }

void nbostream::fail(State s)
{
    _state = static_cast<State>(_state | s);
    throw IllegalStateException(make_string("Stream failed bufsize(%zu), readp(%zu), writep(%zu)", _wbuf.size(), _rp, _wp), VESPA_STRLOC);
}

std::ostream & operator << (std::ostream & os, const nbostream & s) {
    return os << HexDump(&s._rbuf[s._rp], s.left());
}

void nbostream::reserve(size_t sz)
{
    if (capacity() < sz) {
        extend(sz - capacity());
    }
}

void nbostream::compact()
{
    memmove(&_wbuf[0], &_rbuf[_rp], left());
    _wp = left();
    _rp = 0;
}

void nbostream::extend(size_t extraSize)
{
    if (&_wbuf[0] != _rbuf.c_str()) {
        _wbuf.resize(roundUp2inN(_rbuf.size() + extraSize));
        compact();
        _rbuf = ConstBufferRef(&_wbuf[0], _wbuf.capacity());
    }
    if (_rp != 0) {
        compact();
    }
    if (space() < extraSize) {
        _wbuf.resize(roundUp2inN(_wbuf.size() + extraSize));
        _rbuf = ConstBufferRef(&_wbuf[0], _wbuf.capacity());
    }
}

void nbostream::swap(Buffer & buf) {
    if (_rp != 0) {
        compact();
    }
    _wbuf.resize(size());
    _wbuf.swap(buf);
    _rbuf = ConstBufferRef(&_wbuf[0], _wbuf.capacity());
    _wp = _wbuf.size();
    _rp = 0;
    _state = ok;
}

void nbostream::swap(nbostream & os)
{
    std::swap(_rp, os._rp);
    std::swap(_wp, os._wp);
    std::swap(_state, os._state);
    _wbuf.swap(os._wbuf);
    std::swap(_rbuf, os._rbuf);
}

}
<commit_msg>= default<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "nbostream.h"
#include "hexdump.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/util/stringfmt.h>
#include <cassert>

namespace vespalib {

nbostream::nbostream(size_t initialSize) :
    _wbuf(),
    _rbuf(),
    _rp(0),
    _wp(0),
    _state(ok),
    _longLivedBuffer(false)
{
    extend(initialSize);
}

nbostream::nbostream(const void * buf, size_t sz, bool longLivedBuffer) :
    _wbuf(),
    _rbuf(buf, sz),
    _rp(0),
    _wp(sz),
    _state(ok),
    _longLivedBuffer(longLivedBuffer)
{ }

nbostream_longlivedbuf::nbostream_longlivedbuf(const void * buf, size_t sz) :
    nbostream(buf, sz, true)
{ }

nbostream_longlivedbuf::nbostream_longlivedbuf(size_t initialSize) :
    nbostream(initialSize)
{ }

nbostream::nbostream(const void * buf, size_t sz) :
    nbostream(buf, sz, false)
{ }

nbostream::nbostream(Alloc && buf, size_t sz) :
    _wbuf(std::move(buf), sz),
    _rbuf(&_wbuf[0], sz),
    _rp(0),
    _wp(sz),
    _state(ok),
    _longLivedBuffer(false)
{
    assert(_wbuf.size() >= sz);
}

nbostream::nbostream(const nbostream & rhs) :
    _wbuf(),
    _rbuf(),
    _rp(0),
    _wp(0),
    _state(ok),
    _longLivedBuffer(false)
{
    extend(rhs.size());
    _wp = rhs.size();
    memcpy(&_wbuf[0], &rhs._rbuf[rhs._rp], _wp);
}

nbostream &
nbostream::operator = (const nbostream & rhs) {
    if (this != &rhs) {
        nbostream n(rhs);
        swap(n);
    }
    return *this;
}

nbostream::~nbostream() = default;

void nbostream::fail(State s)
{
    _state = static_cast<State>(_state | s);
    throw IllegalStateException(make_string("Stream failed bufsize(%zu), readp(%zu), writep(%zu)", _wbuf.size(), _rp, _wp), VESPA_STRLOC);
}

std::ostream & operator << (std::ostream & os, const nbostream & s) {
    return os << HexDump(&s._rbuf[s._rp], s.left());
}

void nbostream::reserve(size_t sz)
{
    if (capacity() < sz) {
        extend(sz - capacity());
    }
}

void nbostream::compact()
{
    memmove(&_wbuf[0], &_rbuf[_rp], left());
    _wp = left();
    _rp = 0;
}

void nbostream::extend(size_t extraSize)
{
    if (&_wbuf[0] != _rbuf.c_str()) {
        _wbuf.resize(roundUp2inN(_rbuf.size() + extraSize));
        compact();
        _rbuf = ConstBufferRef(&_wbuf[0], _wbuf.capacity());
    }
    if (_rp != 0) {
        compact();
    }
    if (space() < extraSize) {
        _wbuf.resize(roundUp2inN(_wbuf.size() + extraSize));
        _rbuf = ConstBufferRef(&_wbuf[0], _wbuf.capacity());
    }
}

void nbostream::swap(Buffer & buf) {
    if (_rp != 0) {
        compact();
    }
    _wbuf.resize(size());
    _wbuf.swap(buf);
    _rbuf = ConstBufferRef(&_wbuf[0], _wbuf.capacity());
    _wp = _wbuf.size();
    _rp = 0;
    _state = ok;
}

void nbostream::swap(nbostream & os)
{
    std::swap(_rp, os._rp);
    std::swap(_wp, os._wp);
    std::swap(_state, os._state);
    _wbuf.swap(os._wbuf);
    std::swap(_rbuf, os._rbuf);
}

}
<|endoftext|>


<commit_before>#ifndef DICE_RANDOMOPERATION_H
#define DICE_RANDOMOPERATION_H

#include "../stdafx.hpp"

#include "IOperation.hpp"

class RandomOperation : public IOperation
{
    const int _lower, _upper;
    unsigned int _seed;
    bool _fixedSeed;

protected:
    /**
     * \brief Generates one random number from range specified in the
     * constructor.
     *
     * \return Unique pointer to RollResult storing one random number.
     *
     * \exception std::invalid_argument If constructor got bad arguments.
     * (Lower is less than 1 or/and less than upper)
     */
    std::unique_ptr<RollResult> execute();

public:
    // If seed is not given, it will randomize using time
    /**
     * Defines range for RandomOperation. Lower limit is 1, and upper is defined (both are inclusive).
     * by the user.
     *
     * \param upper [in] Upper limit (inclusive) in random range.
     */
    RandomOperation(int upper);
    /**
     * Defines range for RandomOperation. User can specify lower and upper limit (both inclusive).
     * for randomizing a number.
     *
     * \param lower Lower limit (inclusive) in random range.
     * \param upper Upper limit (inclusive) in random range.
     */
    RandomOperation(int lower, int upper);

    // Throws exception if lower >= upper
    /**
     * \brief Calls execute() and does nothing else.
     *
     * \return Returns unique pointer to the RollResult containing one random
     * number from range specified by the constructor.
     */
    std::unique_ptr<RollResult> evaluate();
    /**
     * \brief Sets seed for randomizing a number.
     *
     * If seed is not set, it defaults to timestamp so operation generates
     * random number.\n
     * If it is set, evaluating the operation will return the same result
     * every time.
     *
     * \param newSeed Seed for random operation.
     */
    void changeSeed(unsigned newSeed);
};

#endif // DICE_RANDOMOPERATION_H
<commit_msg>Doc for private vars.<commit_after>#ifndef DICE_RANDOMOPERATION_H
#define DICE_RANDOMOPERATION_H

#include "../stdafx.hpp"

#include "IOperation.hpp"

class RandomOperation : public IOperation
{
    // Upper and lower limits in range for generating number. These values
    // are inclusive.
    const int _lower, _upper;
    // Seed for random number generator that is used in execute().
    unsigned int _seed;
    // It is true if seed has been set, and false if not.
    bool _fixedSeed;

protected:
    /**
     * \brief Generates one random number from range specified in the
     * constructor.
     *
     * \return Unique pointer to RollResult storing one random number.
     *
     * \exception std::invalid_argument If constructor got bad arguments.
     * (Lower is less than 1 or/and less than upper)
     */
    std::unique_ptr<RollResult> execute();

public:
    // If seed is not given, it will randomize using time
    /**
     * Defines range for RandomOperation. Lower limit is 1, and upper is defined (both are inclusive).
     * by the user.
     *
     * \param upper [in] Upper limit (inclusive) in random range.
     */
    RandomOperation(int upper);
    /**
     * Defines range for RandomOperation. User can specify lower and upper limit (both inclusive).
     * for randomizing a number.
     *
     * \param lower Lower limit (inclusive) in random range.
     * \param upper Upper limit (inclusive) in random range.
     */
    RandomOperation(int lower, int upper);

    // Throws exception if lower >= upper
    /**
     * \brief Calls execute() and does nothing else.
     *
     * \return Returns unique pointer to the RollResult containing one random
     * number from range specified by the constructor.
     */
    std::unique_ptr<RollResult> evaluate();
    /**
     * \brief Sets seed for randomizing a number.
     *
     * If seed is not set, it defaults to timestamp so operation generates
     * random number.\n
     * If it is set, evaluating the operation will return the same result
     * every time.
     *
     * \param newSeed Seed for random operation.
     */
    void changeSeed(unsigned newSeed);
};

#endif // DICE_RANDOMOPERATION_H
<|endoftext|>


<commit_before>#include "GuiScraperStart.h"
#include "GuiScraperLog.h"
#include "GuiMsgBoxYesNo.h"

GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
	mBox(window, ":/frame.png"),
	mList(window, Eigen::Vector2i(2, 4)),
	mFilterLabel(mWindow),
	mSystemsLabel(mWindow),
	mManualLabel(mWindow),
	mFiltersOpt(mWindow),
	mSystemsOpt(mWindow, true),
	mManualSwitch(mWindow),
	mStartButton(mWindow)
{
	mFilterLabel.setText("Filter: ");
	mSystemsLabel.setText("Systems: ");
	mManualLabel.setText("Manual mode: ");

	addChild(&mBox);
	addChild(&mList);

	using namespace Eigen;

	//add filters (with first one selected)
	mFiltersOpt.addEntry(mFiltersOpt.makeEntry("All Games",
		[](SystemData*, FileData*) -> bool { return true; }, true));
	mFiltersOpt.addEntry(mFiltersOpt.makeEntry("Missing Image",
		[](SystemData*, FileData* g) -> bool { return g->metadata.get("image").empty(); }));

	mList.setEntry(Vector2i(0, 0), Vector2i(1, 1), &mFilterLabel, false, ComponentListComponent::AlignRight);
	mList.setEntry(Vector2i(1, 0), Vector2i(1, 1), &mFiltersOpt, true, ComponentListComponent::AlignLeft);

	//add systems (with all selected)
	std::vector<SystemData*> sys = SystemData::sSystemVector;
	mSystemsOpt.populate(sys,
		[&](SystemData* s) {
			return mSystemsOpt.makeEntry(s->getName(), s, true);
	});

	mList.setEntry(Vector2i(0, 1), Vector2i(1, 1), &mSystemsLabel, false, ComponentListComponent::AlignRight);
	mList.setEntry(Vector2i(1, 1), Vector2i(1, 1), &mSystemsOpt, true, ComponentListComponent::AlignLeft);

	mList.setEntry(Vector2i(0, 2), Vector2i(1, 1), &mManualLabel, false, ComponentListComponent::AlignRight);
	mList.setEntry(Vector2i(1, 2), Vector2i(1, 1), &mManualSwitch, true, ComponentListComponent::AlignLeft);

	mStartButton.setText("GO GO GO GO", 0x00FF00FF);
	mStartButton.setPressedFunc(std::bind(&GuiScraperStart::pressedStart, this));
	mList.setEntry(Vector2i(0, 3), Vector2i(2, 1), &mStartButton, true, ComponentListComponent::AlignCenter);

	mList.setPosition(Renderer::getScreenWidth() / 2 - mList.getSize().x() / 2, Renderer::getScreenHeight() / 2 - mList.getSize().y() / 2);

	mBox.setEdgeColor(0x333333FF);
	mBox.fitTo(mList.getSize(), mList.getPosition(), Eigen::Vector2f(8, 8));
}

void GuiScraperStart::pressedStart()
{
	std::vector<SystemData*> sys = mSystemsOpt.getSelectedObjects();
	for(auto it = sys.begin(); it != sys.end(); it++)
	{
		if((*it)->getPlatformId() == PlatformIds::PLATFORM_UNKNOWN)
		{
			mWindow->pushGui(new GuiMsgBoxYesNo(mWindow, "Warning: some of your selected systems do not have a platform ID set. Results may be even more inaccurate than usual!\nContinue anyway?",
				std::bind(&GuiScraperStart::start, this)));
			return;
		}
	}

	start();
}

void GuiScraperStart::start()
{
	std::queue<ScraperSearchParams> searches = getSearches(mSystemsOpt.getSelectedObjects(), mFiltersOpt.getSelectedObjects()[0]);

	GuiScraperLog* gsl = new GuiScraperLog(mWindow, searches, mManualSwitch.getState());
	mWindow->pushGui(gsl);
	gsl->start();
	delete this;
}

std::queue<ScraperSearchParams> GuiScraperStart::getSearches(std::vector<SystemData*> systems, GameFilterFunc selector)
{
	std::queue<ScraperSearchParams> queue;
	for(auto sys = systems.begin(); sys != systems.end(); sys++)
	{
		std::vector<FileData*> games = (*sys)->getRootFolder()->getFilesRecursive(GAME);
		for(auto game = games.begin(); game != games.end(); game++)
		{
			if(selector((*sys), (*game)))
			{
				ScraperSearchParams search;
				search.game = *game;
				search.system = *sys;

				queue.push(search);
			}
		}
	}

	return queue;
}

bool GuiScraperStart::input(InputConfig* config, Input input)
{
	bool consumed = GuiComponent::input(config, input);
	if(consumed)
		return true;

	if(input.value != 0 && config->isMappedTo("b", input))
	{
		delete this;
		return true;
	}

	return false;
}
<commit_msg>Don't scrape systems without a platform ID set by default.<commit_after>#include "GuiScraperStart.h"
#include "GuiScraperLog.h"
#include "GuiMsgBoxYesNo.h"

GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
	mBox(window, ":/frame.png"),
	mList(window, Eigen::Vector2i(2, 4)),
	mFilterLabel(mWindow),
	mSystemsLabel(mWindow),
	mManualLabel(mWindow),
	mFiltersOpt(mWindow),
	mSystemsOpt(mWindow, true),
	mManualSwitch(mWindow),
	mStartButton(mWindow)
{
	mFilterLabel.setText("Filter: ");
	mSystemsLabel.setText("Systems: ");
	mManualLabel.setText("Manual mode: ");

	addChild(&mBox);
	addChild(&mList);

	using namespace Eigen;

	//add filters (with first one selected)
	mFiltersOpt.addEntry(mFiltersOpt.makeEntry("All Games",
		[](SystemData*, FileData*) -> bool { return true; }, true));
	mFiltersOpt.addEntry(mFiltersOpt.makeEntry("Missing Image",
		[](SystemData*, FileData* g) -> bool { return g->metadata.get("image").empty(); }));

	mList.setEntry(Vector2i(0, 0), Vector2i(1, 1), &mFilterLabel, false, ComponentListComponent::AlignRight);
	mList.setEntry(Vector2i(1, 0), Vector2i(1, 1), &mFiltersOpt, true, ComponentListComponent::AlignLeft);

	//add systems (all with a platformid specified selected)
	std::vector<SystemData*> sys = SystemData::sSystemVector;
	mSystemsOpt.populate(sys,
		[&](SystemData* s) {
			return mSystemsOpt.makeEntry(s->getName(), s, s->getPlatformId() != PlatformIds::PLATFORM_UNKNOWN);
	});

	mList.setEntry(Vector2i(0, 1), Vector2i(1, 1), &mSystemsLabel, false, ComponentListComponent::AlignRight);
	mList.setEntry(Vector2i(1, 1), Vector2i(1, 1), &mSystemsOpt, true, ComponentListComponent::AlignLeft);

	mList.setEntry(Vector2i(0, 2), Vector2i(1, 1), &mManualLabel, false, ComponentListComponent::AlignRight);
	mList.setEntry(Vector2i(1, 2), Vector2i(1, 1), &mManualSwitch, true, ComponentListComponent::AlignLeft);

	mStartButton.setText("GO GO GO GO", 0x00FF00FF);
	mStartButton.setPressedFunc(std::bind(&GuiScraperStart::pressedStart, this));
	mList.setEntry(Vector2i(0, 3), Vector2i(2, 1), &mStartButton, true, ComponentListComponent::AlignCenter);

	mList.setPosition(Renderer::getScreenWidth() / 2 - mList.getSize().x() / 2, Renderer::getScreenHeight() / 2 - mList.getSize().y() / 2);

	mBox.setEdgeColor(0x333333FF);
	mBox.fitTo(mList.getSize(), mList.getPosition(), Eigen::Vector2f(8, 8));
}

void GuiScraperStart::pressedStart()
{
	std::vector<SystemData*> sys = mSystemsOpt.getSelectedObjects();
	for(auto it = sys.begin(); it != sys.end(); it++)
	{
		if((*it)->getPlatformId() == PlatformIds::PLATFORM_UNKNOWN)
		{
			mWindow->pushGui(new GuiMsgBoxYesNo(mWindow, "Warning: some of your selected systems do not have a platform ID set. Results may be even more inaccurate than usual!\nContinue anyway?",
				std::bind(&GuiScraperStart::start, this)));
			return;
		}
	}

	start();
}

void GuiScraperStart::start()
{
	std::queue<ScraperSearchParams> searches = getSearches(mSystemsOpt.getSelectedObjects(), mFiltersOpt.getSelectedObjects()[0]);

	GuiScraperLog* gsl = new GuiScraperLog(mWindow, searches, mManualSwitch.getState());
	mWindow->pushGui(gsl);
	gsl->start();
	delete this;
}

std::queue<ScraperSearchParams> GuiScraperStart::getSearches(std::vector<SystemData*> systems, GameFilterFunc selector)
{
	std::queue<ScraperSearchParams> queue;
	for(auto sys = systems.begin(); sys != systems.end(); sys++)
	{
		std::vector<FileData*> games = (*sys)->getRootFolder()->getFilesRecursive(GAME);
		for(auto game = games.begin(); game != games.end(); game++)
		{
			if(selector((*sys), (*game)))
			{
				ScraperSearchParams search;
				search.game = *game;
				search.system = *sys;

				queue.push(search);
			}
		}
	}

	return queue;
}

bool GuiScraperStart::input(InputConfig* config, Input input)
{
	bool consumed = GuiComponent::input(config, input);
	if(consumed)
		return true;

	if(input.value != 0 && config->isMappedTo("b", input))
	{
		delete this;
		return true;
	}

	return false;
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_PDELAB_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_PDELAB_HH

#include <memory>
#include <type_traits>

#include <dune/geometry/genericgeometry/topologytypes.hh>

#include <dune/common/typetraits.hh>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/fvector.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#if HAVE_DUNE_ISTL
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/istl/paamg/pinfo.hh>
# include <dune/stuff/common/reenable_warnings.hh>
# include <dune/stuff/la/solver/istl_amg.hh>
#endif

#if HAVE_DUNE_PDELAB
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/pdelab/finiteelementmap/pkfem.hh>
#   include <dune/pdelab/finiteelementmap/qkfem.hh>
#   include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>
#   include <dune/pdelab/constraints/conforming.hh>
# include <dune/stuff/common/reenable_warnings.hh>
#endif // HAVE_DUNE_PDELAB

#include <dune/gdt/spaces/parallel.hh>

#include "../../mapper/pdelab.hh"
#include "../../basefunctionset/pdelab.hh"

#include "base.hh"

namespace Dune {

namespace GDT {
namespace Spaces {
namespace ContinuousLagrange {

#if HAVE_DUNE_PDELAB

// forward, to be used in the traits and to allow for specialization
template< class GridViewImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class PdelabBased
{
  static_assert((Dune::AlwaysFalse< GridViewImp >::value), "Untested for this combination of dimensions!");
};

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class PdelabBasedTraits
{
public:
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  typedef GridViewImp                   GridViewType;
  static const int                      polOrder = polynomialOrder;
  static_assert(polOrder >= 1, "Wrong polOrder given!");
private:
  typedef typename GridViewType::ctype  DomainFieldType;
public:
  static const unsigned int             dimDomain = GridViewType::dimension;
  typedef RangeFieldImp                 RangeFieldType;
  static const unsigned int             dimRange = rangeDim;
  static const unsigned int             dimRangeCols = rangeDimCols;
private:
  template< class G, bool single_geom, bool is_simplex, bool is_cube >
  struct FeMap
  {
    static_assert(Dune::AlwaysFalse< G >::value,
                  "This space is only implemented for either fully simplicial or fully cubic grids!");
  };
  template< class G >
  struct FeMap< G, true, true, false >
  {
    typedef PDELab::PkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  template< class G >
  struct FeMap< G, true, false, true >
  {
    typedef PDELab::QkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  typedef typename GridViewType::Grid GridType;
  static const bool single_geom_ = Dune::Capabilities::hasSingleGeometryType< GridType >::v;
  static const bool simplicial_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                                   == GenericGeometry::SimplexTopology< dimDomain >::type::id);
  static const bool cubic_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                              == GenericGeometry::CubeTopology< dimDomain >::type::id);
  typedef typename FeMap< GridType, single_geom_, simplicial_, cubic_ >::Type FEMapType;
public:
  typedef PDELab::GridFunctionSpace< GridViewType, FEMapType, PDELab::OverlappingConformingDirichletConstraints > BackendType;
  typedef Mapper::SimplePdelabWrapper< BackendType > MapperType;
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;
  typedef BaseFunctionSet::PdelabWrapper
      < BackendType, EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, dimRangeCols >
    BaseFunctionSetType;
  static const Stuff::Grid::ChoosePartView part_view_type = Stuff::Grid::ChoosePartView::view;
  static const bool needs_grid_view = true;

  typedef typename CommunicationChooser<GridViewType>::Type CommunicatorType;
private:
  friend class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols >;
}; // class SpaceWrappedFemContinuousLagrangeTraits

template< class GridViewImp, int polynomialOrder, class RangeFieldImp >
class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
  : public Spaces::ContinuousLagrangeBase< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
                                      , GridViewImp::dimension, RangeFieldImp, 1, 1 >
{
  typedef Spaces::ContinuousLagrangeBase< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
                                     , GridViewImp::dimension, RangeFieldImp, 1, 1 >  BaseType;
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >          ThisType;
public:
  typedef PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 > Traits;

  typedef typename Traits::GridViewType GridViewType;
  static const int                      polOrder = Traits::polOrder;
  typedef typename GridViewType::ctype  DomainFieldType;
  static const unsigned int             dimDomain = GridViewType::dimension;
  typedef FieldVector< DomainFieldType, dimDomain > DomainType;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int               dimRange = Traits::dimRange;
  static const unsigned int               dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType          BackendType;
  typedef typename Traits::MapperType           MapperType;
  typedef typename Traits::BaseFunctionSetType  BaseFunctionSetType;
  typedef typename Traits::CommunicatorType     CommunicatorType;

private:
  typedef typename Traits::FEMapType FEMapType;

public:
  typedef typename BaseType::IntersectionType  IntersectionType;
  typedef typename BaseType::EntityType        EntityType;
  typedef typename BaseType::PatternType       PatternType;
  typedef typename BaseType::BoundaryInfoType  BoundaryInfoType;

  PdelabBased(const std::shared_ptr< const GridViewType >& gV)
    : gridView_(gV)
    , fe_map_(std::make_shared< FEMapType >(*(gridView_)))
    , backend_(std::make_shared< BackendType >(const_cast< GridViewType& >(*gridView_), *(*fe_map_)))
    , mapper_(std::make_shared< MapperType >(*(*backend_)))
    , communicator_(CommunicationChooser<GridViewImp>::create(*gridView_))
    , communicator_prepared_(false)
  {}

  PdelabBased(const ThisType& other)
    : gridView_(other.gridView_)
    , fe_map_(other.fe_map_)
    , backend_(other.backend_)
    , mapper_(other.mapper_)
    , communicator_(other.communicator_)
    , communicator_prepared_(other.communicator_prepared_)
  {}

  ThisType& operator=(const ThisType& other)
  {
    if (this != &other) {
      gridView_ = other.gridView_;
      fe_map_ = other.fe_map_;
      backend_ = other.backend_;
      mapper_ = other.mapper_;
      communicator_ = other.communicator_;
      communicator_prepared_ = other.communicator_prepared_;
    }
    return *this;
  }

  ~PdelabBased() {}

  const std::shared_ptr< const GridViewType >& grid_view() const
  {
    return gridView_;
  }

  const BackendType& backend() const
  {
    return *(*backend_);
  }

  const MapperType& mapper() const
  {
    return *(*mapper_);
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    return BaseFunctionSetType(*(*backend_), entity);
  }

  CommunicatorType& communicator() const
  {
    std::lock_guard<std::mutex> gg(communicator_mutex_);
    if (!communicator_prepared_) {
      communicator_prepared_ = CommunicationChooser<GridViewType>::prepare(*this, *communicator_);
    }
    return *communicator_;
  } // ... communicator(...)

private:
  std::shared_ptr< const GridViewType > gridView_;
  DS::PerThreadValue<std::shared_ptr< const FEMapType >> fe_map_;
  DS::PerThreadValue<std::shared_ptr< const BackendType >> backend_;
  DS::PerThreadValue<std::shared_ptr< const MapperType >> mapper_;
  mutable std::shared_ptr< CommunicatorType > communicator_;
  mutable bool communicator_prepared_;
  mutable std::mutex communicator_mutex_;
}; // class PdelabBased< ..., 1 >

#else // HAVE_DUNE_PDELAB

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class PdelabBased
{
  static_assert((Dune::AlwaysFalse< GridViewImp >::value), "You are missing dune-pdelab!");
};

#endif // HAVE_DUNE_PDELAB

} // namespace ContinuousLagrange
} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_PDELAB_HH
<commit_msg>[spaces.cg.pdelab] simplify member<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_PDELAB_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_PDELAB_HH

#include <memory>
#include <type_traits>

#include <dune/geometry/genericgeometry/topologytypes.hh>

#include <dune/common/typetraits.hh>

#include <dune/stuff/common/disable_warnings.hh>
# include <dune/common/fvector.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#if HAVE_DUNE_ISTL
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/istl/paamg/pinfo.hh>
# include <dune/stuff/common/reenable_warnings.hh>
# include <dune/stuff/la/solver/istl_amg.hh>
#endif

#if HAVE_DUNE_PDELAB
# include <dune/stuff/common/disable_warnings.hh>
#   include <dune/pdelab/finiteelementmap/pkfem.hh>
#   include <dune/pdelab/finiteelementmap/qkfem.hh>
#   include <dune/pdelab/gridfunctionspace/gridfunctionspace.hh>
#   include <dune/pdelab/constraints/conforming.hh>
# include <dune/stuff/common/reenable_warnings.hh>
#endif // HAVE_DUNE_PDELAB

#include <dune/gdt/spaces/parallel.hh>

#include "../../mapper/pdelab.hh"
#include "../../basefunctionset/pdelab.hh"

#include "base.hh"

namespace Dune {

namespace GDT {
namespace Spaces {
namespace ContinuousLagrange {

#if HAVE_DUNE_PDELAB

// forward, to be used in the traits and to allow for specialization
template< class GridViewImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class PdelabBased
{
  static_assert((Dune::AlwaysFalse< GridViewImp >::value), "Untested for this combination of dimensions!");
};

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class PdelabBasedTraits
{
public:
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  typedef GridViewImp                   GridViewType;
  static const int                      polOrder = polynomialOrder;
  static_assert(polOrder >= 1, "Wrong polOrder given!");
private:
  typedef typename GridViewType::ctype  DomainFieldType;
public:
  static const unsigned int             dimDomain = GridViewType::dimension;
  typedef RangeFieldImp                 RangeFieldType;
  static const unsigned int             dimRange = rangeDim;
  static const unsigned int             dimRangeCols = rangeDimCols;
private:
  template< class G, bool single_geom, bool is_simplex, bool is_cube >
  struct FeMap
  {
    static_assert(Dune::AlwaysFalse< G >::value,
                  "This space is only implemented for either fully simplicial or fully cubic grids!");
  };
  template< class G >
  struct FeMap< G, true, true, false >
  {
    typedef PDELab::PkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  template< class G >
  struct FeMap< G, true, false, true >
  {
    typedef PDELab::QkLocalFiniteElementMap < GridViewType, DomainFieldType, RangeFieldType, polOrder> Type;
  };
  typedef typename GridViewType::Grid GridType;
  static const bool single_geom_ = Dune::Capabilities::hasSingleGeometryType< GridType >::v;
  static const bool simplicial_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                                   == GenericGeometry::SimplexTopology< dimDomain >::type::id);
  static const bool cubic_ = (Dune::Capabilities::hasSingleGeometryType< GridType >::topologyId
                              == GenericGeometry::CubeTopology< dimDomain >::type::id);
  typedef typename FeMap< GridType, single_geom_, simplicial_, cubic_ >::Type FEMapType;
public:
  typedef PDELab::GridFunctionSpace< GridViewType, FEMapType, PDELab::OverlappingConformingDirichletConstraints > BackendType;
  typedef Mapper::SimplePdelabWrapper< BackendType > MapperType;
  typedef typename GridViewType::template Codim< 0 >::Entity EntityType;
  typedef BaseFunctionSet::PdelabWrapper
      < BackendType, EntityType, DomainFieldType, dimDomain, RangeFieldType, dimRange, dimRangeCols >
    BaseFunctionSetType;
  static const Stuff::Grid::ChoosePartView part_view_type = Stuff::Grid::ChoosePartView::view;
  static const bool needs_grid_view = true;

  typedef typename CommunicationChooser<GridViewType>::Type CommunicatorType;
private:
  friend class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, rangeDim, rangeDimCols >;
}; // class SpaceWrappedFemContinuousLagrangeTraits

template< class GridViewImp, int polynomialOrder, class RangeFieldImp >
class PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
  : public Spaces::ContinuousLagrangeBase< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
                                      , GridViewImp::dimension, RangeFieldImp, 1, 1 >
{
  typedef Spaces::ContinuousLagrangeBase< PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >
                                     , GridViewImp::dimension, RangeFieldImp, 1, 1 >  BaseType;
  typedef PdelabBased< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 >          ThisType;
public:
  typedef PdelabBasedTraits< GridViewImp, polynomialOrder, RangeFieldImp, 1, 1 > Traits;

  typedef typename Traits::GridViewType GridViewType;
  static const int                      polOrder = Traits::polOrder;
  typedef typename GridViewType::ctype  DomainFieldType;
  static const unsigned int             dimDomain = GridViewType::dimension;
  typedef FieldVector< DomainFieldType, dimDomain > DomainType;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int               dimRange = Traits::dimRange;
  static const unsigned int               dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType          BackendType;
  typedef typename Traits::MapperType           MapperType;
  typedef typename Traits::BaseFunctionSetType  BaseFunctionSetType;
  typedef typename Traits::CommunicatorType     CommunicatorType;

private:
  typedef typename Traits::FEMapType FEMapType;

public:
  typedef typename BaseType::IntersectionType  IntersectionType;
  typedef typename BaseType::EntityType        EntityType;
  typedef typename BaseType::PatternType       PatternType;
  typedef typename BaseType::BoundaryInfoType  BoundaryInfoType;

  PdelabBased(const std::shared_ptr< const GridViewType >& gV)
    : gridView_(gV)
    , fe_map_(*(gridView_))
    , backend_(const_cast< GridViewType& >(*gridView_), fe_map_)
    , mapper_(backend_)
    , communicator_(CommunicationChooser<GridViewImp>::create(*gridView_))
    , communicator_prepared_(false)
  {}

  PdelabBased(const ThisType& other)
    : gridView_(other.gridView_)
    , fe_map_(other.fe_map_)
    , backend_(other.backend_)
    , mapper_(other.mapper_)
    , communicator_(other.communicator_)
    , communicator_prepared_(other.communicator_prepared_)
  {}

  ThisType& operator=(const ThisType& other)
  {
    if (this != &other) {
      gridView_ = other.gridView_;
      fe_map_ = other.fe_map_;
      backend_ = other.backend_;
      mapper_ = other.mapper_;
      communicator_ = other.communicator_;
      communicator_prepared_ = other.communicator_prepared_;
    }
    return *this;
  }

  ~PdelabBased() {}

  const std::shared_ptr< const GridViewType >& grid_view() const
  {
    return gridView_;
  }

  const BackendType& backend() const
  {
    return backend_;
  }

  const MapperType& mapper() const
  {
    return mapper_;
  }

  BaseFunctionSetType base_function_set(const EntityType& entity) const
  {
    return BaseFunctionSetType(backend_, entity);
  }

  CommunicatorType& communicator() const
  {
    std::lock_guard<std::mutex> gg(communicator_mutex_);
    if (!communicator_prepared_) {
      communicator_prepared_ = CommunicationChooser<GridViewType>::prepare(*this, *communicator_);
    }
    return *communicator_;
  } // ... communicator(...)

private:
  std::shared_ptr< const GridViewType > gridView_;
  const FEMapType fe_map_;
  const BackendType backend_;
  const MapperType mapper_;
  mutable std::shared_ptr< CommunicatorType > communicator_;
  mutable bool communicator_prepared_;
  mutable std::mutex communicator_mutex_;
}; // class PdelabBased< ..., 1 >

#else // HAVE_DUNE_PDELAB

template< class GridViewImp, int polynomialOrder, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class PdelabBased
{
  static_assert((Dune::AlwaysFalse< GridViewImp >::value), "You are missing dune-pdelab!");
};

#endif // HAVE_DUNE_PDELAB

} // namespace ContinuousLagrange
} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_PDELAB_HH
<|endoftext|>