<commit_before>/*
    This file is part of cpp-ethereum.

    cpp-ethereum 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.

    cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Pretty-printer for the abstract syntax tree (the "pretty" is arguable), used for debugging.
 */

#include <libsolidity/ASTPrinter.h>
#include <libsolidity/AST.h>

using namespace std;

namespace dev
{
namespace solidity
{

ASTPrinter::ASTPrinter(ASTNode const& _ast,
	string const& _source,
	StructuralGasEstimator::ASTGasConsumption const& _gasCosts
): m_indentation(0), m_source(_source), m_ast(&_ast), m_gasCosts(_gasCosts)
{
}

void ASTPrinter::print(ostream& _stream)
{
	m_ostream = &_stream;
	m_ast->accept(*this);
	m_ostream = nullptr;
}

bool ASTPrinter::visit(ImportDirective const& _node)
{
	writeLine("ImportDirective \"" + _node.getIdentifier() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ContractDefinition const& _node)
{
	writeLine("ContractDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(InheritanceSpecifier const& _node)
{
	writeLine("InheritanceSpecifier \"" + _node.getName()->getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(StructDefinition const& _node)
{
	writeLine("StructDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(EnumDefinition const& _node)
{
	writeLine("EnumDefinition \"" + _node.getName() + "\"");
	return goDeeper();
}

bool ASTPrinter::visit(EnumValue const& _node)
{
	writeLine("EnumValue \"" + _node.getName() + "\"");
	return goDeeper();
}

bool ASTPrinter::visit(ParameterList const& _node)
{
	writeLine("ParameterList");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(FunctionDefinition const& _node)
{
	writeLine("FunctionDefinition \"" + _node.getName() + "\"" +
			  (_node.isPublic() ? " - public" : "") +
			  (_node.isDeclaredConst() ? " - const" : ""));
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(VariableDeclaration const& _node)
{
	writeLine("VariableDeclaration \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ModifierDefinition const& _node)
{
	writeLine("ModifierDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ModifierInvocation const& _node)
{
	writeLine("ModifierInvocation \"" + _node.getName()->getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(EventDefinition const& _node)
{
	writeLine("EventDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(TypeName const& _node)
{
	writeLine("TypeName");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ElementaryTypeName const& _node)
{
	writeLine(string("ElementaryTypeName ") + Token::toString(_node.getTypeName()));
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(UserDefinedTypeName const& _node)
{
	writeLine("UserDefinedTypeName \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Mapping const& _node)
{
	writeLine("Mapping");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ArrayTypeName const& _node)
{
	writeLine("ArrayTypeName");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Block const& _node)
{
	writeLine("Block");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(PlaceholderStatement const& _node)
{
	writeLine("PlaceholderStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(IfStatement const& _node)
{
	writeLine("IfStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(WhileStatement const& _node)
{
	writeLine("WhileStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ForStatement const& _node)
{
	writeLine("ForStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Continue const& _node)
{
	writeLine("Continue");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Break const& _node)
{
	writeLine("Break");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Return const& _node)
{
	writeLine("Return");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(VariableDeclarationStatement const& _node)
{
	writeLine("VariableDeclarationStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ExpressionStatement const& _node)
{
	writeLine("ExpressionStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Assignment const& _node)
{
	writeLine(string("Assignment using operator ") + Token::toString(_node.getAssignmentOperator()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(UnaryOperation const& _node)
{
	writeLine(string("UnaryOperation (") + (_node.isPrefixOperation() ? "prefix" : "postfix") +
			  ") " + Token::toString(_node.getOperator()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(BinaryOperation const& _node)
{
	writeLine(string("BinaryOperation using operator ") + Token::toString(_node.getOperator()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(FunctionCall const& _node)
{
	writeLine("FunctionCall");
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(NewExpression const& _node)
{
	writeLine("NewExpression");
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(MemberAccess const& _node)
{
	writeLine("MemberAccess to member " + _node.getMemberName());
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(IndexAccess const& _node)
{
	writeLine("IndexAccess");
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Identifier const& _node)
{
	writeLine(string("Identifier ") + _node.getName());
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ElementaryTypeNameExpression const& _node)
{
	writeLine(string("ElementaryTypeNameExpression ") + Token::toString(_node.getTypeToken()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Literal const& _node)
{
	char const* tokenString = Token::toString(_node.getToken());
	if (!tokenString)
		tokenString = "[no token]";
	writeLine(string("Literal, token: ") + tokenString + " value: " + _node.getValue());
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

void ASTPrinter::endVisit(ImportDirective const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ContractDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(InheritanceSpecifier const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(StructDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(EnumDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(EnumValue const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ParameterList const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(FunctionDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(VariableDeclaration const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ModifierDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ModifierInvocation const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(EventDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(TypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ElementaryTypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(UserDefinedTypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Mapping const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ArrayTypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Block const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(PlaceholderStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(IfStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(WhileStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ForStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Continue const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Break const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Return const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(VariableDeclarationStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ExpressionStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Assignment const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(UnaryOperation const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(BinaryOperation const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(FunctionCall const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(NewExpression const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(MemberAccess const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(IndexAccess const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Identifier const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ElementaryTypeNameExpression const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Literal const&)
{
	m_indentation--;
}

void ASTPrinter::printSourcePart(ASTNode const& _node)
{
	if (m_gasCosts.count(&_node))
		*m_ostream << getIndentation() << "   Gas costs: " << m_gasCosts.at(&_node) << endl;
	if (!m_source.empty())
	{
		SourceLocation const& location(_node.getLocation());
		*m_ostream << getIndentation() << "   Source: "
				   << escaped(m_source.substr(location.start, location.end - location.start), false) << endl;
	}
}

void ASTPrinter::printType(Expression const& _expression)
{
	if (_expression.getType())
		*m_ostream << getIndentation() << "   Type: " << _expression.getType()->toString() << "\n";
	else
		*m_ostream << getIndentation() << "   Type unknown.\n";
}

string ASTPrinter::getIndentation() const
{
	return string(m_indentation * 2, ' ');
}

void ASTPrinter::writeLine(string const& _line)
{
	*m_ostream << getIndentation() << _line << endl;
}

}
}
<commit_msg>Style.<commit_after>/*
    This file is part of cpp-ethereum.

    cpp-ethereum 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.

    cpp-ethereum 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 cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * @author Christian <c@ethdev.com>
 * @date 2014
 * Pretty-printer for the abstract syntax tree (the "pretty" is arguable), used for debugging.
 */

#include <libsolidity/ASTPrinter.h>
#include <libsolidity/AST.h>

using namespace std;

namespace dev
{
namespace solidity
{

ASTPrinter::ASTPrinter(
	ASTNode const& _ast,
	string const& _source,
	StructuralGasEstimator::ASTGasConsumption const& _gasCosts
): m_indentation(0), m_source(_source), m_ast(&_ast), m_gasCosts(_gasCosts)
{
}

void ASTPrinter::print(ostream& _stream)
{
	m_ostream = &_stream;
	m_ast->accept(*this);
	m_ostream = nullptr;
}

bool ASTPrinter::visit(ImportDirective const& _node)
{
	writeLine("ImportDirective \"" + _node.getIdentifier() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ContractDefinition const& _node)
{
	writeLine("ContractDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(InheritanceSpecifier const& _node)
{
	writeLine("InheritanceSpecifier \"" + _node.getName()->getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(StructDefinition const& _node)
{
	writeLine("StructDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(EnumDefinition const& _node)
{
	writeLine("EnumDefinition \"" + _node.getName() + "\"");
	return goDeeper();
}

bool ASTPrinter::visit(EnumValue const& _node)
{
	writeLine("EnumValue \"" + _node.getName() + "\"");
	return goDeeper();
}

bool ASTPrinter::visit(ParameterList const& _node)
{
	writeLine("ParameterList");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(FunctionDefinition const& _node)
{
	writeLine("FunctionDefinition \"" + _node.getName() + "\"" +
			  (_node.isPublic() ? " - public" : "") +
			  (_node.isDeclaredConst() ? " - const" : ""));
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(VariableDeclaration const& _node)
{
	writeLine("VariableDeclaration \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ModifierDefinition const& _node)
{
	writeLine("ModifierDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ModifierInvocation const& _node)
{
	writeLine("ModifierInvocation \"" + _node.getName()->getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(EventDefinition const& _node)
{
	writeLine("EventDefinition \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(TypeName const& _node)
{
	writeLine("TypeName");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ElementaryTypeName const& _node)
{
	writeLine(string("ElementaryTypeName ") + Token::toString(_node.getTypeName()));
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(UserDefinedTypeName const& _node)
{
	writeLine("UserDefinedTypeName \"" + _node.getName() + "\"");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Mapping const& _node)
{
	writeLine("Mapping");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ArrayTypeName const& _node)
{
	writeLine("ArrayTypeName");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Block const& _node)
{
	writeLine("Block");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(PlaceholderStatement const& _node)
{
	writeLine("PlaceholderStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(IfStatement const& _node)
{
	writeLine("IfStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(WhileStatement const& _node)
{
	writeLine("WhileStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ForStatement const& _node)
{
	writeLine("ForStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Continue const& _node)
{
	writeLine("Continue");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Break const& _node)
{
	writeLine("Break");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Return const& _node)
{
	writeLine("Return");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(VariableDeclarationStatement const& _node)
{
	writeLine("VariableDeclarationStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ExpressionStatement const& _node)
{
	writeLine("ExpressionStatement");
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Assignment const& _node)
{
	writeLine(string("Assignment using operator ") + Token::toString(_node.getAssignmentOperator()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(UnaryOperation const& _node)
{
	writeLine(string("UnaryOperation (") + (_node.isPrefixOperation() ? "prefix" : "postfix") +
			  ") " + Token::toString(_node.getOperator()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(BinaryOperation const& _node)
{
	writeLine(string("BinaryOperation using operator ") + Token::toString(_node.getOperator()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(FunctionCall const& _node)
{
	writeLine("FunctionCall");
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(NewExpression const& _node)
{
	writeLine("NewExpression");
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(MemberAccess const& _node)
{
	writeLine("MemberAccess to member " + _node.getMemberName());
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(IndexAccess const& _node)
{
	writeLine("IndexAccess");
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Identifier const& _node)
{
	writeLine(string("Identifier ") + _node.getName());
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(ElementaryTypeNameExpression const& _node)
{
	writeLine(string("ElementaryTypeNameExpression ") + Token::toString(_node.getTypeToken()));
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

bool ASTPrinter::visit(Literal const& _node)
{
	char const* tokenString = Token::toString(_node.getToken());
	if (!tokenString)
		tokenString = "[no token]";
	writeLine(string("Literal, token: ") + tokenString + " value: " + _node.getValue());
	printType(_node);
	printSourcePart(_node);
	return goDeeper();
}

void ASTPrinter::endVisit(ImportDirective const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ContractDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(InheritanceSpecifier const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(StructDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(EnumDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(EnumValue const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ParameterList const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(FunctionDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(VariableDeclaration const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ModifierDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ModifierInvocation const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(EventDefinition const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(TypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ElementaryTypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(UserDefinedTypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Mapping const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ArrayTypeName const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Block const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(PlaceholderStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(IfStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(WhileStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ForStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Continue const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Break const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Return const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(VariableDeclarationStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ExpressionStatement const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Assignment const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(UnaryOperation const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(BinaryOperation const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(FunctionCall const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(NewExpression const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(MemberAccess const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(IndexAccess const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Identifier const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(ElementaryTypeNameExpression const&)
{
	m_indentation--;
}

void ASTPrinter::endVisit(Literal const&)
{
	m_indentation--;
}

void ASTPrinter::printSourcePart(ASTNode const& _node)
{
	if (m_gasCosts.count(&_node))
		*m_ostream << getIndentation() << "   Gas costs: " << m_gasCosts.at(&_node) << endl;
	if (!m_source.empty())
	{
		SourceLocation const& location(_node.getLocation());
		*m_ostream << getIndentation() << "   Source: "
				   << escaped(m_source.substr(location.start, location.end - location.start), false) << endl;
	}
}

void ASTPrinter::printType(Expression const& _expression)
{
	if (_expression.getType())
		*m_ostream << getIndentation() << "   Type: " << _expression.getType()->toString() << "\n";
	else
		*m_ostream << getIndentation() << "   Type unknown.\n";
}

string ASTPrinter::getIndentation() const
{
	return string(m_indentation * 2, ' ');
}

void ASTPrinter::writeLine(string const& _line)
{
	*m_ostream << getIndentation() << _line << endl;
}

}
}
<|endoftext|>


<commit_before>/*
 * Srtpchannel.cpp
 */

#include <srtp/srtp.h>
#include <nice/nice.h>

#include "SrtpChannel.h"

namespace erizo {
    DEFINE_LOGGER(SrtpChannel, "SrtpChannel");
    bool SrtpChannel::initialized = false;
    boost::mutex SrtpChannel::sessionMutex_;

SrtpChannel::SrtpChannel() {
  boost::mutex::scoped_lock lock(SrtpChannel::sessionMutex_);
  if (SrtpChannel::initialized != true) {
    int res = srtp_init();
    ELOG_DEBUG("Initialized SRTP library %d", res);
    SrtpChannel::initialized = true;
  }

  active_ = false;
  send_session_ = NULL;
  receive_session_ = NULL;
}

SrtpChannel::~SrtpChannel() {
  active_ = false;
  if (send_session_ != NULL) {
    srtp_dealloc(send_session_);
    send_session_ = NULL;
  }
  if (receive_session_ != NULL) {
    srtp_dealloc(receive_session_);
    receive_session_ = NULL;
  }
}

bool SrtpChannel::setRtpParams(char* sendingKey, char* receivingKey) {
    ELOG_DEBUG("Configuring srtp local key %s remote key %s", sendingKey,
            receivingKey);
  if (configureSrtpSession(&send_session_, sendingKey, SENDING) && configureSrtpSession(&receive_session_, receivingKey, RECEIVING)){
    active_ = true;
    return active_;
  }
  return false;
}

bool SrtpChannel::setRtcpParams(char* sendingKey, char* receivingKey) {

    return 0;
}

int SrtpChannel::protectRtp(char* buffer, int *len) {

    if (!active_)
        return 0;
    int val = srtp_protect(send_session_, buffer, len);
    if (val == 0) {
        return 0;
    } else {
        RtcpHeader* head = reinterpret_cast<RtcpHeader*>(buffer);
        RtpHeader* headrtp = reinterpret_cast<RtpHeader*>(buffer);

        ELOG_WARN("Error SrtpChannel::protectRtp %u packettype %d pt %d seqnum %u", val,head->packettype, headrtp->payloadtype, headrtp->seqnum);
        return -1;
    }
}

int SrtpChannel::unprotectRtp(char* buffer, int *len) {

    if (!active_)
        return 0;
    int val = srtp_unprotect(receive_session_, (char*) buffer, len);
    if (val == 0) {
        return 0;
    } else {
      RtcpHeader* head = reinterpret_cast<RtcpHeader*>(buffer);
      RtpHeader* headrtp = reinterpret_cast<RtpHeader*>(buffer);
      if (val!=10) // Do not warn about reply errors
        ELOG_WARN("Error SrtpChannel::unprotectRtp %u packettype %d pt %d", val,head->packettype, headrtp->payloadtype);
      return -1;
    }
}

int SrtpChannel::protectRtcp(char* buffer, int *len) {

    int val = srtp_protect_rtcp(send_session_, (char*) buffer, len);
    if (val == 0) {
        return 0;
    } else {
        RtcpHeader* head = reinterpret_cast<RtcpHeader*>(buffer);
        if (val!=10) // Do not warn about reply errors
          ELOG_WARN("Error SrtpChannel::protectRtcp %upackettype %d ", val, head->packettype);
        return -1;
    }
}

int SrtpChannel::unprotectRtcp(char* buffer, int *len) {

    int val = srtp_unprotect_rtcp(receive_session_, buffer, len);
    if (val == 0) {
        return 0;
    } else {
        if (val!=10) // Do not warn about reply errors
          ELOG_WARN("Error SrtpChannel::unprotectRtcp %u", val);
        return -1;
    }
}

bool SrtpChannel::configureSrtpSession(srtp_t *session, const char* key,
        enum TransmissionType type) {
    srtp_policy_t policy;
    memset(&policy, 0, sizeof(policy));
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    if (type == SENDING) {
        policy.ssrc.type = ssrc_any_outbound;
    } else {

        policy.ssrc.type = ssrc_any_inbound;
    }

    policy.ssrc.value = 0;
    policy.window_size = 1024;
    policy.allow_repeat_tx = 1;
    policy.next = NULL;
    //ELOG_DEBUG("auth_tag_len %d", policy.rtp.auth_tag_len);

    gsize len = 0;
    uint8_t *akey = (uint8_t*) g_base64_decode((gchar*) key, &len);
    ELOG_DEBUG("set master key/salt to %s/", octet_string_hex_string(akey, 16));
    // allocate and initialize the SRTP session
    policy.key = akey;
    int res = srtp_create(session, &policy);
    if (res!=0){
      ELOG_ERROR("Failed to create srtp session with %s, %d", octet_string_hex_string(akey, 16), res);
    }
    g_free(akey); akey = NULL;
    return res!=0? false:true;
}

} /*namespace erizo */

<commit_msg>Removed replay log for SRTP<commit_after>/*
 * Srtpchannel.cpp
 */

#include <srtp/srtp.h>
#include <nice/nice.h>

#include "SrtpChannel.h"

namespace erizo {
    DEFINE_LOGGER(SrtpChannel, "SrtpChannel");
    bool SrtpChannel::initialized = false;
    boost::mutex SrtpChannel::sessionMutex_;

SrtpChannel::SrtpChannel() {
  boost::mutex::scoped_lock lock(SrtpChannel::sessionMutex_);
  if (SrtpChannel::initialized != true) {
    int res = srtp_init();
    ELOG_DEBUG("Initialized SRTP library %d", res);
    SrtpChannel::initialized = true;
  }

  active_ = false;
  send_session_ = NULL;
  receive_session_ = NULL;
}

SrtpChannel::~SrtpChannel() {
  active_ = false;
  if (send_session_ != NULL) {
    srtp_dealloc(send_session_);
    send_session_ = NULL;
  }
  if (receive_session_ != NULL) {
    srtp_dealloc(receive_session_);
    receive_session_ = NULL;
  }
}

bool SrtpChannel::setRtpParams(char* sendingKey, char* receivingKey) {
    ELOG_DEBUG("Configuring srtp local key %s remote key %s", sendingKey,
            receivingKey);
  if (configureSrtpSession(&send_session_, sendingKey, SENDING) && configureSrtpSession(&receive_session_, receivingKey, RECEIVING)){
    active_ = true;
    return active_;
  }
  return false;
}

bool SrtpChannel::setRtcpParams(char* sendingKey, char* receivingKey) {

    return 0;
}

int SrtpChannel::protectRtp(char* buffer, int *len) {

    if (!active_)
        return 0;
    int val = srtp_protect(send_session_, buffer, len);
    if (val == 0) {
        return 0;
    } else {
        RtcpHeader* head = reinterpret_cast<RtcpHeader*>(buffer);
        RtpHeader* headrtp = reinterpret_cast<RtpHeader*>(buffer);

        if (val!=10) // Do not warn about reply errors
          ELOG_WARN("Error SrtpChannel::protectRtp %u packettype %d pt %d seqnum %u", val,head->packettype, headrtp->payloadtype, headrtp->seqnum);
        return -1;
    }
}

int SrtpChannel::unprotectRtp(char* buffer, int *len) {

    if (!active_)
        return 0;
    int val = srtp_unprotect(receive_session_, (char*) buffer, len);
    if (val == 0) {
        return 0;
    } else {
      RtcpHeader* head = reinterpret_cast<RtcpHeader*>(buffer);
      RtpHeader* headrtp = reinterpret_cast<RtpHeader*>(buffer);
      if (val!=10) // Do not warn about reply errors
        ELOG_WARN("Error SrtpChannel::unprotectRtp %u packettype %d pt %d", val,head->packettype, headrtp->payloadtype);
      return -1;
    }
}

int SrtpChannel::protectRtcp(char* buffer, int *len) {

    int val = srtp_protect_rtcp(send_session_, (char*) buffer, len);
    if (val == 0) {
        return 0;
    } else {
        RtcpHeader* head = reinterpret_cast<RtcpHeader*>(buffer);
        if (val!=10) // Do not warn about reply errors
          ELOG_WARN("Error SrtpChannel::protectRtcp %upackettype %d ", val, head->packettype);
        return -1;
    }
}

int SrtpChannel::unprotectRtcp(char* buffer, int *len) {

    int val = srtp_unprotect_rtcp(receive_session_, buffer, len);
    if (val == 0) {
        return 0;
    } else {
        if (val!=10) // Do not warn about reply errors
          ELOG_WARN("Error SrtpChannel::unprotectRtcp %u", val);
        return -1;
    }
}

bool SrtpChannel::configureSrtpSession(srtp_t *session, const char* key,
        enum TransmissionType type) {
    srtp_policy_t policy;
    memset(&policy, 0, sizeof(policy));
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    if (type == SENDING) {
        policy.ssrc.type = ssrc_any_outbound;
    } else {

        policy.ssrc.type = ssrc_any_inbound;
    }

    policy.ssrc.value = 0;
    policy.window_size = 1024;
    policy.allow_repeat_tx = 1;
    policy.next = NULL;
    //ELOG_DEBUG("auth_tag_len %d", policy.rtp.auth_tag_len);

    gsize len = 0;
    uint8_t *akey = (uint8_t*) g_base64_decode((gchar*) key, &len);
    ELOG_DEBUG("set master key/salt to %s/", octet_string_hex_string(akey, 16));
    // allocate and initialize the SRTP session
    policy.key = akey;
    int res = srtp_create(session, &policy);
    if (res!=0){
      ELOG_ERROR("Failed to create srtp session with %s, %d", octet_string_hex_string(akey, 16), res);
    }
    g_free(akey); akey = NULL;
    return res!=0? false:true;
}

} /*namespace erizo */

<|endoftext|>


<commit_before>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>
#include <iostream>
#include <sstream>
#include <memory>

#include "../command.hxx"
#include "../interp.hxx"
#include "../argument.hxx"
#include "../common.hxx"
#include "basic_parsers.hxx"

using namespace std;

namespace tglng {
  template<typename Operator>
  class StringComparison: public BinaryCommand {
    Operator op;

  public:
    StringComparison(Command* left,
                     auto_ptr<Command>& l,
                     auto_ptr<Command>& r)
    : BinaryCommand(left, l, r) {}

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring lstr, rstr;
      if (!interp.exec(lstr, lhs.get()) ||
          !interp.exec(rstr, rhs.get())) return false;

      out = op(lstr,rstr)? L"1" : L"0";
      return true;
    }
  };

  template<typename Operator>
  class StringComparisonParser:
  public BinaryCommandParser<StringComparison<Operator> > {
  };

  static GlobalBinding<StringComparisonParser<equal_to<wstring> > >
  _strequParser(L"str-equ");
  static GlobalBinding<StringComparisonParser<less<wstring> > >
  _strsltParser(L"str-slt");
  static GlobalBinding<StringComparisonParser<greater<wstring> > >
  _strsgtParser(L"str-sgt");

  class StringSearch: public Command {
    auto_ptr<Command> needle, haystack;

  public:
    StringSearch(Command* left,
                 auto_ptr<Command>& n,
                 auto_ptr<Command>& h)
    : Command(left), needle(n), haystack(h)
    { }

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring ns, hs;
      if (!interp.exec(ns, needle  .get())) return false;
      if (!interp.exec(hs, haystack.get())) return false;

      size_t result = hs.find(ns);
      if (result == wstring::npos)
        //Not found
        out = L"";
      else
        out = intToStr((signed)result);

      return true;
    }
  };

  class StringSearchParser: public CommandParser {
  public:
    virtual ParseResult parse(Interpreter& interp, Command*& out,
                              const wstring& text,
                              unsigned& offset) {
      auto_ptr<Command> needle, haystack;
      ArgumentParser a(interp, text, offset, out);
      if (!a[a.h(), a.a(needle), a.a(haystack)])
        return ParseError;

      out = new StringSearch(out, needle, haystack);
      return ContinueParsing;
    }
  };

  static GlobalBinding<StringSearchParser> _stringSearchParser(L"str-str");

  class StringIndex: public Command {
    auto_ptr<Command> begin, end;
    bool treatEndAsLength;
    AutoSection string;

  public:
    StringIndex(Command* left,
                auto_ptr<Command>& begin_,
                auto_ptr<Command>& end_,
                bool treatEndAsLength_,
                Section string_)
    : Command(left),
      begin(begin_), end(end_),
      treatEndAsLength(treatEndAsLength_),
      string(string_)
    { }

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring sb, se, str, strr;
      signed ib, ie;

      //Get the parms
      if ((string.left && !interp.exec(str, string.left)) ||
          !interp.exec(sb, begin.get()) ||
          (end.get() && !interp.exec(se, end.get())) ||
          (string.right && !interp.exec(strr, string.right)))
        return false;

      //Concat section parts
      str += strr;

      //Convert integers
      if (!parseInteger(ib, sb)) {
        wcerr << L"Invalid integer: " << sb << endl;
        return false;
      }

      if (se.empty())
        //Implicitly one character
        ie = ib+1;
      else {
        if (!parseInteger(ie, se)) {
          wcerr << L"Invalid integer: " << se << endl;
          return false;
        }

        //Add ib if in length mode
        if (treatEndAsLength)
          ie += ib;
      }

      //Negative indices are relative to the end (plus one for end)
      if (ib < 0) ib += str.size();
      if (ie < 0) ie += str.size()+1;

      //Clamp indices
      if (ib < 0) ib = 0;
      if (ib > (signed)str.size()) ib = str.size()-1;
      if (ie < ib) ie = ib;
      if (ie > (signed)str.size()) ie = str.size()-1;

      //OK
      out = str.substr(ib, ie-ib);
      return true;
    }
  };

  class StringIndexParser: public CommandParser {
  public:
    virtual ParseResult parse(Interpreter& interp, Command*& out,
                              const wstring& text, unsigned& offset) {
      auto_ptr<Command> begin, end;
      AutoSection string;
      bool length = false;
      ArgumentParser a(interp, text, offset, out);
      if (!a[a.h(), a.a(begin),
             (-a.x(length, L'.'), a.a(end)) -=
             a.s(string)])
        return ParseError;

      out = new StringIndex(out, begin, end, length, string);
      string.clear(); //Now owned by out
      return ContinueParsing;
    }
  };

  static GlobalBinding<StringIndexParser> _stringIndexParser(L"str-ix");

  class StringClass: public Command {
    //The function to check each character
    int (*is)(int);
    //Whether the range of is is restricted to 0..127
    bool asciiOnly;
    //Whether to negate the check
    bool negate;

    auto_ptr<Command> string;

    /* ISO C says that the char varieties are
     *   int f(int)
     * and the wchar_t are
     *   int f(wint_t).
     *
     * G++ considers the two incompatible (due to different signedness), but
     * that won't affect us. On most systems, sizeof(int) ==
     * sizeof(wint_t). Ensure that is true on this system.
     */
    void checkSizeofIntEqualsSizeofWintT() {
      switch (true) {
      case false:
      case sizeof(int) == sizeof(wint_t):;
      }
    }

  public:
    StringClass(Command* left,
                int (*is_)(int),
                bool asciiOnly_,
                bool negate_,
                auto_ptr<Command>& string_)
    : Command(left),
      is(is_), asciiOnly(asciiOnly_), negate(negate_),
      string(string_)
    { }

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring str;
      bool result;
      if (!interp.exec(str, string.get())) return false;

      if (str.empty()) {
        result = false;
        goto done;
      }

      for (unsigned i = 0; i < str.size(); ++i) {
        wchar_t curr = str[i];
        if ((!negate) ^
            ((!asciiOnly || (curr >= 0 && curr < 128)) &&
             is(curr))) {
          //Character failed
          result = false;
          goto done;
        }
      }

      //All chars passed
      result = true;

      done:
      out = (result? L"1" : L"0");
      return true;
    }
  };

  class StringClassParser: public CommandParser {
  public:
    virtual ParseResult parse(Interpreter& interp, Command*& out,
                              const wstring& text, unsigned& offset) {
      wchar_t clazzch;
      unsigned clazzOffset;
      //The wchar_t functions take a wint_t. An assertion in StringClass
      //ensures that the functions are compatible.
      union {
        int (*a)(int);
        int (*u)(wint_t);
      } clazz;
      bool negate, asciiOnly;
      auto_ptr<Command> string;
      ArgumentParser a(interp, text, offset, out);
      if (!a[a.h(), a.h(clazzch) >> clazzOffset, a.a(string)])
        return ParseError;

      switch (clazzch) {
      case L'l': clazz.u = iswlower, negate = false, asciiOnly = false; break;
      case L'L': clazz.u = iswlower, negate = true , asciiOnly = false; break;
      case L'o': clazz.a = islower , negate = false, asciiOnly = true ; break;
      case L'O': clazz.a = islower , negate = true , asciiOnly = true ; break;
      case L'u': clazz.u = iswupper, negate = false, asciiOnly = false; break;
      case L'U': clazz.u = iswupper, negate = true , asciiOnly = false; break;
      case L'v': clazz.a = isupper , negate = false, asciiOnly = true ; break;
      case L'V': clazz.a = isupper , negate = true , asciiOnly = true ; break;
      case L'a': clazz.u = iswalpha, negate = false, asciiOnly = false; break;
      case L'A': clazz.u = iswalpha, negate = true , asciiOnly = false; break;
      case L'b': clazz.a = isalpha , negate = false, asciiOnly = true ; break;
      case L'B': clazz.a = isalpha , negate = true , asciiOnly = true ; break;
      case L'n': clazz.u = iswalnum, negate = false, asciiOnly = false; break;
      case L'N': clazz.u = iswalnum, negate = true , asciiOnly = false; break;
      case L'm': clazz.a = isalnum , negate = false, asciiOnly = true ; break;
      case L'M': clazz.a = isalnum , negate = true , asciiOnly = true ; break;
      case L'\\':clazz.a = iscntrl , negate = false, asciiOnly = true ; break;
      case L'~': clazz.a = iscntrl , negate = true , asciiOnly = true ; break;
      case L'0': clazz.a = isdigit , negate = false, asciiOnly = true ; break;
      case L'9': clazz.a = isdigit , negate = true , asciiOnly = true ; break;
      case L'x': clazz.a = isxdigit, negate = false, asciiOnly = true ; break;
      case L'X': clazz.a = isxdigit, negate = true , asciiOnly = true ; break;
      case L'.':
      case L'p': clazz.u = iswpunct, negate = false, asciiOnly = false; break;
      case L':':
      case L'P': clazz.u = iswpunct, negate = true , asciiOnly = false; break;
      case L',':
      case L'q': clazz.a = ispunct , negate = false, asciiOnly = true ; break;
      case L';':
      case L'Q': clazz.a = ispunct , negate = true , asciiOnly = true ; break;
      case L's':
      case L'_': clazz.u = iswspace, negate = false, asciiOnly = false; break;
      case L'S':
      case L'#': clazz.u = iswspace, negate = true , asciiOnly = false; break;
      case L'g': clazz.u = iswgraph, negate = false, asciiOnly = false; break;
      case L'G': clazz.u = iswgraph, negate = true , asciiOnly = false; break;
      case L'h': clazz.a = isgraph , negate = false, asciiOnly = true ; break;
      case L'H': clazz.a = isgraph , negate = true , asciiOnly = true ; break;
      case L'r': clazz.u = iswprint, negate = false, asciiOnly = false; break;
      case L'R': clazz.u = iswprint, negate = true , asciiOnly = false; break;
      /* Not 's' since people might expect it to be space. */
      case L't': clazz.a = isprint , negate = false, asciiOnly = true ; break;
      case L'T': clazz.a = isprint , negate = true , asciiOnly = true ; break;

      default:
        interp.error(wstring(L"Unknown character class: ") + clazzch,
                     text, clazzOffset);
        return ParseError;
      }

      //OK
      out = new StringClass(out, clazz.a, asciiOnly, negate, string);
      return ContinueParsing;
    }
  };

  static GlobalBinding<StringClassParser> _stringClassParser(L"str-is");

  class StringLength: public UnaryCommand {
  public:
    StringLength(Command* left, auto_ptr<Command>& sub)
    : UnaryCommand(left, sub) {}

    virtual bool exec(wstring& dst, Interpreter& interp) {
      wstring s;
      if (!interp.exec(s, sub.get())) return false;

      dst = intToStr(s.size());
      return true;
    }
  };

  static GlobalBinding<UnaryCommandParser<StringLength> >
  _stringLengthParser(L"str-len");
}
<commit_msg>Correct incorrect clamping on str-ix.<commit_after>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>
#include <iostream>
#include <sstream>
#include <memory>

#include "../command.hxx"
#include "../interp.hxx"
#include "../argument.hxx"
#include "../common.hxx"
#include "basic_parsers.hxx"

using namespace std;

namespace tglng {
  template<typename Operator>
  class StringComparison: public BinaryCommand {
    Operator op;

  public:
    StringComparison(Command* left,
                     auto_ptr<Command>& l,
                     auto_ptr<Command>& r)
    : BinaryCommand(left, l, r) {}

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring lstr, rstr;
      if (!interp.exec(lstr, lhs.get()) ||
          !interp.exec(rstr, rhs.get())) return false;

      out = op(lstr,rstr)? L"1" : L"0";
      return true;
    }
  };

  template<typename Operator>
  class StringComparisonParser:
  public BinaryCommandParser<StringComparison<Operator> > {
  };

  static GlobalBinding<StringComparisonParser<equal_to<wstring> > >
  _strequParser(L"str-equ");
  static GlobalBinding<StringComparisonParser<less<wstring> > >
  _strsltParser(L"str-slt");
  static GlobalBinding<StringComparisonParser<greater<wstring> > >
  _strsgtParser(L"str-sgt");

  class StringSearch: public Command {
    auto_ptr<Command> needle, haystack;

  public:
    StringSearch(Command* left,
                 auto_ptr<Command>& n,
                 auto_ptr<Command>& h)
    : Command(left), needle(n), haystack(h)
    { }

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring ns, hs;
      if (!interp.exec(ns, needle  .get())) return false;
      if (!interp.exec(hs, haystack.get())) return false;

      size_t result = hs.find(ns);
      if (result == wstring::npos)
        //Not found
        out = L"";
      else
        out = intToStr((signed)result);

      return true;
    }
  };

  class StringSearchParser: public CommandParser {
  public:
    virtual ParseResult parse(Interpreter& interp, Command*& out,
                              const wstring& text,
                              unsigned& offset) {
      auto_ptr<Command> needle, haystack;
      ArgumentParser a(interp, text, offset, out);
      if (!a[a.h(), a.a(needle), a.a(haystack)])
        return ParseError;

      out = new StringSearch(out, needle, haystack);
      return ContinueParsing;
    }
  };

  static GlobalBinding<StringSearchParser> _stringSearchParser(L"str-str");

  class StringIndex: public Command {
    auto_ptr<Command> begin, end;
    bool treatEndAsLength;
    AutoSection string;

  public:
    StringIndex(Command* left,
                auto_ptr<Command>& begin_,
                auto_ptr<Command>& end_,
                bool treatEndAsLength_,
                Section string_)
    : Command(left),
      begin(begin_), end(end_),
      treatEndAsLength(treatEndAsLength_),
      string(string_)
    { }

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring sb, se, str, strr;
      signed ib, ie;

      //Get the parms
      if ((string.left && !interp.exec(str, string.left)) ||
          !interp.exec(sb, begin.get()) ||
          (end.get() && !interp.exec(se, end.get())) ||
          (string.right && !interp.exec(strr, string.right)))
        return false;

      //Concat section parts
      str += strr;

      //Convert integers
      if (!parseInteger(ib, sb)) {
        wcerr << L"Invalid integer: " << sb << endl;
        return false;
      }

      if (se.empty())
        //Implicitly one character
        ie = ib+1;
      else {
        if (!parseInteger(ie, se)) {
          wcerr << L"Invalid integer: " << se << endl;
          return false;
        }

        //Add ib if in length mode
        if (treatEndAsLength)
          ie += ib;
      }

      //Negative indices are relative to the end (plus one for end)
      if (ib < 0) ib += str.size();
      if (ie < 0) ie += str.size()+1;

      //Clamp indices
      if (ib < 0) ib = 0;
      if (ib > (signed)str.size()) ib = str.size();
      if (ie < ib) ie = ib;
      if (ie > (signed)str.size()) ie = str.size();

      //OK
      if (ib < (signed)str.size())
        out = str.substr(ib, ie-ib);
      else
        out.clear();
      return true;
    }
  };

  class StringIndexParser: public CommandParser {
  public:
    virtual ParseResult parse(Interpreter& interp, Command*& out,
                              const wstring& text, unsigned& offset) {
      auto_ptr<Command> begin, end;
      AutoSection string;
      bool length = false;
      ArgumentParser a(interp, text, offset, out);
      if (!a[a.h(), a.a(begin),
             (-a.x(length, L'.'), a.a(end)) -=
             a.s(string)])
        return ParseError;

      out = new StringIndex(out, begin, end, length, string);
      string.clear(); //Now owned by out
      return ContinueParsing;
    }
  };

  static GlobalBinding<StringIndexParser> _stringIndexParser(L"str-ix");

  class StringClass: public Command {
    //The function to check each character
    int (*is)(int);
    //Whether the range of is is restricted to 0..127
    bool asciiOnly;
    //Whether to negate the check
    bool negate;

    auto_ptr<Command> string;

    /* ISO C says that the char varieties are
     *   int f(int)
     * and the wchar_t are
     *   int f(wint_t).
     *
     * G++ considers the two incompatible (due to different signedness), but
     * that won't affect us. On most systems, sizeof(int) ==
     * sizeof(wint_t). Ensure that is true on this system.
     */
    void checkSizeofIntEqualsSizeofWintT() {
      switch (true) {
      case false:
      case sizeof(int) == sizeof(wint_t):;
      }
    }

  public:
    StringClass(Command* left,
                int (*is_)(int),
                bool asciiOnly_,
                bool negate_,
                auto_ptr<Command>& string_)
    : Command(left),
      is(is_), asciiOnly(asciiOnly_), negate(negate_),
      string(string_)
    { }

    virtual bool exec(wstring& out, Interpreter& interp) {
      wstring str;
      bool result;
      if (!interp.exec(str, string.get())) return false;

      if (str.empty()) {
        result = false;
        goto done;
      }

      for (unsigned i = 0; i < str.size(); ++i) {
        wchar_t curr = str[i];
        if ((!negate) ^
            ((!asciiOnly || (curr >= 0 && curr < 128)) &&
             is(curr))) {
          //Character failed
          result = false;
          goto done;
        }
      }

      //All chars passed
      result = true;

      done:
      out = (result? L"1" : L"0");
      return true;
    }
  };

  class StringClassParser: public CommandParser {
  public:
    virtual ParseResult parse(Interpreter& interp, Command*& out,
                              const wstring& text, unsigned& offset) {
      wchar_t clazzch;
      unsigned clazzOffset;
      //The wchar_t functions take a wint_t. An assertion in StringClass
      //ensures that the functions are compatible.
      union {
        int (*a)(int);
        int (*u)(wint_t);
      } clazz;
      bool negate, asciiOnly;
      auto_ptr<Command> string;
      ArgumentParser a(interp, text, offset, out);
      if (!a[a.h(), a.h(clazzch) >> clazzOffset, a.a(string)])
        return ParseError;

      switch (clazzch) {
      case L'l': clazz.u = iswlower, negate = false, asciiOnly = false; break;
      case L'L': clazz.u = iswlower, negate = true , asciiOnly = false; break;
      case L'o': clazz.a = islower , negate = false, asciiOnly = true ; break;
      case L'O': clazz.a = islower , negate = true , asciiOnly = true ; break;
      case L'u': clazz.u = iswupper, negate = false, asciiOnly = false; break;
      case L'U': clazz.u = iswupper, negate = true , asciiOnly = false; break;
      case L'v': clazz.a = isupper , negate = false, asciiOnly = true ; break;
      case L'V': clazz.a = isupper , negate = true , asciiOnly = true ; break;
      case L'a': clazz.u = iswalpha, negate = false, asciiOnly = false; break;
      case L'A': clazz.u = iswalpha, negate = true , asciiOnly = false; break;
      case L'b': clazz.a = isalpha , negate = false, asciiOnly = true ; break;
      case L'B': clazz.a = isalpha , negate = true , asciiOnly = true ; break;
      case L'n': clazz.u = iswalnum, negate = false, asciiOnly = false; break;
      case L'N': clazz.u = iswalnum, negate = true , asciiOnly = false; break;
      case L'm': clazz.a = isalnum , negate = false, asciiOnly = true ; break;
      case L'M': clazz.a = isalnum , negate = true , asciiOnly = true ; break;
      case L'\\':clazz.a = iscntrl , negate = false, asciiOnly = true ; break;
      case L'~': clazz.a = iscntrl , negate = true , asciiOnly = true ; break;
      case L'0': clazz.a = isdigit , negate = false, asciiOnly = true ; break;
      case L'9': clazz.a = isdigit , negate = true , asciiOnly = true ; break;
      case L'x': clazz.a = isxdigit, negate = false, asciiOnly = true ; break;
      case L'X': clazz.a = isxdigit, negate = true , asciiOnly = true ; break;
      case L'.':
      case L'p': clazz.u = iswpunct, negate = false, asciiOnly = false; break;
      case L':':
      case L'P': clazz.u = iswpunct, negate = true , asciiOnly = false; break;
      case L',':
      case L'q': clazz.a = ispunct , negate = false, asciiOnly = true ; break;
      case L';':
      case L'Q': clazz.a = ispunct , negate = true , asciiOnly = true ; break;
      case L's':
      case L'_': clazz.u = iswspace, negate = false, asciiOnly = false; break;
      case L'S':
      case L'#': clazz.u = iswspace, negate = true , asciiOnly = false; break;
      case L'g': clazz.u = iswgraph, negate = false, asciiOnly = false; break;
      case L'G': clazz.u = iswgraph, negate = true , asciiOnly = false; break;
      case L'h': clazz.a = isgraph , negate = false, asciiOnly = true ; break;
      case L'H': clazz.a = isgraph , negate = true , asciiOnly = true ; break;
      case L'r': clazz.u = iswprint, negate = false, asciiOnly = false; break;
      case L'R': clazz.u = iswprint, negate = true , asciiOnly = false; break;
      /* Not 's' since people might expect it to be space. */
      case L't': clazz.a = isprint , negate = false, asciiOnly = true ; break;
      case L'T': clazz.a = isprint , negate = true , asciiOnly = true ; break;

      default:
        interp.error(wstring(L"Unknown character class: ") + clazzch,
                     text, clazzOffset);
        return ParseError;
      }

      //OK
      out = new StringClass(out, clazz.a, asciiOnly, negate, string);
      return ContinueParsing;
    }
  };

  static GlobalBinding<StringClassParser> _stringClassParser(L"str-is");

  class StringLength: public UnaryCommand {
  public:
    StringLength(Command* left, auto_ptr<Command>& sub)
    : UnaryCommand(left, sub) {}

    virtual bool exec(wstring& dst, Interpreter& interp) {
      wstring s;
      if (!interp.exec(s, sub.get())) return false;

      dst = intToStr(s.size());
      return true;
    }
  };

  static GlobalBinding<UnaryCommandParser<StringLength> >
  _stringLengthParser(L"str-len");
}
<|endoftext|>


<commit_before>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

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

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

#include <algorithm>
#include <mutex>
#include <config.h>

#include "connections.h"

const char* libhttppp::ConnectionData::getData(){
  return _Data;
}

size_t libhttppp::ConnectionData::getDataSize(){
  return _DataSize;
}

libhttppp::ConnectionData *libhttppp::ConnectionData::nextConnectionData(){
  return _nextConnectionData;
}

libhttppp::ConnectionData::ConnectionData(const char*data,size_t datasize){
  _nextConnectionData=NULL;
  std::copy(data,data+datasize,_Data);
  _DataSize=datasize;
}

libhttppp::ConnectionData::~ConnectionData(){
  if(_nextConnectionData)
    delete _nextConnectionData;
}

libhttppp::ClientSocket *libhttppp::Connection::getClientSocket(){
  return _ClientSocket;
}

libhttppp::Connection *libhttppp::Connection::nextConnection(){
  return _nextConnection;
}

/** \brief a method to add Data to Sendqueue
  * \param data an const char* to add to sendqueue
  * \param datasize an size_t to set datasize
  * \return the last ConnectionData Block from Sendqueue
  *
  * This method does unbelievably useful things.
  * And returns exceptionally the new connection data block.
  * Use it everyday with good health.
  */
libhttppp::ConnectionData *libhttppp::Connection::addSendQueue(const char*data,size_t datasize){
  size_t written=0;
  for(size_t cursize=datasize; cursize>0; cursize=datasize-written){
    if(cursize>BLOCKSIZE){
      cursize=BLOCKSIZE;
    }
    if(!_SendDataFirst){
      _SendDataFirst= new ConnectionData(data+written,cursize);
      _SendDataLast=_SendDataFirst;
    }else{
      _SendDataLast->_nextConnectionData=new ConnectionData(data+written,cursize);
      _SendDataLast=_SendDataLast->_nextConnectionData;
    }
    written+=cursize;
  }
  _SendDataSize+=written;
  return _SendDataLast;
}

void libhttppp::Connection::cleanSendData(){
   if(_SendDataFirst)
     delete _SendDataFirst;
   _SendDataFirst=NULL;
   _SendDataLast=NULL;
   _SendDataSize=0;
}

libhttppp::ConnectionData *libhttppp::Connection::resizeSendQueue(size_t size){
  return _resizeQueue(&_SendDataFirst,&_SendDataLast,&_SendDataSize,size);
}

libhttppp::ConnectionData* libhttppp::Connection::getSendData(){
  return _SendDataFirst;
}

size_t libhttppp::Connection::getSendSize(){
  return _SendDataSize;
}

libhttppp::ConnectionData *libhttppp::Connection::addRecvQueue(const char data[BLOCKSIZE],size_t datasize){
  if(!_ReadDataFirst){
    _ReadDataFirst= new ConnectionData(data,datasize);
    _ReadDataLast=_ReadDataFirst;
  }else{
    _ReadDataLast->_nextConnectionData=new ConnectionData(data,datasize);
    _ReadDataLast=_ReadDataLast->_nextConnectionData;
  }
  _ReadDataSize+=datasize;
  return _ReadDataLast;
}

void libhttppp::Connection::cleanRecvData(){
   delete _ReadDataFirst;
  _ReadDataFirst=NULL;
  _ReadDataLast=NULL;
  _ReadDataSize=0;
}

libhttppp::ConnectionData *libhttppp::Connection::resizeRecvQueue(size_t size){
  return _resizeQueue(&_ReadDataFirst,&_ReadDataLast,&_ReadDataSize,size);
}

libhttppp::ConnectionData *libhttppp::Connection::getRecvData(){
  return _ReadDataFirst;
}

size_t libhttppp::Connection::getRecvSize(){
  return _ReadDataSize;
}

libhttppp::ConnectionData *libhttppp::Connection::_resizeQueue(ConnectionData** firstdata, ConnectionData** lastdata,
					 size_t *qsize, size_t size){
  ConnectionData *firstdat=*firstdata;
  while(firstdat!=NULL && size!=0){
    size_t delsize=0;
    if(size>=firstdat->getDataSize()){
       delsize=firstdat->getDataSize();
       ConnectionData *deldat=firstdat;
       firstdat=firstdat->_nextConnectionData;
       if(deldat==*lastdata)
         *lastdata=firstdat;
       deldat->_nextConnectionData=NULL;
       delete deldat;
    }else{
       delsize=size;
       firstdat->_DataSize-=size;
       std::copy(firstdat->_Data+delsize,firstdat->_Data+BLOCKSIZE,firstdat->_Data);
       memset(firstdat->_Data+firstdat->_DataSize,(BLOCKSIZE-firstdat->_DataSize),'\0');
    }
    size-=delsize;
    *qsize-=delsize;
  }
  *firstdata=firstdat;
  return firstdat;
}

int libhttppp::Connection::copyValue(ConnectionData* startblock, int startpos,
                          ConnectionData* endblock, int endpos, char** buffer){
  size_t copysize=0,copypos=0;
  for(ConnectionData *curdat=startblock; curdat; curdat=curdat->nextConnectionData()){
    if(curdat==endblock){
      copysize+=endpos;
      break;
    }
    copysize+=curdat->getDataSize();
  }
  copysize-=startpos;
  char *buf;
  buf = new char[(copysize+1)]; //one more for termination
  for(ConnectionData *curdat=startblock; curdat; curdat=curdat->nextConnectionData()){
    if(curdat==startblock && curdat==endblock){
      std::copy(curdat->_Data+startpos,curdat->_Data+(endpos-startpos),buf+copypos);
    }else if(curdat==startblock){
      std::copy(curdat->_Data+startpos,curdat->_Data+(curdat->getDataSize()-startpos),buf+copypos);
      copypos+=curdat->getDataSize()-startpos;
    }else if(curdat==endblock){
      std::copy(curdat->_Data,curdat->_Data+endpos,buf+copypos);
      copypos+=endpos;
    }else{
      std::copy(curdat->_Data,curdat->_Data+curdat->getDataSize(),buf+copypos);
      copypos+=curdat->getDataSize();
    }
    if(curdat==endblock)
      break;
  }
  buf[copysize]='\0';
  *buffer=buf;
  return copysize; //not include termination
}

int libhttppp::Connection::searchValue(ConnectionData* startblock, ConnectionData** findblock,
			    const char* keyword){
  return searchValue(startblock, findblock, keyword,strlen(keyword));
}

int libhttppp::Connection::searchValue(ConnectionData* startblock, ConnectionData** findblock,
			    const char* keyword,size_t keylen){
  size_t fpos=0,fcurpos=0;
  for(ConnectionData *curdat=startblock; curdat; curdat=curdat->nextConnectionData()){
    for(size_t pos=0; pos<curdat->getDataSize(); pos++){
      if(keyword[fcurpos]==curdat->_Data[pos]){
        if(fcurpos==0){
          fpos=pos;
          *findblock=curdat;
        }
        fcurpos++;
      }else{
        fcurpos=0;
        fpos=0;
        *findblock=NULL;
      }
      if(fcurpos==keylen)
        return fpos;
    }
  }
  return -1;
}

bool libhttppp::Connection::tryLock(){
  try{
    _Locked->try_lock();
    return true;
  }catch(HTTPException &e){
    return false;
  }
}

bool libhttppp::Connection::tryUnlock(){
  try{
    _Locked->unlock();
    return true;
  }catch(HTTPException &e){
    return false;
  }
}

libhttppp::Connection::Connection(){
  _ClientSocket=new ClientSocket;
  _nextConnection=NULL;
  _ReadDataFirst=NULL;
  _ReadDataLast=NULL;
  _ReadDataSize=0;
  _SendDataFirst=NULL;
  _SendDataLast=NULL;
  _SendDataSize=0;
  _Locked=new std::mutex;
}

libhttppp::Connection::~Connection(){
  delete _ClientSocket;
  delete _ReadDataFirst;
  delete _SendDataFirst;
  delete _nextConnection;
}

libhttppp::ConnectionPool::ConnectionPool(ServerSocket *socket){
  _firstConnection=NULL;
  _lastConnection=NULL;
  _ServerSocket=socket;
  if(!_ServerSocket){
    _httpexception.Cirtical("ServerSocket not set!");
    throw _httpexception;
  }
}

libhttppp::ConnectionPool::~ConnectionPool(){
    delete _firstConnection;
}

libhttppp::Connection* libhttppp::ConnectionPool::addConnection(){
  if(!_firstConnection){
    _firstConnection=new Connection;
    _lastConnection=_firstConnection;
  }else{
    _lastConnection->_nextConnection=new Connection;
    _lastConnection=_lastConnection->_nextConnection;
  }
  return _lastConnection;
}

#ifndef Windows
libhttppp::Connection* libhttppp::ConnectionPool::delConnection(int socket){
  return delConnection(getConnection(socket));
}
#else
libhttppp::Connection* libhttppp::ConnectionPool::delConnection(SOCKET socket){
  return delConnection(getConnection(socket));
}
#endif

libhttppp::Connection* libhttppp::ConnectionPool::delConnection(ClientSocket *clientsocket){
  return delConnection(getConnection(clientsocket));
}

libhttppp::Connection* libhttppp::ConnectionPool::delConnection(Connection *delcon){
  Connection *prevcon=NULL;
  for(Connection *curcon=_firstConnection; curcon; curcon=curcon->nextConnection()){
    if(curcon==delcon){
      if(prevcon){
        prevcon->_nextConnection=curcon->_nextConnection;
        if(_lastConnection==delcon)
          _lastConnection=prevcon;
      }else{
        _firstConnection=curcon->_nextConnection;
        if(_lastConnection==delcon)
          _lastConnection=_firstConnection;
      }
      curcon->_nextConnection=NULL;
      delete curcon;
      break;
    }
    prevcon=curcon;
  }
  if(prevcon && prevcon->_nextConnection)
    return prevcon->_nextConnection;
  else
    return _firstConnection;
}

libhttppp::Connection* libhttppp::ConnectionPool::getConnection(ClientSocket *clientsocket){
  for(Connection *curcon=_firstConnection; curcon; curcon=curcon->nextConnection()){
    if(curcon->getClientSocket()==clientsocket)
      return curcon;
  }
  return NULL;
}

#ifndef Windows
libhttppp::Connection* libhttppp::ConnectionPool::getConnection(int socket){
#else
libhttppp::Connection* libhttppp::ConnectionPool::getConnection(SOCKET socket){
#endif
  for(Connection *curcon=_firstConnection; curcon; curcon=curcon->nextConnection()){
    if(curcon->getClientSocket()->getSocket()==socket)
      return curcon;
  }
  return NULL;
}
<commit_msg>fied mutex in connections<commit_after>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

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

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

#include <algorithm>
#include <mutex>
#include <config.h>

#include "connections.h"

const char* libhttppp::ConnectionData::getData(){
  return _Data;
}

size_t libhttppp::ConnectionData::getDataSize(){
  return _DataSize;
}

libhttppp::ConnectionData *libhttppp::ConnectionData::nextConnectionData(){
  return _nextConnectionData;
}

libhttppp::ConnectionData::ConnectionData(const char*data,size_t datasize){
  _nextConnectionData=NULL;
  std::copy(data,data+datasize,_Data);
  _DataSize=datasize;
}

libhttppp::ConnectionData::~ConnectionData(){
  if(_nextConnectionData)
    delete _nextConnectionData;
}

libhttppp::ClientSocket *libhttppp::Connection::getClientSocket(){
  return _ClientSocket;
}

libhttppp::Connection *libhttppp::Connection::nextConnection(){
  return _nextConnection;
}

/** \brief a method to add Data to Sendqueue
  * \param data an const char* to add to sendqueue
  * \param datasize an size_t to set datasize
  * \return the last ConnectionData Block from Sendqueue
  *
  * This method does unbelievably useful things.
  * And returns exceptionally the new connection data block.
  * Use it everyday with good health.
  */
libhttppp::ConnectionData *libhttppp::Connection::addSendQueue(const char*data,size_t datasize){
  size_t written=0;
  for(size_t cursize=datasize; cursize>0; cursize=datasize-written){
    if(cursize>BLOCKSIZE){
      cursize=BLOCKSIZE;
    }
    if(!_SendDataFirst){
      _SendDataFirst= new ConnectionData(data+written,cursize);
      _SendDataLast=_SendDataFirst;
    }else{
      _SendDataLast->_nextConnectionData=new ConnectionData(data+written,cursize);
      _SendDataLast=_SendDataLast->_nextConnectionData;
    }
    written+=cursize;
  }
  _SendDataSize+=written;
  return _SendDataLast;
}

void libhttppp::Connection::cleanSendData(){
   if(_SendDataFirst)
     delete _SendDataFirst;
   _SendDataFirst=NULL;
   _SendDataLast=NULL;
   _SendDataSize=0;
}

libhttppp::ConnectionData *libhttppp::Connection::resizeSendQueue(size_t size){
  return _resizeQueue(&_SendDataFirst,&_SendDataLast,&_SendDataSize,size);
}

libhttppp::ConnectionData* libhttppp::Connection::getSendData(){
  return _SendDataFirst;
}

size_t libhttppp::Connection::getSendSize(){
  return _SendDataSize;
}

libhttppp::ConnectionData *libhttppp::Connection::addRecvQueue(const char data[BLOCKSIZE],size_t datasize){
  if(!_ReadDataFirst){
    _ReadDataFirst= new ConnectionData(data,datasize);
    _ReadDataLast=_ReadDataFirst;
  }else{
    _ReadDataLast->_nextConnectionData=new ConnectionData(data,datasize);
    _ReadDataLast=_ReadDataLast->_nextConnectionData;
  }
  _ReadDataSize+=datasize;
  return _ReadDataLast;
}

void libhttppp::Connection::cleanRecvData(){
   delete _ReadDataFirst;
  _ReadDataFirst=NULL;
  _ReadDataLast=NULL;
  _ReadDataSize=0;
}

libhttppp::ConnectionData *libhttppp::Connection::resizeRecvQueue(size_t size){
  return _resizeQueue(&_ReadDataFirst,&_ReadDataLast,&_ReadDataSize,size);
}

libhttppp::ConnectionData *libhttppp::Connection::getRecvData(){
  return _ReadDataFirst;
}

size_t libhttppp::Connection::getRecvSize(){
  return _ReadDataSize;
}

libhttppp::ConnectionData *libhttppp::Connection::_resizeQueue(ConnectionData** firstdata, ConnectionData** lastdata,
					 size_t *qsize, size_t size){
  ConnectionData *firstdat=*firstdata;
  while(firstdat!=NULL && size!=0){
    size_t delsize=0;
    if(size>=firstdat->getDataSize()){
       delsize=firstdat->getDataSize();
       ConnectionData *deldat=firstdat;
       firstdat=firstdat->_nextConnectionData;
       if(deldat==*lastdata)
         *lastdata=firstdat;
       deldat->_nextConnectionData=NULL;
       delete deldat;
    }else{
       delsize=size;
       firstdat->_DataSize-=size;
       std::copy(firstdat->_Data+delsize,firstdat->_Data+BLOCKSIZE,firstdat->_Data);
       memset(firstdat->_Data+firstdat->_DataSize,(BLOCKSIZE-firstdat->_DataSize),'\0');
    }
    size-=delsize;
    *qsize-=delsize;
  }
  *firstdata=firstdat;
  return firstdat;
}

int libhttppp::Connection::copyValue(ConnectionData* startblock, int startpos,
                          ConnectionData* endblock, int endpos, char** buffer){
  size_t copysize=0,copypos=0;
  for(ConnectionData *curdat=startblock; curdat; curdat=curdat->nextConnectionData()){
    if(curdat==endblock){
      copysize+=endpos;
      break;
    }
    copysize+=curdat->getDataSize();
  }
  copysize-=startpos;
  char *buf;
  buf = new char[(copysize+1)]; //one more for termination
  for(ConnectionData *curdat=startblock; curdat; curdat=curdat->nextConnectionData()){
    if(curdat==startblock && curdat==endblock){
      std::copy(curdat->_Data+startpos,curdat->_Data+(endpos-startpos),buf+copypos);
    }else if(curdat==startblock){
      std::copy(curdat->_Data+startpos,curdat->_Data+(curdat->getDataSize()-startpos),buf+copypos);
      copypos+=curdat->getDataSize()-startpos;
    }else if(curdat==endblock){
      std::copy(curdat->_Data,curdat->_Data+endpos,buf+copypos);
      copypos+=endpos;
    }else{
      std::copy(curdat->_Data,curdat->_Data+curdat->getDataSize(),buf+copypos);
      copypos+=curdat->getDataSize();
    }
    if(curdat==endblock)
      break;
  }
  buf[copysize]='\0';
  *buffer=buf;
  return copysize; //not include termination
}

int libhttppp::Connection::searchValue(ConnectionData* startblock, ConnectionData** findblock,
			    const char* keyword){
  return searchValue(startblock, findblock, keyword,strlen(keyword));
}

int libhttppp::Connection::searchValue(ConnectionData* startblock, ConnectionData** findblock,
			    const char* keyword,size_t keylen){
  size_t fpos=0,fcurpos=0;
  for(ConnectionData *curdat=startblock; curdat; curdat=curdat->nextConnectionData()){
    for(size_t pos=0; pos<curdat->getDataSize(); pos++){
      if(keyword[fcurpos]==curdat->_Data[pos]){
        if(fcurpos==0){
          fpos=pos;
          *findblock=curdat;
        }
        fcurpos++;
      }else{
        fcurpos=0;
        fpos=0;
        *findblock=NULL;
      }
      if(fcurpos==keylen)
        return fpos;
    }
  }
  return -1;
}

bool libhttppp::Connection::tryLock(){
  try{
    _Locked->try_lock();
    return true;
  }catch(HTTPException &e){
    return false;
  }
}

bool libhttppp::Connection::tryUnlock(){
  try{
    _Locked->unlock();
    return true;
  }catch(HTTPException &e){
    return false;
  }
}

libhttppp::Connection::Connection(){
  _ClientSocket=new ClientSocket;
  _nextConnection=NULL;
  _ReadDataFirst=NULL;
  _ReadDataLast=NULL;
  _ReadDataSize=0;
  _SendDataFirst=NULL;
  _SendDataLast=NULL;
  _SendDataSize=0;
  _Locked=new std::mutex;
}

libhttppp::Connection::~Connection(){
  delete _ClientSocket;
  delete _ReadDataFirst;
  delete _SendDataFirst;
  delete _nextConnection;
  delete _Locked;
}

libhttppp::ConnectionPool::ConnectionPool(ServerSocket *socket){
  _firstConnection=NULL;
  _lastConnection=NULL;
  _ServerSocket=socket;
  if(!_ServerSocket){
    _httpexception.Cirtical("ServerSocket not set!");
    throw _httpexception;
  }
}

libhttppp::ConnectionPool::~ConnectionPool(){
    delete _firstConnection;
}

libhttppp::Connection* libhttppp::ConnectionPool::addConnection(){
  if(!_firstConnection){
    _firstConnection=new Connection;
    _lastConnection=_firstConnection;
  }else{
    _lastConnection->_nextConnection=new Connection;
    _lastConnection=_lastConnection->_nextConnection;
  }
  return _lastConnection;
}

#ifndef Windows
libhttppp::Connection* libhttppp::ConnectionPool::delConnection(int socket){
  return delConnection(getConnection(socket));
}
#else
libhttppp::Connection* libhttppp::ConnectionPool::delConnection(SOCKET socket){
  return delConnection(getConnection(socket));
}
#endif

libhttppp::Connection* libhttppp::ConnectionPool::delConnection(ClientSocket *clientsocket){
  return delConnection(getConnection(clientsocket));
}

libhttppp::Connection* libhttppp::ConnectionPool::delConnection(Connection *delcon){
  Connection *prevcon=NULL;
  for(Connection *curcon=_firstConnection; curcon; curcon=curcon->nextConnection()){
    if(curcon==delcon){
      if(prevcon){
        prevcon->_nextConnection=curcon->_nextConnection;
        if(_lastConnection==delcon)
          _lastConnection=prevcon;
      }else{
        _firstConnection=curcon->_nextConnection;
        if(_lastConnection==delcon)
          _lastConnection=_firstConnection;
      }
      curcon->_nextConnection=NULL;
      delete curcon;
      break;
    }
    prevcon=curcon;
  }
  if(prevcon && prevcon->_nextConnection)
    return prevcon->_nextConnection;
  else
    return _firstConnection;
}

libhttppp::Connection* libhttppp::ConnectionPool::getConnection(ClientSocket *clientsocket){
  for(Connection *curcon=_firstConnection; curcon; curcon=curcon->nextConnection()){
    if(curcon->getClientSocket()==clientsocket)
      return curcon;
  }
  return NULL;
}

#ifndef Windows
libhttppp::Connection* libhttppp::ConnectionPool::getConnection(int socket){
#else
libhttppp::Connection* libhttppp::ConnectionPool::getConnection(SOCKET socket){
#endif
  for(Connection *curcon=_firstConnection; curcon; curcon=curcon->nextConnection()){
    if(curcon->getClientSocket()->getSocket()==socket)
      return curcon;
  }
  return NULL;
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013 lailongwei<lailongwei@126.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "llbc/common/Export.h"
#include "llbc/common/BeforeIncl.h"

#include "llbc/common/Common.h"

__LLBC_NS_BEGIN

int __LLBC_CommonStartup()
{
    // Create library TLS.
    __LLBC_CreateLibTls();

    // Init errors.
    __LLBC_InitErrors();

    // Fill entry thread TLS info.
    __LLBC_LibTls *tls = __LLBC_GetLibTls();
    tls->coreTls.llbcThread = true;
    tls->coreTls.entryThread = true;
    tls->coreTls.threadHandle = LLBC_INVALID_HANDLE;

#if LLBC_TARGET_PLATFORM_WIN32
    tls->coreTls.threadId = ::GetCurrentThreadId();
#elif LLBC_TARGET_PLATFORM_LINUX || LLBC_TARGET_PLATFORM_ANDROID
    tls->coreTls.threadId = ::gettid();
#else // LLBC_TARGET_PLATFORM_IPHONE || LLBC_TARGET_PLATFORM_MAC (FreeBSD kernel)
    tls->coreTls.threadId = pthread_getthreadid_np();
#endif

#if LLBC_TARGET_PLATFORM_NON_WIN32
    tls->coreTls.nativeThreadHandle = pthread_self();
#else // LLBC_TARGET_PLATFORM_WIN32
    HANDLE pseudoHandle = ::GetCurrentThread();
    ::DuplicateHandle(GetCurrentProcess(),
                      pseudoHandle,
                      GetCurrentProcess(),
                      &tls->coreTls.nativeThreadHandle,
                      0,
                      FALSE,
                      DUPLICATE_SAME_ACCESS);
#endif // LLBC_TARGET_PLATFRM_NON_WIN32

    // Set endian type constant.
    LLBC_MachineEndian = LLBC_GetMachineEndianType();

    return LLBC_OK;
}

void __LLBC_CommonCleanup()
{
    // Reset entry thread tls info.
#if LLBC_TARGET_PLATFORM_WIN32
    __LLBC_LibTls *tls = __LLBC_GetLibTls();
    ::CloseHandle(tls->coreTls.nativeThreadHandle);
    tls->coreTls.nativeThreadHandle = LLBC_INVALID_NATIVE_THREAD_HANDLE;
#endif // LLBC_TARGET_PLATFORM_WIN32
    __LLBC_ResetLibTls();

    // Destroy errors.
    __LLBC_DestroyErrors();

    // Destroy library TLS.
    __LLBC_DestroyLibTls();
}

__LLBC_NS_END

#include "llbc/common/AfterIncl.h"
<commit_msg>Fix compile error.<commit_after>// The MIT License (MIT)

// Copyright (c) 2013 lailongwei<lailongwei@126.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "llbc/common/Export.h"
#include "llbc/common/BeforeIncl.h"

#include "llbc/common/Common.h"

__LLBC_NS_BEGIN

int __LLBC_CommonStartup()
{
    // Create library TLS.
    __LLBC_CreateLibTls();

    // Init errors.
    __LLBC_InitErrors();

    // Fill entry thread TLS info.
    __LLBC_LibTls *tls = __LLBC_GetLibTls();
    tls->coreTls.llbcThread = true;
    tls->coreTls.entryThread = true;
    tls->coreTls.threadHandle = LLBC_INVALID_HANDLE;

#if LLBC_TARGET_PLATFORM_WIN32
    tls->coreTls.threadId = ::GetCurrentThreadId();
#elif LLBC_TARGET_PLATFORM_LINUX || LLBC_TARGET_PLATFORM_ANDROID
    tls->coreTls.threadId = syscall(SYS_gettid);
#else // LLBC_TARGET_PLATFORM_IPHONE || LLBC_TARGET_PLATFORM_MAC (FreeBSD kernel)
    tls->coreTls.threadId = pthread_getthreadid_np();
#endif

#if LLBC_TARGET_PLATFORM_NON_WIN32
    tls->coreTls.nativeThreadHandle = pthread_self();
#else // LLBC_TARGET_PLATFORM_WIN32
    HANDLE pseudoHandle = ::GetCurrentThread();
    ::DuplicateHandle(GetCurrentProcess(),
                      pseudoHandle,
                      GetCurrentProcess(),
                      &tls->coreTls.nativeThreadHandle,
                      0,
                      FALSE,
                      DUPLICATE_SAME_ACCESS);
#endif // LLBC_TARGET_PLATFRM_NON_WIN32

    // Set endian type constant.
    LLBC_MachineEndian = LLBC_GetMachineEndianType();

    return LLBC_OK;
}

void __LLBC_CommonCleanup()
{
    // Reset entry thread tls info.
#if LLBC_TARGET_PLATFORM_WIN32
    __LLBC_LibTls *tls = __LLBC_GetLibTls();
    ::CloseHandle(tls->coreTls.nativeThreadHandle);
    tls->coreTls.nativeThreadHandle = LLBC_INVALID_NATIVE_THREAD_HANDLE;
#endif // LLBC_TARGET_PLATFORM_WIN32
    __LLBC_ResetLibTls();

    // Destroy errors.
    __LLBC_DestroyErrors();

    // Destroy library TLS.
    __LLBC_DestroyLibTls();
}

__LLBC_NS_END

#include "llbc/common/AfterIncl.h"
<|endoftext|>


<commit_before>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <chrono>
#include <iostream>
#include <thread>

#include <franka/duration.h>
#include <franka/exception.h>
#include <franka/robot.h>

#include "examples_common.h"

/**
 * @example communication_test.cpp
 * An example indicating the network performance.
 *
 * @warning Before executing this example, make sure there is enough space in front of the robot.
 */

int main(int argc, char** argv) {
  if (argc != 2) {
    std::cerr << "Usage: " << argv[0] << " <robot-hostname>" << std::endl;
    return -1;
  }

  uint64_t counter = 0;
  double avg_success_rate = 0.0;
  double min_success_rate = 1.0;
  double max_success_rate = 0.0;
  uint64_t time = 0;
  std::cout.precision(2);
  std::cout << std::fixed;

  try {
    franka::Robot robot(argv[1]);
    setDefaultBehavior(robot);

    // First move the robot to a suitable joint configuration
    std::array<double, 7> q_goal = {{0, -M_PI_4, 0, -3 * M_PI_4, 0, M_PI_2, M_PI_4}};
    MotionGenerator motion_generator(0.5, q_goal);
    std::cout << "WARNING: This example will move the robot! "
              << "Please make sure to have the user stop button at hand!" << std::endl
              << "Press Enter to continue..." << std::endl;
    std::cin.ignore();
    robot.control(motion_generator);
    std::cout << "Finished moving to initial joint configuration." << std::endl << std::endl;
    std::cout << "Starting communication test." << std::endl;

    robot.setCollisionBehavior(
        {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}}, {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}},
        {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}}, {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}},
        {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}}, {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}},
        {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}}, {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}});

    franka::Torques zero_torques{{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};
    robot.control(
        [&time, &counter, &avg_success_rate, &min_success_rate, &max_success_rate, zero_torques](
            const franka::RobotState& robot_state, franka::Duration period) -> franka::Torques {
          time += period.toMSec();
          counter++;
          if (robot_state.control_command_success_rate == 0.0) {
            return zero_torques;
          }

          if (counter % 100 == 0) {
            std::cout << "#" << counter
                      << " Current success rate: " << robot_state.control_command_success_rate
                      << std::endl;
          }
          std::this_thread::sleep_for(std::chrono::microseconds(100));

          avg_success_rate += robot_state.control_command_success_rate;
          if (robot_state.control_command_success_rate > max_success_rate) {
            max_success_rate = robot_state.control_command_success_rate;
          }
          if (robot_state.control_command_success_rate < min_success_rate) {
            min_success_rate = robot_state.control_command_success_rate;
          }

          if (time >= 10000) {
            std::cout << std::endl << "Finished test, shutting down example" << std::endl;
            return franka::MotionFinished(zero_torques);
          }

          // Sending zero torques - if EE is configured correctly, robot should not move
          return zero_torques;
        });
  } catch (const franka::Exception& e) {
    std::cout << e.what() << std::endl;
    return -1;
  }

  avg_success_rate = avg_success_rate / counter;

  std::cout << std::endl
            << std::endl
            << "#######################################################" << std::endl;
  uint64_t lost_robot_states = time - counter;
  if (lost_robot_states > 0) {
    std::cout << "The control loop did not get executed " << lost_robot_states << " times in the"
              << std::endl
              << "last " << time << " milliseconds! (lost " << lost_robot_states << " robot states)"
              << std::endl
              << std::endl;
  }

  std::cout << "Control command success rate of " << counter << " samples: " << std::endl;
  std::cout << "Max: " << max_success_rate << std::endl;
  std::cout << "Avg: " << avg_success_rate << std::endl;
  std::cout << "Min: " << min_success_rate << std::endl;

  if (avg_success_rate < 0.90) {
    std::cout << std::endl
              << "WARNING: THIS SETUP IS PROBABLY NOT SUFFICIENT FOR FCI!" << std::endl;
    std::cout << "PLEASE TRY OUT A DIFFERENT PC / NIC" << std::endl;
  } else if (avg_success_rate < 0.95) {
    std::cout << std::endl << "WARNING: MANY PACKETS GOT LOST!" << std::endl;
    std::cout << "PLEASE INSPECT YOUR SETUP AND FOLLOW ADVICE ON" << std::endl
              << "https://frankaemika.github.io/docs/troubleshooting.html" << std::endl;
  }
  std::cout << "#######################################################" << std::endl << std::endl;

  return 0;
}
<commit_msg>Communication test: Skip first loop.<commit_after>// Copyright (c) 2017 Franka Emika GmbH
// Use of this source code is governed by the Apache-2.0 license, see LICENSE
#include <chrono>
#include <iostream>
#include <thread>

#include <franka/duration.h>
#include <franka/exception.h>
#include <franka/robot.h>

#include "examples_common.h"

/**
 * @example communication_test.cpp
 * An example indicating the network performance.
 *
 * @warning Before executing this example, make sure there is enough space in front of the robot.
 */

int main(int argc, char** argv) {
  if (argc != 2) {
    std::cerr << "Usage: " << argv[0] << " <robot-hostname>" << std::endl;
    return -1;
  }

  uint64_t counter = 0;
  double avg_success_rate = 0.0;
  double min_success_rate = 1.0;
  double max_success_rate = 0.0;
  uint64_t time = 0;
  std::cout.precision(2);
  std::cout << std::fixed;

  try {
    franka::Robot robot(argv[1]);
    setDefaultBehavior(robot);

    // First move the robot to a suitable joint configuration
    std::array<double, 7> q_goal = {{0, -M_PI_4, 0, -3 * M_PI_4, 0, M_PI_2, M_PI_4}};
    MotionGenerator motion_generator(0.5, q_goal);
    std::cout << "WARNING: This example will move the robot! "
              << "Please make sure to have the user stop button at hand!" << std::endl
              << "Press Enter to continue..." << std::endl;
    std::cin.ignore();
    robot.control(motion_generator);
    std::cout << "Finished moving to initial joint configuration." << std::endl << std::endl;
    std::cout << "Starting communication test." << std::endl;

    robot.setCollisionBehavior(
        {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}}, {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}},
        {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}}, {{20.0, 20.0, 18.0, 18.0, 16.0, 14.0, 12.0}},
        {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}}, {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}},
        {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}}, {{20.0, 20.0, 20.0, 25.0, 25.0, 25.0}});

    franka::Torques zero_torques{{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}};
    robot.control(
        [&time, &counter, &avg_success_rate, &min_success_rate, &max_success_rate, zero_torques](
            const franka::RobotState& robot_state, franka::Duration period) -> franka::Torques {
          time += period.toMSec();
          if (time == 0.0) {
            return zero_torques;
          }
          counter++;

          if (counter % 100 == 0) {
            std::cout << "#" << counter
                      << " Current success rate: " << robot_state.control_command_success_rate
                      << std::endl;
          }
          std::this_thread::sleep_for(std::chrono::microseconds(100));

          avg_success_rate += robot_state.control_command_success_rate;
          if (robot_state.control_command_success_rate > max_success_rate) {
            max_success_rate = robot_state.control_command_success_rate;
          }
          if (robot_state.control_command_success_rate < min_success_rate) {
            min_success_rate = robot_state.control_command_success_rate;
          }

          if (time >= 10000) {
            std::cout << std::endl << "Finished test, shutting down example" << std::endl;
            return franka::MotionFinished(zero_torques);
          }

          // Sending zero torques - if EE is configured correctly, robot should not move
          return zero_torques;
        });
  } catch (const franka::Exception& e) {
    std::cout << e.what() << std::endl;
    return -1;
  }

  avg_success_rate = avg_success_rate / counter;

  std::cout << std::endl
            << std::endl
            << "#######################################################" << std::endl;
  uint64_t lost_robot_states = time - counter;
  if (lost_robot_states > 0) {
    std::cout << "The control loop did not get executed " << lost_robot_states << " times in the"
              << std::endl
              << "last " << time << " milliseconds! (lost " << lost_robot_states << " robot states)"
              << std::endl
              << std::endl;
  }

  std::cout << "Control command success rate of " << counter << " samples: " << std::endl;
  std::cout << "Max: " << max_success_rate << std::endl;
  std::cout << "Avg: " << avg_success_rate << std::endl;
  std::cout << "Min: " << min_success_rate << std::endl;

  if (avg_success_rate < 0.90) {
    std::cout << std::endl
              << "WARNING: THIS SETUP IS PROBABLY NOT SUFFICIENT FOR FCI!" << std::endl;
    std::cout << "PLEASE TRY OUT A DIFFERENT PC / NIC" << std::endl;
  } else if (avg_success_rate < 0.95) {
    std::cout << std::endl << "WARNING: MANY PACKETS GOT LOST!" << std::endl;
    std::cout << "PLEASE INSPECT YOUR SETUP AND FOLLOW ADVICE ON" << std::endl
              << "https://frankaemika.github.io/docs/troubleshooting.html" << std::endl;
  }
  std::cout << "#######################################################" << std::endl << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>#include "core/skybox.h"

skybox::skybox()
    : m_shader("skybox/skybox.vert", "skybox/skybox.frag")
{
    quad = gluNewQuadric();
	gluQuadricDrawStyle(quad, GLU_FILL);
	gluQuadricTexture(quad, TRUE);
	gluQuadricNormals(quad, GLU_SMOOTH);
}

void skybox::display(const camera& cam, glm::vec3 skycolor)
{
	float RayMult = 0; //Rayleigh scattering multipliers
	float MieMult = 0; //Mie scattering multipliers
	float InMult = 0; //Inscattering multipliers
    m_shader.bind();

    m_shader.set("view", cam.view(false));
	m_shader.set("proj", cam.proj());

	glm::vec4 altitude = glm::vec4(0);

	altitude.x = 0; //actualy supposed to by Eye->y/1000.0f but as Eye->y currently can only = 0 have simplified;
	altitude.y = std::pow(0.95f, altitude.x);
	altitude.z = 20000.0f * std::exp(0); //0 supposed to be -Eye->y/10000.0f
	altitude.w = 8000.0f * std::exp(0); //0 Supposed to be -Eye->y/20000.0f

	float g = 0.444f + cam.dir().y * 1.053e-5 - 5.984e-2 * (0) - 3.521e-6 * (0) *cam.dir().y;  //(0) = GetSunTheta;
	float g2 = 0.1f + cam.dir().y * 1.11e-5 - 3.18e-2*(0) - 6.01e-6 * (0) * cam.dir().y;  //(0) = GetSunTheta;
	float c = -0.076923f + 153.846f * MieMult;
	g = g + c*(g2 - g);
	glm::vec4 phase = glm::vec4(1-g*g,1+g*g,2*g,InMult);

	m_shader.set("altitudeDensity", altitude);
	m_shader.set("totalRayleighScattering", glm::vec3(0));
	m_shader.set("totalRayleighScatteringMult", glm::vec3(0 * 3 / (16 * 3.14))); //above * 3/16pi
	m_shader.set("totalMieScattering", glm::vec3(0));
	m_shader.set("totalMieScatteringMult", glm::vec3(0 * 1 / (4 * 3.14))); //above * 1/4pi
	glm::vec3 tmp = (glm::vec3(0 * 1 / (4 * 3.14))*glm::vec3(0 * 3 / (16 * 3.14)));
	m_shader.set("OneOverTotalRM", glm::vec3(1.0f / tmp.x, 1.0f / tmp.y, 1.0f / tmp.z));
	m_shader.set("phase", phase);
	m_shader.set("SunColorIntensity", glm::vec4(0.988f,0.831f,0.251f, 0.5f)); //SunIntensity

    //glBegin();
    gluSphere(quad, 100, 32, 32);
    //glEnd();

    m_shader.unbind();
}
<commit_msg>fixed sunintensity<commit_after>#include "core/skybox.h"

skybox::skybox()
    : m_shader("skybox/skybox.vert", "skybox/skybox.frag")
{
    quad = gluNewQuadric();
	gluQuadricDrawStyle(quad, GLU_FILL);
	gluQuadricTexture(quad, TRUE);
	gluQuadricNormals(quad, GLU_SMOOTH);
}

void skybox::display(const camera& cam, glm::vec3 skycolor)
{
	float RayMult = 0; //Rayleigh scattering multipliers
	float MieMult = 0; //Mie scattering multipliers
	float InMult = 0; //Inscattering multipliers
    m_shader.bind();

    m_shader.set("view", cam.view(false));
	m_shader.set("proj", cam.proj());

	glm::vec4 altitude = glm::vec4(0);

	altitude.x = 0; //actualy supposed to by Eye->y/1000.0f but as Eye->y currently can only = 0 have simplified;
	altitude.y = std::pow(0.95f, altitude.x);
	altitude.z = 20000.0f * std::exp(0); //0 supposed to be -Eye->y/10000.0f
	altitude.w = 8000.0f * std::exp(0); //0 Supposed to be -Eye->y/20000.0f

	float g = 0.444f + cam.dir().y * 1.053e-5 - 5.984e-2 * (0) - 3.521e-6 * (0) *cam.dir().y;  //(0) = GetSunTheta;
	float g2 = 0.1f + cam.dir().y * 1.11e-5 - 3.18e-2*(0) - 6.01e-6 * (0) * cam.dir().y;  //(0) = GetSunTheta;
	float c = -0.076923f + 153.846f * MieMult;
	g = g + c*(g2 - g);
	glm::vec4 phase = glm::vec4(1-g*g,1+g*g,2*g,InMult);

	m_shader.set("altitudeDensity", altitude);
	m_shader.set("totalRayleighScattering", glm::vec3(0));
	m_shader.set("totalRayleighScatteringMult", glm::vec3(0 * 3 / (16 * 3.14))); //above * 3/16pi
	m_shader.set("totalMieScattering", glm::vec3(0));
	m_shader.set("totalMieScatteringMult", glm::vec3(0 * 1 / (4 * 3.14))); //above * 1/4pi
	glm::vec3 tmp = (glm::vec3(0 * 1 / (4 * 3.14))*glm::vec3(0 * 3 / (16 * 3.14)));
	m_shader.set("OneOverTotalRM", glm::vec3(1.0f / tmp.x, 1.0f / tmp.y, 1.0f / tmp.z));
	m_shader.set("phase", phase);
	glm::vec4 sunIntensity = glm::vec4(0.988f, 0.831f, 0.251f, 0);
	sunIntensity.w = 9.2f - 550.0f * MieMult;
	m_shader.set("SunColorIntensity", sunIntensity); //SunIntensity

    //glBegin();
    gluSphere(quad, 100, 32, 32);
    //glEnd();

    m_shader.unbind();
}
<|endoftext|>